import boto3
import threading

from typing import (
    NewType,
    Optional,
)
from .banana import ModelRunInputs
from .grid_types import GridImageInfo
from .signing import Signer

CacheKey = NewType("CacheKey", str)

class DiffusionCache:
    VERSION = 0
    KEY_SIGNING_KEY = "key-hashing-not-security-relevant"

    class _Local(threading.local):
        # non-lambda servers may be threaded
        def __init__(self):
            self.s3 = boto3.client("s3")

    def __init__(self, bucket: str):
        self._bucket = bucket
        self._local = self._Local()
        self._key_signer = Signer(key=self.KEY_SIGNING_KEY)

    def fetch(self, key: CacheKey) -> Optional[GridImageInfo]:
        try:
            response = self._local.s3.get_object(
                Bucket=self._bucket,
                Key=key,
            )
        except self._local.s3.exceptions.NoSuchKey:
            return None
        else:
            return GridImageInfo.parse_raw(response["Body"].read())

    def store(self, key: CacheKey, grid_image: GridImageInfo) -> None:
        self._local.s3.put_object(
            Bucket=self._bucket,
            Key=key,
            Body=grid_image.json(),
        )

    def key(self, run_inputs: ModelRunInputs) -> CacheKey:
        inputs_hash = self._key_signer.sign_message(**run_inputs.dict())

        return CacheKey(f"cache_v{self.VERSION}/inputs={inputs_hash}.json")


import unittest
import loft.Tailer
import loft.FilterEngine
import Queue
import time
import threading

class TestTailer(unittest.TestCase):
    def setUp(self):
        self.raw_queue = Queue.Queue()
        self.outQueue = Queue.Queue()
        self.m_stop = threading.Event()
        self.m = loft.Tailer.FileTailer(self.raw_queue, r'../test/messagesTail', self.m_stop)
        self.m.daemon = True
        self.m.start()
        print (self.m)
        time.sleep(1)

    def test_throughput(self):
        self.assertTrue(self.m.isAlive())
        print(self.raw_queue.qsize())
        #Get the input size
        input = (self.raw_queue.qsize())
        self.assertTrue(self.raw_queue.qsize() != 0)
        time.sleep(1)
        self.m_stop.set()
        time.sleep(1)
        self.assertFalse(self.m.isAlive())
        loft.FilterEngine.Filter(inQueue=self.raw_queue, outQueue=self.outQueue, runOnce=True )
        self.assertTrue(self.raw_queue.qsize() == 0)
        self.assertEqual(self.outQueue.qsize(), input)

class TestFilter(unittest.TestCase):
    def setUp(self):
        self.smartFilter = {
            '25_fifth_condition': 'fifth regex',
            '10_second_condition': 'second regex',
            '15_third_condition': 'third regex',
            '05_first_condition': 'some regex',
            '20_fourth_condition': 'fourth regex',
        }

        self.expectedOrder = [
            ('05_first_condition', 'some regex'),
            ('10_second_condition', 'second regex'),
            ('15_third_condition', 'third regex'),
            ('20_fourth_condition', 'fourth regex'),
            ('25_fifth_condition', 'fifth regex'),
        ]

        self.raw_queue = Queue.Queue()
        self.outQueue = Queue.Queue()

        self.filter = loft.FilterEngine.Filter(self.raw_queue, self.outQueue, runOnce=True)

    def test_sortRegexList(self):
        orderedList = self.filter._Filter__sortRegexDict(self.smartFilter)
        self.assertTrue(orderedList == self.expectedOrder)

    def test_buildDumbRegexList(self):
        regexList = self.filter._Filter__buildDumbRegexList(self.filter._Filter__sortRegexDict(self.smartFilter))
        self.assertTrue(regexList[0].pattern == 'some regex')
        self.assertTrue(regexList[4].pattern == 'fifth regex')

    def test_buildSmartRegexList(self):
        regexList = self.filter._Filter__buildSmartRegexList(self.filter._Filter__sortRegexDict(self.smartFilter))
        t = regexList[0]
        self.assertTrue(t[0].pattern == 'some regex')
        self.assertTrue(t[1] is False)

    def test_smartFilterGreen(self):
        ttl = 300
        #run all the strings through the filter so we should hit a green status
        self.filter.stateInspector('some regex', ttl)
        self.filter.stateInspector('second regex', ttl)
        self.filter.stateInspector('third regex', ttl)
        self.filter.stateInspector('fourth regex', ttl)
        self.filter.stateInspector('fifth regex', ttl)

        self.assertTrue(self.outQueue.get() == 'System health check GREEN')

    def test_smartFilterNotMet(self):
        ttl = 300
        #add just a few matches
        self.filter.stateInspector('some regex', ttl)
        self.filter.stateInspector('second regex', ttl)
        self.filter.stateInspector('third regex', ttl)

        #should have nothing in queue
        self.assertTrue(self.outQueue.empty())

    def test_smartFilterRed(self):
        ttl = 2
        #add just a few matches
        self.filter.stateInspector('some regex', ttl)
        self.filter.stateInspector('second regex', ttl)
        self.filter.stateInspector('third regex', ttl)

        #sleep 2 seconds
        time.sleep(3)

        #try a fourth filter - should be after ttl
        self.filter.stateInspector('fourth regex', ttl)

        #should have red status in the queue
        self.assertTrue(self.outQueue.get() == 'System health check RED')

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


import xlrd

from PIL import Image, ImageDraw, ImageFont

file_location="names.xlsx"

font_type= ImageFont.truetype('arial.ttf',70)
#add ttf files in '.fonts' folder

workbook=xlrd.open_workbook(file_location)
sheet=workbook.sheet_by_index(0)
#sheet1

for i in range(sheet.nrows):
    name=sheet.cell_value(i,0)
    #names should be in first column
    name=name.capitalize()
    w,h=font_type.getsize(name)
    image= Image.open("template.jpg")
    draw=ImageDraw.Draw(image)
    draw.text(xy=((910),((1250-h)/2)),text=name,fill="#000000",font=font_type)

    image.save('foldername/{}.jpg'.format(name))


import pandas as pd
import numpy as np
from unidecode import unidecode
from sklearn import preprocessing
from sklearn.model_selection import train_test_split
from joblib import dump, load

def select_features(df_list):
    # Select features
    df_list = df_list[[
        ### LISTINGS ID - FOR USE IN SENTIMENT ANALYSIS
        "id",

        ### INFO ABOUT LOCATION & HOST
        "neighbourhood_cleansed",  # names of neighbourhoods
        # "host_since",  # older hosts = more credibility? (will not work on new host)
        "host_response_rate",  # linked to credibility - problematic for new entries
        "host_acceptance_rate",  # same
        "host_is_superhost",  # same (new host always false - how is superhost defined?)
        "host_listings_count",  # more listings = more experience = higher ratings?
        "host_identity_verified",  # identity verified/not higher ratings (is likely string)
        "latitude",  # LAT - LONG need preprocessing
        "longitude",

        ### INFO ABOUT ROOM
        "room_type",  # more meaningful & diverse than property type (check visualisation)
        "bathrooms_text",  # needs preprocessing -> int
        "bedrooms",  # !!!! Bedrooms and beds might contain the same amount of info
        "beds",  # run a correlation with bedrooms
        "accommodates",  # similar to beds, bedrooms
        "amenities",  # extract features and preprocess with T/F & 1-hot-encoding

        ### INFO ABOUT PRICE-RATINGS
        "number_of_reviews",
        # more reviews -> more likely to get booked -> more high reviews (does not apply to new clients)
        "reviews_per_month",  # Same

        ### RESPONSE
        "price",  # turn to int ? check missingness!!

    ]].copy()
    return df_list

def fix_rates(df_list):
    ##### Transform percentages represented as strings to float
    def rate_text_to_float(val):
        return float(val[:-1]) / 100 if pd.notna(val) else val

    df_list.loc[:, "host_response_rate"] = df_list["host_response_rate"].apply(rate_text_to_float)
    df_list.loc[:, "host_acceptance_rate"] = df_list["host_acceptance_rate"].apply(rate_text_to_float)

    return df_list

