# Author : David Martin
# Date   : April 2, 2022
# Course : ITT103

'''Description :  A Program to Accept salesperson details to include number, name,
sale amount and their class. The Algorithm should also calculate and print the
commission as well as other details received.'''

                                    # Declarations

#START

def main() :
    s_Num = 0
    commission = 0
    import sys

                                      #Program Start

                                      # Input Section

                                      # Loop for my Termination

    while True:
        try:
            s_Num = int(input("Please Enter : a positive number to continue or a negative number to end the program\nEnter A positive or A negative number please: "))
            print()

        except ValueError :
            print("Invalid Input Please enter a positive or a negative number.")
            print()

        else :
            if s_Num > 0:
                print()
                print()
                print("                          Welcome to JamEx Limited         ")
                print ("                     Sales Commission Program Calculator   ")
                print ("                     ------------------------------------  ")
                print()
                print ("                      Please Enter the Data Requested Below ")
                break

            if s_Num < 0:
                print()
                print (" <<<<<<<<....... You have chosen to end the program .........>>>>>>>>>")
                print ("    <<<<<<<<............Have a Blessed Day.................>>>>>>>>")
                sys.exit()
                break                  #Termination Loop End

    print()

    while True:                         # Loop for my Id Number begin
        try:
            s_IdNum = int(input("Please Enter the Salesperson ID Number\nThe Salesperson ID Number is : "))

        except ValueError:
            print("Please enter the correct input")
            continue

        else:                          #_IdNum was successfully parsed!
             break                     #s_IdNum loop end.

    Cls = int(input("Please Enter Salesperson Class:\nEnter either (1, 2, 3):  "))

    while True:                         #Sales Amount Loop Begin
        try:
            sales_Amt = int(input("Please Enter Salesperson Amount:\nThe Salesperson Amount is :  "))

        except ValueError:
            print("Error please enter a correct input an Integer")
            continue

        else:
            #sales_Amt was successfully parsed!
            #we're ready to exit the loop.
            break                               #Sales Amount Loop End

    sales_Rate = 0
    print()

    if    Cls== 1:                                          #If class is 1

          if sales_Amt <= 1000:                             #If sale amount less than or equal to 1000
              sales_Rate = 6                                #6% comission
              commission = (sales_Amt*sales_Rate)

          if 2000 > sales_Amt > 1000:                       #If sale amount is greater than 1000 but less than 2000
              sales_Rate = 7                                #7% comission
              commission = (sales_Amt*sales_Rate)

          if sales_Amt >= 2000:                             #If sale amount is greater than 1000 but less than 2000
              sales_Rate = 10                               #10% comission
              commission = (sales_Amt*sales_Rate)
                                                            #The same conditions as above, only the comission percentage is different

    elif   Cls == 2 :                                       #If class is 2
           if sales_Amt < 1000:
              sales_Rate = 4                                #4% comission
              commission = (sales_Amt*sales_Rate)

           if sales_Amt >= 1000:
               sales_Rate = 6                               #6% comission
               commission = (sales_Amt*sales_Rate)

    elif   Cls == 3 :                                       #If class is 3
          sales_Rate = 4.5                                  #4.5% comission
          commission = (sales_Amt*sales_Rate)

    else :
        print("An Invalid Class was Entered")              #If any invalid class is entered
    if sales_Rate !=0 :
        print ("********** O U T P U T *********")
        print ("************* F O R *************")
        print ("****** P R I N T I N G *********")
        print ("-------------------------------  ")
        print()
        print(" Salesperson Id Number is:" + str(s_IdNum))
        print(" The Salesperson Class is: " + str(Cls))
        print(" The Salesperson Amount is: " + str("$"),(sales_Amt) )                              #If any invalid class is entered 0%
        print(" The Salesperson Rate is: " + str(sales_Rate), ("%"))
        print(" The Commission on the Sales Amount is: " + str("$"),(sales_Amt*sales_Rate/100)  )  #If any invalid class is entered 0$

                              #begin the option to do another calculation

    print()
    restart = (input("Do you wish to do another Calculation?\n Please Enter 'Y' for 'Yes' or 'N' for 'No':")).lower()

    if restart =="y" :
        main()

    else:
        print  (" <<<<<<.........You have chosen to end the program.......>>>>>>>>>>"    )
        print()
        print("<<<<<......Thank for using JamEx Limited Sales Commission Program Calculator....>>>>")
        print("          <<<<<............Have a Blessed day......>>>>>>>>")

                                    # Jamex program Calculator ends here

main()                              # To do another calculation - Start Here

#STOP


from fastapi import FastAPI, Request, BackgroundTasks
from fastapi.responses import RedirectResponse, HTMLResponse
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles

import uvicorn
import socket

app = FastAPI()

app.mount("/static", StaticFiles(directory="static"), name="static")

templates = Jinja2Templates(directory="templates")

conn = None
connected = False

async def connect():
    global conn, connected
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    local_pc = ""
    port = 12345
    s.bind((local_pc, port))
    s.listen()
    print("Waiting for connection...")
    conn, address = s.accept()
    connected = True
    print("Connection from: " + str(address))
    # return address
    return RedirectResponse(url="/home")

async def get_command(command: str):
    # conn, address = s.accept()
    # print("Connection from: " + str(address))
    try:
        conn.sendall(command.encode())
        packet = conn.recv(100000)
        decoded = packet.decode()
        # print(decoded)
        return decoded
    except:
        print("Connection closed")
        conn.close()
        connected = False
        return "Connection closed"

@app.get("/", response_class=HTMLResponse)
async def read_root(request: Request, background_tasks: BackgroundTasks):
    # address = await connect()
    # background_tasks.add_task(connect)
    if not connected:
        background_tasks.add_task(connect)

    return templates.TemplateResponse("index.html", {"request": request, "connected": connected})

@app.get("/command/{command}")
async def getCommand(command: str):
    result = await get_command(command)
    print(result)
    return result

if __name__ == '__main__':
    uvicorn.run("server_app:app", host="0.0.0.0", port=8000, reload=True)


from wand.image import Image
from wand.color import Color
from wand.drawing import Drawing

def cross_process(image_filename, output_path):
    with Image(filename=image_filename) as image:
        image.contrast_stretch(black_point=0.15, white_point=0.90,
                               channel='red')
        image.contrast_stretch(black_point=0.10, white_point=0.95,
                               channel='green')
        image.save(filename=output_path)

def aged_photo(image_filename, output_path):
    with Image(filename=image_filename) as image:
        tone_image = Image(height=image.height, width=image.width,
                           background=Color('#705a41'))
        image.modulate(brightness=100, saturation=20, hue=100)
        image.composite_channel(channel='all_channels', operator='overlay',
                                image=tone_image, left=0, top=0)

        image.save(filename=output_path)

def vivid(image_filename, output_path):
    with Image(filename=image_filename) as image:
        image.contrast_stretch(black_point=0.05, white_point=0.95,
                               channel='all_channels')
        image.modulate(brightness=100, saturation=150, hue=100)
        image.unsharp_mask(radius=1.5, amount=200, threshold=0.2, sigma=0.5)
        image.save(filename=output_path)

def bw_punch(image_filename, output_path):
    with Image(filename=image_filename) as image:
        image.transform_colorspace('gray')
        image.normalize()
        image.contrast_stretch(black_point=0.1, white_point=0.90)
        image.gamma(1.2)
        image.save(filename=output_path)

