from datetime import datetime, timedelta
import unittest

if __name__ == "__main__":
    import utils
    utils.import_depends()

from brokertest import TestBrokerCommand

EXPIRY = datetime.utcnow().replace(microsecond=0) + timedelta(days=1)
EXPIRY = EXPIRY.isoformat().replace("T", " ")

class TestAddRebootIntervention(TestBrokerCommand):

    def test_00_basic_reboot_intervention(self):
        command = ["show_reboot_intervention",
                   "--hostname=server1.aqd-unittest.ms.com"]
        out = self.notfoundtest(command)

        command = ["add_reboot_intervention", "--expiry", EXPIRY,
                   "--reason=test",
                   "--hostname=server1.aqd-unittest.ms.com"]
        self.successtest(command)

        command = ["show_reboot_intervention",
                   "--hostname=server1.aqd-unittest.ms.com"]
        out = self.commandtest(command)
        self.searchoutput(out, "RebootIntervention$", command)
        self.matchoutput(out, "Bound to: Host server1.aqd-unittest.ms.com",
                         command)
        self.matchoutput(out, "Start: ", command)
        self.matchoutput(out, "Expiry: ", command)

        command = ["cat", "--reboot_intervention",
                   "--hostname=server1.aqd-unittest.ms.com"]
        out = self.commandtest(command)
        self.matchoutput(out,
                         "structure template resource"
                         "/host/server1.aqd-unittest.ms.com"
                         "/reboot_iv/reboot_intervention/config;",
                         command)
        self.matchoutput(out, "\"name\" = \"reboot_intervention\";", command)
        self.matchoutput(out, "\"start\" =", command)
        self.matchoutput(out, "\"expiry\" =", command)

        command = ["cat", "--reboot_intervention",
                   "--hostname=server1.aqd-unittest.ms.com",
                   "--generate"]
        newout = self.commandtest(command)
        self.assertEqual(out, newout)

        command = ["show_reboot_intervention", "--all"]
        out = self.commandtest(command)
        self.searchoutput(out, "RebootIntervention$", command)

    def test_11_addexisting(self):
        EXPIRY = datetime.utcnow().replace(microsecond=0) + timedelta(days=2)
        command = ["add_reboot_intervention", "--expiry", EXPIRY,
                   "--reason=test",
                   "--hostname=server1.aqd-unittest.ms.com"]
        out = self.badrequesttest(command)
        self.matchoutput(out, "already exists", command)

    def test_12_addbadtime(self):
        command = ["add_reboot_intervention", "--start_time=2013/01/01",
                   "--expiry=2013/01/14",
                   "--reason=test",
                   "--hostname=server2.aqd-unittest.ms.com"]
        out = self.badrequesttest(command)
        self.matchoutput(out, "The start time or expiry time are in the past.", command)

    def test_15_notfoundri(self):
        command = ["cat", "--reboot_intervention",
                   "--hostname=server3.aqd-unittest.ms.com"]
        self.notfoundtest(command)

    def test_30_checkthehost(self):
        command = ["show_host", "--host=server1.aqd-unittest.ms.com"]
        out = self.commandtest(command)
        self.matchoutput(out, "RebootIntervention", command)

        command = ["make", "--hostname=server1.aqd-unittest.ms.com"]
        out = self.successtest(command)

        command = ["cat", "--generate",
                   "--hostname", "server1.aqd-unittest.ms.com", "--data"]
        out = self.commandtest(command)
        self.matchoutput(out,
                         '"system/resources/reboot_iv" = '
                         'append(create("resource/host/server1.aqd-unittest.ms.com/reboot_iv/reboot_intervention/config"))',
                         command)

        command = ["show_host", "--hostname=server1.aqd-unittest.ms.com",
                   "--format=proto"]
        host = self.protobuftest(command, expect=1)[0]
        found = False
        for resource in host.resources:
            if resource.name == "reboot_intervention" and \
               resource.type == "reboot_iv":
                found = True
        self.assertTrue(found, "No reboot_iv found in host protobuf.")

if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(
        TestAddRebootIntervention)
    unittest.TextTestRunner(verbosity=2).run(suite)


# -*- coding: utf-8 -*-
# Standard Library Imports
from datetime import datetime, timedelta
from glob import glob
import json
import logging
from math import radians, sin, cos, atan2, sqrt, degrees
import os
import sys
import hashlib
import hmac
import base64
import urllib.parse as urlparse
import traceback

# 3rd Party Imports
from s2cell import s2cell

# Local Imports
from PokeAlarm import not_so_secret_url
from PokeAlarm import config
from PokeAlarm import Unknown

log = logging.getLogger("Utils")

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SYSTEM UTILITIES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# Checks is a line contains any substitutions located in args
def contains_arg(line, args):
    for word in args:
        if (f"<{word}>") in line:
            return True
    return False

def get_path(path):
    if not os.path.isabs(path):  # If not absolute path
        path = os.path.join(config["ROOT_PATH"], path)
    return path

def parse_boolean(val):
    b = str(val).lower()
    if b in {"t", "true", "y", "yes"}:
        return True
    if b in ("f", "false", "n", "no"):
        return False
    return None

# Used for lazy installs - installs required module with pip
def pip_install(req, version):
    import subprocess

    target = f"{req}=={version}"
    log.info("Attempting to pip install %s...", target)
    subprocess.call(["pip", "install", target])
    log.info("%s install complete.", target)

# Used to exit when leftover parameters are found
def reject_leftover_parameters(dict_, location):
    if len(dict_) > 0:
        log.error("Unknown parameters at %s: ", location)
        log.error(list(dict_.keys()))
        log.error("Please consult the PokeAlarm wiki for accepted parameters.")
        sys.exit(1)

# Load a key from the given dict, or throw an error if it isn't there
def require_and_remove_key(key, _dict, location):
    if key in _dict:
        return _dict.pop(key)
    else:
        log.error(
            "The parameter '%s' is required for %s. "
            "Please check the PokeAlarm wiki for correct formatting.",
            key,
            location,
        )
        sys.exit(1)

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ POKEMON UTILITIES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# Returns the id corresponding with the pokemon name
# (use all locales for flexibility)
def get_pkmn_id(pokemon_name):
    try:
        name = pokemon_name.lower()
        return get_pkmn_id.ids.get(name)
    except AttributeError:
        get_pkmn_id.ids = {}
        files = glob(get_path("locales/*.json"))
        for file_ in files:
            with open(file_, "r") as f:
                j = json.load(f)
                f.close()
            j = j["pokemon"]
            for id_ in j:
                nm = j[id_].lower()
                get_pkmn_id.ids[nm] = int(id_)

        return get_pkmn_id.ids.get(name)

# Returns the id corresponding with the move (use all locales for flexibility)
def get_move_id(move_name):
    try:
        name = move_name.lower()
        return get_move_id.ids.get(name)
    except AttributeError:
        get_move_id.ids = {}
        files = glob(get_path("locales/*.json"))
        for file_ in files:
            with open(file_, "r") as f:
                j = json.load(f)
                f.close()
            j = j["moves"]
            for id_ in j:
                nm = j[id_].lower()
                get_move_id.ids[nm] = int(id_)

        return get_move_id.ids.get(name)

# Returns the id corresponding with the pokemon name
# (use all locales for flexibility)
def get_team_id(team_name):
    try:
        name = team_name.lower()
        return get_team_id.ids.get(name)
    except AttributeError:
        get_team_id.ids = {}
        files = glob(get_path("locales/*.json"))
        for file_ in files:
            with open(file_, "r") as f:
                j = json.load(f)
                f.close()
            j = j["teams"]
            for id_ in j:
                nm = j[id_].lower()
                get_team_id.ids[nm] = int(id_)

        return get_team_id.ids.get(name)

# Returns type id corresponding with the type name
def get_type_id(type_name):
    try:
        name = type_name.lower()
        return get_type_id.info.get(name, 0)
    except AttributeError:
        get_type_id.info = {}
        file_ = get_path("locales/en.json")
        with open(file_, "r") as f:
            j = json.load(f)
            f.close()
        for id_, name_ in j["types"].items():
            get_type_id.info[name_.lower()] = int(id_)

        return get_type_id.info.get(name, 0)

# Returns the types of a move when requesting
def get_move_type(move_id):
    try:
        return get_move_type.info.get(move_id, Unknown.SMALL)
    except AttributeError:
        get_move_type.info = {}
        file1_ = get_path("data/fast_moves.json")
        file2_ = get_path("data/charged_moves.json")
        for file_ in [file1_, file2_]:
            with open(file_, "r") as f:
                j = json.load(f)
                f.close()
            for mv in j:
                get_move_type.info[mv["move_id"]] = get_type_id(mv["type"])

        return get_move_type.info.get(move_id, Unknown.SMALL)

# Returns the damage of a move when requesting
def get_move_damage(move_id):
    try:
        return get_move_damage.info.get(move_id, "unkn")
    except AttributeError:
        get_move_damage.info = {}
        file1_ = get_path("data/fast_moves.json")
        file2_ = get_path("data/charged_moves.json")
        for file_ in [file1_, file2_]:
            with open(file_, "r") as f:
                j = json.load(f)
                f.close()
            for mv in j:
                get_move_damage.info[mv["move_id"]] = mv["power"]

        return get_move_damage.info.get(move_id, "unkn")

# Returns the dps of a move when requesting
def get_move_dps(move_id):
    try:
        return get_move_dps.info.get(move_id, "unkn")
    except AttributeError:
        get_move_dps.info = {}
        file1_ = get_path("data/fast_moves.json")
        file2_ = get_path("data/charged_moves.json")
        for file_ in [file1_, file2_]:
            with open(file_, "r") as f:
                j = json.load(f)
                f.close()
            for mv in j:
                get_move_dps.info[mv["move_id"]] = round(
                    (mv["power"] / mv["duration"]) * 1000, 2
                )

        return get_move_dps.info.get(move_id, "unkn")

# Returns the duration of a move when requesting
def get_move_duration(move_id):
    try:
        return get_move_duration.info.get(move_id, "unkn")
    except AttributeError:
        get_move_duration.info = {}
        file1_ = get_path("data/fast_moves.json")
        file2_ = get_path("data/charged_moves.json")
        for file_ in [file1_, file2_]:
            with open(file_, "r") as f:
                j = json.load(f)
                f.close()
            for mv in j:
                get_move_duration.info[mv["move_id"]] = mv["duration"]

        return get_move_duration.info.get(move_id, "unkn")

# Returns the duration of a move when requesting
def get_move_energy(move_id):
    try:
        return get_move_energy.info.get(move_id, "unkn")
    except AttributeError:
        get_move_energy.info = {}
        file1_ = get_path("data/fast_moves.json")
        file2_ = get_path("data/charged_moves.json")
        for file_ in [file1_, file2_]:
            with open(file_, "r") as f:
                j = json.load(f)
                f.close()
            for mv in j:
                get_move_energy.info[mv["move_id"]] = abs(mv["energy_delta"])

        return get_move_energy.info.get(move_id, "unkn")