def fix_bools(df_list):
    ##### Transform text 't' / 'f' values to corresponding bool
    def string_to_bool(val):
        return int(val == 't')

    df_list.loc[:, "host_is_superhost"] = df_list["host_is_superhost"].apply(string_to_bool)
    df_list.loc[:, "host_identity_verified"] = df_list["host_identity_verified"].apply(string_to_bool)

    return df_list

def fix_neighbourhoods(df_list):
    df_list.loc[:, "neighbourhood_cleansed"] = df_list["neighbourhood_cleansed"].apply(
        lambda x: "neighbourhood_" + unidecode(x).lower().replace(" ", "_").replace("-", "_"))

    return df_list

def fix_amenities(df_list):
    def list_from_string(s):
        return [el.strip(' ').strip('"').replace(" ", "_") for el in s[1:-1].split(',')]

    df_list.loc[:, "amenities"] = df_list["amenities"].apply(list_from_string)

    return df_list

def create_bathrooms_number(df_list):
    """
    Input: dataframe with bathrooms column as text
    Output: dataframe with new "bathrooms_number" column (float) and dropped "bathrooms_text" column
    """

    df_list["bathrooms_number"] = df_list.bathrooms_text.str.split(pat=" ", expand=True)[0]
    df_list["bathrooms_number"].replace({"Half-bath": "0.5", "Shared": "1"}, inplace=True)
    df_list["bathrooms_number"] = df_list["bathrooms_number"].astype('float64')
    df_list.drop(columns=["bathrooms_text"], inplace=True, axis=1)
    return df_list

def fix_price(df_list):
    df_list.loc[:, "price"] = df_list["price"].apply(lambda x: float(x[1:].replace(',', '')) if pd.notna(x) else x)
    return df_list

def combine_pre_split_fixes(df_list):
    df_list = select_features(df_list)
    df_list = fix_rates(df_list)
    df_list = fix_bools(df_list)
    df_list = fix_neighbourhoods(df_list)
    df_list = fix_amenities(df_list)
    df_list = create_bathrooms_number(df_list)
    df_list = fix_price(df_list)

    return df_list

def split_dataset(df_list):
    X = df_list.drop(columns="price")
    y = df_list["price"]
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
    return X_train, X_test, y_train, y_test

def find_bound(y_train, upper=True):
    iqr = np.subtract(*np.percentile(y_train, [75, 25]))

    if upper:

        upperbound = np.percentile(y_train, 75) + 1.5 * iqr

        return upperbound

    else:

        lowerbound = np.percentile(y_train, 25) - 1.5 * iqr

        return lowerbound

def remove_outliers(X_train, y_train):
    upper_bound = find_bound(y_train)
    X_train = X_train.loc[(y_train < upper_bound), :]
    y_train = y_train[(y_train < upper_bound)]
    return X_train, y_train

def save_fit_scaler(X_train):
    features_to_be_scaled = ['host_response_rate',
                            'host_acceptance_rate',
                            'host_listings_count',
                            'latitude',
                            'longitude',
                            'bedrooms',
                            'beds',
                            'accommodates',
                            'number_of_reviews',
                            'reviews_per_month'
                            ]

    scaler = preprocessing.StandardScaler()

    # Scaler will be fit on training data
    scaler = scaler.fit(X_train[features_to_be_scaled])

    dump(scaler, 'data/scaler.joblib')

def scale_features(data):
    """
    Scales specified features.

    ### Inputs:

    X_train: dataframe upon which the scaler will be fit
    X_test: specified test dataframe that will be transformed
    test: whether the scaler involves training or testing process

    #### Outputs:

    X_train or X_test: scaled dataframes
    """

    features_to_be_scaled = ['host_response_rate',
                             'host_acceptance_rate',
                             'host_listings_count',
                             'latitude',
                             'longitude',
                             'bedrooms',
                             'beds',
                             'accommodates',
                             'number_of_reviews',
                             'reviews_per_month'
                             ]

    scaler = load('data/scaler.joblib')

    data[features_to_be_scaled] = scaler.transform(data[features_to_be_scaled])

    return data

def generate_fill_values(X_train):
    mode_feats = ["neighbourhood_cleansed", "host_is_superhost", "host_identity_verified", "room_type"]

    fill_values_df = {}
    for feat in X_train.columns[[col not in ['id', 'amenities'] for col in X_train.columns]]:
        fill_values_df[feat] = X_train[feat].mode() if feat in mode_feats else X_train[feat].median()

    fill_values_df['amenities'] = '[]'

    fill_values_df = pd.DataFrame(fill_values_df)
    fill_values_df.to_csv("data/fill_values.csv", index=False)

def impute_missing_values(data):
    fill_values = pd.read_csv("data/fill_values.csv")
    fill_values_dict = fill_values.to_dict(orient='records')[0]
    return data.fillna(fill_values_dict)

def one_hot_amenities(data):
    """
    Performs one-hot encoding to fixed amenities.
    The most provided (>4000) amenities are used as one-hot features.

    ### Inputs

    df_list: dataframe

    ### Outputs

    df_list: dataframe with one-hot encodings on most frequent amenities.

    """

    amenities_cat = pd.read_csv('data/amenities_cat.csv')
    wanted_keys = amenities_cat.iloc[:, 0].tolist()
    #### Initialise list
    one_hot = []

    for j in wanted_keys:
        # Performs a True-False check for each amenity in wanted_keys. Booleans are converted to 1-0.
        # Check done: sum(df_list["Kitchen"]) = value_count of Kitchen

        one_hot.append([int(j in i) for i in data["amenities"]])

    print(len(one_hot))

    for i, j in zip(wanted_keys, one_hot):
        # Concatenate one-hot with wanted_keys

        data[i] = j

    data.drop("amenities", axis=1, inplace=True)
    return data

def fix_room_type(data):
    """
    Inputs:
    df_list (dataframe): dataframe whose "room_type" will be turned to one hot encoding
    "room_type" (str) : string that specifies "room_type"

    Outputs:

    df_list (dataframe): concatenated dataframe with one hot encoidng of features and dropped previous "room_type"
    """
    data.loc[:, "room_type"] = data["room_type"].apply(lambda x: x.replace(" ", "_").replace("/", "_"))

    # room_types = ["Entire_home_apt", "Hotel_room", "Private_room", "Shared_room"]
    room_types = pd.read_csv('data/room_types.csv').iloc[:, 0]
    data.loc[:, "room_type"] = data.loc[:, "room_type"].astype(pd.CategoricalDtype(categories=room_types))
    dummies = pd.get_dummies(data["room_type"])
    data = pd.concat([data, dummies], axis=1)
    data.drop(columns=["room_type"], inplace=True, axis=1)
    return data

def one_hot_neighbourhood(data):
    neighbourhoods = pd.read_csv('data/neighbourhoods.csv').iloc[:, 0]
    data.loc[:, "neighbourhood_cleansed"] = data.loc[:, "neighbourhood_cleansed"].astype(
        pd.CategoricalDtype(categories=neighbourhoods))
    new_feats = pd.get_dummies(data["neighbourhood_cleansed"])

    data.drop("neighbourhood_cleansed", axis=1, inplace=True)
    return pd.concat([data, new_feats], axis=1)

def generate_categories(df_list):
    # Generate and save neighbourhoods
    neighbourhoods = pd.Series(pd.get_dummies(df_list["neighbourhood_cleansed"]).columns)
    neighbourhoods.to_csv('data/neighbourhoods.csv', index=False)
    # Generate and save room types
    room_types = pd.Series(pd.get_dummies(df_list["room_type"]).columns)
    room_types.to_csv('data/room_types.csv', index=False)
    # Generate and save amenities
    # Create long list of amenities
    flat = [item for sublist in df_list["amenities"] for item in sublist]
    # We will try to group them by amenity and count the most frequent
    from collections import Counter
    # Insert value counts to dataframe
    amenities_df = pd.DataFrame(list(Counter(flat).items())).rename(columns={0: "Amenity", 1: "Count"})

    # Keep most used amenities
    condition = 4000
    amenities_df_pivot = amenities_df[amenities_df["Count"] > condition].sort_values(by="Count",
                                                                                ascending=False).pivot_table(
        values="Count", columns="Amenity")

    wanted_keys = pd.Series([keys.strip(" ").strip("'") for keys in amenities_df_pivot.columns])

    wanted_keys.to_csv('data/amenities_cat.csv', index=False)