def vignette(image_filename, output_path):
    with Image(filename=image_filename) as image:
        with Drawing() as draw:
            draw.stroke_color = Color('black')
            draw.stroke_width = 2
            draw.fill_color = Color('white')
            perimeter_point = (image.height + image.width) / 5000
            draw.circle((image.width // 200, image.height // 200),  # Center point
                        (perimeter_point, perimeter_point))  # Perimeter point
            with Image(width=(image.width // 100), height=(image.height // 100),
                       background=Color('black')) as vignette_border:
                draw(vignette_border)
                vignette_border.resize(width=image.width, height=image.height,
                                       filter='hermite', blur=6.0)
                image.composite_channel(channel='all_channels',
                                        operator='multiply',
                                        image=vignette_border,
                                        left=0, top=0)
                image.save(filename=output_path)


from pathlib import Path
import numpy as np
import matplotlib.pyplot as plt

if __name__ == '__main__':
    fileName = "game_20210417233458_plot.txt"

    path = "log/"
    Path(path).mkdir(parents=True, exist_ok=True)
    filePath = path + fileName
    file = open(filePath, "r")
    listFromFile = file.read().splitlines()
    file.close()

    numberList = list()
    for x in range(len(listFromFile)):
        numberList.append([int(i) for i in listFromFile[x].split()])

    array = np.array(numberList)

    x = array[:, 0]
    yFitness = array[:, 10]

    yIntroversion = array[:, 1]
    yGatherer = array[:, 2]
    yHungry = array[:, 3]
    yConfidence = array[:, 3]
    yAggression = array[:, 5]
    yFearful = array[:, 6]
    yClump = array[:, 7]
    yShelter = array[:, 8]
    yProtect = array[:, 9]

    plt.xlabel("Turns")

    plt.plot(x, yFitness, color='red', label='Fitness')

    plt.plot(x, yIntroversion, color='peru', label='Introversion')
    plt.plot(x, yGatherer, color='peachpuff', label='Gatherer')
    plt.plot(x, yHungry, color='coral', label='Hungry')

    plt.plot(x, yConfidence, color='fuchsia', label='Confidence')
    plt.plot(x, yAggression, color='orchid', label='Aggression')
    plt.plot(x, yFearful, color='mediumvioletred', label='Fearful')

    plt.plot(x, yClump, color='blue', label='Clump')
    plt.plot(x, yShelter, color='darkblue', label='Shelter')
    plt.plot(x, yProtect, color='slateblue', label='Protect')
    plt.legend()
    plt.show()


def BurrowsWheelerTransform(string):
    BWT_arr = []
    str_len = len(string)
    string = string + "$"
    BWT_arr.append(string)
    curr_str = string
    for i in range(str_len):
        curr_str = curr_str[-1] + curr_str[:-1]
        BWT_arr.append(curr_str)
    BWT_arr.sort()
    BWT = ""
    for i in range(str_len+1):
        BWT += BWT_arr[i][str_len]
    return BWT

if __name__ == "main":
    string = "chitchat"
    print (BurrowsWheelerTransform(string))


import os
import pandas as pd
import time
from bamboo_lib.connectors.models import Connector
from bamboo_lib.helpers import query_to_df
from bamboo_lib.logger import logger

def format_text(df, cols_names=None, stopwords=None):
    for ele in cols_names:
        df[ele] = df[ele].str.title().str.strip()
        for ene in stopwords:
            df[ele] = df[ele].str.replace(" " + ene.title() + " ", " " + ene + " ")

    return df

def clean_tables(table_name: str, connector_path: str):
    db_connector = Connector.fetch("clickhouse-database", open(connector_path))

    try:
        query_to_df(db_connector, raw_query=f"DROP TABLE {table_name}")
        logger.info(f"Table {table_name} dropped!")
    except:
        pass

def wait_for_downloads(folder_path):
    print("Waiting for downloads", end="")
    while any([filename.endswith(".crdownload") for filename in os.listdir(folder_path)]):
        time.sleep(10)
        print(".", end="")

def clickhouse_table(db_connector, dim_query):
    try:
        table = query_to_df(db_connector, raw_query=dim_query)
    except:
        table = pd.DataFrame()

    return table


# License: BSD 3 clause

import unittest

import numpy as np

from tick.base.inference import InferenceTest
from tick.survival import SimuCoxReg, CoxRegression
from tick.simulation import weights_sparse_gauss
from tick.preprocessing.features_binarizer import FeaturesBinarizer
from tick.prox import ProxZero, ProxL1, ProxL2Sq, ProxElasticNet, ProxTV, \
    ProxBinarsity
from tick.solver import GD, AGD

class Test(InferenceTest):
    solvers = ['gd', 'agd']

    penalties = ['none', 'l2', 'l1', 'elasticnet', 'tv', 'binarsity']

    float_1 = 5.23e-4
    float_2 = 3.86e-2
    int_1 = 3198
    int_2 = 230

    @staticmethod
    def get_train_data(n_features=10, n_samples=10000, nnz=3, seed=12):
        np.random.seed(seed)
        coeffs0 = weights_sparse_gauss(n_features, nnz=nnz)
        features, times, censoring = SimuCoxReg(coeffs0,
                                                verbose=False).simulate()
        return features, times, censoring

    def test_CoxRegression_fit(self):
        """...Test CoxRegression fit with different solvers and penalties
        """
        raw_features, times, censoring = Test.get_train_data()

        coeffs_pen = {
            'none':
                np.array([
                    -0.03068462, 0.03940001, 0.16758354, -0.24838003,
                    0.16940664, 0.9650363, -0.14818724, -0.0802245,
                    -1.52869811, 0.0414509
                ]),
            'l2':
                np.array([
                    -0.02403681, 0.03455527, 0.13470436, -0.21654892,
                    0.16637723, 0.83125941, -0.08555382, -0.12914753,
                    -1.35294435, 0.02312935
                ]),
            'l1':
                np.array([
                    0., 1.48439371e-02, 1.03806171e-01, -1.57313537e-01,
                    1.40448847e-01, 8.05306416e-01, -5.41296030e-02,
                    -1.07753576e-01, -1.37612207e+00, 6.43289248e-05
                ]),
            'elasticnet':
                np.array([
                    0., 0.01011823, 0.10530518, -0.16885214, 0.14373715,
                    0.82547312, -0.06122141, -0.09479487, -1.39454662,
                    0.00312597
                ]),
            'tv':
                np.array([
                    0.03017556, 0.03714465, 0.0385349, -0.10169967, 0.15783755,
                    0.64860815, -0.00617636, -0.22235137, -1.07938977,
                    -0.07181225
                ]),
            'binarsity':
                np.array([
                    0.03794176, -0.04473702, 0.00339763, 0.00339763,
                    -0.16493989, 0.05497996, 0.05497996, 0.05497996,
                    -0.08457476, -0.08457476, 0.0294825, 0.13966702,
                    0.10251257, 0.02550264, -0.07207419, -0.05594102,
                    -0.10018038, -0.10018038, 0.10018038, 0.10018038,
                    -0.47859686, -0.06685181, -0.00850803, 0.55395669,
                    0.00556327, -0.00185442, -0.00185442, -0.00185442,
                    0.26010429, 0.09752455, -0.17881442, -0.17881442, 0.932516,
                    0.32095387, -0.49766315, -0.75580671, 0.0593833,
                    -0.01433773, 0.01077109, -0.05581666
                ])
        }

        for penalty in self.penalties:

            if penalty == 'binarsity':
                # binarize features
                n_cuts = 3
                binarizer = FeaturesBinarizer(n_cuts=n_cuts)
                features = binarizer.fit_transform(raw_features)
            else:
                features = raw_features

            for solver in self.solvers:

                solver_kwargs = {
                    'penalty': penalty,
                    'tol': 0,
                    'solver': solver,
                    'verbose': False,
                    'max_iter': 10
                }

                if penalty != 'none':
                    solver_kwargs['C'] = 50

                if penalty == 'binarsity':
                    solver_kwargs['blocks_start'] = binarizer.blocks_start
                    solver_kwargs['blocks_length'] = binarizer.blocks_length

                learner = CoxRegression(**solver_kwargs)
                learner.fit(features, times, censoring)

                np.testing.assert_array_almost_equal(coeffs_pen[penalty],
                                                     learner.coeffs, decimal=1)

    def test_CoxRegression_warm_start(self):
        """...Test CoxRegression warm start
        """
        features, times, censoring = Test.get_train_data()

        for solver in self.solvers:
            solver_kwargs = {
                'solver': solver,
                'max_iter': 2,
                'warm_start': True,
                'tol': 0,
                'penalty': 'none'
            }
            learner = CoxRegression(**solver_kwargs)
            learner.fit(features, times, censoring)
            score_1 = learner.score()
            learner.fit(features, times, censoring)
            score_2 = learner.score()
            # Thanks to warm start the score should have decreased (no
            # penalization here)
            self.assertLess(score_2, score_1)

        for solver in self.solvers:
            solver_kwargs = {
                'solver': solver,
                'max_iter': 2,
                'warm_start': False,
                'tol': 0,
                'penalty': 'none'
            }
            learner = CoxRegression(**solver_kwargs)
            learner.fit(features, times, censoring)
            score_1 = learner.score()
            learner.fit(features, times, censoring)
            score_2 = learner.score()
            # No warm start here, so the scores should be the same
            self.assertAlmostEqual(score_2, score_1)

    def test_CoxRegression_settings(self):
        """...Test CoxRegression basic settings
        """
        # solver
        solver_class_map = {'gd': GD, 'agd': AGD}
        for solver in self.solvers:
            learner = CoxRegression(solver=solver)
            solver_class = solver_class_map[solver]
            self.assertTrue(isinstance(learner._solver_obj, solver_class))

        msg = '^``solver`` must be one of agd, gd, got wrong_name$'
        with self.assertRaisesRegex(ValueError, msg):
            CoxRegression(solver='wrong_name')

        # prox
        prox_class_map = {
            'none': ProxZero,
            'l1': ProxL1,
            'l2': ProxL2Sq,
            'elasticnet': ProxElasticNet,
            'tv': ProxTV,
            'binarsity': ProxBinarsity
        }

        for penalty in self.penalties:
            if penalty == 'binarsity':
                learner = CoxRegression(penalty=penalty, blocks_start=[0],
                                        blocks_length=[1])
            else:
                learner = CoxRegression(penalty=penalty)

            prox_class = prox_class_map[penalty]
            self.assertTrue(isinstance(learner._prox_obj, prox_class))

        msg = '^``penalty`` must be one of binarsity, elasticnet, l1, l2, none, ' \
              'tv, got wrong_name$'
        with self.assertRaisesRegex(ValueError, msg):
            CoxRegression(penalty='wrong_name')

    def test_CoxRegression_penalty_C(self):
        """...Test CoxRegression setting of parameter of C
        """

        for penalty in self.penalties:
            if penalty != 'none':
                if penalty == 'binarsity':
                    learner = CoxRegression(penalty=penalty, C=self.float_1,
                                            blocks_start=[0],
                                            blocks_length=[1])
                else:
                    learner = CoxRegression(penalty=penalty, C=self.float_1)
                self.assertEqual(learner.C, self.float_1)
                self.assertEqual(learner._prox_obj.strength, 1. / self.float_1)
                learner.C = self.float_2
                self.assertEqual(learner.C, self.float_2)
                self.assertEqual(learner._prox_obj.strength, 1. / self.float_2)

                msg = '^``C`` must be positive, got -1$'
                with self.assertRaisesRegex(ValueError, msg):
                    if penalty == 'binarsity':
                        CoxRegression(penalty=penalty, C=-1, blocks_start=[0],
                                      blocks_length=[1])
                    else:
                        CoxRegression(penalty=penalty, C=-1)

            else:
                msg = '^You cannot set C for penalty "%s"$' % penalty
                with self.assertWarnsRegex(RuntimeWarning, msg):
                    CoxRegression(penalty=penalty, C=self.float_1)

                learner = CoxRegression(penalty=penalty)
                with self.assertWarnsRegex(RuntimeWarning, msg):
                    learner.C = self.float_1

            msg = '^``C`` must be positive, got -2$'
            with self.assertRaisesRegex(ValueError, msg):
                learner.C = -2

    def test_CoxRegression_penalty_elastic_net_ratio(self):
        """...Test CoxRegression setting of parameter of elastic_net_ratio
        """
        ratio_1 = 0.6
        ratio_2 = 0.3

        for penalty in self.penalties:
            if penalty == 'elasticnet':

                learner = CoxRegression(penalty=penalty, C=self.float_1,
                                        elastic_net_ratio=ratio_1)
                self.assertEqual(learner.C, self.float_1)
                self.assertEqual(learner.elastic_net_ratio, ratio_1)
                self.assertEqual(learner._prox_obj.strength, 1. / self.float_1)
                self.assertEqual(learner._prox_obj.ratio, ratio_1)

                learner.elastic_net_ratio = ratio_2
                self.assertEqual(learner.C, self.float_1)
                self.assertEqual(learner.elastic_net_ratio, ratio_2)
                self.assertEqual(learner._prox_obj.ratio, ratio_2)

            else:
                msg = '^Penalty "%s" has no elastic_net_ratio attribute$' % \
                      penalty
                with self.assertWarnsRegex(RuntimeWarning, msg):
                    if penalty == 'binarsity':
                        CoxRegression(penalty=penalty, elastic_net_ratio=0.8,
                                      blocks_start=[0], blocks_length=[1])
                    else:
                        CoxRegression(penalty=penalty, elastic_net_ratio=0.8)

                if penalty == 'binarsity':
                    learner = CoxRegression(penalty=penalty, blocks_start=[0],
                                            blocks_length=[1])
                else:
                    learner = CoxRegression(penalty=penalty)
                with self.assertWarnsRegex(RuntimeWarning, msg):
                    learner.elastic_net_ratio = ratio_1

    def test_CoxRegression_solver_basic_settings(self):
        """...Test CoxRegression setting of basic parameters of solver
        """
        for solver in self.solvers:
            # tol
            learner = CoxRegression(solver=solver, tol=self.float_1)
            self.assertEqual(learner.tol, self.float_1)
            self.assertEqual(learner._solver_obj.tol, self.float_1)
            learner.tol = self.float_2
            self.assertEqual(learner.tol, self.float_2)
            self.assertEqual(learner._solver_obj.tol, self.float_2)

            # max_iter
            learner = CoxRegression(solver=solver, max_iter=self.int_1)
            self.assertEqual(learner.max_iter, self.int_1)
            self.assertEqual(learner._solver_obj.max_iter, self.int_1)
            learner.max_iter = self.int_2
            self.assertEqual(learner.max_iter, self.int_2)
            self.assertEqual(learner._solver_obj.max_iter, self.int_2)

            # verbose
            learner = CoxRegression(solver=solver, verbose=True)
            self.assertEqual(learner.verbose, True)
            self.assertEqual(learner._solver_obj.verbose, True)
            learner.verbose = False
            self.assertEqual(learner.verbose, False)
            self.assertEqual(learner._solver_obj.verbose, False)

            learner = CoxRegression(solver=solver, verbose=False)
            self.assertEqual(learner.verbose, False)
            self.assertEqual(learner._solver_obj.verbose, False)
            learner.verbose = True
            self.assertEqual(learner.verbose, True)
            self.assertEqual(learner._solver_obj.verbose, True)

            # print_every
            learner = CoxRegression(solver=solver, print_every=self.int_1)
            self.assertEqual(learner.print_every, self.int_1)
            self.assertEqual(learner._solver_obj.print_every, self.int_1)
            learner.print_every = self.int_2
            self.assertEqual(learner.print_every, self.int_2)
            self.assertEqual(learner._solver_obj.print_every, self.int_2)

            # record_every
            learner = CoxRegression(solver=solver, record_every=self.int_1)
            self.assertEqual(learner.record_every, self.int_1)
            self.assertEqual(learner._solver_obj.record_every, self.int_1)
            learner.record_every = self.int_2
            self.assertEqual(learner.record_every, self.int_2)
            self.assertEqual(learner._solver_obj.record_every, self.int_2)

    def test_CoxRegression_solver_step(self):
        """...Test CoxRegression setting of step parameter of solver
        """
        for solver in self.solvers:
            learner = CoxRegression(solver=solver, step=self.float_1)
            self.assertEqual(learner.step, self.float_1)
            self.assertEqual(learner._solver_obj.step, self.float_1)
            learner.step = self.float_2
            self.assertEqual(learner.step, self.float_2)
            self.assertEqual(learner._solver_obj.step, self.float_2)

    def test_CoxRegression_score(self):
        """...Test CoxRegression score
        """
        features, times, censoring = Test.get_train_data()
        learner = CoxRegression()
        learner.fit(features, times, censoring)
        self.assertAlmostEqual(learner.score(), 3.856303803547875)

        features, times, censoring = Test.get_train_data(seed=123)
        self.assertAlmostEqual(
            learner.score(features, times, censoring), 5.556509086276002)

        msg = '^You must fit the model first$'
        learner = CoxRegression()
        with self.assertRaisesRegex(RuntimeError, msg):
            learner.score()

        msg = '^Passed ``features`` is None$'
        learner = CoxRegression().fit(features, times, censoring)
        with self.assertRaisesRegex(ValueError, msg):
            learner.score(None, times, censoring)

        msg = '^Passed ``times`` is None$'
        learner = CoxRegression().fit(features, times, censoring)
        with self.assertRaisesRegex(ValueError, msg):
            learner.score(times, None, censoring)

        msg = '^Passed ``censoring`` is None$'
        learner = CoxRegression().fit(features, times, censoring)
        with self.assertRaisesRegex(ValueError, msg):
            learner.score(features, times, None)

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


import argparse

import speech_recognition as sr
from pynput.keyboard import Key, Controller

def keypress(keyInput):
    keyboard = Controller()
    keyboard.press(keyInput)
    keyboard.release(keyInput)

def play():
    keypress(Key.space)

def fullscreen():
    keypress('f')

def forward():
    keypress(Key.right)

def backward():
    keypress(Key.left)

def vUp():
    keypress(Key.up)

def vDown():
    keypress(Key.down)

def run(args):
    r = sr.Recognizer()
    r.energy_threshold = args.threshold
    times = args.skip
    with sr.Microphone() as source:
        while 1:
            audio = r.listen(source, phrase_time_limit=5)
            try:
                user = r.recognize_google(audio)

                print(user)

                if 'play' in user:
                    play()
                elif 'stop' in user:
                    play()
                elif 'full screen' in user:
                    fullscreen()
                elif 'volume up' in user:
                    vUp()
                elif 'volume down' in user:
                    vDown()
                elif 'forward' in user:
                    for _ in range(int(times)):
                        forward()
                    play()
                elif 'backward' in user:
                    for _ in range(int(times)):
                        backward()
                    play()

            except sr.UnknownValueError:
                print("Google Speech Recognition could not understand audio")
            except sr.RequestError as e:
                print("Could not request results from Google Speech Recognition service; {0}".format(e))

def main():
    parser = argparse.ArgumentParser(description='Send key inputs using voice commands.')
    parser.add_argument(
        '-thresh',
        help='Set microphone sensitivity at which it will react to sound. Higher number - lower sensitivity. Default - 4000.',
        dest='threshold',
        type=int,
        default=4000,
        required=False)
    parser.add_argument(
        '-skip',
        help='Set the amount of skips (forward and backward) to do after you say "forward" or "backward". Default - 4',
        dest='skip',
        type=int,
        default=4,
        required=False)
    parser.set_defaults(func=run)
    args = parser.parse_args()
    args.func(args)

if __name__ == '__main__':
    main()


import os
import csv

def readcsv(filename):
    ifile = open(filename, "rU")
    reader = csv.reader(ifile, delimiter=",")

    rownum = 0
    a = []

    for row in reader:
        a.append(row)
        rownum += 1

    ifile.close()
    return a

def findVisit(array, string):
    for row in array:
        if(row[0] == string and not(row[5]=="90" or row[5] == "21")):
            return row

def findHY(array, string):
    for row in array:
        if(row[1] == string):
            return row

root_dir = os.path.abspath('./')
img_dir = os.path.join(root_dir, 'Regular')
csv_dir = os.path.join(root_dir, 'All_CSV')
init_file = os.path.join(csv_dir, 'all.csv')
work_file = os.path.join(csv_dir, 'UPDRS_Pre-Dose.csv')

#write to
sec_dir = os.path.join(root_dir, 'Run_CSV')
all_files = os.path.join(sec_dir, 'updrs_Pre_diagnosis.csv')

all_image = []

import csv

results = readcsv(init_file)
pre_dose = readcsv(work_file)

for subdir, dirs, files in os.walk(img_dir):
    counter = 0
    for file in files:
        resut = []

        split_name = file.split(".")
        split_n = split_name[0].split("_")

        id_init = split_n[len(split_n)-1]
        id_fin = id_init[1:]
        row = findVisit(results, id_fin)

        if(not row is None):
            visit = int(findVisit(results, id_fin)[5])
            name = findVisit(results, id_fin)[1]

            rating = findHY(pre_dose, name)
            if(not rating is None and visit<16):
                rate = rating[visit+3]
                print(rate)
                resut = [file, rate]
        if(len(resut)>0):
            all_image.append(resut)

myFile = open(all_files,'w' ,newline='')
print(all_image)

with myFile:
    #write 2d array to csv
    print("a")
    writer = csv.writer(myFile)
    writer.writerows(all_image)
    print("b")

Running Files -- Extract/NII_File_Writer.py


from selenium.webdriver.common.by import By
from framework.base_classes.base_form import BaseForm
from framework.base_classes.elements import TextField, DropDownList, Text, Button
from framework.utils.config_manager import ConfigManager
from framework.utils.other_utils import StringUtils, DateUtils
from framework.utils.logger_utils import LoggerUtils

class DatePickerPage(BaseForm):
    __date_field = TextField(
        locator=(By.XPATH, "//input[@id='datePickerMonthYearInput']"),
        elem_name="Date Field")

    __date_and_time_field = TextField(
        locator=(By.XPATH, "//input[@id='dateAndTimePickerInput']"),
        elem_name="Date and Time Field")

    __month_selector = DropDownList(
        locator=(By.XPATH, "//div[contains(@class, 'react-datepicker__month-dropdown-container')]"),
        elem_name="Month Selector")

    __year_selector = DropDownList(
        locator=(By.XPATH, "//div[contains(@class, 'react-datepicker__year-dropdown-container')]"),
        elem_name="Year Selector")

    __month_option = Text(
        locator=(By.XPATH, f"//option[text()='{ConfigManager.get_test_data()['month']}']"),
        elem_name="Month Option")

    __calendar_dates = Button(
        locator=(
            By.XPATH,
            "//div[@class='react-datepicker__week']//child::div[contains(@class, 'react-datepicker__day')]"),
        elem_name="Calendar Dates")

    __date = Button(
        locator=(By.XPATH, f"//div[text()='{ConfigManager.get_test_data()['date']}']\
            [contains(@aria-label, '{ConfigManager.get_test_data()['month']}')]"),
        elem_name="Date")

    __selected_month_and_year = Text(
        locator=(By.XPATH, "//div[contains(@class, 'react-datepicker__current-month')]"),
        elem_name="Selected Month and Date")

    def __init__(self):
        super().__init__(
            unique_element=self.__date_field,
            name="Date Picker Page")

    def click_date_field(self):
        LoggerUtils().debug("Clicking on the Date Field on the '%s'", self._name)
        self.__date_field.click()

    def click_month_selector(self):
        LoggerUtils().debug("Clicking on the Month Selector on the '%s'", self._name)
        self.__month_selector.click()

    def click_year_selector(self):
        LoggerUtils().debug("Clicking on the Year Selector on the '%s'", self._name)
        self.__year_selector.click()

    def choose_month(self):
        LoggerUtils().debug("Clicking on the Month Option on the '%s'", self._name)
        self.__month_option.click()

    def get_date_from_date_field(self):
        LoggerUtils().debug("Getting value of the Date Field attribute on the '%s'", self._name)
        return self.__date_field.get_attribute("value")

    def get_date_time_from_date_and_time_field(self):
        LoggerUtils().debug("Getting value of the Date and Time Field attribute on the '%s'", self._name)
        return self.__date_and_time_field.get_attribute("value")

    def get_selected_month_and_year(self):
        LoggerUtils().debug("Getting text from the Selected Month and Year Field on the '%s'", self._name)
        return self.__selected_month_and_year.get_text()

    def check_if_date_is_in_the_calendar(self):
        LoggerUtils().debug("Checking if the target date is in the calendar on the '%s'", self._name)
        return True if self.__date.is_present() else False

    def choose_date(self):
        LoggerUtils().debug("Clicking on the Date Field on the '%s'", self._name)
        self.__date.click_with_js()

    def choose_one_year_after(self):
        LoggerUtils().debug("Choosing the follwoing year with the down arrow on the '%s'", self._name)
        self.__year_selector.press_down_arrow()
        self.__year_selector.press_enter()

    def select_year_that_has_target_date(self):
        LoggerUtils().debug("Looking for the year that has the target date on the '%s'", self._name)
        while self.check_if_date_is_in_the_calendar() is False:
            self.click_year_selector()
            self.choose_one_year_after()

    def get_selected_month_date_year(self):
        LoggerUtils().debug("Returning the selected month, date and year on the '%s'", self._name)
        date = str(ConfigManager.get_test_data()["date"])
        selected_month = DateUtils.convert_month_to_number(
            StringUtils.get_str_without_digits(self.get_selected_month_and_year()))
        selected_year = str(StringUtils.get_int_from_str(self.get_selected_month_and_year()))
        return selected_month + "/" + date + "/" + selected_year


import socket
import ssl

class mockSSLSocket:
	def __init__(self):
		self._readBuffer = bytearray()
		self._writeBuffer = bytearray()
		self._isClosed = False
		self._isFragmented = False
		self._fragmentDoneThrowError = False
		self._currentFragments = bytearray()
		self._fragments = list()
		self._flipWriteError = False
		self._flipWriteErrorCount = 0

	# TestHelper APIs
	def refreshReadBuffer(self, bytesToLoad):
		self._readBuffer = bytesToLoad

	def reInit(self):
		self._readBuffer = bytearray()
		self._writeBuffer = bytearray()
		self._isClosed = False
		self._isFragmented = False
		self._fragmentDoneThrowError = False
		self._currentFragments = bytearray()
		self._fragments = list()
		self._flipWriteError = False
		self._flipWriteErrorCount = 0

	def getReaderBuffer(self):
		return self._readBuffer

	def getWriteBuffer(self):
		return self._writeBuffer

	def addReadBufferFragment(self, fragmentElement):
		self._fragments.append(fragmentElement)

	def setReadFragmented(self):
		self._isFragmented = True

	def setFlipWriteError(self):
		self._flipWriteError = True
		self._flipWriteErrorCount = 0

	def loadFirstFragmented(self):
		self._currentFragments = self._fragments.pop(0)

	# Public APIs
	# Should return bytes, not string
	def read(self, numberOfBytes):
		if not self._isFragmented:  # Read a lot, then nothing
			if len(self._readBuffer) == 0:
				raise socket.error(ssl.SSL_ERROR_WANT_READ, "End of read buffer")
			# If we have enough data for the requested amount, give them out
			if numberOfBytes <= len(self._readBuffer):
				ret = self._readBuffer[0:numberOfBytes]
				self._readBuffer = self._readBuffer[numberOfBytes:]
			else:
				ret = self._readBuffer
				self._readBuffer = self._readBuffer[len(self._readBuffer):]  # Empty
			return ret
		else:  # Read 1 fragement util it is empty, then throw error, then load in next
			if self._fragmentDoneThrowError and len(self._fragments) > 0:
				self._currentFragments = self._fragments.pop(0)  # Load in next fragment
				self._fragmentDoneThrowError = False  # Reset ThrowError flag
				raise socket.error(ssl.SSL_ERROR_WANT_READ, "Not ready for read op")
			# If we have enough data for the requested amount in the current fragment, give them out
			ret = bytearray()
			if numberOfBytes <= len(self._currentFragments):
				ret = self._currentFragments[0:numberOfBytes]
				self._currentFragments = self._currentFragments[numberOfBytes:]
				if len(self._currentFragments) == 0:
					self._fragmentDoneThrowError = True  # Will throw error next time
			else:
				ret = self._currentFragments
				self._currentFragments = self._currentFragments[len(self._currentFragments):]  # Empty
				self._fragmentDoneThrowError = True
			return ret

	# Should write bytes, not string
	def write(self, bytesToWrite):
		if self._flipWriteError:
			if self._flipWriteErrorCount % 2 == 1:
				self._writeBuffer += bytesToWrite  # bytesToWrite should always be in 'bytes' type
				self._flipWriteErrorCount += 1
				return len(bytesToWrite)
			else:
				self._flipWriteErrorCount += 1
				raise socket.error(ssl.SSL_ERROR_WANT_WRITE, "Not ready for write op")
		else:
			self._writeBuffer += bytesToWrite  # bytesToWrite should always be in 'bytes' type
			return len(bytesToWrite)

	def close(self):
		self._isClosed = True


print('Digite a nota do aluno no Primeiro, Segundo, Terceiro e Quarto bimestre.')
n1 = float(input('Primeiro Bimestre: '))
n2 = float(input('Segundo Bimestre: '))
n3 = float(input('Terceiro Bimestre: '))
n4 = float(input('Quarto Bimestre: '))
m = (n1 + n2 + n3 + n4) / 4
print('Sua média de notas é {:.1f}.'.format(m))
if m <= 6.9:
    print('Você está reprovado!')
else:
    print('Você está aprovado!')

#print('Você está aprovado!' if m >= 7 else ('Você está reprovado!'))


import sys
import os

cesar3 = {
    'a': 'd',
    'b': 'e',
    'c': 'f',
    'd': 'g',
    'e': 'h',
    'f': 'i',
    'g': 'j',
    'h': 'k',
    'i': 'l',
    'j': 'm',
    'k': 'n',
    'l': 'o',
    'm': 'p',
    'n': 'q',
    'o': 'r',
    'p': 's',
    'q': 't',
    'r': 'u',
    's': 'v',
    't': 'w',
    'u': 'x',
    'v': 'y',
    'w': 'z',
    'x': 'a',
    'y': 'b',
    'z': 'c',
    ' ' : ' '
}

#Completa esta funcion
def generar_cifrador(offset):
    letras = [
        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
        'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
    ]

#Completa esta funcion (quita # para activar)
try:
    archivo = open("nombre.txt", "r")
    lista = archivo.readline()
    archivo.close()
    print(lista)
except IOError as identifier:
    print("No se pudo leer el archivo")
    sys.exit(1)

def cifrar(palabra, cifrador):
    letras = [item for item in palabra]
    print(letras)
    #print(cifrador.values())
    palabra_cifrada=[]
    for letra in palabra:
        palabra_cifrada.append(cifrador.get(letra))
    print(palabra_cifrada)
    print(' '.join(palabra_cifrada))

def curp():
    nombre = ["a","l","e","x"," ","v","i","l","l","a", " ","o","c","a"]
    curp = []
    #print(nombre)
    for letra in nombre:
        nombre.pop()
    print(nombre)
curp()
#cifrar(lista, cesar3)
#Completa esta funcion (quita # para activar)
#def mostrar_cifrador(cifrador):

#Completa el resto del codigo


from flask_app import app
from flask import render_template, redirect, request, flash, session
from flask_app.models.users import Users
from flask_app.models.clubs import Carmeets

@app.route('/dashboard')
def user_dash():
    if 'user_id' not in session:
        return redirect('/register')
    data = { 'id': session['user_id']}
    return render_template('profile_dashboard.html',users = Users.get_follow(data))

@app.route('/dashboard/create', methods=['POST'])
def user_create():
    data = {
        'creator_id': request.form['creator_id'],
        'name': request.form['name'],
        'type': request.form['type'],
        'location': request.form['location'],
        'date_time': request.form['date_time'],
    }
    if 'user_id' not in session:
        return redirect('/')
    Carmeets.create_meet(data)
    return redirect('/dashboard')

@app.route('/pick/<int:carmeets_id>')
def pick(carmeets_id):
    data = {
        'id': id,
        'id': session['user_id'],
    }
    if 'user_id' not in session:
        return redirect('/register')
    return render_template('show_club.html', users = Users.get_id(data), carmeets = Carmeets.meet_up(carmeets_id))

@app.route('/following', methods=['POST'])
def following():
    data = {
        'follow_id': request.form['follow_id'],
        'meet_id': request.form['meet_id'],
    }
    if 'user_id' not in session:
        return redirect('/')
    Carmeets.follow(data)
    return redirect('/dashboard')

@app.route('/club/dash')
def club_dash():
    data = {
        'id': session['user_id']
    }
    if 'user_id' not in session:
        return redirect('/register')
    return render_template('club_dashboard.html', users = Users.get_id(data), carmeets = Carmeets.get_club_id())

@app.route('/club/<int:carmeets_id>')
def club_edit(carmeets_id):
    data = {
        'id': id,
        'id': session['user_id'],
    }
    if 'user_id' not in session:
        return redirect('/register')
    return render_template('update.html', users = Users.get_id(data), carmeets = Carmeets.meet_up(carmeets_id))

@app.route('/update/<int:carmeets_id>', methods=['POST'])
def edit(carmeets_id):
    data = {
        'id': request.form['id'],
        'creator_id': request.form['creator_id'],
        'name': request.form['name'],
        'type': request.form['type'],
        'location': request.form['location'],
        'date_time': request.form['date_time'],
    }
    if 'user_id' not in session:
        return redirect('/')
    Carmeets.update(data)
    return redirect(f'/pick/{carmeets_id}')

@app.route('/delete/<int:carmeets_id>')
def delete_meet(carmeets_id):
    Carmeets.delete(carmeets_id)
    return redirect('/club/dash')


import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule

class LanbojiniSpider(CrawlSpider):
    name = 'lanbojini'
    # allowed_domains = ['www.che168.com']
    start_urls = ['https://www.che168.com/china/lanbojini/?pvareaid=101025']

    rules = (
        Rule(LinkExtractor(allow=r'/china/lanbojini/a0_0msdgscncgpi1ltocsp\d+exx0/\?pvareaid=102179#currengpostion'),
             callback='parse_item', follow=True),
    )

    def parse_item(self, response):
        print("===========================================")
        print(response.text)
        print("===========================================")


import pygame as pg

vec = pg.math.Vector2

class Universe:
    def __init__(self):
        self.bodies = []
        self.particles = []
        self.zoom = 1
        self.camera = vec(0, 0)
        self.focus = None

    def update(self, dt, t):
        if not (self.focus is None):
            self.camera = self.focus.pos - vec(450, 300) * 1 / self.zoom
            if self.focus.vel.length() > 300:
                self.zoom = vec(self.zoom, 0).lerp(vec(0.5, 0), 0.5 * dt).x
            else:
                self.zoom = vec(self.zoom, 0).lerp(vec(1, 0), 0.5 * dt).x

        for b in self.bodies:
            b.update(dt, t)

    def draw_poly(self, screen, color, global_points, parallax=1):
        points = [self.get_render_point(p, parallax) for p in global_points]
        pg.draw.polygon(screen, color, points)

    def draw_circle(self, screen, color, global_center, radius, parallax=1):
        center = self.get_render_point(global_center, parallax)
        pg.draw.circle(screen, color, center, max(1, radius * self.zoom))

    def get_render_point(self, point, parallax=1):
        return (vec(point) - self.camera) * self.zoom * parallax


from django.urls import path
from .views import ListPokemon,GetPokemonId,GetPokemonNombre,ListPokedex,GetPokedexId,GetPokedexNombre

urlpatterns = [
    path('pokemon/',ListPokemon.as_view(),name='lista_pokemones'),
    path('pokemon/<int:id>',GetPokemonId.as_view(),name='id_pokemon'),
    path('pokemon/<nombre>',GetPokemonNombre.as_view(),name='nombre_pokemon'),
    path('pokedex/',ListPokedex.as_view(),name='lista_pokedex'),
    path('pokedex/<int:id>',GetPokedexId.as_view(), name='id_pokedex'),
    path('pokedex/<nombre>',GetPokedexNombre.as_view(),name='nombre_pokedex')
]


class FoldablePaper:

    def __init__(self,filename):
        self.points = set()
        self.folds = []
        self.read_input_file(filename)
        self.folds_complete = 0

    def print_points(self):
        #Find biggest x and y co-ordinate
        x_max=39
        y_max=6
        #build grid to size of co-ordinates
        array = [[' ' for x in range(0,x_max)] for y in range(0,y_max)]
        pass
        #Add points to grid
        for location in self.points:
            array[location[1]][location[0]] = '#'
        #print grid
        for row in array:
            for point in row:
                print(point,end='')
            print()

    def execute_next_fold(self):
        fold_line = self.folds[self.folds_complete]
        new_points = set()
        for point in self.points:
            new_point = ()
            if fold_line[0] == 'y':
                if point[1] > fold_line[1]:
                    new_point = (point[0], 2*fold_line[1] - point[1])
                else:
                    new_point = point
            else:
                if point[0] > fold_line[1]:
                    new_point = (2*fold_line[1] - point[0], point[1])
                else:
                    new_point = point
            #print(f'{point} becomes {new_point}')
            new_points.add(new_point)
        self.points = new_points
        self.folds_complete += 1

    def read_input_file(self,filename):
        with open(filename,'r') as f:
            for line in f:
                line = line.strip()
                if line == '':
                    pass
                elif line[0] == 'f':
                    line = line.split(' ')
                    fold = line[2].split('=')
                    self.folds.append((fold[0],int(fold[1])))
                else:
                    point = line.split(',')
                    point  = (int(point[0]),int(point[1]))
                    self.points.add(point)
        print(f'{len(self.points)} points and {len(self.folds)} folds loaded')


#https://www.ime.usp.br/~macmulti/exercicios/inteiros/index.html
#Dados um inteiro x e um inteiro não-negativo n, calcular x elevado n.

import math

def main():
    numbase=int(input("Digite o númeo base: "))
    numexpo=int(input("Digite a potência: "))

    resultado=math.pow(numbase, numexpo);

    print(f"{resultado}")

main()


# ==================================================
# Problem  :   722B - Verse Pattern
# Run time :   0.062 sec.
# Language :   Python 3.5
# ==================================================

def main():
	from sys import stdin, stdout

	# stdin = open("input.txt", "r")

	inp = stdin.readlines()

	n = int(inp[0])

	versePattern = iter(map(int, inp[1].split()))

	ans = True

	for line in inp[2:]:
		vowelCnt = 0

		for x in line:
			if x in "aeiouy":
				vowelCnt += 1

		if vowelCnt != next(versePattern):
			ans = False
			break

	stdout.write("YES\n" if ans else "NO\n")

if __name__ == '__main__':
	main()


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

# import libs
import flask
from flask import jsonify, request
from keras.applications.vgg16 import VGG16, preprocess_input, decode_predictions
from keras.preprocessing import image
from PIL import Image
from io import BytesIO
import numpy as np
import tensorflow as tf
import requests
import sys
import os

# initialize flask and keras model
app = flask.Flask(__name__)
#app.config['DEBUG'] = True # Enable it for debug
#app.config["JSON_AS_ASCII"] = False # for fix chinese issue
model = None
graph = None

def load_model():
    global model
    model = VGG16(weights='imagenet')

    #
    global graph
    graph = tf.get_default_graph()

def get_image(filename, target):
    img = None
    # download image
    if filename.startswith('http://') or filename.startswith('https://'):
        response = requests.get(filename)
        img = Image.open(BytesIO(response.content))
        img = img.resize( target, Image.BILINEAR)
    # local file
    else:
        if not os.path.exists(filename):
            print('file does not exist')
        else:
            img = image.load_img(filename, target_size= target)

    return img

def process_image(img):
    x = None
    if img is not None:
        if img.mode != "RGB":
            img = img.convert("RGB")

        x = image.img_to_array(img)
        x = np.expand_dims(x, axis = 0)
        x = preprocess_input(x)

    return x

@app.route('/', methods=['GET'])
def home():
    return "
Hello Flask!
"

# featuresize: length of predict result
@app.route('/predict', methods=['POST'])
def predict():
    img = None
    img_path = ""
    featuresize = 10
    target = (224, 224)
    data = {"success": False}

    if 'size' in request.values:
        featuresize = int(request.values['size'])

    if 'img_path' in request.values:
        img_path = request.values['img_path']
        print('img_path='+img_path)
        img = get_image(img_path, target= target)

        # process image
        img = process_image(img)

        # predict
        with graph.as_default():
            preds = model.predict(img)
        results = decode_predictions(preds, top=featuresize)[0]
        data["predictions"] = []

        # loop over and format the result
        for (imagenetID, label, prob) in results:
            r = {"label": label, "probability": float(("{0:.2f}".format(prob * 100)))}
            data["predictions"].append(r)

        data["success"] = True

    return jsonify(data)

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


# -*- coding: utf-8 -*-
'''
Created on 16 août 2018

@author: Mahery
'''
# # K-nearest neighbors module

# %%

import numpy as np
import math as mt
import itertools as it
import operator as op
import copy as cp
import scipy.spatial.distance as sci_dist
# from numpy import * # Pour PyDev
# from sklearn.metrics.pairwise import pairwise_distances as dist_pairwise

# %%

# NaN (not a number) que l'on convertit en float
nan = float('nan')

# %%

def set_range(liste):
    """Convertit un range de liste en un ensemble pour que les tests
    d'appartenance soit en O(1)."""
    return set(range(liste))

# %%

def table_dimension_2d(list_tab):
    """Return the height and the width of a 2d list of lists."""

    # !!! A améliorer pour pouvoir recevoir une liste en 1D !!!
    list_height = len(list_tab)
    list_width = len(list_tab[0])
    return list_height, list_width

# %%

def remove_lin_col(list_tab, ind_lin=[], ind_col=[]):
    """Elimine les variables des lignes ou colonnes spécifiées d'une liste
    et retourne une table tronquée des lignes ou des colonnes voulues.

    Keywords arguments:
        list_table -- liste python
        ind_lin -- liste des indices des lignes des variables à
        tronquer (default [])
        ind_col -- liste des indices des colonnes des variables à
        tronquer (default [])

    Returns:
        list_tab_tronq -- table tronquée des lignes ou des colonnes
        voulues
    """

    # table sans les variables qualitatives
    list_tab_tronq = [list_tab[i][j] for i in set_range(
            table_dimension_2d(list_tab)[0]) for j in set_range(
                    table_dimension_2d(list_tab)[1])
        if i not in set(ind_lin) and j not in set(ind_col)]

    return list_tab_tronq

# %%

def conversion_array(list_tab, new_shape_lin=-1, new_shape_col=-1):
    """Convertit une liste en un tableau de numpy et le reforme.

    Keywords arguments:
        new_shape_lin -- nouvelle hauteur voulue du tableau (default -1)
        new_shape_col -- nouvelle largeur voulue du tableau (default -1)

    Returns:
        array_list_tab -- tableau numpy reformé
    """

    # Conversion de la table en array
    array_list_tab = np.array(list_tab)
    array_list_tab = array_list_tab.reshape(new_shape_lin, new_shape_col)

    return array_list_tab

# %%

def detecter_nan(array_input):
    """Détecte les nan dans un array et retourne une liste des index des
    lignes correspondants.

    Returns:
        coord_nan -- coordonnées des valeurs numériques
        ind_lin_nan -- indice des lignes des valeurs numèriques
        ind_col_nan -- indice des colonnes des valeurs numèriques
        coord_not_nan -- coordonnées des valeurs non numèriques
    """

    ind_lin_nan = []  # indices des lignes qui ont au moins un nan
    ind_col_nan = []  # indices des colonnes qui ont au moins un nan
    coord_nan = []  # coordonnées des valeurs nan
    coord_not_nan = []  # coordonnées des valeurs non nan

    # Extraction des indices de lignes qui contiennent un nan
    for ind, e in np.ndenumerate(array_input):
        if mt.isnan(e):
            # print (f'isnan: ind = {ind}, val = {e}')
            ind_lin_nan.append(ind[0])
            ind_col_nan.append(ind[1])
            coord_nan.append(ind)
        else:
            # print (f'is not nan: ind = {ind}, val = {e}')
            coord_not_nan.append(ind)

    # Conversion en set pour ne garder que les éléments uniques
    ind_lin_nan = list(set(ind_lin_nan))
    ind_col_nan = list(set(ind_col_nan))

    return coord_nan, ind_lin_nan, ind_col_nan, coord_not_nan

# %%

def group_indcol_tuple(tupl_list):
    """ Regroupe les coordonnées des valeurs d'une liste de tuples
    sous la forme: [(première valeur du tuple, [liste des autres valeurs
    de tuple ayant la première valeur en commun])].

        Returns:
            tupl_list_group -- coordonnées des valeurs d'une liste de tuples
    sous la forme: [(première valeur du tuple, [liste des autres valeurs
    de tuple ayant la première valeur en commun])]
            len_tupl_list_group -- taille de la liste de sortie
    """

    tupl_list_group = [(n, list(list(zip(*g))[1])) for n, g in it.groupby(
            tupl_list, op.itemgetter(0))]
    # print(f'tupl_list_group =\n{tupl_list_group}\n')
    len_tupl_list_group = len(tupl_list_group)

    return tupl_list_group, len_tupl_list_group

# %%

def distance(array_ref, array_pointtest, ind_lin_pttest, ind_col_pttest,
             sr_height_array_ref, metrique='euclidean'):
    """Retourne la distance de chaque point test aux pts de références.

    Keywords arguments:
        array_ref -- tableau des points de référence
        array_pointtest -- tableau des points de test
        ind_lin_pttest -- indice des lignes des valeurs des points test
        ind_col_pttest -- liste des indices des colonnes des valeurs des
        points test
        sr_height_array_ref -- ensemble du range de la hauteur du tableau de
        référence
        metrique
    """

#        print(f'array_ref[0]=\n{array_ref[0]}\nshape = {array_ref[0].shape} ')
#        test_pttest = array_pointtest[ind_lin_pttest,ind_col_pttest]
#        print\
#        (f'array_pointtest[ind_lin_pttest,ind_col_pttest]=\n{test_pttest}\n\
#         shape = {test_pttest.shape} ')

    if metrique == 'euclidean':
        distances = [np.linalg.norm(array_ref[i]-array_pointtest[
                ind_lin_pttest, ind_col_pttest]) for i in sr_height_array_ref]
    elif metrique == 'braycurtis':
        distances = [sci_dist.braycurtis(array_ref[i], array_pointtest[
                ind_lin_pttest, ind_col_pttest]) for i in sr_height_array_ref]
    elif metrique == 'cityblock':
        distances = [sci_dist.cityblock(array_ref[i], array_pointtest[
                ind_lin_pttest, ind_col_pttest]) for i in sr_height_array_ref]
    elif metrique == 'canberra':
        distances = [sci_dist.canberra(array_ref[i], array_pointtest[
                ind_lin_pttest, ind_col_pttest]) for i in sr_height_array_ref]
    elif metrique == 'chebyshev':
        distances = [sci_dist.chebyshev(array_ref[i], array_pointtest[
                ind_lin_pttest, ind_col_pttest]) for i in sr_height_array_ref]
    elif metrique == 'cosine':
        distances = [sci_dist.cosine(array_ref[i], array_pointtest[
                ind_lin_pttest, ind_col_pttest]) for i in sr_height_array_ref]
    elif metrique == 'correlation':
        distances = [sci_dist.correlation(array_ref[i], array_pointtest[
                ind_lin_pttest, ind_col_pttest]) for i in sr_height_array_ref]
    elif metrique == 'minkowski':
        distances = [sci_dist.minkowski(array_ref[i], array_pointtest[
                ind_lin_pttest, ind_col_pttest]) for i in sr_height_array_ref]
    elif metrique == 'jaccard':
        distances = [sci_dist.jaccard(array_ref[i], array_pointtest[
                ind_lin_pttest, ind_col_pttest]) for i in sr_height_array_ref]

    return distances

# %%

def k_nn(pointtest, list_references, K, ind_col_quali=[], metrique='euclidean',
         imputation=False):
    """Retourne un tableau imputé, calcule les K plus proches voisins
    d'un point test, et retourne les indices des lignes et les
    distances à ceux-ci.

    Keywords arguments:
        pointtest -- liste 2d ou 2darray des points test;
        pour l'instant les points test n'ont pas de variables qualitatives,
        mais doivent avoir le MÊME nombre de modalités quantitatives que
        les valeurs de référence.
        Il faudrait modifier le programme de façon à ce qu'il puisse
        éliminer d'éventuelles modalités qualitatives des points test
        list_references -- liste 2d des points de référence
        ind_col_quali -- liste des indices des colonnes des variables
        qualitatives
        K -- rang du K plus proche voisin voulu pour le calcul de distance
        metrique -- {'braycurtis', 'cityblock', 'canberra', 'chebyshev',
                     'cosine', 'correlation', 'minkowski', 'jaccard'},
        optional (default='euclidean')
        imputation -- True si on veut déclencher l'imputation des valeurs Nan

    Return:
        imputed_points -- nd_array des points considérés comme imputés
        ind_lin_k_nearest -- indices des lignes des k plus proches voisins
        distances_k_nearest -- k distances les plus proches

    """
    # print(f'list_references =\n{list_references}\n')

    # Dimensions de la table des points tests
    height_pointtest, width_pointtest = table_dimension_2d(pointtest)

    # print(f'nb_ligne_pttest = {height_pointtest}')
    # print(f'nb_col_pttest = {width_pointtest}\n')

    # ## Détection des lignes avec nan

    # tab ref sans colonne quali
    list_ref_quanti = remove_lin_col(list_references, ind_col=ind_col_quali)

    # conversion de tab_ref en array sans valeurs qualitatives
    array_ref_quanti = conversion_array(
            list_ref_quanti, new_shape_lin=table_dimension_2d(
                    list_references)[0])
    # print(f'array_ref_quanti =\n{array_ref_quanti}\n')

    # conversion de la liste pointtest en array
    array_pointtest = conversion_array(pointtest,
                                       new_shape_lin=height_pointtest)
    # print(f'\narray_pointtest=\n{array_pointtest}\narray_pointtest.shape =\n\
# {array_pointtest.shape}')

    # coordonnées des valeurs nan dans points_test
    # ind colonnes avec nan des points_test
    # coordonnées des valeurs non nan dans points_test
    coord_pttest_nan, _, ind_col_pttest_nan, coord_pttest_no_nan = \
        detecter_nan(array_pointtest)

    # print(f'coord_pttest_nan = \n{coord_pttest_nan}\n')
    # print(f'ind_col_pttest_nan = \n{ind_col_pttest_nan}\n')
    # print(f'coord_pttest_no_nan = \n{coord_pttest_no_nan}\n')

    # ind ligne avec nan de la table de reference
    ind_lin_tab_ref_nan = detecter_nan(array_ref_quanti)[1]
    # print(f'ind_lin_tab_ref_nan = \n{ind_lin_tab_ref_nan}\n')

    # Suppression des lignes avec nan dans la table de référence:
    array_ref_no_nan = remove_lin_col(array_ref_quanti,
                                      ind_lin=ind_lin_tab_ref_nan)

    # Reshape en array
    array_ref_no_nan = conversion_array(
            array_ref_no_nan, new_shape_col=table_dimension_2d(
                    array_ref_quanti)[1])
    # print(f'array_ref_no_nan =\n{array_ref_no_nan}\n')

    # ### Distance des points de référence aux points de test

    array_ref_tronq = list()
    # Rassemblement des K plus faibles distances
    distances_k_nearest_all = list()
    # Rassemblement de tous les indices des lignes des K plus faibles distances
    ind_lin_k_nearest_all = list()

    # Données des valeurs nan des points test à traiter
    coord_pttest_nan_grouped, len_coord_pttest_nan_grouped = \
        group_indcol_tuple(coord_pttest_nan)

    # Indices des lignes des points test
    ind_lin_pttest_nan = [coord_pttest_nan_grouped[i][0] for i in set_range(
            len_coord_pttest_nan_grouped)]
    # print(f'Indice des lignes des points test "ind_lin_pttest_nan" =\n\
# {ind_lin_pttest_nan}\n')

    # Indices des colonnes des points test
    ndlist_ind_col_pttest_nan = [coord_pttest_nan_grouped[i][1] for i in
                                 set_range(len_coord_pttest_nan_grouped)]
    # print(f'Indice des colonnes des points test
    # "ndlist_ind_col_pttest_nan"=\n\{ndlist_ind_col_pttest_nan}\n')

    # Données des valeurs numériques des points test à traiter
    coord_pttest_no_nan_grouped, len_coord_pttest_no_nan_grouped =\
        group_indcol_tuple(coord_pttest_no_nan)

    # Points à imputer après calculs
    imputed_points = cp.deepcopy(array_pointtest)  # deep copy

    if imputation:
        # Moyennes des valeurs du tableau de référence par colonnes
        moyenne_colonne_ref = array_ref_no_nan.mean(axis=0)

    for j in set_range(len_coord_pttest_no_nan_grouped):
        # Indice de la ligne du point test en cours de traitement
        ind_lin_pttest_no_nan = coord_pttest_no_nan_grouped[j][0]
        # print('Indice de la ligne du point test en cours:')
        # print(f'ind_lin_pttest_no_nan = {ind_lin_pttest_no_nan}\n')

        # Indice de la colonne du point test en cours de traitement
        ind_col_pttest_no_nan = coord_pttest_no_nan_grouped[j][1]
        # print('Indice de la colonne du point test en cours:')
        # print(f'ind_col_pttest_no_nan = {ind_col_pttest_no_nan}\n')

        # Donne un tableau des points de référence tronqué des colonnes de
        # mêmes indices que les colonnes du pointtest qui contiennent
        # au moins un nan.
        array_ref_tronq = array_ref_no_nan[:, ind_col_pttest_no_nan]
        height_array_ref_tronq = len(array_ref_tronq)
        sr_height_array_ref_tronq = set_range(height_array_ref_tronq)

        print('\n', 79*'-', '\n')
        print(f'tour = {j+1}\n')
        # print(f'array_ref_tronq=\n{array_ref_tronq}\n')
        # print(f'shape(array_ref_tronq) = {np.shape(array_ref_tronq)}\n')

        # Distances de chaque point test aux pts de références:
        list_distances = distance(
                array_ref_tronq, array_pointtest, ind_lin_pttest_no_nan,
                ind_col_pttest_no_nan,
                sr_height_array_ref=sr_height_array_ref_tronq,
                metrique=metrique)
        # print(f'distances {metrique} =\n{list_distances}\n')

        # ## Classement des distances:
        # TROUVER les INDICES des lignes de la table de référence, pour les K
        # plus faibles distances au point test!

        # Distances classées des points de références aux points test
        distances_sorted = sorted(list_distances)

        # Indices classés des lignes du tableau de référence qui correspondent
        # aux distances des points de référence aux points test:
        indices_distances = [indx for dstncs_srtd in set(distances_sorted)
                             for indx, vl in enumerate(list_distances)
                             if vl == dstncs_srtd]
        # print(f'indices_distances =\n{indices_distances}\n')

        # On ne garde que les K plus faibles distances:
        distances_k_nearest = distances_sorted[:K]
        # print(f'distances_k_nearest =\n{distances_k_nearest}\n')

        # Placement de toutes les distances dans une liste
        distances_k_nearest_all.append(distances_k_nearest)

        # Indices des lignes du tableau de référence qui correspondent aux K
        # plus faibles distances des points de référence aux points test:
        ind_lin_k_nearest = sorted(indices_distances[:K])
        # print(f'ind_lin_k_nearest =\n{ind_lin_k_nearest}\n')

        # Placement de tous les indices dans une liste
        ind_lin_k_nearest_all.append(ind_lin_k_nearest)

        if imputation:
            # Ne fonctionne pas !
            # imputed_points = imputation_knn(
            #        imputed_points, moyenne_colonne_ref, array_ref_no_nan,
            #        len_coord_pttest_nan_grouped, ndlist_ind_col_pttest_nan,
            #        array_ref_quanti, ind_lin_pttest_nan,
            #        ind_lin_pttest_no_nan, ind_lin_k_nearest)

            # # Imputation des valeurs manquantes
            # Calcul des valeurs d'imputation
            for m in set_range(len_coord_pttest_nan_grouped):
                # Si toutes les colonnes d'une ligne sont nan, on calcule les
                # moyennes entre toutes les valeurs des colonnes des points de
                # référence afin d'imputer le point
                if len(ndlist_ind_col_pttest_nan[m]) ==\
                        np.shape(array_ref_quanti)[1]:
                            imputed_points[ind_lin_pttest_nan[m]][:] =\
                                moyenne_colonne_ref[:]

                # Conditionner l'indice de la colonne à traiter de façon à ce
                # qu'on ne traite que les points de mêmes indices de ligne à
                # chaque tour.
                if ind_lin_pttest_nan[m] == ind_lin_pttest_no_nan:
                    nb_nan_in_col = len(ndlist_ind_col_pttest_nan[m])
                    # print(
                    # f'nombre de nan dans la colonne = {nb_nan_in_col}\n')

                    for p in set_range(nb_nan_in_col):
                        # Calcul de la moyenne
                        valeur_imputation = np.mean(
                                [array_ref_no_nan[n][
                                        ndlist_ind_col_pttest_nan[m][p]] for n
                                    in set(ind_lin_k_nearest)])
                        # print(f'Coordonnées pt test = \
        # <{ind_lin_pttest_nan[m]},{ndlist_ind_col_pttest_nan[m][p]}>')
                        # print(f'valeur d imputation = {valeur_imputation}\n')

                        # On remplace chaque nan par les valeurs d'imputation
                        imputed_points[ind_lin_pttest_nan[m]][
                                ndlist_ind_col_pttest_nan[m][p]] =\
                            valeur_imputation

    # print(f'ind_lin_k_nearest_all =\n{ind_lin_k_nearest_all}\n')
    # print(f'distances_k_nearest_all =\n{distances_k_nearest_all}\n')
    # print(f'imputed_points =\n{imputed_points}\n')

    return imputed_points, ind_lin_k_nearest_all, distances_k_nearest_all


#! /usr/bin/python
import sys

f = open('poster.txt',"rb")
write = sys.stdout.write
while True:
	buf=f.read(8)
	if not buf or not buf.isdigit():
		break
	write(chr(int(buf,2)))
f.close()


# Given an array of integers, find the first missing positive integer in linear time and constant space. In other words, find the lowest positive integer that does not exist in the array. The array can contain duplicates and negative numbers as well.
# For example, the input [3, 4, -1, 1] should give 2. The input [1, 2, 0] should give 3.
# You can modify the input array in-place.

def seperate_negative(arr):
    np = 0
    for i in range(len(arr)):
        if arr[i] <= 0:
            arr.insert(np, arr.pop(i))
            np+=1
    return arr[np:]
def find_min(arr):
    arr = seperate_negative(arr)
    n = len(arr)
    for i in range(n):
        index = abs(arr[i])-1
        if index < n and arr[index] > 0:
            arr[index] *= -1
    print(arr)
    for i in range(n):
        if arr[i] > 0:
            return i+1
    return n+1
if __name__ == "__main__":
    arr = [3, 4, -1, 1]
    print(find_min(arr))


from time import gmtime, strftime
import os
import time

basket1 = [
["Baked Beans",0.89,50],
["Loaf of bread",0.99,0],
["6 x Cans of cola",2.99,0],
["Pasta",0.75,10],
["Rice",1.98,50],
["Flour",0.94,0],
["Breakfast cereal",1.49,0]
  ]

# making the quit screen
def QuitScreen():
  os.system("cls")
  print("BYE")
  time.sleep(0.5)

# making the menu
def Menu(options, acceptableMenuChoices):
  print("")
  print("Please choose your option: ")
  print("")
  theChoice = ""
  for option in options:
    print(option)
    print("")
  while(theChoice not in acceptableMenuChoices):
    theChoice = input("Choose ur thing idk: ").lower()
  return theChoice

# making the receipt
def Receipt():
  os.system("cls")
  TotalPrice = 0.0
  TotalDiscount = 0.0

  # carrier bag option
  bagCost = 0.05
  carrierBag = input("Do you want a carrier bag? Y/N:")
  if carrierBag == "Y":
    basket1.append(["carrier bag",0.05,0])

# receipt layout
  os.system("cls")
  print("*" * 35)
  print("")
  print("Main Street Supermarket")
  print("")
  for item in basket1:
      price = item[1]
      # aligning the price and the item
      lenn = len(item[0])
      spaces = 30 - lenn

      #working out the discount and taking it away from the total cost
      if item[2] > 0:
          discount = (item[1] / 100) * item[2]
          price = round(item[1] - discount, 2)
          TotalDiscount = TotalDiscount + discount
          roundedDiscount = round(TotalDiscount, 2)
      print(str(item[0]) + " " * spaces + "£" + str(price))
      TotalPrice = TotalPrice + price
      RoundedTotal = round(TotalPrice, 2)
  # getting the date and time
  datetime = strftime("%Y-%m-%d %H:%M:%S", gmtime())
  print("")
  print("-" * 12)
  print("")
  # printing total and money saved
  print("The total is:" + " " * 17 + "£" + str(RoundedTotal))
  print("you have saved:" + " " * 15 + "£" + str(roundedDiscount))
  print("")
  #idk lol
  print("Cat Points earned:                9")

  print("")
  print("-" * 12)
  print("")
  # thankyou message
  print("Thankyou for shopping with us!")
  print("")
  print(datetime)
  print("*" * 35)
  print("")

  # kind of quit screen
  time.sleep(0.5)
  print("")
  option = input("press 'q' to quit: ")
  if option == "q":
    QuitScreen()

# start menu
menu = Menu([
  "r - reciept",
  "q - quit"
], [
  "r",
  "q"
])
if menu == "r":
  Receipt()
else:
  QuitScreen()

# print("You need to make the above list into a receipt!")
# print("Watch video 1 on firefly to help you understand what the receipt should look like.")
# print("Watch video 2 on firefly for hints and tips")


#!/usr/bin/env python3
# https://adventofcode.com/2022/day/14

import os
import glob
import contextlib

from PIL import Image
from copy import deepcopy

# TODO: do you need the png's as an intermediate step? just store in memory?
# TODO: optimizations on frame generation? keep prev frame and apply diff? only render sand on a base image?

################################################################################
##                                                                            ##
##  Configuration                                                             ##
##                                                                            ##
################################################################################

home_dir    = os.path.expanduser('~')
make_print  = False       # print frames to stdout
make_gif    = False       # generate a gif of the drips
frames_dir  = home_dir + "/Desktop/aoc-2022-day-14-frames"
frames_glob = home_dir + "/Desktop/aoc-2022-day-14-frames/frame_*.png"
gif_out     = home_dir + "/Desktop/aoc-2022-day-14.gif"

################################################################################
##                                                                            ##
##  Pixels                                                                    ##
##                                                                            ##
################################################################################

sand = [
    (244, 237, 219), (244, 237, 219), (205, 192, 175), (203, 190, 170), (118, 107, 90),
    (231, 217, 202), (231, 217, 202), (179, 165, 149), (155, 142, 125), (63, 49, 40),
    (212, 198, 186), (212, 198, 186), (222, 209, 197), (168, 154, 238), (100, 79, 66),
    (177, 171, 157), (177, 171, 157), (166, 156, 141), (142, 127, 112), (109, 92, 87),
    (177, 171, 157), (177, 171, 157), (166, 156, 141), (142, 127, 112), (109, 92, 87),
]

stone = [
    (98, 114, 120), (98, 114, 120), (72, 88, 94), (40, 56, 63), (40, 56, 63),
    (72, 88, 94),   (72, 88, 94),   (40, 56, 63), (72, 88, 94), (72, 88, 94),
    (72, 88, 94),   (72, 88, 94),   (40, 56, 63), (72, 88, 94), (72, 88, 94),
    (72, 88, 94),   (72, 88, 94),   (40, 56, 63), (72, 88, 94), (72, 88, 94),
    (72, 88, 94),   (72, 88, 94),   (40, 56, 63), (72, 88, 94), (72, 88, 94),
]

air = [
    (205, 224, 228), (205, 224, 228), (205, 224, 228), (205, 224, 228), (205, 224, 228),
    (205, 224, 228), (205, 224, 228), (205, 224, 228), (205, 224, 228), (205, 224, 228),
    (205, 224, 228), (205, 224, 228), (205, 224, 228), (205, 224, 228), (205, 224, 228),
    (205, 224, 228), (205, 224, 228), (205, 224, 228), (205, 224, 228), (205, 224, 228),
    (205, 224, 228), (205, 224, 228), (205, 224, 228), (205, 224, 228), (205, 224, 228),
]

nozzle = [
    (36, 37, 32),    (36, 37, 32),    (36, 37, 32),    (36, 37, 32),    (36, 37, 32),
    (36, 37, 32),    (36, 37, 32),    (36, 37, 32),    (36, 37, 32),    (36, 37, 32),
    (36, 37, 32),    (36, 37, 32),    (36, 37, 32),    (36, 37, 32),    (36, 37, 32),
    (205, 224, 228), (205, 224, 228), (205, 224, 228), (205, 224, 228), (205, 224, 228),
    (205, 224, 228), (205, 224, 228), (205, 224, 228), (205, 224, 228), (205, 224, 228),
]

################################################################################
##                                                                            ##
##  Functions                                                                 ##
##                                                                            ##
################################################################################

def print_matrix(matrix: list, grain: list):
    for idy, line in enumerate(matrix):
        if idy == grain[1]:
            temp = line.copy()
            temp[grain[0]] = 'o'
            print(''.join(temp))
        else:
            print(''.join(line))

def render_frame(matrix, grain):
    global frame

    # TODO: add grain to print render! it's not in the matrix

    img = Image.new('RGB', (matrix_width * 5, matrix_height * 5))
    for idy, row in enumerate(matrix):
        for idx, dot in enumerate(row):

            scale_x_ctr = (idx * 5) + 2
            scale_y_ctr = (idy * 5) + 2
            around = [[x, y] for x in range(scale_x_ctr - 2, scale_x_ctr + 3) for y in range(scale_y_ctr - 2, scale_y_ctr + 3)]

            if [idx, idy] == grain:
                pixel = sand
            elif dot == '#':
                pixel = stone
            elif dot == 'o':
                pixel = sand
            elif dot == '+':
                pixel = nozzle
            else:
                pixel = air

            for idx, loc in enumerate(around):
                img.putpixel((loc[0], loc[1]), pixel[idx])

    img.save(f'{home_dir}/Desktop/aoc-2022-day-14-frames/frame_{frame:05}.png')
    frame += 1

def render_gif():
    with contextlib.ExitStack() as stack:
        # grab images list and determine duration
        files    = glob.glob(frames_glob)
        frames   = len(files)
        fps      = 60
        duration = int(frames / fps)

        # lazy load images
        imgs = (stack.enter_context(Image.open(f)) for f in sorted(files))

        # extract  first image from iterator
        img = next(imgs)

        # build the gif
        img.save(fp=gif_out,
                 format='GIF',
                 append_images=imgs,
                 save_all=True,
                 duration=duration,
                 loop=1)

def points_between(start: list, end: list) -> list:
    min_x = min(start[0], end[0])
    max_x = max(start[0], end[0])
    min_y = min(start[1], end[1])
    max_y = max(start[1], end[1])
    if min_x == max_x:
        # x is not changing
        points = [[min_x, i] for i in range(min_y, max_y + 1)]
    else:
        # y is not changing
        points = [[i, min_y] for i in range(min_x, max_x + 1)]

    return points

def widen_matrix(matrix: list, direction: str) -> list:
    new_matrix = []

    if direction == 'left':
        # grow matrix one to the left
        for row in matrix:
            new_matrix.append(['.'])
            new_matrix[-1].extend(row)
        new_matrix[-1][0] = '#'
        return new_matrix
    elif direction == 'right':
        # grow matrix one to the right
        for row in matrix:
            new_matrix.append(row)
            new_matrix[-1].append('.')
        new_matrix[-1][-1] = '#'
        return new_matrix

def drip(matrix: list, start: list, floor: bool) -> bool:
    """
    Drip one grain of sand to a stopping point.
    """
    falling = True
    grain   = start

    global matrix_width, matrix_height

    while falling:
        if make_gif:
            # render a frame
            render_frame(matrix, grain)
        elif make_print:
            # print a frame
            print_matrix(matrix, grain)

        # grab all spaces blow the grain
        x_pos = grain[0]
        y_pos = grain[1]
        beneath_coords   = [[x_pos, i] for i in range(y_pos + 1, matrix_height)]
        beneath_material = [matrix[i][x_pos] for i in range(y_pos + 1, matrix_height)]

        # bail if there is nothing for us to land on
        if '#' not in beneath_material and 'o' not in beneath_material:
            return False, matrix

        # id location of the grain or rock directly below us
        stop_idx  = beneath_material.index(next(filter(lambda i: i != '.', beneath_material)))
        stop_loc  = beneath_coords[stop_idx - 1]

        # if we have some distance to fall go straight down
        if stop_idx > 0:
            grain = stop_loc
            continue

        # otherwise see if we can fall left
        pos_down = grain[1] + 1
        pos_left = grain[0] - 1
        if pos_left < 0 or pos_down >= matrix_height:
            if floor and pos_down < matrix_height - 1:
                matrix = widen_matrix(matrix, 'left')
                matrix_width += 1
                grain = [grain[0], pos_down]
                start[0] += 1
                continue
            elif floor:
                matrix[grain[1]][grain[0]] = 'o'
                return True, matrix
            else:
                return False, matrix
        if matrix[pos_down][pos_left] == '.':
            grain = [pos_left, pos_down]
            continue

        # otherwise see if we can fall right
        pos_right = grain[0] + 1
        if pos_right > matrix_width - 1 or pos_down >= matrix_height:
            if floor and pos_down < matrix_height - 1:
                matrix = widen_matrix(matrix, 'right')
                matrix_width += 1
                grain = [pos_right, pos_down]
                continue
            elif floor:
                matrix[grain[1]][grain[0]] = 'o'
                return True, matrix
            else:
                return False, matrix
        if matrix[pos_down][pos_right] == '.':
            grain = [pos_right, pos_down]
            continue

        # otherwise just stay put
        matrix[grain[1]][grain[0]] = 'o'

        return True, matrix

def count_grains(matrix: list) -> int:
    total = 0
    for row in matrix:
        for col in row:
            if col == 'o':
                total += 1
    return total

################################################################################
##                                                                            ##
##  Transform Data                                                            ##
##                                                                            ##
################################################################################

frame = 0

# ingest data
data  = open(os.path.join(os.path.dirname(__file__), 'data.txt'), 'r')
lines = data.read().splitlines()

# start position
start_pos = [500, 0]

# build coord list for each line and find min max for x y
# starting point for sand [500,0] is our current min max
vectors = []
min_x   = start_pos[0]
max_x   = start_pos[0]
min_y   = start_pos[1]
max_y   = start_pos[1]
for line in lines:
    coords = [[int(i.split(',')[0]), int(i.split(',')[1])] for i in line.split(' -> ')]
    vectors.append(coords)
    min_x = min(min_x, min(coords, key=lambda c: c[0])[0])
    max_x = max(max_x, max(coords, key=lambda c: c[0])[0])
    min_y = min(min_y, min(coords, key=lambda c: c[1])[1])
    max_y = max(max_y, max(coords, key=lambda c: c[1])[1])

# build out matrix, normalize based on range
matrix = []
for y in range(min_y, max_y + 1):
    matrix.append([])
    for x in range(min_x, max_x + 1):
        matrix[-1].append('.')

# normalize and apply start position
start_pos = [start_pos[0] - min_x, start_pos[1] - min_y]
matrix[start_pos[1]][start_pos[0]] = '+'

matrix_height = len(matrix)
matrix_width  = len(matrix[0])

# normalize all vectors and apply to matrix
for vector in vectors:
    for i in range(len(vector) - 1):
        # grab coords to compare
        point_a = vector[i]
        point_b = vector[i + 1]
        # normalize coordinates
        point_a = [point_a[0] - min_x, point_a[1] - min_y]
        point_b = [point_b[0] - min_x, point_b[1] - min_y]
        # draw points in matrix
        for rock in points_between(point_a, point_b):
            matrix[rock[1]][rock[0]] = '#'

################################################################################
##                                                                            ##
##  Part 1                                                                    ##
##                                                                            ##
################################################################################

# prep dir if needed
if make_gif:
    if not os.path.exists(frames_dir):
        os.makedirs(frames_dir)

# work with a copy of the matrix
p1_matrix = deepcopy(matrix)

# simulate sand dripping
stacking  = True
while stacking:
    stacking, p1_matrix = drip(p1_matrix, start_pos, False)

print('part 1:', count_grains(p1_matrix))

if make_gif:
    render_gif()

    # clean up
    files = glob.glob(frames_glob)
    for f in files:
        os.remove(f)
    os.rmdir(frames_dir)

################################################################################
##                                                                            ##
##  Part 2                                                                    ##
##                                                                            ##
################################################################################

make_gif = False

# add the floor
matrix.append(['.' for _ in range(matrix_width)])
matrix.append(['#' for _ in range(matrix_width)])

# re-measure matrix_height
matrix_height = len(matrix)

stacking = True
while stacking:
    stacking, matrix = drip(matrix, start_pos, True)
    if '+' not in matrix[0]:
        break

print('part 2:', count_grains(matrix))


import requests
import os
import gtts
import time as t
def text_speak(text):

    mytext = text
    language = 'en'
    file= gtts.gTTS(text=mytext, lang=language, slow=False)
    print(file)
    file.save("call.mp3")
    os.startfile("call.mp3")

while(1):
    i=0
    r=requests.get('http://indianiotcloud.com/retrieve.php?id=NQUEES7HH78J9XVFDN29')
    d=r.json()
    print(d)
    d1=d['result'][0]['field1']
    d2=d['result'][0]['field2']
    while(i<3):
        if(len(d1)>0):
            text='HELLO '+str(d1)+' YOUR MOM '+str(d2)+'IS CALLING YOU PLEASE GO'
            text_speak(text)
            t.sleep(7)
        i=i+1