# Returns the base height for a pokemon
def get_base_height(pokemon_id):
    try:
        return get_base_height.info.get(pokemon_id, 0)
    except AttributeError:
        get_base_height.info = {}
        file_ = get_path("data/pokemon_data.json")
        with open(file_, "r") as f:
            j = json.load(f)
            f.close()
        for id_ in j:
            get_base_height.info[int(id_)] = j[id_].get("height")

        return get_base_height.info.get(pokemon_id, 0)

# Returns the base weight for a pokemon
def get_base_weight(pokemon_id):
    try:
        return get_base_weight.info.get(pokemon_id, 0)
    except AttributeError:
        get_base_weight.info = {}
        file_ = get_path("data/pokemon_data.json")
        with open(file_, "r") as f:
            j = json.load(f)
            f.close()
        for id_ in j:
            get_base_weight.info[int(id_)] = j[id_].get("weight")

        return get_base_weight.info.get(pokemon_id, 0)

# Returns the types for a pokemon and its forms
def get_base_stats(pokemon_id, form_id=0):
    try:
        get_base_stats.info
    except AttributeError:
        get_base_stats.info = {}
        file_ = get_path("data/pokemon_data.json")
        with open(file_, "r") as f:
            j = json.load(f)
            f.close()
        for id_ in j:
            normal_form_stats = j[id_].get("stats")
            get_base_stats.info[int(id_) * 100_000] = normal_form_stats

            for form_id_ in j[id_].get("forms", {}):
                if form_id_ == "0":
                    continue
                form_ = j[id_]["forms"][form_id_]
                if (
                    form_["name"] in ("Shadow", "Purified", "Normal")
                    or form_.get("stats") is None
                ):
                    form_stats = normal_form_stats
                else:
                    form_stats = form_["stats"]
                stats_key = int(id_) * 100_000 + int(form_id_)
                get_base_stats.info[stats_key] = form_stats

    stats_key = pokemon_id * 100_000 + form_id
    default_stats = {"attack": 0, "defense": 0, "stamina": 0}
    return get_base_stats.info.get(stats_key, default_stats)

# Returns possible evolutions for a pokemon and its forms
def get_evolutions(base_pokemon_id, base_form_id=0):
    try:
        get_evolutions.info
    except AttributeError:
        get_evolutions.info = {}
        file_ = get_path("data/pokemon_data.json")
        with open(file_, "r") as f:
            j = json.load(f)
            f.close()
        for id_ in j:
            normal_form_chain = get_evolution_chain(j, id_, "0")
            get_evolutions.info[int(id_) * 100_000] = normal_form_chain
            for form_id_ in j[id_].get("forms", {}):
                if form_id_ == "0":
                    continue
                if j[id_]["forms"][form_id_]["name"] in (
                    "Shadow",
                    "Purified",
                    "Normal",
                ):
                    evo_chain = normal_form_chain
                else:
                    evo_chain = get_evolution_chain(j, id_, form_id_)

                evo_key = int(id_) * 100_000 + int(form_id_)
                get_evolutions.info[evo_key] = evo_chain

    evo_key = base_pokemon_id * 100_000 + base_form_id
    return get_evolutions.info.get(evo_key, [])

# Return the list of evolutions depending on the form of the pokemon
def get_evolution_chain(j, id_, form_id_, a=None):
    if a is None:
        a = []
    if form_id_ != "0":
        evolutions = j[id_]["forms"][form_id_].get("evolutions")
        if evolutions is not None:
            for evo_id in evolutions:
                if int(evo_id) > 1010:  # block unreleased generations
                    continue

                evo_form_id = evolutions[evo_id]["form"]
                a.append((int(evo_id), int(evo_form_id)))

                next_id_ = str(evolutions[evo_id]["pokemon"])
                next_form_id_ = str(evolutions[evo_id]["form"])
                get_evolution_chain(j, next_id_, next_form_id_, a)
    else:
        evolutions = j[id_].get("evolutions")
        if evolutions is not None:
            for evo_id in evolutions:
                if int(evo_id) > 1010:  # block unreleased generations
                    continue

                evo_form_id = evolutions[evo_id]["form"]
                a.append((int(evo_id), int(evo_form_id)))

                next_id_ = str(evolutions[evo_id]["pokemon"])
                get_evolution_chain(j, next_id_, "0", a)
    return a

# Returns evolution costs from a pokemon and its forms
def get_evolution_costs(pokemon_id, form_id=0):
    try:
        get_evolution_costs.info
    except AttributeError:
        get_evolution_costs.info = {}
        file_ = get_path("data/pokemon_data.json")
        with open(file_, "r") as f:
            j = json.load(f)
            f.close()
        for id_ in j:
            normal_form_chain = get_evolution_cost_chain(j, id_, "0")
            get_evolution_costs.info[int(id_) * 100_000] = normal_form_chain
            for form_id_ in j[id_].get("forms", {}):
                if form_id_ == "0":
                    continue
                if j[id_]["forms"][form_id_]["name"] in (
                    "Shadow",
                    "Purified",
                    "Normal",
                ):
                    cost_chain = normal_form_chain
                else:
                    cost_chain = get_evolution_cost_chain(j, id_, form_id_)

                mon_key = int(id_) * 100_000 + int(form_id_)
                get_evolution_costs.info[mon_key] = cost_chain

    mon_key = pokemon_id * 100_000 + form_id
    return get_evolution_costs.info.get(mon_key, [])

# Return the list of evolution costs depending on the form of the pokemon
def get_evolution_cost_chain(j, id_, form_id_, a=None):
    if a is None:
        a = []
    if form_id_ != "0":
        evolutions = j[id_]["forms"][form_id_].get("evolutions", {})
        for evo_id in evolutions:
            if int(evo_id) > 1010:  # block unreleased generations
                continue

            candy_cost = int(evolutions[evo_id].get("candyCost", 0))
            a.append(candy_cost)

            get_evolution_cost_chain(
                j,
                str(evolutions[evo_id]["pokemon"]),
                str(evolutions[evo_id]["form"]),
                a,
            )
    else:
        evolutions = j[id_].get("evolutions", {})
        for evo_id in evolutions:
            if int(evo_id) > 1010:  # block unreleased generations
                continue

            candy_cost = int(evolutions[evo_id].get("candyCost", 0))
            a.append(candy_cost)

            get_evolution_cost_chain(
                j,
                str(evolutions[evo_id]["pokemon"]),
                "0",
                a,
            )
    return a

# Returns default form names for all the pokemon
def get_raw_form_names():
    try:
        return get_raw_form_names.info
    except AttributeError:
        get_raw_form_names.info = {}
        file_ = get_path("data/pokemon_data.json")
        with open(file_, "r") as f:
            j = json.load(f)
            f.close()
        for id_ in j:
            get_raw_form_names.info[int(id_)] = {}
            get_raw_form_names.info[int(id_)][0] = "Normal"
            for form_id_ in j[id_].get("forms", {}):
                if form_id_ != "0":
                    get_raw_form_names.info[int(id_)][int(form_id_)] = j[id_]["forms"][
                        form_id_
                    ]["name"]

        return get_raw_form_names.info

# Return CP multipliers
def get_cp_multipliers():
    try:
        return get_cp_multipliers.info
    except AttributeError:
        file_ = get_path("data/cp_multipliers.json")
        with open(file_, "r") as f:
            j = json.load(f)
            get_cp_multipliers.info = {}
            for lvl in j:
                get_cp_multipliers.info[float(lvl)] = j[lvl]
        return get_cp_multipliers.info

def get_cp_multiplier_squares():
    try:
        return get_cp_multiplier_squares.info
    except AttributeError:
        multipliers = get_cp_multipliers()
        get_cp_multiplier_squares.info = {}
        for lvl in multipliers:
            get_cp_multiplier_squares.info[lvl] = multipliers[lvl] ** 2
        return get_cp_multiplier_squares.info

def bisect_levels(cp_limit, cp_base, first, last):
    try:
        bisect_levels.levels
    except AttributeError:
        # Generate levels tuple (1.0, 1.5, 2.0, ... , 49.5, 50.0)
        bisect_levels.levels = tuple(x / 10 for x in range(10, 501, 5))

    multiplier_squares = get_cp_multiplier_squares()

    best_cp = 0
    best_level = 0
    range_first = int(first * 2 - 2)
    range_last = int(last * 2 - 2)

    while range_first <= range_last:
        range_mid = (range_first + range_last) // 2
        level = bisect_levels.levels[range_mid]
        cp = max(10, int(cp_base * multiplier_squares[level]))

        if cp > cp_limit:
            range_last = range_mid - 1
        else:
            best_level = level
            best_cp = cp
            if cp < cp_limit:
                range_first = range_mid + 1
            else:
                break  # found exact limit

    return best_cp, best_level

# Get the max CP of a pokemon
def max_cp(monster_id, form_id=0):
    return calculate_cp(monster_id, form_id, 15, 15, 15, 50)

# Calculate CP using pokemon IV
def calculate_cp(monster_id, form_id, atk, de, sta, lvl):
    multipliers = get_cp_multiplier_squares()
    cp_base = calculate_cp_base(monster_id, form_id, atk, de, sta)
    return max(10, int(cp_base * multipliers[lvl]))

def calculate_cp_base(monster_id, form_id, atk, de, sta):
    base_stats = get_base_stats(monster_id, form_id)
    return (
        (base_stats["attack"] + atk)
        * sqrt(base_stats["defense"] + de)
        * sqrt(base_stats["stamina"] + sta)
        / 10
    )

def get_best_product(league, pokemon_id, form_id):
    try:
        get_best_product.info
    except AttributeError:
        get_best_product.info = {
            "great": {},
            "ultra": {},
        }
        file_ = get_path("data/stat_products.json")
        with open(file_, "r") as f:
            j = json.load(f)
            f.close()
        for id_ in j:
            for form_id_ in j[id_]:
                key_ = int(id_) * 100_000 + int(form_id_)
                get_best_product.info["great"][key_] = j[id_][form_id_].get(
                    "1500_highest_product"
                )
                get_best_product.info["ultra"][key_] = j[id_][form_id_].get(
                    "2500_highest_product"
                )

    base_key = pokemon_id * 100_000
    return get_best_product.info[league].get(
        base_key + form_id, get_best_product.info[league].get(base_key, 0)
    )

# Returns the highest possible stat product for PvP great league for a pkmn
def get_best_great_product(pokemon_id, form_id=0):
    return get_best_product("great", pokemon_id, form_id)

# Returns the highest possible stat product for PvP ultra league for a pkmn
def get_best_ultra_product(pokemon_id, form_id=0):
    return get_best_product("ultra", pokemon_id, form_id)