def preprocess(df_list):

    df_list = combine_pre_split_fixes(df_list)

    X_train, X_test, y_train, y_test = split_dataset(df_list)

    X_train, y_train = remove_outliers(X_train, y_train)

    generate_fill_values(X_train)
    X_train = impute_missing_values(X_train)
    X_test = impute_missing_values(X_test)

    save_fit_scaler(X_train)
    X_train = scale_features(X_train)
    X_test = scale_features(X_test)

    generate_categories(df_list)
    # One Hot Encoding of room type
    X_train, X_test = fix_room_type(X_train), fix_room_type(X_test)

    # One-Hot Encoding of most frequent amenities
    X_train, X_test = one_hot_amenities(X_train), one_hot_amenities(X_test)

    # One hot encode neighbourhood
    X_train, X_test = one_hot_neighbourhood(X_train), one_hot_neighbourhood(X_test)

    return X_train, X_test, y_train, y_test

def main():
    df_list = pd.read_csv("data/listings.csv")
    X_train, X_test, y_train, y_test = preprocess(df_list)
    X_train.to_csv("data/X_train.csv", index=False)
    X_test.to_csv("data/X_test.csv", index=False)
    y_train.to_csv("data/y_train.csv", index=False)
    y_test.to_csv("data/y_test.csv", index=False)

if __name__ == "__main__":
    main()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri May 15 11:15:55 2020

@author: ivan

On regression and regularization:
    http://bjlkeng.github.io/posts/a-probabilistic-view-of-regression/
    http://bjlkeng.github.io/posts/probabilistic-interpretation-of-regularization/
"""
import numpy as np

def calculate_gradient(x, y, theta, regularizer):
    grad = np.zeros_like(theta)
    for dp, label in zip(x, y):
        power = - np.dot(theta, dp.transpose())[0]
        grad -= dp * (label - 1 / (1 + np.exp(power)))

    reg_theta = np.hstack((np.zeros((1, 1)), theta[:, 1:]))
    return grad + regularizer * reg_theta

def calculate_loss(x, y, theta):
    loss = 0
    for dp, label in zip(x, y):
        power = - np.dot(theta, dp.transpose())[0]
        loss += - label * np.log(1 / (1 + np.exp(power))) - (1 - label) * np.log(1 - 1 / (1 + np.exp(power)))
    return loss

def train(x, y, regularizer):
    theta = np.random.normal(size=(1, x.shape[1]))
    prev_theta = theta
    alpha = 0.01
    while True:
        grad = calculate_gradient(x, y, theta, regularizer)
        prev_theta = theta
        theta = prev_theta - alpha * grad

        loss = calculate_loss(x, y, theta)
        change = np.linalg.norm(theta - prev_theta)
        print(f"Change in parameters {change} and loss {loss}")
        if change < 1e-4:
            break
    return theta

def predict(data, theta):
    labels = []
    for dp in data:
        power = - np.dot(theta, dp.transpose())[0]
        probability = 1 / (1 + np.exp(power))
        labels.append(1 if probability > 0.5 else 0)
    return labels

# First two digits are X, last one is label y
# Rule: sum(X) > 7 => class 1, else class 0
train_data = [
    [2, 3, 0],
    [3, 2, 0],
    [1, 4, 0],
    [3, 8, 1],
    [8, 0, 1],
    [13, 2, 1],
    [10, 3, 1],
    [0, 5, 0],
    [7, 0, 0],
    [6, 2, 1],
]
train_data = np.array(train_data)
train_x, train_y = train_data[:, :-1], train_data[:, -1]
train_x = np.hstack((np.ones(shape=(train_x.shape[0], 1)), train_x))
theta = train(train_x, train_y, regularizer=0.1)

print(f"Obtained theta is {theta}")

test_x = [
    [0, 0],  # 0
    [3, 4],  # 0
    [10, 0],  # 1
    [5, 5],  # 1
    [2, 3],  # 0
]
test_x = np.array(test_x)
test_x = np.hstack((np.ones(shape=(test_x.shape[0], 1)), test_x))

pred_train_y = predict(train_x, theta)
print(f"Predicted labels on the training dataset {pred_train_y}")

pred_test_y = predict(test_x, theta)
print(f"Predicted labels on the testing dataset {pred_test_y}")


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Nekozilla is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Nekozilla is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Nekozilla.  If not, see <https://www.gnu.org/licenses/>.

"""
Implementation of the conversion data types.
"""
import enum
import typing
from dataclasses import dataclass
from decimal import Decimal

from neko3 import algorithms

__all__ = ("UnitCategoryModel", "UnitModel", "UnitCollectionModel", "PotentialValueModel", "ValueModel", "pretty_print")

@enum.unique
class UnitCategoryModel(enum.Enum):
    """Holds a category of units."""

    DISTANCE = enum.auto()
    TIME = enum.auto()
    SPEED = enum.auto()
    VOLUME = enum.auto()
    FORCE_MASS = (enum.auto(),)
    DATA = (enum.auto(),)
    TEMPERATURE = enum.auto()

class UnitModel:
    """
    Representation of some unit measurement definition, such as meters.

    This will not store an arbitrary quantity. It exists as a way of
    simplifying
    the definition of what a unit is.

    The last name should be the abbreviated form to use for output. I could
    make that into a kwarg but YOLO.

    :param to_si: formulae to take a decimal and convert it to SI from this.
    :param from_si: formulae to take a decimal and convert it from SI to this.
    :param name: main name.
    :param other_names: other names and abbreviations.
    :param is_si: True if this is an SI measurement, False otherwise and by
            default.
    :param exclude_from_conversions: Defaults to false. When True, the
            measurement is allowed as valid input, but will not appear in
            lists of conversions generated by the application. This is useful
            for allowing `mm` as input while not displaying it as a separate
            entity to `m` which can be pretty-printed to `mm` anyway.
    :param never_use_std_form: Defaults to False. If True, it requests that any
            code formatting a string from this unit should not use standard
            form
            and instead prefer kilo/mega/giga prefixes, etc.
    """

    # What 1 si of whatever this unit measures is in this specific unit.
    def __init__(
        self,
        to_si: typing.Callable[[Decimal], Decimal],
        from_si: typing.Callable[[Decimal], Decimal],
        name: str,
        *other_names: str,
        is_si: bool = False,
        exclude_from_conversions=False,
        never_use_std_form=False,
    ):
        self.names = (name, *other_names)
        self._to_si = to_si
        self._from_si = from_si
        self.is_si = is_si
        self.unit_type: UnitCategoryModel
        self.exclude_from_conversions = exclude_from_conversions
        self.never_use_std_form = never_use_std_form

    @property
    def name(self) -> str:
        return self.names[0]

    def to_si(self, this: Decimal) -> Decimal:
        """Converts this measurement to the SI equivalent."""
        return self._to_si(this)

    def from_si(self, si: Decimal) -> Decimal:
        """Converts this measurement from the SI equivalent to this."""
        return self._from_si(si)

    def __eq__(self, other: typing.Union[str, "UnitModel"]):
        """Equality is defines as a string match for any name"""
        if isinstance(other, UnitModel):
            return super().__eq__(other)
        else:
            return other.lower() in (n.lower() for n in self.names)

    def __hash__(self):
        """Enables hashing by the unit's primary name."""
        return hash(self.name.lower())

    def __str__(self):
        return self.name

    def __repr__(self):
        # noinspection PyUnresolvedReferences
        return f"<Unit name={self.name} " f'aliases={f", ".join(a for a in self.names[1:])}'

    def _set_unit_category(self, cat: UnitCategoryModel):
        self.unit_type = cat

    @classmethod
    def new_cv(
        cls,
        si_per_this: typing.Union[str, Decimal],
        name: str,
        *other_names: str,
        exclude_from_conversions=False,
        never_use_std_form=False,
    ) -> "UnitModel":
        """
        Initialises a unit that is purely a multiple of the SI quantity.

        This is useful if there is a constant linear relationship, as is for
        most measurements, except for Temperature.
        """
        if isinstance(si_per_this, str):
            si_per_this = Decimal(si_per_this)

        def to_si(c: Decimal):
            return c * si_per_this

        def from_si(c: Decimal):
            return c / si_per_this

        return cls(
            to_si,
            from_si,
            name,
            *other_names,
            exclude_from_conversions=exclude_from_conversions,
            never_use_std_form=never_use_std_form,
        )

    @classmethod
    def new_si(cls, name: str, *other_names: str, never_use_std_form=False) -> "UnitModel":
        """Initialises a new SI measurement."""

        # noinspection PyTypeChecker
        def pass_through(x):
            return x

        return cls(pass_through, pass_through, name, *other_names, is_si=True, never_use_std_form=never_use_std_form)

class UnitCollectionModel:
    def __init__(self, category: UnitCategoryModel, si: UnitModel, *other_conversions: UnitModel):
        self.si = si
        self.unit_type = category
        # Obviously.
        self.si.is_si = True
        self.conversions = (si, *other_conversions)

        for conversion in self.conversions:
            # noinspection PyProtectedMember
            conversion._set_unit_category(self.unit_type)

    def find_unit(self, name: str) -> typing.Optional[UnitModel]:
        """
        Looks for a unit with a matching name, and returns it.

        If one does not exist, we return None.
        """
        return algorithms.find(lambda c: c == name, self.conversions)

    def __contains__(self, unit: str):
        """
        Determine if we can match the given string to some unit definition.
        :param unit: string to look up.
        :return: true if we can, false otherwise.
        """
        return bool(self.find_unit(unit))

    @staticmethod
    def convert(qty: Decimal, unit: UnitModel, to: UnitModel):
        """
        Converts one quantity to another assuming they are the same
        type of unit.
        """
        if unit == to:
            return qty
        else:
            return Decimal("1")

    def find_conversions(self, qty: Decimal, unit: UnitModel):
        """
        Returns a list of all conversion equivalents for this unit.

        The unit passed in is not included in this.
        """
        results = []
        for other_unit in self.conversions:
            if other_unit == unit:
                continue

            results.append(self.convert(qty, unit, other_unit))

        return tuple(results)

    def __iter__(self) -> typing.Iterator[UnitModel]:
        return iter(self.conversions)

@dataclass()
class PotentialValueModel:
    """
    A tokenized potential measurement that matches our input regex. It has not
    yet been verified as an existing measurement in our dictionary however.
    """

    value: Decimal
    unit: str

    def __str__(self):
        return f"{self.value} {self.unit}"

@dataclass(init=False)
class ValueModel:
    """An instance of a measurement that we have interpreted successfully."""

    value: Decimal
    unit: UnitModel

    def __init__(self, value: typing.Union[str, Decimal], unit: UnitModel):
        self.value = Decimal(value)
        self.unit = unit

    @property
    def name(self):
        names = self.unit.names
        if len(names) == 1 or self.value == Decimal(1):
            return names[0]
        else:
            return names[1]

    def __hash__(self):
        return hash(self.value)

    def __str__(self):
        return f"{round(float(self.value), 4):g} {self.unit.names[-1]}"

# Maps a base-10 logarithm to the suffix. For example,
# -6 = 10^-6 = micro = µ. The mapped values are a tuple of abbreviation
# and full name, so in this example, we expect the pair `-6: ('µ', 'micro')`
bases = {
    -24: ("y", "yocto"),
    -21: ("z", "zepto"),
    -18: ("a", "atto"),
    -15: ("f", "femto"),
    -12: ("p", "pico"),
    -9: ("n", "nano"),
    -6: ("µ", "micro"),
    -3: ("m", "milli"),
    -2: ("c", "centi"),
    # Ignore deci, as this is not often used.
    +0: ("", ""),
    +3: ("k", "kilo"),
    +6: ("M", "mega"),
    +9: ("G", "giga"),
    +12: ("T", "tera"),
    +15: ("P", "peta"),
    +18: ("E", "exa"),
    +21: ("Z", "zetta"),
    +24: ("Y", "yotta"),
}

def pretty_print(d: Decimal, suffix_name: str, use_long_suffix=False, use_std_form=True, none_if_rounds_to_zero=False):
    """
    Python is a pain when it comes to formatting decimals/floats in the
    format I want. Therefore it is probably just easier for me to write the
    algorithm myself that I want to use to produce a clean representation
    of the data.

    :param d: the decimal to format
    :param suffix_name: the abbreviated unit name (e.g. m for meters)
    :param use_long_suffix: true if we should use "milli-" instead of "m".
        False if unspecified.
    :param use_std_form: False by default. When true, we just use standard
        form. This will override use_long_suffix.
    :param none_if_rounds_to_zero: False by default. If true, if we round
        down to zero, then we return None to allow the caller to exclude it
        from results.
    """

    def trunc(rounded_str):
        # Remove trailing zeros if we have any.
        if "." in rounded_str and "e" not in rounded_str.lower():
            while rounded_str[-1] in ("0", "."):
                premature_break = rounded_str[-1] == "."
                rounded_str = rounded_str[:-1]
                if premature_break:
                    break
        return rounded_str

    if d > 0:
        real_pot = int(d.log10())
    else:
        real_pot = 0

    if real_pot in bases:
        suffix = bases[real_pot]
        chosen_pot = real_pot
    else:
        # Find the closest logarithm.
        choices = bases.keys()

        differences = {abs(real_pot - c): c for c in choices}
        sorted_choices = sorted(differences.keys())

        chosen_pot = differences[sorted_choices[0]]
        suffix = bases[chosen_pot]

    # Divide by the chosen power of ten to get the
    # value in the base we want.
    if use_std_form:
        if Decimal("0.00001") <= abs(d) < Decimal("1000000000") or d.is_zero():
            rounded_str = f"{d:,.6f}"
            return f"{trunc(rounded_str)} {suffix_name}"
            # return f'{d:,.4f} {suffix_name}'
        else:
            return f"{d:,.4e} {suffix_name}"
            # return f'{d:,.4g} {suffix_name}'
    else:
        d /= Decimal(10 ** chosen_pot)

        rounded = round(d, 3)

        if rounded == Decimal(0) and none_if_rounds_to_zero:
            return None
        else:
            rounded_str = f"{rounded:,f}"
            rounded_str = trunc(rounded_str)
            return f"{rounded_str} " f"{suffix[1 if use_long_suffix else 0]}{suffix_name}"


from django.urls import path, re_path

from rest_framework.urlpatterns import format_suffix_patterns
from .views import (
    ExchangeRatesDetail,
    ExchangeRatesList,
    DailyExchangeRatesDetail,
    DailyExchangeRatesList
)

app_name = 'exchange-rate'

urlpatterns = [
    path('exchange-rates/',
         ExchangeRatesList.as_view(),
         name="index"),
    path('exchange-rates/<int:pk>/',
         ExchangeRatesDetail.as_view(),
         name="detail"),
    re_path('daily-exchange-rates/$',
            DailyExchangeRatesDetail.as_view(), name="daily-detail"),
    path('daily-exchange-rates/list',
         DailyExchangeRatesList.as_view(), name="daily-list")
]

urlpatterns = format_suffix_patterns(urlpatterns)


# -*- coding: utf-8 -*-
"""
Created on Fri Feb 28 09:34:41 2020

@author: zhangguoqing

E-mail: zhangguoqing84@westlake.edu.cn

"""

# 字符串和正则表达式：re模块
import re