# Returns a cp range for a certain level of a pokemon caught in a raid
def get_pokemon_cp_range(level, pokemon_id, form_id=0):
    stats = get_base_stats(pokemon_id, form_id)

    try:
        cp_multi = get_pokemon_cp_range.info[level]
    except AttributeError:
        get_pokemon_cp_range.info = {}
        file_ = get_path("data/cp_multipliers.json")
        with open(file_, "r") as f:
            j = json.load(f)
            f.close()
        for lvl_ in j:
            get_pokemon_cp_range.info[float(lvl_)] = j[lvl_]

        cp_multi = get_pokemon_cp_range.info[level]

    # minimum IV for a egg/raid pokemon is 10/10/10
    min_cp = int(
        (
            (stats["attack"] + 10.0)
            * pow((stats["defense"] + 10.0), 0.5)
            * pow((stats["stamina"] + 10.0), 0.5)
            * pow(cp_multi, 2)
        )
        / 10.0
    )
    max_cp = int(
        (
            (stats["attack"] + 15.0)
            * pow((stats["defense"] + 15.0), 0.5)
            * pow((stats["stamina"] + 15.0), 0.5)
            * pow(cp_multi, 2)
        )
        / 10.0
    )

    return min_cp, max_cp

# Returns the size ratio of a pokemon
def size_ratio(pokemon_id, height, weight):
    height_ratio = height / get_base_height(pokemon_id)
    weight_ratio = weight / get_base_weight(pokemon_id)

    return height_ratio + weight_ratio

# Returns the appraised size_id of a pokemon
def get_pokemon_size(pokemon_id, height, weight):
    size = size_ratio(pokemon_id, height, weight)
    if size < 1.5:
        return 1
    elif size <= 1.75:
        return 2
    elif size <= 2.25:
        return 3
    elif size <= 2.5:
        return 4
    else:
        return 5

# Returns the gender symbol:
def get_gender_sym(gender):  # TODO - support other languages
    gender = str(gender).lower()
    if gender == "?":
        return "?"
    if gender == "1" or gender == "male":
        return "\u2642"  # male symbol
    elif gender == "2" or gender == "female":
        return "\u2640"  # female symbol
    elif gender == "3" or gender == "neutral":
        return "\u26b2"  # neutral
    else:
        raise ValueError(
            f"Unable to interpret '{gender}' as a supported gender name or id."
        )

# Returns the types for a pokemon and its forms
def get_base_types(pokemon_id, form_id=0):
    try:
        get_base_types.info
    except AttributeError:
        get_base_types.info = {}
        file_ = get_path("data/pokemon_data.json")
        with open(file_, "r") as f:
            j = json.load(f)
            f.close()
        for id_ in j:
            normal_form_types = ([int(k) for k in j[id_].get("types")] + [0] * 2)[:2]
            get_base_types.info[int(id_) * 100_000] = normal_form_types

            for form_id_ in j[id_].get("forms", {}):
                if form_id_ == "0":
                    continue
                form_ = j[id_]["forms"][form_id_]
                if (
                    form_["name"] in ("Shadow", "Purified", "Normal")
                    or form_.get("types") is None
                ):
                    base_types = normal_form_types
                else:
                    base_types = ([int(k) for k in form_["types"]] + [0] * 2)[:2]

                mon_key = int(id_) * 100_000 + int(form_id_)
                get_base_types.info[mon_key] = base_types

    mon_key = pokemon_id * 100_000 + form_id
    return get_base_types.info.get(mon_key, [0, 0])

# Returns the types for a pokemon
def get_mon_type(pokemon_id, form_id=0):
    types = get_base_types(pokemon_id, form_id)
    return types["type1"], types["type2"]

def get_powerup_costs(type):
    try:
        return get_powerup_costs.info.get(type)
    except AttributeError:
        get_powerup_costs.info = {}
        file_ = get_path("data/powerup_costs.json")
        with open(file_, "r") as f:
            j = json.loads(f.read())
            f.close()
        for type_ in j:
            get_powerup_costs.info[type_] = []
            for key in j[type_]:
                levels = key.split("-")
                level = float(levels[0])
                endlevel = float(levels[1])
                while level <= endlevel:
                    get_powerup_costs.info[type_].append(int(j[type_][key]))
                    level += 0.5

        return get_powerup_costs.info.get(type)

# Return the list of stardust costs for powering up a pokemon
def get_stardust_costs():
    return get_powerup_costs("stardust")

# Return the list of candy costs for powering up a pokemon
def get_candy_costs():
    return get_powerup_costs("candy")

# Return the list of xl candy costs for powering up a pokemon
def get_xl_candy_costs():
    return get_powerup_costs("xl_candy")

def calculate_candy_cost(start_level, target_level, evo_candy_cost=0):
    if start_level >= target_level:
        return (0, 0)

    candy_costs = get_candy_costs()
    xl_candy_costs = get_xl_candy_costs()

    # Calculate indices from levels
    start = int(float(start_level) / 0.5 - 2)
    end = int(float(target_level) / 0.5 - 2)

    candy_cost = sum(candy_costs[start : min(80, end)], evo_candy_cost)
    xl_candy_cost = (
        sum(xl_candy_costs[0 : end - len(candy_costs)]) if target_level > 40 else 0
    )

    return (candy_cost, xl_candy_cost)

def calculate_stardust_cost(start_level, target_level):
    if start_level >= target_level:
        return 0

    stardust_costs = get_stardust_costs()

    # Calculate indices from levels
    start = int(float(start_level) / 0.5 - 2)
    end = int(float(target_level) / 0.5 - 2)

    return sum(stardust_costs[start:end])

def calculate_evolution_cost(monster_id, target_id, evolutions, evolution_costs):
    if monster_id == target_id or not ([True for s in evolutions if target_id == s[0]]):
        return 0
    evo_candy_cost = evolution_costs[0]

    for evo_id, evo_form_id in evolutions:
        if evo_id == target_id:
            return evo_candy_cost
        evo_candy_cost += evolution_costs[1]

    return evo_candy_cost

# Return a boolean for whether the monster or the type is weather boosted
def is_weather_boosted(weather_id, pokemon_id=0, form_id=0, mon_type=None):
    try:
        boosted_types = is_weather_boosted.info.get(str(weather_id), {})
    except AttributeError:
        is_weather_boosted.info = {}
        file_ = get_path("data/weather_boosts.json")
        with open(file_, "r") as f:
            j = json.load(f)
            f.close()
        for w_id in j:
            is_weather_boosted.info[w_id] = j[w_id]

        boosted_types = is_weather_boosted.info.get(str(weather_id), {})

    if mon_type is None:
        types = get_base_types(pokemon_id, form_id)
        return types[0] in boosted_types or types[1] in boosted_types
    else:
        return mon_type in boosted_types

def weather_id_is_boosted(desired_status, weather_id):
    if desired_status is True and weather_id != 0 and weather_id is not None:
        return True
    if desired_status is False and (weather_id == 0 or weather_id is None):
        return True
    return False

def get_weather_emoji(weather_id):
    return {
        1: "☀",
        2: "☔",
        3: "⛅",
        4: "☁",
        5: "💨",
        6: "⛄",
        7: "🌁",
    }.get(weather_id, "")

def get_type_emoji(type_id):
    return {
        1: "⭕",
        2: "🥋",
        3: "🐦",
        4: "☠",
        5: "⛰",
        6: "💎",
        7: "🐛",
        8: "👻",
        9: "⚙",
        10: "🔥",
        11: "💧",
        12: "🍃",
        13: "⚡",
        14: "🔮",
        15: "❄",
        16: "🐲",
        17: "🌑",
        18: "💫",
    }.get(type_id, "")

def get_spawn_verified_emoji(spawn_verified_id):
    return {
        0: "❌",
        1: "✅",
    }.get(spawn_verified_id, "❔")

def get_team_emoji(team_id):
    return {
        0: "⚪",
        1: "🔵",
        2: "🔴",
        3: "🟡",
    }.get(team_id, "❔")

def get_ex_eligible_emoji(ex_eligible):
    return {
        0: "",
        1: "✉",
    }.get(ex_eligible, "")

def get_shiny_emoji(can_be_shiny):
    if can_be_shiny:
        return "✨"
    else:
        return ""

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MAPS API UTILITIES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# Returns a String link to Google Maps Pin at the location
def get_gmaps_link(lat, lng, nav=False):
    _api = "dir" if nav else "search"
    _prm = "destination" if nav else "query"
    latlng = f"{lat:5f}%2C{lng:5f}"
    return f"https://www.google.com/maps/{_api}/?api=1&{_prm}={latlng}"

# Returns a String link to Apple Maps Pin at the location
def get_applemaps_link(lat, lng, nav=False):
    _prm = "daddr" if nav else "address"
    latlng = f"{lat:5f}%2C{lng:5f}"
    return f"https://maps.apple.com/maps?{_prm}={latlng}&t=m"

# Returns a String link to Waze Maps Navigation at the location
def get_waze_link(lat, lng, nav=False):
    _nav = "yes" if nav else "no"
    latlng = f"{lat:5f}%2C{lng:5f}"
    return f"https://waze.com/ul?navigate={_nav}&ll={latlng}"

# Returns a static map url with <lat> and <lng> parameters for dynamic test
def get_gmaps_static_url(settings, api_key=None):
    if api_key is None or not parse_boolean(settings.get("enabled", "True")):
        return None
    width = settings.get("width", "250")
    height = settings.get("height", "125")
    maptype = settings.get("maptype", "roadmap")
    zoom = settings.get("zoom", "15")

    center = "<lat>%2C<lng>"
    query_center = f"center={center}"
    query_markers = f"markers=color:red%7C{center}"
    query_size = f"size={width}x{height}"
    query_zoom = f"zoom={zoom}"
    query_maptype = f"maptype={maptype}"
    query_key = f"key={api_key}"

    map_ = (
        "https://www.google.com/maps/api/staticmap?maptype=roadmap"
        f"{query_center}&{query_markers}&{query_maptype}&"
        f"{query_size}&{query_zoom}&{query_key}"
    )

    return map_

# Signs the Static Map URL using a URL signing secret
def sign_gmaps_static_url(input_url=None, secret=None):
    if input_url is None:
        log.error("Maps static url is required is to sign it")

    # If there is no signing secret, return the unsigned url
    if secret is None:
        log.debug("Signing secret is not defined. Using unsigned url.")
        return input_url

    try:
        url = urlparse.urlparse(input_url)

        # We only need to sign the path+query part of the string
        url_to_sign = f"{url.path}?{url.query}"

        # Decode the private key into its binary format
        # We need to decode the URL-encoded private key
        decoded_key = base64.urlsafe_b64decode(secret)

        # Create a signature using the private key and the URL-encoded
        # string using HMAC SHA1. This signature will be binary.
        signature = hmac.new(decoded_key, str.encode(url_to_sign), hashlib.sha1)

        # Encode the binary signature into base64 for use within a URL
        encoded_signature = base64.urlsafe_b64encode(signature.digest())

        original_url = f"{url.scheme}://{url.netloc}{url.path}?{url.query}"

        # Return signed URL
        return f"{original_url}&signature={encoded_signature.decode()}"

    except Exception as e:
        log.error("Unable to sign maps static url: %s. Using unsigned url.", e)
        log.debug("Stack trace: \n %s", traceback.format_exc())

        return input_url

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GENERAL UTILITIES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#