def main():
    username = input('请输入用户名: ')
    qq = input('请输入QQ号: ')
    # match函数的第一个参数是正则表达式字符串或正则表达式对象
    # 第二个参数是要跟正则表达式做匹配的字符串对象
    m1 = re.match(r'^[0-9a-zA-Z_]{6,20}$', username)
    if not m1:
        print('请输入有效的用户名.')
    m2 = re.match(r'^[1-9]\d{4,11}$', qq)
    if not m2:
        print('请输入有效的QQ号.')
    if m1 and m2:
        print('你输入的信息是有效的!')

if __name__ == '__main__':
    main()

# 替换字符串中的不良内容

# 拆分长字符串
import re

def main():
    poem = '窗前明月光，疑是地上霜。举头望明月，低头思故乡。'
    sentence_list = re.split(r'[，。, .]', poem)
    while '' in sentence_list:
        sentence_list.remove('')
    print(sentence_list)  # ['窗前明月光', '疑是地上霜', '举头望明月', '低头思故乡']

if __name__ == '__main__':
    main()


import serial
import struct
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FuncAnimation

# Définir le format de la structure
struct_format = '=fff'  # Trois flottants non alignés

# Configuration du port série
port = "/dev/ttyACM0"  # Assurez-vous de spécifier le bon port
baudrate = 115200

# Ouvrir le port série
ser = serial.Serial(port, baudrate, timeout=1)

# Initialiser les listes pour stocker les données
data_x = []
data_y = []
data_z = []

min_bound = 0.8
max_bound = 1.2

# Initialiser la figure avec trois sous-plots (signal temporel, FFT, spectre de fréquence)
fig, (ax1, ax2, ax3) = plt.subplots(3, 1)

# Initialiser les lignes des courbes pour le signal temporel
line_x, = ax1.plot([], [], label='accX')
line_min, = ax1.plot([], [], label='min', color='red')
line_max, = ax1.plot([], [], label='max', color='red')

# Initialiser les lignes des courbes pour la FFT
line_fft_x, = ax2.plot([], [], label='FFT accX')

# Spectre de fréquence
sampling_interval = 0.4
fs = 1 / sampling_interval

freq_spec, = ax3.plot([], [], label='spectre de fréquence accX')

# Fonction d'animation
def update(frame):
    # Lecture de données depuis le port série
    line = ser.readline().strip()  # Lire la ligne et supprimer les caractères de fin de ligne
    if len(line) != 12:
        print("Données incorrectes:", line)
        return

    data = struct.unpack(struct_format, line)

    print(data)

    # Ajouter les données aux listes
    data_x.append(data[0])

    if len(data_x) > 50:
        data_x.pop(0)

    # Temporal signal
    line_x.set_data(range(len(data_x)), data_x)
    line_min.set_data(range(len(data_x)), min_bound)
    line_max.set_data(range(len(data_x)), max_bound)
    ax1.relim()
    ax1.autoscale_view()

    # FFT
    if data[0] > max_bound or data[0] < min_bound:
        fft_x = np.fft.fft(data_x)
        line_fft_x.set_data(range(len(fft_x)), np.abs(fft_x))

        # Mettre à jour les barres pour le spectre de fréquence
        fft_freqs = np.fft.fftfreq(fft_x.size, sampling_interval)  # Utiliser l'intervalle d'échantillonnage
        idx = np.argsort(fft_freqs)
        freq_spec.set_data(fft_freqs[idx][fft_x.size//2:], np.abs(fft_x)[idx][fft_x.size//2:])

    ax2.relim()
    ax2.autoscale_view()

    ax3.relim()
    ax3.autoscale_view()

    # Ajouter des légendes
    ax1.legend()
    ax2.legend()
    ax3.legend()

# Créer l'animation
ani = FuncAnimation(fig, update, blit=False)

# Afficher le graphique en continu
plt.show()

# Fermer le port série à la fin
ser.close()


# -*- coding: utf-8 -*-
# (c) 2009-2023 Martin Wendt and contributors; see WsgiDAV https://github.com/mar10/wsgidav
# Licensed under the MIT license:
# http://www.opensource.org/licenses/mit-license.php
"""
WSGI middleware that handles GET requests on collections to display directories.
"""
import os
import sys
from fnmatch import fnmatch
from urllib.parse import unquote

from jinja2 import Environment, FileSystemLoader, select_autoescape

from wsgidav import __version__, util
from wsgidav.dav_error import HTTP_MEDIATYPE_NOT_SUPPORTED, HTTP_OK, DAVError
from wsgidav.mw.base_mw import BaseMiddleware
from wsgidav.util import get_uri_name, safe_re_encode, send_redirect_response

__docformat__ = "reStructuredText"

_logger = util.get_module_logger(__name__)

ASSET_SHARE = "/:dir_browser"

DAVMOUNT_TEMPLATE = """
<dm:mount xmlns:dm="http://purl.org/NET/webdav/mount">
  <dm:url>{}</dm:url>
</dm:mount>
""".strip()

MS_OFFICE_TYPE_TO_EXT_MAP = {
    "excel": ("xls", "xlt", "xlm", "xlsm", "xlsx", "xltm", "xltx"),
    "powerpoint": ("pps", "ppt", "pptm", "pptx", "potm", "potx", "ppsm", "ppsx"),
    "word": ("doc", "dot", "docm", "docx", "dotm", "dotx"),
    "visio": ("vsd", "vsdm", "vsdx", "vstm", "vstx"),
}
MS_OFFICE_EXT_TO_TYPE_MAP = {}
for t, el in MS_OFFICE_TYPE_TO_EXT_MAP.items():
    for e in el:
        MS_OFFICE_EXT_TO_TYPE_MAP[e] = t
OPEN_OFFICE_EXTENSIONS = {"odt", "odp", "odx"}

class WsgiDavDirBrowser(BaseMiddleware):
    """WSGI middleware that handles GET requests on collections to display directories."""

    def __init__(self, wsgidav_app, next_app, config):
        super().__init__(wsgidav_app, next_app, config)

        self.dir_config = util.get_dict_value(config, "dir_browser", as_dict=True)

        # mount path must be "" or start (but not end) with '/'
        self.mount_path = config.get("mount_path") or ""

        htdocs_path = self.dir_config.get("htdocs_path")
        if htdocs_path:
            self.htdocs_path = os.path.realpath(htdocs_path)
        else:
            self.htdocs_path = os.path.join(os.path.dirname(__file__), "htdocs")

        if not os.path.isdir(self.htdocs_path):
            raise ValueError(
                "Invalid dir_browser htdocs_path {!r}".format(self.htdocs_path)
            )

        # Add an additional read-only FS provider that serves the dir_browser assets
        self.wsgidav_app.add_provider(ASSET_SHARE, self.htdocs_path, readonly=True)
        # and make sure we have anonymous access there
        config.get("simple_dc", {}).get("user_mapping", {}).setdefault(
            ASSET_SHARE, True
        )

        # Prepare a Jinja2 template
        templateLoader = FileSystemLoader(searchpath=self.htdocs_path)
        templateEnv = Environment(loader=templateLoader, autoescape=select_autoescape())
        self.template = templateEnv.get_template("template.html")

    def is_disabled(self):
        return self.dir_config.get("enable") is False

    def __call__(self, environ, start_response):
        path = environ["PATH_INFO"]

        dav_res = None
        if environ["wsgidav.provider"]:
            dav_res = environ["wsgidav.provider"].get_resource_inst(path, environ)

        if (
            environ["REQUEST_METHOD"] in ("GET", "HEAD")
            and dav_res
            and dav_res.is_collection
        ):

            if util.get_content_length(environ) != 0:
                self._fail(
                    HTTP_MEDIATYPE_NOT_SUPPORTED,
                    "The server does not handle any body content.",
                )

            if environ["REQUEST_METHOD"] == "HEAD":
                return util.send_status_response(
                    environ, start_response, HTTP_OK, is_head=True
                )

            # Support DAV mount (http://www.ietf.org/rfc/rfc4709.txt)
            if self.dir_config.get("davmount") and "davmount" in environ.get(
                "QUERY_STRING", ""
            ):
                collectionUrl = util.make_complete_url(environ)
                collectionUrl = collectionUrl.split("?", 1)[0]
                res = util.to_bytes(DAVMOUNT_TEMPLATE.format(collectionUrl))
                # TODO: support <dm:open>%s</dm:open>

                start_response(
                    "200 OK",
                    [
                        ("Content-Type", "application/davmount+xml"),
                        ("Content-Length", str(len(res))),
                        ("Cache-Control", "private"),
                        ("Date", util.get_rfc1123_time()),
                    ],
                )
                return [res]

            directory_slash = self.dir_config.get("directory_slash")
            requrest_uri = environ.get("REQUEST_URI")
            if directory_slash and requrest_uri and not requrest_uri.endswith("/"):
                _logger.info(f"Redirect {requrest_uri} to {requrest_uri}/")
                return send_redirect_response(
                    environ, start_response, location=requrest_uri + "/"
                )

            context = self._get_context(environ, dav_res)

            res = self.template.render(**context)
            res = util.to_bytes(res)
            start_response(
                "200 OK",
                [
                    ("Content-Type", "text/html; charset=utf-8"),
                    ("Content-Length", str(len(res))),
                    ("Cache-Control", "private"),
                    ("Date", util.get_rfc1123_time()),
                ],
            )
            return [res]

        return self.next_app(environ, start_response)

    def _fail(self, value, context_info=None, src_exception=None, err_condition=None):
        """Wrapper to raise (and log) DAVError."""
        e = DAVError(value, context_info, src_exception, err_condition)
        if self.verbose >= 4:
            _logger.warning(
                "Raising DAVError {}".format(
                    safe_re_encode(e.get_user_info(), sys.stdout.encoding)
                )
            )
        raise e

    def _get_context(self, environ, dav_res):
        """
        @see: http://www.webdav.org/specs/rfc4918.html#rfc.section.9.4
        """
        assert dav_res.is_collection

        is_readonly = environ["wsgidav.provider"].is_readonly()
        ms_sharepoint_support = self.dir_config.get("ms_sharepoint_support")
        libre_office_support = self.dir_config.get("libre_office_support")
        is_top_dir = dav_res.path in ("", "/")

        # TODO: WebDAV URLs only on Windows?
        # TODO: WebDAV URLs only on HTTPS?
        # is_windows = "Windows NT " in environ.get("HTTP_USER_AGENT", "")

        context = {
            "htdocs": self.mount_path + ASSET_SHARE,
            "rows": [],
            "version": __version__,
            "display_path": unquote(dav_res.get_href()),
            "url": dav_res.get_href(),  # util.make_complete_url(environ),
            # "parent_url": util.get_uri_parent(dav_res.get_href()),
            "is_top_dir": is_top_dir,
            "config": self.dir_config,
            "is_readonly": is_readonly,
            "access": "read-only" if is_readonly else "read-write",
            "is_authenticated": False,
        }

        trailer = self.dir_config.get("response_trailer")
        if trailer is True:
            trailer = "${version} - ${time}"

        if trailer:
            trailer = trailer.replace(
                "${version}",
                f"WsgiDAV/{__version__}",
            )
            trailer = trailer.replace("${time}", util.get_rfc1123_time())

        context["trailer"] = trailer

        rows = context["rows"]

        # Ask collection for member info list
        dir_info_list = dav_res.get_directory_info()

        if dir_info_list is None:
            # No pre-build info: traverse members
            dir_info_list = []
            childList = dav_res.get_descendants(depth="1", add_self=False)
            for res in childList:
                di = res.get_display_info()
                href = res.get_href()
                ofe_prefix = None
                tr_classes = []
                a_classes = []

                # #268 Use relative paths to support reverse proxies:
                rel_href = get_uri_name(href)
                if res.is_collection:
                    tr_classes.append("directory")
                    rel_href = f"./{rel_href}/"  # 274

                add_link_html = []

                if not is_readonly and not res.is_collection:
                    ext = os.path.splitext(href)[1].lstrip(".").lower()
                    ms_office_type = MS_OFFICE_EXT_TO_TYPE_MAP.get(ext)
                    if ms_office_type:
                        if ms_sharepoint_support:
                            ofe_prefix = f"ms-{ms_office_type}:ofe|u|"
                            a_classes.append("msoffice")
                            if libre_office_support:
                                add_link_html.append(
                                    f"Edit"
                                )
                                # ofe_prefix_2 = "vnd.libreoffice.command:ofv|u|"
                                # a_classes.append("msoffice")
                        elif libre_office_support:
                            ofe_prefix = "vnd.libreoffice.command:ofv|u|"
                            # a_classes.append("msoffice")

                    elif ext in OPEN_OFFICE_EXTENSIONS:
                        if libre_office_support:
                            ofe_prefix = "vnd.libreoffice.command:ofv|u|"
                            a_classes.append("msoffice")

                if res.is_link():
                    a_classes.append("symlink")

                entry = {
                    "href": rel_href,
                    "ofe_prefix": ofe_prefix,
                    "a_class": " ".join(a_classes),
                    "add_link_html": "".join(add_link_html),
                    "tr_class": " ".join(tr_classes),
                    "display_name": res.get_display_name(),
                    "last_modified": res.get_last_modified(),
                    "is_collection": res.is_collection,
                    "content_length": res.get_content_length(),
                    "display_type": di.get("type"),
                    "display_type_comment": di.get("typeComment"),
                }

                dir_info_list.append(entry)
        #
        ignore_patterns = self.dir_config.get("ignore", [])
        if util.is_basestring(ignore_patterns):
            ignore_patterns = ignore_patterns.split(",")

        ignored_list = []
        for entry in dir_info_list:
            # Skip ignore patterns
            ignore = False
            for pat in ignore_patterns:
                if fnmatch(entry["display_name"], pat):
                    ignored_list.append(entry["display_name"])
                    # _logger.debug("Ignore {}".format(entry["display_name"]))
                    ignore = True
                    break
            if ignore:
                continue
            #
            last_modified = entry.get("last_modified")
            if last_modified is None:
                entry["str_modified"] = ""
            else:
                entry["str_modified"] = util.get_rfc1123_time(last_modified)

            entry["str_size"] = "-"
            if not entry.get("is_collection"):
                content_length = entry.get("content_length")
                if content_length is not None:
                    entry["str_size"] = util.byte_number_string(content_length)

            rows.append(entry)
        if ignored_list:
            _logger.debug(
                "Dir browser ignored {} entries: {}".format(
                    len(ignored_list), ignored_list
                )
            )

        # sort
        sort = "name"
        if sort == "name":
            rows.sort(
                key=lambda v: "{}{}".format(
                    not v["is_collection"], v["display_name"].lower()
                )
            )

        if "wsgidav.auth.user_name" in environ:
            context.update(
                {
                    "is_authenticated": bool(environ.get("wsgidav.auth.user_name")),
                    "user_name": (environ.get("wsgidav.auth.user_name") or "anonymous"),
                    "realm": environ.get("wsgidav.auth.realm"),
                    "user_roles": ", ".join(environ.get("wsgidav.auth.roles") or []),
                    "user_permissions": ", ".join(
                        environ.get("wsgidav.auth.permissions") or []
                    ),
                }
            )

        return context


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
# from __future__ import unicode_literals
import numpy as np
from PIL import Image
import time
import argparse
from pyflow import pyflow
import cv2
import sys
sys.path.insert(0,'../')
from metrics import flow_metrics

parser = argparse.ArgumentParser(
    description='Demo for python wrapper of Coarse2Fine Optical Flow')
parser.add_argument(
    '-viz', dest='viz', action='store_true',
    help='Visualize (i.e. save) output of flow.')
parser.add_argument('-alg', type=str, default='pyflow', help='')

def read_file(path):
    """Read an optical flow map from disk
    Optical flow maps are stored in disk as 3-channel uint16 PNG images,
    following the method described in the KITTI optical flow dataset 2012
    (http://www.cvlibs.net/datasets/kitti/eval_stereo_flow.php?benchmark=flow).
    Returns:
      numpy array with shape [height, width, 3]. The first and second channels
      denote the corresponding optical flow 2D vector (u, v). The third channel
      is a mask denoting if an optical flow 2D vector exists for that pixel.
      Vector components u and v values range [-512..512].
    """
    data = cv2.imread(path, -1).astype('float32')
    result = np.empty(data.shape, dtype='float32')
    result[:,:,0] = (data[:,:,2] - 2**15) / 64
    result[:,:,1] = (data[:,:,1] - 2**15) / 64
    result[:,:,2] = data[:,:,0]

    return result

def coarse2Fine(prev_frame, curr_frame, args):
    prev_frame_gray_nc = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY)
    curr_frame_gray_nc = cv2.cvtColor(curr_frame, cv2.COLOR_BGR2GRAY)

    prev_frame_gray = prev_frame_gray_nc[:, :, np.newaxis]
    curr_frame_gray = curr_frame_gray_nc[:, :, np.newaxis]

    prev_array = np.asarray(prev_frame_gray)
    curr_array = np.asarray(curr_frame_gray)

    # prev_array = np.asarray(prev_frame)
    # curr_array = np.asarray(curr_frame)

    prev_array = prev_array.astype(float) / 255.
    curr_array = curr_array.astype(float) / 255.

    # Flow Options:
    alpha = 0.012
    ratio = 0.75
    minWidth = 20
    nOuterFPIterations = 7
    nInnerFPIterations = 1
    nSORIterations = 30
    colType = 0  # 0 or default:RGB, 1:GRAY (but pass gray image with shape (h,w,1))

    s = time.time()
    u, v, im2W = pyflow.coarse2fine_flow(
        prev_array, curr_array, alpha, ratio, minWidth, nOuterFPIterations, nInnerFPIterations,
        nSORIterations, colType)
    e = time.time()
    print('Time Taken: %.2f seconds for image of size (%d, %d, %d)' % (
        e - s, prev_array.shape[0], prev_array.shape[1], prev_array.shape[2]))
    flow = np.concatenate((u[..., None], v[..., None]), axis=2)

    array_ones = np.ones((u.shape[0], u.shape[1]))
    flow_return = np.ndarray((u.shape[0], u.shape[1], 3))
    flow_return[:,:,0] = u
    flow_return[:,:,1] = v
    flow_return[:,:,2] = array_ones
    # np.save('examples/outFlow.npy', flow)

    if args.viz:
        hsv = np.zeros(prev_frame.shape, dtype=np.uint8)
        hsv[:, :, 0] = 255
        hsv[:, :, 1] = 255
        mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1])
        hsv[..., 0] = ang * 180 / np.pi / 2
        hsv[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)
        rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
        cv2.imwrite('output/pyflow.png', rgb)
        # cv2.imwrite('examples/car2Warped_new.jpg', im2W[:, :, ::-1] * 255)
        cv2.imshow("optical flow", rgb)
        cv2.waitKey()

        arrows = draw_flow(curr_frame_gray_nc, flow)
        cv2.imwrite('output/pyflow_arrows.png', arrows)
        cv2.imshow('pyflow', arrows)
        cv2.waitKey()

    return flow, flow_return