# Returns a cardinal direction (N/NW/W/SW, etc)
# of the pokemon from the origin point, if set
def get_cardinal_dir(pt_a, pt_b=None):
    if pt_b is None:
        return "?"

    lat1, lng1, lat2, lng2 = map(radians, [pt_b[0], pt_b[1], pt_a[0], pt_a[1]])
    directions = ["S", "SE", "E", "NE", "N", "NW", "W", "SW", "S"]
    bearing = (
        degrees(
            atan2(
                cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lng2 - lng1),
                sin(lng2 - lng1) * cos(lat2),
            )
        )
        + 450
    ) % 360
    return directions[int(round(bearing / 45))]

# Return the distance formatted correctly
def get_dist_as_str(dist, units):
    if units == "imperial":
        if dist > 1760:  # yards per mile
            return f"{dist / 1760.0:.1f}mi"
        else:
            return f"{dist:.1f}yd"
    else:  # Metric
        if dist > 1000:  # meters per km
            return f"{dist / 1000.0:.1f}km"
        else:
            return f"{dist:.1f}m"

# Returns an integer representing the distance between A and B
def get_earth_dist(pt_a, pt_b=None, units="imperial"):
    if type(pt_a) is str or pt_b is None:
        return "unkn"  # No location set
    lat_a = radians(pt_a[0])
    lng_a = radians(pt_a[1])
    lat_b = radians(pt_b[0])
    lng_b = radians(pt_b[1])
    lat_delta = lat_b - lat_a
    lng_delta = lng_b - lng_a
    a = sin(lat_delta / 2) ** 2 + cos(lat_a) * cos(lat_b) * sin(lng_delta / 2) ** 2
    c = 2 * atan2(sqrt(a), sqrt(1 - a))
    radius = 6373000  # radius of earth in meters
    if units == "imperial":
        radius = 6975175  # radius of earth in yards
    dist = c * radius
    return dist

# Return the time as a string in different formats
def get_time_as_str(t, timezone=None):
    if timezone is None:
        timezone = config.get("TIMEZONE")
    s = (t - datetime.utcnow()).total_seconds()
    (m, s) = divmod(s, 60)
    (h, m) = divmod(m, 60)
    d = timedelta(hours=h, minutes=m, seconds=s)
    if timezone is not None:
        disappear_time = datetime.now(tz=timezone) + d
    else:
        disappear_time = datetime.now() + d
    # Time remaining in minutes and seconds
    time = f"{m:.0f}m {s:.0f}s" if h == 0 else f"{h:.0f}h {m:.0f}m"
    # Disappear time in 12h format, eg "2:30:16 PM"
    time_12h = (
        disappear_time.strftime("%I:%M:%S") + disappear_time.strftime("%p").lower()
    )
    # Disappear time in 24h format including seconds, eg "14:30:16"
    time_24h = disappear_time.strftime("%H:%M:%S")

    # Get the same as above but without seconds
    time_no_sec = f"{m:.0f}m" if h == 0 else f"{h:.0f}h {m:.0f}m"
    time_12h_no_sec = (
        disappear_time.strftime("%I:%M") + disappear_time.strftime("%p").lower()
    )
    time_24h_no_sec = disappear_time.strftime("%H:%M")

    time_raw_hours = int(h)
    time_raw_minutes = int(m)
    time_raw_seconds = int(s)

    return (
        time,
        time_12h,
        time_24h,
        time_no_sec,
        time_12h_no_sec,
        time_24h_no_sec,
        time_raw_hours,
        time_raw_minutes,
        time_raw_seconds,
    )

# Return the time in seconds
def get_seconds_remaining(t, timezone=None):
    if timezone is None:
        timezone = config.get("TIMEZONE")
    seconds = (t - datetime.utcnow()).total_seconds()
    return seconds

# Return the default url for images and stuff
def get_image_url(suffix):
    return f"{not_so_secret_url}{suffix}"

# Returns the id corresponding with the weather
# (use all locales for flexibility)
def get_weather_id(weather_name):
    try:
        name = str(weather_name).lower()
        id_found = name in get_weather_id.ids
    except AttributeError:
        get_weather_id.ids = {}
        files = glob(get_path("locales/*.json"))
        for file_ in files:
            with open(file_, "r") as f:
                j = json.load(f)
                f.close()
            j = j["weather"]
            for id_ in j:
                nm = j[id_].lower()
                get_weather_id.ids[nm] = int(id_)

        id_found = name in get_weather_id.ids

    try:
        if id_found:
            return get_weather_id.ids[name]
        else:
            return int(name)  # try as an integer
    except ValueError:
        raise ValueError(
            f"Unable to interpret '{weather_name}' as a valid weather name or id."
        )

# Returns the id of the cached weather from (lat,lng)
def get_cached_weather_id_from_coord(lat, lng, cache):
    cell_id = s2cell.lat_lon_to_cell_id(lat, lng, 10)
    return cache.cell_weather_id(str(cell_id))

# Returns true if any item is in the provided list
def match_items_in_array(list, items):
    for obj in list:
        if obj in items:
            return True
    return False

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


import datetime
import re
from typing import List

from django import template
from django.conf import settings
from django.urls import reverse
from django.utils.functional import SimpleLazyObject

from magplan.models import Vote, Comment
from magplan.utils import safe_cast
from magplan.views import posts, ideas

register = template.Library()

MAX_VOTE_OPTIONS_NUMBER = len(Vote.SCORE_CHOICES)
VOTE_SCORE_STEP = 100 // (MAX_VOTE_OPTIONS_NUMBER - 1)
FAILBACK_VOTE_INDEX = 2
CSS_COLORS = (
    'danger',
    'warning',
    'light',
    'info',
    'success',
)

EMOJI_SCORES = (
    'Ъц«',
    'Ъце',
    'Ъўљ',
    'ЪўЈ',
    'ЪўЇ',
)

@register.filter(name='voted')
def voted(value, user):
    return value.voted(user)

@register.filter(name='humanize_score_index')
def humanize_score_index(index) -> str:
    if not isinstance(index, int):
        index = safe_cast(index, int, -1)

    if index == -1:  # error cast
        return Vote.SCORE_CHOICES[FAILBACK_VOTE_INDEX][1]

    score = index * VOTE_SCORE_STEP

    # Provide untrusted data
    # Underlying function will validate data
    return humanize_score(score)

@register.filter(name='humanize_score')
def humanize_score(value) -> str:
    if not isinstance(value, int):
        value = safe_cast(value, int, -1)

    if value == -1:  # error cast
        return Vote.SCORE_CHOICES[FAILBACK_VOTE_INDEX][1]

    if value % VOTE_SCORE_STEP != 0:
        return Vote.SCORE_CHOICES[FAILBACK_VOTE_INDEX][1]

    if not (0 <= value <= 100):
        return Vote.SCORE_CHOICES[FAILBACK_VOTE_INDEX][1]

    choice_index = value // VOTE_SCORE_STEP

    return Vote.SCORE_CHOICES[choice_index][1]

@register.filter(name='times')
def times(number):
    return range(number)

@register.filter(name='trim_filename')
def trim_filename(filename):
    if len(filename) > 30:
        return '%s...%s' % (
            filename[:10],
            filename[-20:]
        )
    return filename

@register.filter
def divide(value, arg):
    try:
        return int(value) / int(arg)
    except (ValueError, ZeroDivisionError):
        return None

class SetVarNode(template.Node):

    def __init__(self, var_name, var_value):
        self.var_name = var_name
        self.var_value = var_value

    def render(self, context):
        try:
            value = template.Variable(self.var_value).resolve(context)
        except template.VariableDoesNotExist:
            value = ""
        context[self.var_name] = value

        return u""

@register.tag(name='set')
def set_var(parser, token):
    """
    {% set some_var = '123' %}
    """
    parts = token.split_contents()
    if len(parts) < 4:
        raise template.TemplateSyntaxError(
            "'set' tag must be of the form: {% set <var_name> = <var_value> %}")

    return SetVarNode(parts[1], parts[3])

@register.filter
def can_be_moved_to_stage_by(post, user: SimpleLazyObject):
    return (post.stage.assignee and post.stage.assignee == user.user) or \
           (not post.stage.assignee and post.editor == user.user)

@register.filter
def sub(value, arg):
    return value - arg

@register.filter
def url_for_post_comments(post):
    return reverse(posts.comments, kwargs={
        'post_id': post.id,
    })

@register.filter
def url_for_idea_comments(idea):
    return reverse(ideas.comments, kwargs={
        'idea_id': idea.id,
    })

@register.filter
def is_overdue(date):
    return date > datetime.datetime.now()

# @register.filter
# def humazine_payment_type(payment):
#     return Payment.FORMAT_CHOICES[payment.format][1]

@register.filter
def count_human_comments(comments: List[Comment]) -> int:
    """Count comment from arrays, made by real users.

    It seems, plain iterator with incrementable counter may be faster
    as it does not produce additional map in closure.

        counter = 0
        for comment in comments:
            if comment.type != Comment.TYPE_SYSTEM:
                counter+=1
        return counter

    :param comments: Array of Comment instances
    :return: Actual comments number
    """
    return len(list(filter(lambda c: c.type != Comment.TYPE_SYSTEM, comments)))

@register.filter
def date_class(datetime_obj: datetime.datetime) -> str:
    """Return numeric representaion of provided dates, where:

    datetime_obj|f = 1 if passed
    datetime_obj|f = 2 if today
    datetime_obj|f = 0 else
    """
    # Convert 'datetime' => 'date' class for easier comparison
    date = datetime_obj.date()
    today = datetime.datetime.now().date()

    if date < today:
        return 'past'
    elif date == today:
        return 'today'
    else:
        return ''

@register.filter
def get_item(dictionary, key):
    return dictionary[key]

numeric_test = re.compile("^\d+$")

@register.filter(name='get_attr')
def get_attr(value, arg):
    """Gets an attribute of an object dynamically from a string name"""

    if hasattr(value, str(arg)):
        return getattr(value, arg)
    elif hasattr(value, 'has_key') and value.has_key(arg):
        return value[arg]
    elif numeric_test.match(str(arg)) and len(value) > int(arg):
        return value[int(arg)]
    else:
        return settings.TEMPLATE_STRING_IF_INVALID

@register.filter(name='score_css_color_by_index')
def score_css_color_by_index(index):
    if not isinstance(index, int):
        index = safe_cast(index, int, -1)

    if index == -1:  # error cast
        return CSS_COLORS[FAILBACK_VOTE_INDEX]

    if not (0 <= index <= (MAX_VOTE_OPTIONS_NUMBER - 1)):
        return CSS_COLORS[FAILBACK_VOTE_INDEX]

    return CSS_COLORS[index]

@register.filter(name='emoji_sign_by_index')
def emoji_sign_by_index(index):
    if not isinstance(index, int):
        index = safe_cast(index, int, -1)

    if index == -1:  # error cast
        return EMOJI_SCORES[FAILBACK_VOTE_INDEX]

    if not (0 <= index <= (MAX_VOTE_OPTIONS_NUMBER - 1)):
        return EMOJI_SCORES[FAILBACK_VOTE_INDEX]

    return EMOJI_SCORES[index]