def farneback(prev_frame, curr_frame, args):
    curr_gray = cv2.cvtColor(curr_frame, cv2.COLOR_BGR2GRAY)
    prev_gray = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY)

    s = time.time()
    flow = cv2.calcOpticalFlowFarneback(prev_gray, curr_gray, None, 0.5, 3, 15, 3, 5, 1.2, 0)
    e = time.time()
    print('Time Taken: %.2f seconds for image of size (%d, %d, %d)' % (
        e - s, prev_gray.shape[0], prev_gray.shape[1], 1))
    array_ones = np.ones((flow.shape[0], flow.shape[1]))
    flow_return = np.ndarray((flow.shape[0], flow.shape[1], 3))
    flow_return[:,:,0] = flow[:,:,0]
    flow_return[:,:,1] = flow[:,:,1]
    flow_return[:,:,2] = array_ones

    if args.viz:
        u = flow[:,:,0]
        v = flow[:,:,1]
        print_flow = np.concatenate((u[..., None], v[..., None]), axis=2)
        hsv = np.zeros(prev_frame.shape, dtype=np.uint8)
        hsv[:, :, 0] = 255
        hsv[:, :, 1] = 255
        mag, ang = cv2.cartToPolar(print_flow[..., 0], print_flow[..., 1])
        hsv[..., 0] = ang * 180 / np.pi / 2
        hsv[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)
        rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
        cv2.imwrite('output/farneback.png', rgb)
        # cv2.imwrite('examples/car2Warped_new.jpg', im2W[:, :, ::-1] * 255)
        cv2.imshow("optical flow", rgb)
        cv2.waitKey()

        arrows = draw_flow(curr_gray, flow)
        cv2.imwrite('output/farneback_arrows.png', arrows)
        cv2.imshow('Farneback', arrows)
        cv2.waitKey()

    return flow, flow_return

def lk_algorithm(prev_frame, curr_frame, args):
    lk_params = dict(winSize=(15, 15),
                     maxLevel=2,
                     criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))

    feature_params = dict(maxCorners=100,
                          qualityLevel=0.3,
                          minDistance=7,
                          blockSize=7)

    curr_gray = cv2.cvtColor(curr_frame, cv2.COLOR_BGR2GRAY)
    prev_gray = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY)

    s = time.time()
    p0 = cv2.goodFeaturesToTrack(prev_gray, mask=None, **feature_params)

    p1, st, err = cv2.calcOpticalFlowPyrLK(prev_gray, curr_gray, p0, None, **lk_params)
    e = time.time()
    print('Time Taken: %.2f seconds for image of size (%d, %d, %d)' % (
        e - s, prev_gray.shape[0], prev_gray.shape[1], 1))

    # Select good points
    good_new = p1[st == 1]
    good_old = p0[st == 1]

    motion = np.zeros([prev_gray.shape[0], prev_gray.shape[1], 3])
    u = np.zeros([prev_gray.shape[0], prev_gray.shape[1]])
    v = np.zeros([prev_gray.shape[0], prev_gray.shape[1]])

    factor = 1.1

    for idx, good_point in enumerate(good_old):
        prev_frame_x = good_point[1]
        prev_frame_y = good_point[0]
        curr_frame_x = good_new[idx][1]
        curr_frame_y = good_new[idx][0]

        motion[int(prev_frame_x), int(prev_frame_y)] = np.array([curr_frame_x-prev_frame_x, curr_frame_y-prev_frame_y, 1])
        u[int(prev_frame_x), int(prev_frame_y)] = np.array([(curr_frame_x - prev_frame_x)*factor])
        v[int(prev_frame_x), int(prev_frame_y)] = np.array([(curr_frame_y - prev_frame_y)*factor])

        cv2.arrowedLine(prev_frame, (prev_frame_y, prev_frame_x),
                        (int(curr_frame_y*factor), int(curr_frame_x*factor)), (0, 0, 255), 1)

    flow = np.concatenate((u[..., None], v[..., None]), axis=2)

    if args.viz:
        cv2.imshow("lk", prev_frame)
        cv2.imwrite('output/lk.png', prev_frame)
        cv2.waitKey()

        # print_flow = draw_flow(prev_gray, flow)
        # cv2.imshow("lk", print_flow)
        # cv2.waitKey()

        # print_flow = np.concatenate((u[..., None], v[..., None]), axis=2)
        # hsv = np.zeros(prev_frame.shape, dtype=np.uint8)
        # hsv[:, :, 0] = 255
        # hsv[:, :, 1] = 255
        # mag, ang = cv2.cartToPolar(print_flow[..., 0], print_flow[..., 1])
        # hsv[..., 0] = ang * 180 / np.pi / 2
        # hsv[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)
        # rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
        # cv2.imwrite('output/lk.png', rgb)
        # # cv2.imwrite('examples/car2Warped_new.jpg', im2W[:, :, ::-1] * 255)
        # cv2.imshow("lk", rgb)
        # cv2.waitKey()

    return flow, motion