from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.index, name="index"),
    url(r'^category/(?P<cat_id>[0-9]+)$', views.single_category, name="single_cat"),
    url(r'^(?P<books_id>[0-9]+)$', views.book, name="book"),
    url(r'^cat', views.category, name="category"),
    url(r'^login', views.login, name="login"),
]


class HtmlResult:

	blocks = []
	html = ""

	def __init__(self):
		with open("example.html",'r') as f:
			self.html = f.read()

	def make_one_block(self, fio: str, link_to: str, picture_links: list):
		photos = []

		for link in picture_links:
			photos.append(f"""

			""")

		string = ""
		for a in photos:
			string += a

		block = f"""

						{fio} (≈{len(picture_links)})

					{string}

			"""
		self.blocks.append(block)

	def result(self):

		n = self.html.find("
") + 5

		new = ""
		for block in self.blocks:
			new += block

		self.html = self.html[:n] + new + self.html[n:]
		return self.html


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

from testcase import TestCase

class TestHereDoc(TestCase):

    def test_one_heredoc0(self):
        self._test("""
print(<<EOF)
42
EOF
""", """42
""")

    def test_one_heredoc10(self):
        self._test("""
print(<<EOF)
EOFfoo
EOF
""", """EOFfoo
""")

    def test_two_heredoc0(self):
        self._test("""
print(<<EOF1, <<EOF2)
42
EOF1
26
EOF2
""", """42
26
""")

    def test_error0(self):
        def test_stderr(stderr):
            self._test_regexp("SyntaxError: File \"[^\"]+\", line 2: EOF while scanning heredoc\n", stderr)

        self._test("""
print(<<EOF)
""", stderr=test_stderr)

    def test_with_conditional_expr0(self):
        self._test("""
print(true ? <<EOF : <<EOF)
foo
EOF
bar
EOF
""", """foo
""")

# vim: tabstop=4 shiftwidth=4 expandtab softtabstop=4


class HttpResponseBase(object):
    status_code = 200

    def __init__(self, content_type=None, status=None, reason=None, charset=None):
        pass

class HttpResponse(HttpResponseBase):
    def __init__(self, content=b"", *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Content is a bytestring. See the `content` property methods.
        self.content = content

class HttpResponseRedirectBase(HttpResponse):
    def __init__(self, redirect_to, *args, **kwargs):
        super().__init__(*args, **kwargs)
        ...

class HttpResponsePermanentRedirect(HttpResponseRedirectBase):
    status_code = 301

class HttpResponseRedirect(HttpResponseRedirectBase):
    status_code = 302

class HttpResponseNotFound(HttpResponse):
    status_code = 404

class JsonResponse(HttpResponse):

    def __init__(
        self,
        data,
        encoder=...,
        safe=True,
        json_dumps_params=None,
        **kwargs
    ):
        # fake code to represent what is going on :)
        kwargs.setdefault("content_type", "application/json")
        data = str(data)
        super().__init__(content=data, **kwargs)


import json

from db.RepositoryExternal import RepositoryExternal

def get_ranking(event, context) -> json:
    int_position = 0
    int_size = 10
    if 'queryStringParameters' in event and event['queryStringParameters'] is not None:
        query_string_parameters = event['queryStringParameters']

        # check if key are presents
        if 'from' in query_string_parameters:
            position = query_string_parameters['from']
            int_position = int(position)

        if 'size' in query_string_parameters:
            size = query_string_parameters['size']
            int_size = int(size)

    print("get_ranking: " + str(int_position) + " " + str(int_size))

    repo_ext = RepositoryExternal()
    list_restaurants = repo_ext.get_ranking(int_position, int_size)

    response = {
        'statusCode': 200,
        'headers': {
            'Access-Control-Allow-Headers': 'Content-Type',
            'Access-Control-Allow-Credentials': 'true',
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Methods': 'OPTIONS,POST,GET'
        },
        "body": json.dumps(list_restaurants)
    }

    return response


from iota import *
import json
import requests

def get_tld_content(tld_name):
    IOTA_config()
    tld_name = "ALP"+tld_name.upper()

    print("Get the TAG for this TLD name.")

    hashes_list = api.find_transactions(tags=[tld_name])

    print("Get the Transaction Hash List for this TLD name.")
    print(hashes_list)

    count = 0
    trytes_length = []
    trytes_list = []
    if hashes_list['hashes']:
        for n in hashes_list['hashes']:

            print("Get the TLD name Trytes from Tangle")

            tld_content_trytes = api.get_trytes(hashes_list['hashes'])['trytes'][count]

            print(tld_content_trytes)

            trytes_length.append(len(str(tld_content_trytes).split('999')[0]))
            trytes_list.append(tld_content_trytes)
            count+=1
        latest = trytes_length.index(max(trytes_length))

        print("Get the currect Transaction Hash for this TLD name.")
        print(hashes_list['hashes'][latest])

        tld_content_string = Transaction.from_tryte_string(trytes_list[latest]).signature_message_fragment.decode('ignore')

        print("Convert the content from Trytes to String.")
        print(tld_content_string)

        tld_content_dict = json.loads(tld_content_string)
        tld_content_hash = hashes_list['hashes'][latest]
        return [tld_content_dict,tld_content_hash]
    else:

        return "Not Found !"

def IOTA_config():
    global api
    url = 'https://node1.puyuma.org:443'
    api = Iota(url)

def get_domain_root(tld_name,domain_name):
    tld_content_dict = get_tld_content(tld_name)
    if tld_content_dict == "Not Found !":
        return "Not Found"
    else:
        if tld_content_dict[0]['TLD_Content']['Domain_list'][domain_name]:
            mam_root = tld_content_dict[0]['TLD_Content']['Domain_list'][domain_name]
            return mam_root
        else:
            return "Not Found"

def get_domain_content(domain_root):
    data = domain_root
    headers = {'Content-Type': 'text/plain'}
    domain_content = requests.post("http://localhost:3000/search", data=data, headers=headers)
    return domain_content.text

def find_domain(url):
    IOTA_config()
    tld_name = url.split('.')[-1]
    domain_name = url.split('.')[-2]
    domain_root = get_domain_root(tld_name, domain_name)
    domian_content = get_domain_content(domain_root)
    return [domian_content,domain_root]


import numpy as np
import cv2
from keras.models import load_model
import csv

width, height = 28, 28

model = load_model('mnist_cnn.model')

image = cv2.imread('test/img_1.jpg')

def img_process(image):
    image = cv2.resize(image, (width, height))
    img = np.array(image).reshape((width, height, 3))
    img = np.expand_dims(img, axis = 0)
    return img

def prediction(img):
    prediction = model.predict(img)[0]
    for i in range(10):
        if(prediction[i] == 1):
            return i

print(prediction(img_process(image)))


from flask import Flask, jsonify,send_file
from flask_cors import CORS
from compressImage import compressImage
import json
# configuration
DEBUG = True

# instantiate the app
app = Flask(__name__)
app.config.from_object(__name__)

# enable CORS
CORS(app, resources={r'/*': {'origins': '*'}})

# sanity check route
@app.route('/compress', methods=['GET','POST'])
def ping_pong():
    f = open('../vue/Data/image.json')
    data1 = json.load(f)
    base = data1["image"][0]['base64']
    percentage = data1["image"][0]['percentage']
    percentage = int(percentage)
    namaFile = data1["image"][0]['namaFile']
    base2 = base.split(',', 1)[1]
    imageExt = compressImage(base2,percentage,namaFile)
    print(imageExt)
    return send_file('../vue/src/assets/test' + imageExt) #jsonify('abc')
if __name__ == '__main__':
    app.run()


from time import sleep

from appium import webdriver

# server 启动参数
from appium.webdriver.common.touch_action import TouchAction

desired_caps = {}
# 设备信息
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '5.1'
desired_caps['deviceName'] = '192.168.56.101:5555'
# 输入中文
desired_caps['unicodeKeyboard'] = True
desired_caps['resetKeyboard'] = True
# app的信息
desired_caps['appPackage'] = 'com.android.settings'
desired_caps['appActivity'] = '.Settings'

# 声明我们的driver对象
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)

"""
    目标：模拟音量键
    需求：
        1. 减三次音量缩小键，每减1次暂停1秒
        2. 增三次音量增大键，每增1次暂停1秒

    提示：
        1. 24为增加音量键码
        2. 25为：减少音量键码
        3. 方法：keyevent()

"""
# 减少 3此音量键
for i in range(6):
    print("i:",i)
    sleep(1)
    driver.keyevent(25)
    sleep(1)
    driver.keyevent(24)

# # 增加 3此音量键
# for y in range(4):
#     sleep(1)
#     print("y:",y)
#     driver.keyevent(24)

sleep(10)
driver.quit()


#!/usr/bin/env python3

import numpy as np
import rospy
from sensor_msgs.msg import Imu
from geometry_msgs.msg import TwistWithCovarianceStamped, PoseWithCovarianceStamped
from utils import ros_q2np_q, ros_xyz2np_array
import csv
import argparse
from constants import XYZW
from utils import ros_obj2np
import tf

parser = argparse.ArgumentParser()
parser.add_argument('--filename', type=str, default='imu.csv')
parser.add_argument('--msg_cls', type=str, default='Imu')
parser.add_argument('--topic', type=str, default='/ekf/input/imu')

class CSVWriter:

    fieldnames = []

    def __init__(self, filename, topic, cls) -> None:
        self._f = open(filename, 'w')
        self._writer = csv.DictWriter(self._f, self.fieldnames)
        self._writer.writeheader()
        rospy.Subscriber(topic, cls, self._on_msg, queue_size=1000)

    def __del__(self):
        self._f.close()

    def _preprocess(self, msg, *args, **kwargs):
        return msg

    def _datarow(self, msg, *args, **kwargs):
        return []

    def _on_msg(self, msg):
        msg = self._preprocess(msg)
        datarow = self._datarow(msg)
        dictrow = {k:v for k, v in zip(self.fieldnames, datarow)}
        self._writer.writerow(dictrow)

class IMUCSVWriter(CSVWriter):

    fieldnames = [
                    'timestamp',
                    'quaternion_x',
                    'quaternion_y',
                    'quaternion_z',
                    'quaternion_w',
                    'acceleration_x',
                    'acceleration_y',
                    'acceleration_z',
                    'gyroscope_x',
                    'gyroscope_y',
                    'gyroscope_z'
    ]

    def _datarow(self, msg, *args, **kwargs):
        t = msg.header.stamp.to_sec()
        q = ros_q2np_q(msg.orientation)
        acc = ros_xyz2np_array(msg.linear_acceleration)
        gyro = ros_xyz2np_array(msg.angular_velocity)
        return [t, *q, *acc, *gyro]

class IMURPYCSVWriter(CSVWriter):
    fieldnames = [
                'timestamp',
                'roll',
                'pitch',
                'yaw',
                'acceleration_x',
                'acceleration_y',
                'acceleration_z',
                'gyroscope_x',
                'gyroscope_y',
                'gyroscope_z'
    ]

    def _datarow(self, msg, *args, **kwargs):
        q = ros_obj2np(msg.orientation, XYZW)
        acc = ros_obj2np(msg.linear_acceleration)
        gyro = ros_obj2np(msg.angular_velocity)
        rpy = tf.transformations.euler_from_quaternion(q)
        return [msg.header.stamp.to_sec(), *rpy, *acc, *gyro]

class TWISTCSVWriter(CSVWriter):

    fieldnames = [
        'timestamp',
        'linear_x',
        'linear_y',
        'linear_z',
        'angular_x',
        'angular_y',
        'angular_z'
    ]

    def _datarow(self, msg, *args, **kwargs):
        twist_linear = ros_obj2np(msg.twist.twist.linear)
        twist_angular = ros_obj2np(msg.twist.twist.angular)
        return [msg.header.stamp.to_sec(), *twist_linear, *twist_angular]

if __name__ == "__main__":
    rospy.init_node('csv_maker')
    args = parser.parse_args()
    filename = args.filename
    topic = args.topic
    msg_cls_str = args.msg_cls
    msg_cls = eval(msg_cls_str)

    if msg_cls is Imu:
        writer_cls = IMURPYCSVWriter
    elif msg_cls is TwistWithCovarianceStamped:
        writer_cls = TWISTCSVWriter
    else:
        raise ValueError(f"Unknown class: {msg_cls}")

    writer = writer_cls(filename, topic, msg_cls)

    rospy.spin()


import sys
import subprocess
host = '127.0.0.1:27020'
dbUser='rootNinja'
dbName='test_624'
collectionName='Group'
fileName='group.json'
def main(args):
    with open(args[1], "r") as f:
        section=f.read().split('"links": [')
        group=section[0][:-8]
        group=group.split('\n',2)[2]
        group='[\n'+group+'\n]'
        with open(fileName, "w") as j:
            j.write(group)
    subprocess.Popen(['mongoimport',
                    '--host', host,
                    '-u', dbUser,
                    '-p', args[2],
                    '--authenticationDatabase','admin',
                    '--db', dbName,
                    '--collection', collectionName,
                    '--file' ,fileName ,
                    '--jsonArray'])

if __name__ == "__main__":
    main(sys.argv)


#!/usr/bin/env python3

import sys
from nltk.tree import Tree

def sort_nps():
    with open(sys.argv[1]) as np_doc:
        for line in np_doc:
            np = Tree.fromstring(line)
            print(np.height(), line, end ="")

sort_nps()


def solve(sena):
    if 'R' not in sena or 'D' not in sena:
        return sena
    new_sena = []
    silent_r = 0
    silent_d = 0
    for i in range(len(sena)):
        if sena[i] == 'R':
            if silent_r == 0:
                silent_d += 1
                new_sena.append(sena[i])
            else:
                silent_r -= 1
        elif sena[i] == 'D':
            if silent_d == 0:
                silent_r += 1
                new_sena.append(sena[i])
            else:
                silent_d -= 1
    if silent_d != 0 or silent_r != 0:
        for i in range(len(new_sena)):
            if silent_d > 0 and 'D' in new_sena:
                new_sena.remove('D')
                silent_d -= 1
            elif silent_r > 0 and 'R' in new_sena:
                new_sena.remove('R')
                silent_r -= 1
            else:
                break
    return solve(new_sena)

dota_str = input()
x = solve(dota_str)
if x[-1] == 'R':
    print('Radiant')
else:
    print('Dire')


import numpy as np;
from numpy import random;
import matplotlib.pyplot as plt;

results = np.zeros(1000);

def head_100():
	result = random.randint(0,2,100).sum();
	return result;

def mu():
	global results;
	return results.sum()/len(results);

def sigma():
	global results;
	mean = mu();
	sq_dif = (results-mean)**2;
	var = sq_dif.sum()/len(results);
	return var**(0.5);

def gaus():
	mean = mu();
	si = sigma();
	x = np.linspace(0,100,1000);
	val = 1/si/(2*np.pi)**(0.5)*np.exp(-(x-mean)**2/2/si**2);
	return x, val;

f, ax = plt.subplots();
for i in range(1000):
	results[i] = head_100();

ax.hist(results, bins = np.arange(0, 102), density = True, label = "Coin Toss Hist");
ax.plot(*gaus(), color = "red", label = "Gaussian distribution");
ax.set(title = "Coin toss simulation", xlabel = "Number of heads", ylabel = "Probability");
ax.legend();
f.savefig("/home/zky/zhou_5993043_homework/zhou_5993043_hw6/p4_hw6.eps", format = "eps");
plt.show()


# exception handling or error handling
# a = input("Num1: ")
# b = input("Num2: ")

# try and finally always execute
# if error is occurs then except will execute otherwise else will execute
tup = 3, 6, 9
try:
    # print("before add")
    # print("The sum is:", int(a) + int(b))
    # print("after add")
    tup.insert(0, 3)
    # tup[21]

except IndexError as f:
    print("Index error found")

except AttributeError:
    print("Attribute Error found")

else:
    print("No error occurs")

finally:
    print("addition ends")

#************************************************************
# a = input("Num1: ")
# b = input("Num2: ")
#
# try:
#      print("before add")
#      print("The sum is:", int(a) + int(b))
#      print("after add")
#
# except:
#     print("i am except")
#
# else:
#     print("i'am else")
#
# finally:
#     print("i am finally")
num1 = input("please enter your 1st no.")
num2 = input("please enter your 2nd no. ")

try:
    print(f"the sum of the two number s : {int(num1)+int(num2)}")

except Exception:
    print(num1)
else:
    print("your successfully add two no.s ")

finally:
    print("Hello World !")


import random
import string

from sycamore.data import Document, Element
from sycamore.llms import LLM
from sycamore.transforms.summarize import LLMElementTextSummarizer

class TestSummarize:
    def test_summarize_text_does_not_call_llm(self, mocker):
        llm = mocker.Mock(spec=LLM)
        doc = Document()
        element1 = Element()
        element1.text_representation = "".join(random.choices(string.ascii_letters, k=10))
        doc.elements = [element1]

        text_summarizer = LLMElementTextSummarizer(llm, filter_elements_on_length)
        doc = text_summarizer.summarize(doc)

        assert doc.elements[0].properties == {}

    def test_summarize_text_calls_llm(self, mocker):
        llm = mocker.Mock(spec=LLM)
        generate = mocker.patch.object(llm, "generate")
        generate.return_value = {"summary": "summary"}
        doc = Document()
        element1 = Element()
        element1.text_representation = "".join(random.choices(string.ascii_letters, k=10))
        element2 = Element()
        element2.text_representation = "".join(random.choices(string.ascii_letters, k=20))
        doc.elements = [element1, element2]

        text_summarizer = LLMElementTextSummarizer(llm, filter_elements_on_length)
        doc = text_summarizer.summarize(doc)

        assert doc.elements[0].properties == {}
        assert doc.elements[1].properties == {"summary": "summary"}

def filter_elements_on_length(element: Element) -> bool:
    return False if element.text_representation is None else len(element.text_representation) > 10


import os
import numpy as np
from scipy.sparse import coo_matrix, diags
import torch
from torch import nn
from torch_geometric.data import Data, DataLoader
from torch_geometric.nn import GCNConv, SAGEConv
from torch_geometric.transforms import AddSelfLoops
from torch_sparse import SparseTensor

# device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

def load_data(path, unknowns, cfl):

    print('##############################################################')
    print('n: ',unknowns)

    # Get the directory of the current file
    current_dir = f'C:/Users/soha9/Documents/python/neuralif/neuralif_advection/data/{path}/'

    # Load the data
    A_matrix_path = os.path.join(current_dir, f'A_ex9_{unknowns}_{cfl}.txt')
    u_vector_path = os.path.join(current_dir, f'u_ex9_{unknowns}_{cfl}.txt')

    A_info = np.loadtxt(A_matrix_path)
    u = (np.reshape(np.loadtxt(u_vector_path), (-1,1))).astype(np.float64)

    # Extract the row, column, and value arrays from the data
    row_A = (A_info[:, 0].astype(int)) - 1
    col_A = (A_info[:, 1].astype(int)) - 1
    val_A = A_info[:, 2]

    # Create the sparse matrix using COO format
    A = coo_matrix((val_A, (row_A, col_A)))
    num_nodes = A.shape[0]

#     print(A.shape)
#     print(u.shape)

    #u = np.random.rand(num_nodes, 1).astype(np.float32)
    b = A.dot(u)

    A_coo_precon = A
    b_precon = b
    u_precon = u

    # calculate the inverse of the square root of D
    D = (A.diagonal()).astype(np.float64)
    D_inv_sqrt = diags(1 / np.sqrt(D), dtype=np.float64)

    # pre-multiply A and b by D_inv_sqrt using the dot method
    A_normalized = coo_matrix(D_inv_sqrt.dot(A))
    b_normalized = (D_inv_sqrt.dot(b))

    A = A_normalized
    b = b_normalized

    # Convert A to PyTorch SparseTensor
    indices = torch.from_numpy(np.vstack((A.row, A.col))).long()
    values = torch.from_numpy(A.data)
    shape = torch.Size(A.shape)

    A = torch.sparse.FloatTensor(indices, values, shape)
    u = torch.reshape(torch.from_numpy(u), [-1,1])
    b = torch.reshape(torch.from_numpy(b), [-1,1])

    A = torch.tensor(A, dtype=torch.float64)
    u = torch.tensor(u, dtype=torch.float64)
    b = torch.tensor(b, dtype = torch.float64)

    print('A shape: ', A.shape)
    print('b shape: ', b.shape)
    print('u shape: ', u.shape)

    residual = torch.sum(torch.abs(torch.matmul(A, u) - b))
    print(f'Residual error |Ax-b|: {residual}')

    return A, u, b, A_normalized, b_normalized


from scipy.io import loadmat
import pandas as pd
import argparse
import os

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="This programs creates a macrocomplex given the pair of interactions.")
    parser.add_argument('-i', '--input',
                        dest="input",
                        action="store",
                        required=True,
                        help="The input folder containing the complexes files")
    parser.add_argument('-o', '--output',
                        dest="output",
                        action="store",
                        default=".output/",
                        help="The output file")

    options = parser.parse_args()

    if os.path.isfile(os.path.abspath(options.input)):
        cells_physicell = loadmat(os.path.abspath(options.input))
        data = pd.DataFrame(cells_physicell['cells'])
        data = data.transpose()
        data.to_csv("./output/%s.csv" %os.path.splitext(os.path.basename(os.path.abspath(options.input)))[0])
    else:
        pass


"""fish

Revision ID: 8ba5678b7708
Revises: 4733d7261b6f
Create Date: 2020-10-22 21:28:31.568920

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '8ba5678b7708'
down_revision = '4733d7261b6f'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('result_cache', sa.Column('cache_time', sa.DateTime(), nullable=True))
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column('result_cache', 'cache_time')
    # ### end Alembic commands ###


import subprocess32
from swcFuncs import transSWC
from asciiFuncs import readASCII_numpy
from asciiSWCConverters import ascii2swc, swc2ascii
import tempfile
import os
import shutil
import numpy as np
import pandas as pd

def getTransformFromRICPOut(outStr, marker):

    outSplit = outStr.splitlines()
    markerInd = outSplit.index(marker)
    minR = np.loadtxt(outSplit[markerInd + 5: markerInd + 8])
    minA = np.loadtxt(outSplit[markerInd + 9: markerInd + 12])
    minT = np.loadtxt(outSplit[markerInd + 13: markerInd + 16]).reshape((3, ))
    minFRE = float(outSplit[markerInd + 17])
    return minR, minA, minT, minFRE

def runRICPCPP(testASCII, refASCII, tempDir, initTrans=None, logFile=None, timeout=240):

    filePath = os.path.split(__file__)[0]
    old_cwd = os.getcwd()
    os.chdir(tempDir)

    try:

        if initTrans is None:
            initTransStr = 'No init specified'
            out = subprocess32.check_output([os.path.join(filePath, 'bin', 'ASICP_MD_ANN'),
                                             testASCII,
                                             refASCII,
                                             ],
                                            stderr=subprocess32.STDOUT, timeout=timeout)
        else:
            with open(initTrans) as fle:
                initTransStr = fle.read()
            out = subprocess32.check_output([os.path.join(filePath, 'bin', 'ASICP_MD_ANN'),
                                           testASCII,
                                           refASCII,
                                           initTrans
                                           ],
                                          stderr=subprocess32.STDOUT, timeout=timeout)

        minR, minA, minT, minFRE = getTransformFromRICPOut(out, 'Final answer: 3 3')
        print('Finished with a minFRE of {}'.format(minFRE))

    except subprocess32.TimeoutExpired:

        minR = minA = minT = None
        minFRE = np.inf

        out = 'Did not finish even after {} seconds'.format(timeout)
        print(out)

    out = 'Using following Inittrans:\n' + initTransStr + '\n' + out
    os.chdir(old_cwd)
    if logFile:
        with open(logFile, 'w') as fle:
            fle.write(out)

    return minR, minA, minT, minFRE

class InitTransGen:

    def __init__(self, refFile, testFile):

        self.refFile = refFile
        self.testFile = testFile
        self.refData = readASCII_numpy(refFile)
        self.refStd = self.refData.std(axis=0)
        self.testData = readASCII_numpy(testFile)
        meanDiff = self.refData.mean(axis=0) - self.testData.mean(axis=0)
        self.firstTrans = np.eye(4)
        self.firstTrans[:3, 3] = meanDiff
        self.count = -1

    def __iter__(self):

        self.count = -1

    def next(self):

        self.count += 1

        if self.count == 0:

            return None
        elif self.count == 1:
            return self.firstTrans

        else:
            tmp = self.firstTrans.copy()
            tmp[:3, 3] += 3 * self.refStd * np.random.rand(3)
            return tmp

def runRICP(refInFile, testInFile, outFile, deleteTempFiles=True, maxTries=10):
    tempDir = tempfile.mkdtemp(dir=os.getcwd())
    inAsciiFiles = []
    inSWCFiles = []
    for inFle in [refInFile, testInFile]:
        if inFle.endswith('.swc'):
            thrash, tempFile = tempfile.mkstemp(dir=tempDir, suffix='.ascii')
            swc2ascii(inFle, tempFile)
            inSWCFiles.append(inFle)
            inAsciiFiles.append(tempFile)
        elif inFle.endswith('.ascii'):
            thrash, tempFile = tempfile.mkstemp(dir=tempDir, suffix='.swc')
            inAsciiFiles.append(inFle)
            ascii2swc(inFle, tempFile)
            inSWCFiles.append(tempFile)
        else:
            raise(IOError('Unsupported file format for %s. Supported formats are ascii and swc,' % inFle))

    [refAsciiFile, testAsciiFile] = inAsciiFiles
    [refSWCFile, testSWCFile] = inSWCFiles

    initTransGen = InitTransGen(refFile=refAsciiFile, testFile=testAsciiFile)

    allRes = []
    allResSuccess = []

    for iterNo in range(maxTries):

        print('Trial number {}'.format(iterNo))
        initTrans = initTransGen.next()

        if initTrans is None:
            initTransFile = None
        else:
            thrash, initTransFile = tempfile.mkstemp(dir=tempDir, suffix='.ascii')

            np.savetxt(initTransFile, initTrans)

        minR, minA, minT, minFRE = runRICPCPP(testAsciiFile, refAsciiFile, tempDir, initTransFile,
                                      '{}_try{}.log'.format(outFile, iterNo + 1))

        if all([x is not None for x in [minR, minA, minT, minFRE]]):
            allResSuccess.append(True)
        else:
            allResSuccess.append(False)

        allRes.append((minR, minA, minT, minFRE))

    print('The minFRES:\n{}'.format([x[3] for x in allRes]))

    if any(allResSuccess):
        bestInd = np.argmin([x[3] for x in allRes])
        print('Choosing index {}'.format(bestInd))
        (bestMinR, bestMinA, bestMinT, bestMinFRE) = allRes[bestInd]
        transSWC(testSWCFile, np.dot(bestMinR, bestMinA), bestMinT, outFile)
    else:
        print('No solutions found for {} number of trials'.format(maxTries))

    if deleteTempFiles:
        shutil.rmtree(tempDir)
    else:
        print('TempFiles in %s not deleted' % tempDir)


class Solution(object):
    def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
            """
        if root is None:
            return []

        stack = [root]
        nums = []

        while len(stack) > 0:
            tem = []
            tem_num = []
            for node in stack:
                tem_num.append(node.val)
                if node.left:
                    tem.append(node.left)
                if node.right:
                    tem.append(node.right)
            nums.append(tem_num)
            stack = tem
        return nums