def draw_flow(img, flow, step=8):
    h, w = img.shape[:2]
    y, x = np.mgrid[step/2:h:step, step/2:w:step].reshape(2,-1).astype(int)
    fx, fy = flow[y,x].T
    lines = np.vstack([x, y, x+fx, y+fy]).T.reshape(-1, 2, 2)
    lines = np.int32(lines + 0.5)
    vis = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
    cv2.polylines(vis, lines, 0, (0, 255, 0))
    for (x1, y1), (x2, y2) in lines:
        cv2.circle(vis, (x1, y1), 1, (0, 255, 0), -1)
    return vis

def switch_alg(argument):
    switcher = {
        'pyflow': coarse2Fine,
        'farneback': farneback,
        'lk': lk_algorithm,
    }
    func = switcher[argument]
    return func

if __name__ == '__main__':

    args = parser.parse_args()

    video_dir = '../../datasets/AICity_data/train/S03/c010/vdo.avi'
    capture = cv2.VideoCapture(video_dir)
    frame_idx = 0

    opt_flow_alg = switch_alg(args.alg)

    frame1_rgb = cv2.imread('../000045_10.png')
    frame2_rgb = cv2.imread('../000045_11.png')
    gt = read_file('../gt_000045_10.png')

    # frame1_rgb = cv2.imread('../000157_10.png')
    # frame2_rgb = cv2.imread('../000157_11.png')
    # gt = read_file('../gt_000157_10.png')

    _,flow = opt_flow_alg(frame1_rgb, frame2_rgb, args)
    msen, pepn, img_err, vect_err = flow_metrics(flow, gt)
    print("Results with "+args.alg+" algorithm--> MSEN:", msen, "PEPN:",pepn)

    #### Whole Video Sequence
    # resize_factor = 0.35
    #
    # current_frame = None
    # previous_frame = None
    # while True:
    #     success, frame = capture.read()
    #     if not success:
    #         break
    #     frame_idx += 1
    #     if frame_idx == 1:
    #         previous_frame = frame
    #         previous_frame = cv2.resize(previous_frame, (0, 0), fx=resize_factor, fy=resize_factor)
    #         continue
    #     else:
    #         current_frame = frame
    #         current_frame = cv2.resize(current_frame, (0, 0), fx=resize_factor, fy=resize_factor)
    #
    #     opt_flow_alg(previous_frame, current_frame, args)
    #####


from .chinese_provinces_improved import \
    aggregate_inhabitants_by_province
from pyspark.sql import SparkSession
from pyspark.sql.types import StructType, \
    StructField, StringType, LongType, BooleanType

def test_aggregate_inhabitants_by_province():
    """The number of inhabitants per province should be aggregated,
    regardless of their distinctive features.
    """

    spark = SparkSession.builder.getOrCreate()

    fields = [
        StructField("country", StringType(), True),
        StructField("province", StringType(), True),
        StructField("inhabitants", LongType(), True),
        StructField("foo", BooleanType(), True),  # distinctive features
    ]

    frame = spark.createDataFrame({
        ("China", "A", 3, False),
        ("China", "A", 2, True),
        ("China", "B", 14, False),
        ("US", "A", 4, False)},
        schema=StructType(fields)
    )
    actual = aggregate_inhabitants_by_province(frame).cache()

    # In the older implementation, the data was first filtered for a specific
    # country, after which you'd aggregate by province. The same province
    # name could occur in multiple countries though.
    # This test is expecting the data to be grouped by country,
    # then province from aggregate_inhabitants_by_province()
    expected = spark.createDataFrame(
        {("China", "A", 5), ("China", "B", 14), ("US", "A", 4)},
        schema=StructType(fields[:3])
    ).cache()

    assert actual.schema == expected.schema, "schemas don't match up"
    assert sorted(actual.collect()) == sorted(expected.collect()),\
        "data isn't equal"


'''
task1.

edit distance
but each cell keeps track of max
max starts at zero
whenever you move diagonally with an increase of 0 in cost,
	-> max of the new cell is max of previous+1
when moving horizontally or vertically, doesn't change value
the movement is chosen from the one that gives max value

'''
def longestCommonSubseq(A, B):
	m = len(A)
	n = len(B)
	# create table T of size mXn, initialized to 0
	T = []
	for _ in range(m+1):
		T.append([0 for _ in range(n+1)])

	for i in range(1,m+1):
		for j in range(1,n+1):
			if A[i-1:i] == B[j-1:j]:
				temp = T[i-1][j-1]+1
			else:
				temp = T[i-1][j-1]
			T[i][j] = max(temp, T[i-1][j], T[i][j-1])
	return T[m][n]

print(longestCommonSubseq('abcde', 'xyabcz'))

'''
task2.

binary search
'''

def maxInShiftedA(a, low, high):
	# returns index of max
	mid = (low+high)//2
	if mid == low:
		if a[mid] > a[high]:
			return mid
		else:
			return high
	if a[mid] >= a[low]:
		return maxInShiftedA(a, mid+1, high)
	else:
		return maxInShiftedA(a, low, mid-1)

a = [35,42,5,15,27,29]
print(a[maxInShiftedA(a, 0, len(a)-1)])

'''
task 3.

basic idea: if you can get to the second next, don't
stop at next

proof on paper

run-time complexity: O(n)
'''
def gasStops(m, d):
	result = []
	cap = m
	n = len(d)
	for i in range(n-1):
		if d[i+1] > cap:
			cap = d[i] + m
			result.append(d[i])
	return result

print(gasStops(10,[6,8,12,17,23]))

'''
task 4.

there will need to be a queen on each row
stack holds where each queen is positioned
	first item in stack indicates index of queen on first row
	second item in stack indicates index of queen on second row
	....
if gets to an invalid configuration, pop last queen from stack and keep on trying from there
'''
class Stack:
    def __init__(self, size):

        assert size > 0, "Size should be positive"

        self.the_array = size*[None]
        self.count = 0
        self.top = -1

    def is_empty(self):
        return self.__len__() == 0

    def is_full(self):
        return self.__len__() >= len(self.the_array)

    def reset(self):
        self.count = 0
        self.top = -1

    def pop(self):
        assert not self.is_empty(), "Stack is empty"

        item = self.the_array[self.top]
        self.top -= 1
        self.count -= 1

        return item

    def push(self, item):
        assert not self.is_full(), "Stack is full"

        self.top += 1
        self.the_array[self.top] = item
        self.count += 1

    def peek(self):
        assert not self.is_empty(), "Stack is empty"

        return self.the_array[self.top]

    def __len__(self):
        return self.count

    def __str__(self):
        a_string = ""
        for n in range(self.count -1, -1 , -1):
            a_string += str(self.the_array[n])
            if n != 0:
                a_string += " "
        return a_string

def nQueens(N):
	S = Stack(N)
	pos = 0
	while not S.is_full():
		while pos < N and not checkValidity(S, pos):
			pos += 1
		if pos != N:
			S.push(pos)
			pos = 0
		while pos == N:
			pos = S.pop() + 1
	printSolution(S)

def checkValidity(S, pos):
	a = []
	while not S.is_empty():
		a.append(S.pop())
	a.reverse()
	for item in a:
		S.push(item)
	for i in range(len(a)):
		if a[i] == pos or a[i]+len(a)-i == pos or a[i]-len(a)+i == pos:
			return False
	return True

def printSolution(S):
	result = []
	N = len(S)
	while not S.is_empty():
		pos = S.pop()
		tmp = []
		for i in range(N):
			if i == pos:
				tmp.append("Q")
			else:
				tmp.append("*")
		result.append(tmp)
	# result.reverse()
	for item in result:
		print(item)

nQueens(9)

algorithms & data structures/prac5/lab12.py