剑指offer/剑指 Offer 32 - II. 从上到下打印二叉树 II.py


import random

from PIL import Image
import cv2
import blobfile as bf

import numpy as np
from torch.utils.data import DataLoader, Dataset
from einops import rearrange, repeat
from torchvision import transforms as T
import torch as th

def load_data(
    *,
    data_dir,
    frame_num,
    batch_size,
    image_size,
    class_cond=False,
    order_cond=False,
    deterministic=False,
    random_crop=False,
    random_flip=True,
    num_workers=0,
    frame_gap=8

):
    """
    For a dataset, create a generator over (images, kwargs) pairs.

    Each images is an NCHW float tensor, and the kwargs dict contains zero or
    more keys, each of which map to a batched Tensor of their own.
    The kwargs dict can be used for class labels, in which case the key is "y"
    and the values are integer tensors of class labels.

    :param data_dir: a dataset directory.
    :param batch_size: the batch size of each returned pair.
    :param image_size: the size to which images are resized.
    :param class_cond: if True, include a "y" key in returned dicts for class
                       label. If classes are not available and this is true, an
                       exception will be raised.
    :param deterministic: if True, yield results in a deterministic order.
    :param random_crop: if True, randomly crop the images for augmentation.
    :param random_flip: if True, randomly flip the images for augmentation.
    """
    if not data_dir:
        raise ValueError("unspecified data directory")
    data_dir_splits = data_dir.split(',')

    all_files = []
    for data_dir_split in data_dir_splits:
        all_files.extend(_list_video_files_recursively(data_dir_split))

    print(f"len(data loader):{len(all_files)}")
    classes = None
    if class_cond:
        # Assume classes are the first part of the filename,
        # before an underscore.
        class_names = [path.split("/")[-2] for path in all_files]
        class_labels = set(class_names)
        sorted_classes = {x: i for i, x in enumerate(sorted(class_labels))}
        classes = [sorted_classes[x] for x in class_names]

        print(f"len(data loader classes):{len(class_labels)}")

    dataset = VideoDataset(
        all_files,
        image_size,
        frame_num,
        classes=classes,
        shard=0,
        num_shards=1,
        random_crop=random_crop,
        random_flip=random_flip,
        frame_gap = frame_gap,
        order_cond = order_cond
    )

    # train_sampler = torch.utils.data.distributed.DistributedSampler(dataset)
    if deterministic:
        loader = DataLoader(
            dataset, batch_size=batch_size, shuffle=False, num_workers=num_workers, drop_last=True
        )
    else:
        loader = DataLoader(
            dataset, batch_size=batch_size, shuffle=True,  num_workers=num_workers, drop_last=True
        )

    while True:
        yield from loader

def _list_video_files_recursively(data_dir):
    results = []
    for entry in sorted(bf.listdir(data_dir)):
        full_path = bf.join(data_dir, entry)
        ext = entry.split(".")[-1]
        if "." in entry and ext.lower() in ["avi", "gif", "mp4","png"]:

            results.append(full_path)
        elif bf.isdir(full_path):

            results.extend(_list_video_files_recursively(full_path))
    return results

class VideoDataset(Dataset):
    def __init__(
        self,
        video_paths,
        resolution,
        frame_num,
        classes=None,
        shard=0,
        num_shards=1,
        random_crop=False,
        random_flip=False,
        frame_gap=8,
        order_cond=False
    ):
        super().__init__()
        self.resolution = resolution
        self.local_videos = video_paths[shard:][::num_shards]
        self.local_classes = None if classes is None else classes[shard:][::num_shards]
        self.random_crop = random_crop
        self.random_flip = random_flip
        self.frame_num = frame_num
        self.frame_gap = frame_gap
        self.order_cond = order_cond

    def __len__(self):
        return len(self.local_videos)

    def resize_img(self, img):# size:64:64
        '''
        resize img to target_size with padding
        '''

        old_size = img.size
        ratio = min(float(self.resolution)/(old_size[i]) for i in range(len(old_size)))
        new_size = tuple([int(i*ratio) for i in old_size])

        img = img.resize((new_size[1], new_size[0]),Image.BICUBIC) #cv2.resize(img,(new_size[1], new_size[0]))
        img = np.array(img)
        pad_w = self.resolution - new_size[1]
        pad_h = self.resolution- new_size[0]
        top,bottom = pad_h//2, pad_h-(pad_h//2)
        left,right = pad_w//2, pad_w -(pad_w//2)
        img_new = cv2.copyMakeBorder(img,top,bottom,left,right,cv2.BORDER_CONSTANT,None,(0,0,0))
        return img_new

    def _get_gif(self, path):
        with bf.BlobFile(path, "rb") as f:
            pil_images = Image.open(f)
            pil_images = list(map(self.resize_img, seek_all_images(pil_images, channels = 3)))
        return pil_images

    def _get_vid(self, path):
        cap = cv2.VideoCapture(path)
        frames = []
        count = 0
        while cap.isOpened():
            ret, frame = cap.read()
            if ret == False:
                break

            img =Image.fromarray(cv2.cvtColor(frame,cv2.COLOR_BGR2RGB))
            frames.append(self.resize_img(img))
            count+=1
        return frames

    def __getitem__(self, idx):
        path = self.local_videos[idx]
        # load gif
        post_fix=path.split('.')[-1]
        if post_fix == 'gif':
            video = th.tensor(np.array(self._get_gif(path)))
        elif post_fix in ['avi', 'mp4']:
            video = th.tensor(np.array(self._get_vid(path)))
        elif post_fix in ['png']:
            video = th.tensor(np.array(Image.open(path).convert('RGB'))) # H,W,C
            f_num = video.shape[0] // self.resolution
            video = rearrange(video, "(f1 h) (f2 w) c -> (f1 f2) h w c", f1=f_num, f2=f_num)

        video= video.permute([0,3,1,2])#[B,C,H,W]

        if len(video) < self.frame_num:
            append = self.frame_num - len(video)
            video = th.cat([video, video[-1:].repeat(append,1,1,1)],dim=0)
        elif  len(video) >= self.frame_num and len(video) <=  self.frame_num * self.frame_gap:
            indices = np.linspace(0, len(video)-1, self.frame_num)
            video = th.stack([video[int(indice)] for indice in indices], dim=0)
        else:
            start = random.randint(0, len(video) - self.frame_num * self.frame_gap - 1)
            video = video[start : start + self.frame_num * self.frame_gap : self.frame_gap]

        video_after_process = video#.float() / 127.5 - 1 #0-1

        return video_after_process

def seek_all_images(img, channels = 3):

    i = 0
    while True:
        try:
            img.seek(i)
            yield img.convert("RGB")
        except EOFError:
            break
        i += 1

def load_data_for_worker(base_samples, image_size, frame_num, frame_gap=1, class_cond=False, batch_size=1):
    if base_samples.endswith('npz'):
        with bf.BlobFile(base_samples, "rb") as f:
            obj = np.load(f)
            image_arr = obj["arr_0"]
            if class_cond:
                label_arr = obj["arr_1"]

        while True:
            for i in range(len(image_arr)):
                video= image_arr[i]
                #b,f,h,w,c->b,f
                yield video
    else:

        dataset = load_data(
            data_dir=base_samples,
            batch_size=batch_size,
            frame_num=frame_num,
            image_size=image_size,
            class_cond=class_cond,
            num_workers=4,
            frame_gap=frame_gap,
            deterministic=True
        )

        for batchdata in dataset:
            # import pdb; pdb.set_trace()
            batchdata= batchdata.permute(0, 1, 3, 4, 2)#.astype('uint8')  #[batchsize, frame, W, H, C]
            if batchdata.shape[1] < 16:
                batchdata =th.cat([batchdata, batchdata[:,-1:,].repeat(1,8,1,1,1)], dim=1)

                # video = th.cat([video, video[-1:].repeat(append,1,1,1)],dim=0)
            yield batchdata


import flask
from flask import request, jsonify
from flask_cors import CORS
app = flask.Flask(__name__)
cors = CORS(app)
measurements = [
    {
        "city": "El Paso",
        "coordinates": {"latitude": 31.7656, "longitude": -106.455},
        "country": "US",
        "date":
            {"utc": "2020-12-01T15:00:00Z", "local": "2020-12-01T08:00:00-07:00"},
        "location": "Chamizal C41",
        "parameter": "o3",
        "unit": "ppm",
        "value": 0.01
    }
]

@app.route('/api/v1/measurements', methods=['POST'])
def add_measurement():
    print("request is" + str(request.json), flush=True)
    if not request.json or not 'city' in request.json:
        flask.abort(400)
    measurement = {
        "city": request.json['city'],
        "coordinates": request.json['coordinates'],
        "country": request.json['country'],
        "date": request.json['date'],
        "location": request.json['location'],
        "parameter": request.json['parameter'],
        "unit": request.json['unit'],
        "value": request.json['value']
    }
    print("Created measurement", flush=True);
    measurements.append(measurement)
    print(measurements, flush=True)
    return jsonify(measurement), 201

@app.route('/api/v1/measurements/<string:city_name>', methods=['GET'])
def get_city_measurements(city_name):
    city_measurements = []
    print("Got into city_measurements", flush=True)
    for m in measurements:
        if m['city'] == city_name:
            print("Found city" + city_name,flush=True)
            city_measurements.append(m)
    return jsonify(city_measurements), 201

if __name__ == '__main__':
    app.run(host='localhost', port=5050, debug=True)


from django.contrib import admin

from . models import Product, Cash, Order, Setting

from django.contrib.admin import SimpleListFilter

admin.site.site_header = "Powerfix Administration"
admin.site.site_title = "Powerfix Administration"

class SettingAdmin(admin.ModelAdmin):

    list_display=(
        'key',
        'value'
    )

#custom Filter for ProductAdmin
class LowStockFilter(SimpleListFilter):

    title = 'Available Stocks'
    parameter_name = 'stock_available'

    def lookups(self, request, model_admin):

        return(
            ('low', 'Low Stock'),
            ('high', 'High Stock' )
        )

    def queryset(self, request, queryset):

        if self.value() == 'low':
            return queryset.filter(stock__lte=F('minimum_stock'))
        if self.value() == 'high':
            return queryset.filter(stock__gte=F('minimum_stock'))

class ProductAdmin(admin.ModelAdmin):
    actions = ['delete_selected']

    list_display = (
        'name',
        'description',
        'code',
        'price',
        'stock',
        'minimum_stock',
        'stock_applies'
    )

    list_display_links = (
        'code',
        'name',
    )

    search_fields = (
        'code',
        'name'

    )

    list_filter = (
        LowStockFilter,
    )

def safe_delete_order(modeladmin, request, queryset):
        queryset.filter(done=True).delete()
        safe_delete_order.short_description = "Safely Delete Completed Orders"

class OrderAdmin(admin.ModelAdmin):

    actions = [safe_delete_order]

    list_display = (
        'user',
        'total_price',
        'done',
        'last_change'
    )

    #sidebar Filter
    list_filter = (
        'done'
    )

    ordering = ('done',)

admin.site.register(Cash)
admin.site.register(Product)
admin.site.register(Order)
admin.site.register(Setting)


"""
LocalMPPTAlgorithm.py

Author: Matthew Yu, Array Lead (2020).
Contact: matthewjkyu@gmail.com
Created: 11/18/20
Last Modified: 02/27/22
Description: Implementation of the LocalMPPTAlgorithm class.
"""
# Library Imports.

# Custom Imports.
from ArraySimulation.MPPT.MPPTComponents.AdaptiveStride import AdaptiveStride
from ArraySimulation.MPPT.MPPTComponents.BisectionStride import BisectionStride
from ArraySimulation.MPPT.MPPTComponents.OptimalStride import OptimalStride
from ArraySimulation.MPPT.MPPTComponents.Stride import Stride

class LocalMPPTAlgorithm:
    """
    The LocalMPPTAlgorithm class provides the base API for derived classes to
    calculate or predict voltage setpoints that would maximize the output power
    of the PVSource given a set of input conditions.
    """

    # The upper voltage bound that should be predicted by any model. We expect
    # the PV to always be at open circuit voltage at this point. Adjustable
    # based on the number of cells determined from the initialization.
    MAX_VOLTAGE = 100

    # The upper voltage bound for a single cell that should be predicted by any
    # model. We expect the PV to always be at open circuit voltage at this
    # point. The reference value was determined from experimentation from the
    # Maxeon Gen III Bin Le1 solar cells, which have a rated voltage of .721V at
    # standard conditions.
    MAX_VOLTAGE_PER_CELL = 0.8

    def __init__(self, numCells=1, MPPTLocalAlgoType="Default", strideType="Fixed"):
        """
        Sets up the initial source parameters.

        Parameters
        ----------
        numCells: int
            The number of cells that should be accounted for in the MPPT
            algorithm.
        MPPTLocalAlgoType: String
            The name of the local MPPT algorithm type.
        strideType: String
            The name of the stride algorithm type.
        """
        LocalMPPTAlgorithm.MAX_VOLTAGE = (
            numCells * LocalMPPTAlgorithm.MAX_VOLTAGE_PER_CELL
        )
        self._MPPTLocalAlgoType = MPPTLocalAlgoType

        if strideType == "Adaptive":
            self._strideModel = AdaptiveStride()
        elif strideType == "Bisection":
            self._strideModel = BisectionStride()
        elif strideType == "Optimal":
            self._strideModel = OptimalStride()
        elif strideType == "Fixed":
            self._strideModel = Stride()
        else:
            self._strideModel = Stride()

        # Previous array voltage value.
        self.vOld = 0.0

        # Previous array current voltage.
        self.iOld = 0.0

        # Previous array power voltage.
        self.pOld = 0.0

        # Previous array irradiance value.
        self.irrOld = 0.0

        # Previous array temperature value.
        self.tOld = 0.0

        # Bounds for the LocalMPPTAlgorithm. A naive assumption is that the
        # function within these bounds are unimodal.
        self.leftBound = 0
        self.rightBound = LocalMPPTAlgorithm.MAX_VOLTAGE

    def setup(self, VMPP=0.621, leftBound=0, rightBound=MAX_VOLTAGE):
        """
        Reinitializes the predicted parameters for the local MPPT algorithms context.

        Parameters
        ----------
        VMPP: float
            The voltage of the Maximum Power Point.
        """
        self.leftBound = leftBound
        self.rightBound = rightBound
        self._strideModel.setup(VMPP)

    def getReferenceVoltage(self, arrVoltage, arrCurrent, irradiance, temperature):
        """
        Calculates the reference voltage output for the given PVSource input.
        May use prior history.

        Parameters
        ----------
        arrVoltage: float
            Array voltage in V.
        arrCurrent: float
            Array current in A.
        irradiance: float
            Irradiance in W/M^2 (G)
        temperature: float
            Cell Temperature in C.

        Return
        ------
        float: The reference voltage that should be applied to the array in the
        next cycle.

        Assumptions
        -----------
        This method is called sequentially in increasing cycle order. The
        arrVoltage and arrCurrent are expected to have stabilized to the
        reference voltage applied in the last cycle, if any.

        Note that the second assumption doesn't hold true in reality, as large
        changes in reference voltage may mean the array does not converge to
        steady state behavior by the next MPPT cycle. This should always be
        considered in the algorithms.
        """
        return 0.0

    def reset(self):
        """
        Resets any internal variables set by the MPPT algorithm during operation.
        """
        self._strideModel.reset()
        self.vOld = 0.0
        self.iOld = 0.0
        self.pOld = 0.0
        self.irrOld = 0.0
        self.tOld = 0.0
        self.leftBound = 0
        self.rightBound = LocalMPPTAlgorithm.MAX_VOLTAGE

    def getLocalMPPTType(self):
        """
        Returns the Local MPPT algorithm type used for the simulation.

        Return
        ------
        String: Model type name.
        """
        return self._MPPTLocalAlgoType

    def getStrideType(self):
        """
        Returns the Stride model type used for the simulation.

        Return
        ------
        String: Model type name.
        """
        return self._strideModel.getStrideType()