import urllib

import flask
from backend.models import Guess, Submission
from flask import Blueprint
from flask import current_app as app
from flask import jsonify, make_response, render_template
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from flask_restx import Api, Resource

leaderboard = Blueprint("leaderboard", __name__, static_folder="../static")

api = Api(
    leaderboard,
    title="Leaderboard API",
    description="The API documentation. Please click on **default** to show all the possible endpoints.",
    doc="/doc/",
)

limiter = Limiter(
    get_remote_address,
    storage_uri="memory://",
)

@api.route("/security/<path:key>/<path:guess>/<path:traces>", methods=["POST"])
@api.param("key", "Your key")
@api.param("guess", "Your guess")
@api.param("traces", "The number of traces your measured")
class Security(Resource):
    """
    Submits a guess for the security round.
    """

    # https://stackoverflow.com/questions/60369112/flask-limiter-does-not-work-with-flask-restful-api-based-application
    decorators = [limiter.limit("30 per minute")]

    def post(self, key, guess, traces):
        try:
            app.config["CONFIG"].get_group_by_key(key)  # IndexError if invalid key
            guess_bytes = urllib.parse.unquote_to_bytes(guess)
            traces_int = int(traces)

            app.config["CONFIG"].rounds_config.add_security_round_submission(
                key, guess_bytes, traces_int
            )
            return make_response(
                jsonify(
                    {
                        "guess": guess,
                        "traces": traces,
                    }
                ),
                200,
            )
        except IndexError:
            return make_response(
                jsonify(
                    {
                        "error": "the provided key does not match any group name",
                        "key": key,
                    }
                ),
                401,
            )
        except IndexError:
            return make_response(
                jsonify(
                    {
                        "error": "traces could not be parse into an integer",
                        "traces": traces,
                    }
                ),
                401,
            )
        except:
            return make_response(
                jsonify(
                    {
                        "error": "the provided guess cannot be properly decoded using base64.b64decode",
                        "guess": guess,
                    }
                ),
                401,
            )

@api.route("/submit/<path:key>/<path:guess>", methods=["POST"])
@api.param("key", "Your key")
@api.param("guess", "Your guess")
class Submit(Resource):
    """
    Submits a guess to current round and current lap.
    """

    def dispatch_request(self, key, guess):
        try:
            guess = Guess[guess.lower()]  # KeyError if invalid answer
            app.config["CONFIG"].get_group_by_key(key)  # IndexError if invalid key

            rounds_config = app.config["CONFIG"].rounds_config
            current_round = rounds_config.get_current_round()
            current_lap = rounds_config.get_current_lap()
            penalized = not rounds_config.accepts_submissions()

            if not rounds_config.is_paused():
                rounds_config.add_submission(
                    Submission(
                        round=current_round,
                        lap=current_lap,
                        key=key,
                        guess=guess,
                        penalized=penalized,
                    )
                )
                return make_response(
                    jsonify(
                        {
                            "guess": guess,
                            "round": current_round,
                            "lap": current_lap,
                            "penalized": penalized,
                        }
                    ),
                    200,
                )

            return make_response(
                jsonify(
                    {
                        "error": "no submissions are allowed, please wait for a new round to start"
                    }
                ),
                400,
            )
        except IndexError:
            return make_response(
                jsonify(
                    {
                        "error": "the provided key does not match any group name",
                        "key": key,
                    }
                ),
                401,
            )
        except KeyError:
            return make_response(
                jsonify(
                    {
                        "error": "the provided guess does not exist",
                        "guess": guess.lower(),
                        "possible-values": Guess.possible_values(),
                    }
                ),
                400,
            )

    @api.response(200, "Success")
    @api.response(400, "Submissions currently not allowed")
    @api.response(401, "Invalid key")
    def post(self, key, guess, patch=False):
        """Submit a guess to current round and current lap."""

    @api.response(200, "Success")
    @api.response(400, "Submissions currently not allowed")
    @api.response(401, "Invalid key")
    def patch(self, key, guess):
        """
        Changes the last guess of current round and current lap.

        If not guesses were made, this is equivalent to the POST method.
        """

@api.route(
    "/submissions/<path:key>",
    methods=["GET", "DELETE"],
    defaults={"round": None, "lap": None},
)
@api.route(
    "/submissions/<path:key>/<path:round>",
    methods=["GET", "DELETE"],
    defaults={"round": None},
)
@api.route("/submissions/<path:key>/<path:round>/<path:lap>", methods=["GET", "DELETE"])
@api.param("key", "Your key")
@api.param(
    "round", "The round from which submissions are taken", type=int, required=False
)
@api.param("lap", "The lap from which submissions are taken", type=int, required=False)
class Submissions(Resource):
    """
    Manipulates submissions, with optinal valeus for round and lap numbers.

    If GET, returns the list of submissions.

    If DELETE, deletes the submissions.
    """

    def dispatch_request(self, key, round, lap):
        try:
            app.config["CONFIG"].get_group_by_key(key)  # IndexError if invalid key
            rounds_config = app.config["CONFIG"].rounds_config

            if flask.request.method == "GET":
                submissions = rounds_config.get_submissions_as_dict(
                    key=key, round=round, lap=lap
                )
                return make_response(
                    jsonify(
                        {
                            "method": flask.request.method,
                            "round": round,
                            "lap": lap,
                            "submissions": submissions,
                        }
                    ),
                    200,
                )
            elif flask.request.method == "DELETE":
                rounds_config.delete_submissions(key=key, round=round, lap=lap)
                return make_response(
                    jsonify(
                        {"method": flask.request.method, "round": round, "lap": lap}
                    ),
                    200,
                )
            else:
                raise ValueError(f"Unsupported method type: {flask.request.method}")
        except IndexError:
            return make_response(
                jsonify(
                    {
                        "error": "the provided key does not match any group name",
                        "key": key,
                    }
                ),
                401,
            )

    @api.response(200, "Success")
    @api.response(401, "Invalid key")
    def get(self, key, round, lap):
        """Returns all submissions from a given group."""

    @api.response(200, "Success")
    @api.response(401, "Invalid key")
    def delete(self, key, round, lap):
        """Returns all submissions from a given group."""

@api.route("/check/<path:key>", methods=["GET"])
@api.param("key", "Your key")
class Get(Resource):
    @api.response(200, "Success")
    @api.response(401, "Invalid key")
    def get(self, key):
        """
        Checks wether a key is valid of not.
        """
        try:
            response = app.config["CONFIG"].get_group_by_key(key).dict()
            del response["key"]
            return make_response(jsonify(response), 200)
        except IndexError:
            return make_response(
                jsonify(
                    {
                        "error": "the provided key does not match any group name",
                        "key": key,
                    }
                ),
                401,
            )

@api.route("/status/", methods=["GET"], defaults={"key": None})
@api.route(
    "/status/<path:key>",
    methods=["GET"],
)
@api.param("key", "Your key, only admin allowed", required=False)
class Status(Resource):
    @api.response(200, "Success")
    @api.response(401, "Invalid key")
    @api.response(403, "Unauthorized user")
    def get(self, key):
        """
        Returns the current status of the leaderboard.
        """
        try:
            leaderboard_status = app.config["CONFIG"].get_leaderboard_status().dict()
            del leaderboard_status["leaderboard"]

            if key:
                if not app.config["CONFIG"].get_group_by_key(key).admin:
                    return make_response(
                        jsonify({"error": "the provided key has no admin rights"}), 403
                    )
            else:
                del leaderboard_status["current_correct_guess"]
                del leaderboard_status["time_before_playing"]

            return make_response(
                jsonify(leaderboard_status),
                200,
            )
        except IndexError:
            return make_response(
                jsonify(
                    {
                        "error": "the provided key does not match any group name",
                        "key": key,
                    }
                ),
                401,
            )

@api.route(
    "/play/<path:key>",
    methods=["POST"],
)
@api.param("key", "Your key, only admin allowed")
class Play(Resource):
    @api.response(200, "Success")
    @api.response(401, "Invalid key")
    @api.response(403, "Unauthorized user")
    def post(self, key):
        """
        Plays the rounds.
        """
        try:
            if not app.config["CONFIG"].get_group_by_key(key).admin:
                return make_response(
                    jsonify({"error": "the provided key has no admin rights"}), 403
                )

            app.config["CONFIG"].rounds_config.play()

            return make_response(
                jsonify({"status": "playing"}),
                200,
            )
        except IndexError:
            return make_response(
                jsonify(
                    {
                        "error": "the provided key does not match any group name",
                        "key": key,
                    }
                ),
                401,
            )

@api.route(
    "/pause/<path:key>",
    methods=["POST"],
)
@api.param("key", "Your key, only admin allowed")
class Pause(Resource):
    @api.response(200, "Success")
    @api.response(401, "Invalid key")
    @api.response(403, "Unauthorized user")
    def post(self, key):
        """
        Pauses the rounds.
        """
        try:
            if not app.config["CONFIG"].get_group_by_key(key).admin:
                return make_response(
                    jsonify({"error": "the provided key has no admin rights"}), 403
                )

            app.config["CONFIG"].rounds_config.pause()

            return make_response(
                jsonify({"status": "paused"}),
                200,
            )
        except IndexError:
            return make_response(
                jsonify(
                    {
                        "error": "the provided key does not match any group name",
                        "key": key,
                    }
                ),
                401,
            )

@api.route(
    "/restart/<path:key>",
    methods=["POST"],
)
@api.param("key", "Your key, only admin allowed")
class Restart(Resource):
    @api.response(200, "Success")
    @api.response(401, "Invalid key")
    @api.response(403, "Unauthorized user")
    def post(self, key):
        """
        Restarts the rounds.
        """
        try:
            if not app.config["CONFIG"].get_group_by_key(key).admin:
                return make_response(
                    jsonify({"error": "the provided key has no admin rights"}), 403
                )

            app.config["CONFIG"].rounds_config.restart()

            return make_response(
                jsonify({"status": "restarted"}),
                200,
            )
        except IndexError:
            return make_response(
                jsonify(
                    {
                        "error": "the provided key does not match any group name",
                        "key": key,
                    }
                ),
                401,
            )

@api.route("/list/", methods=["GET"])
class List(Resource):
    def get(self):
        """
        Lists all possible guesses.
        """
        return make_response(
            jsonify(Guess.possible_values()),
            200,
        )

@api.route("/rename/<path:key>/<path:name>", methods=["PATCH"])
@api.param("key", "Your key")
@api.param("name", "Your new group name")
class Rename(Resource):
    @api.response(200, "Success")
    @api.response(400, "Name already exists")
    @api.response(401, "Invalid key")
    def patch(self, key, name):
        """
        Rename a group.
        """
        try:
            group_conf = app.config["CONFIG"].get_group_by_key(key)

            try:
                _ = app.config["CONFIG"].get_group_by_name(name)
                return make_response(
                    jsonify(
                        {
                            "error": "the provided name already exists",
                            "name": name,
                        }
                    ),
                    400,
                )
            except IndexError:
                pass

            group_conf.name = name
            app.config["CONFIG_NEEDS_SAVE"] = True

            return make_response(jsonify({"name": name}), 200)
        except IndexError:
            return make_response(
                jsonify(
                    {
                        "error": "the provided key does not match any group name",
                        "key": key,
                    }
                ),
                401,
            )

@api.route("", doc=False)
@api.route("/index", doc=False)
class Index(Resource):
    def get(self):
        headers = {"Content-Type": "text/html"}
        return make_response(render_template("leaderboard.html"), 200, headers)


from collections import defaultdict
import pickle

class ImpactModel(object):

    def __init__(self, impact_terms_json, impact_rules_json, aspect_terms_json):
        self.impact_terms = [make_impact_term(term_json) for term_json in impact_terms_json]
        self.impact_rules = [make_impact_rule(rule_json) for rule_json in impact_rules_json]
        self.make_rule_index()
        self.index_aspect_terms(aspect_terms_json)

    def make_rule_index(self):
        """makes an indexes of all impact rules per impact term"""
        self.impact_rule_index = defaultdict(list)
        for impact_rule in self.impact_rules:
            self.impact_rule_index[impact_rule.impact_term.string].append(impact_rule)

    def impact_term_rules(self, impact_term):
        """returns all impact rules for a given impact term"""
        if impact_term not in self.impact_rule_index:
            return None
        else:
            return self.impact_rule_index[impact_term]

    def index_aspect_terms(self, aspect_terms_json):
        """indexes aspect terms per group and aspect groups per term"""
        self.aspect_group_index = defaultdict(dict)
        self.aspect_term_index = defaultdict(dict)
        for aspect_term_json in aspect_terms_json:
            term = aspect_term_json["Aspect_term"]
            group = aspect_term_json["Aspect_category"]
            self.aspect_group_index[group][term] = 1
            self.aspect_term_index[term][group] = 1

    def aspect_term(self, term):
        """returns a dictionary of an aspect terms and its aspect group(s)"""
        if term not in self.aspect_term_index:
            return None
        groups = self.aspect_term_index[term].keys()
        if len(groups) == 1:
            groups = groups[0]
        return {
            "aspect_term": term,
            "aspect_group": groups
        }

    def aspect_group(self, group):
        """returns a dictionary of an aspect group and its aspect terms"""
        if group not in self.aspect_group_index:
            return None
        return {
            "aspect_term": self.aspect_group_index[group].keys(),
            "aspect_group": group
        }

class ImpactTerm(object):

    def __init__(self, impact_string, impact_group, string_pos, group_type):
        self.string = impact_string
        self.group = impact_group
        self.pos = string_pos
        self.type = group_type

    def __repr__(self):
        return "%s(%r)" % (self.__class__, self.__dict__)

class AspectTerm(object):

    def __init__(self, term, category):
        self.string = term
        self.category = category

    def __repr__(self):
        return "%s(%r)" % (self.__class__, self.__dict__)

class ImpactRule(object):

    def __init__(self, impact_term, code, condition, filter_condition, remarks, ignorecase=None):
        self.impact_term = impact_term
        self.code = None if code == "" else code
        self.condition = None if condition == "" else parse_condition(condition)
        self.filter = False if filter_condition == "" else True
        self.remarks = None if remarks == "" else remarks
        self.impact_type = expand_impact_code(code)
        self.ignorecase = ignorecase

    def __repr__(self):
        return "%s(%r)" % (self.__class__, self.__dict__)

def parse_phrase_wildcards(phrase):
    return phrase.replace("*", r"\w*")

def parse_discontinuous_phrase(phrase):
    """
    Transform discontinuous phrase into a regular expression. Discontinuity is
    interpreted as taking place at any whitespace outside of terms grouped by
    parentheses. That is, the whitespace indicates that anything can be in between
    the left side and right side.
    Example 1: x1 (x2 (x3"x4")) becomes x1.+(x2 (x3|x4))
    """
    level = 0
    parsed_phrase = ""
    for index, char in enumerate(phrase):
        if char == "(":
            level += 1
        elif char == ")":
            level -= 1
        elif char == " " and level == 0:
            char = ".+"
        parsed_phrase += char
    return parsed_phrase

def term_string(impact_term):
    if "discontinuous" in impact_term["Impact_group"]:
        impact_term["Impact_term"] = parse_discontinuous_phrase(impact_term["Impact_term"])
    return impact_term["Impact_term"]

def term_group(impact_term):
    return impact_term["Impact_group"]

def term_type(impact_term):
    if "phrase" in term_group(impact_term):
        return "phrase"
    else:
        return "term"

def term_pos(impact_term):
    if "adjective" in term_group(impact_term):
        return "adj"
    elif "noun" in term_group(impact_term):
        return "noun"
    elif "adverb" in term_group(impact_term):
        return "adv"
    elif "verb" in term_group(impact_term):
        return "verb"

def make_impact_term(term_json):
    return ImpactTerm(
        term_string(term_json),
        term_group(term_json),
        term_pos(term_json),
        term_type(term_json)
    )

# Conditions
# @...   Refers to group in sheet of book aspects
# %(...) Continuous group must be present in neighbourhood
# %...   Word must be present in neighbourhood
# ^...   Word must be present at start of sentence
# #(...) discontinuous group must be present in neighbourhood

def parse_condition(condition_string):
    """parses coded condition of impact rule to more readable json"""
    condition_symbol = condition_string[0]
    condition_term = condition_string[1:]
    condition = {
        "condition_type": "context_term",
        "context_term": condition_term,
        "term_type": "term",
        "location": "neighbourhood"
    }
    if condition_symbol == "@":
        condition["condition_type"] = "aspect_term"
        del condition["context_term"]
        condition["aspect_group"] =  condition_term
    elif condition_symbol == "%":
        condition["location"] = "neighbourhood"
        if condition_term[0] == "(" and condition_term[-1] == ")":
            condition["term_type"] = "phrase"
            condition["phrase_type"] = "continuous"
    elif condition_symbol == "^":
        condition["location"] = "sentence_start"
    elif condition_symbol == "$":
        condition["location"] = "sentence_end"
    elif condition_symbol == "#":
        if condition_term[0] == "(" and condition_term[-1] == ")":
            condition["context_term"] = condition["context_term"][1:-1]
        condition["term_type"] = "phrase"
        condition["phrase_type"] = "discontinuous"
        condition["context_term"] = parse_discontinuous_phrase(condition["context_term"])
    if condition["term_type"] == "phrase":
        condition["context_term"] = parse_phrase_wildcards(condition["context_term"])
    return condition

def expand_impact_code(code):
    """map impact code to readable impact type"""
    if code == "R":
        return "Reflection"
    if code == "A":
        return "Affect"
    if code == "N":
        return "Narrative"
    if code == "S":
        return "Style"
    else:
        return None

def make_impact_rule(rule_json):
    rule_fields = ["Impact_group", "Impact_term", "Code as", "Condition", "neg filter*", "remarks"]
    impact_term = ImpactTerm(term_string(rule_json), term_group(rule_json), term_pos(rule_json), term_type(rule_json))
    ignorecase = rule_fields["Ignore case"] if "Ignore case" in rule_fields else True
    return ImpactRule(
        impact_term,
        rule_json["Code as"],
        rule_json["Condition"],
        rule_json["neg filter*"],
        rule_json["remarks"],
        ignorecase
    )

def make_aspect_term(aspect_term_json):
    return AspectTerm(aspect_term_json["Aspect_term"], aspect_term_json["Aspect_category"])

def load_model(model_file):
    """Load an impact model from a pickle file."""
    with open(model_file, 'rb') as fh:
        return pickle.load(fh)


from django.contrib import admin
from import_export import resources, fields
from import_export.admin import ImportExportActionModelAdmin, ImportExportModelAdmin
from import_export.widgets import ForeignKeyWidget

from .models import Publisher, Book, Buyer, Order

# Register your models here.

class BookResource(resources.ModelResource):
    school = fields.Field(column_name='publisher_name',
                          attribute='publisher',
                          widget=ForeignKeyWidget(Publisher, 'name'))

    class Meta:
        model = Book
        skip_unchanged = True
        report_skipped = False
        fields = ('id', 'title', 'publisher_name', 'link', 'author', 'suply', 'edition', 'year_of_publication',
                  'price_foreign_currency', 'price_indian_currency', 'ISBN', 'discount', 'expected_price', 'description', 'subject',)

class BookAdmin(ImportExportActionModelAdmin):
    resource_class = BookResource

    pass

admin.site.register(Publisher)
admin.site.register(Book, BookAdmin)
admin.site.register(Buyer)
admin.site.register(Order)


from typing import List

class Page:

    def __init__(self, resp: dict):
        self.meta: dict = resp.get('meta', {})
        self.data: List[dict] = resp.get('data', [])

        _links: dict = self.meta.get('links', {})
        self.previous_url: str = _links.get('previous_url')
        self.current_url: str = _links.get('current_url')
        if not len(self.data):
            self.next_url = None
        else:
            self.next_url: str = _links.get('next_url')

        self.query: dict = self.meta.get('query')

class DataSet:

    def __init__(self, client: 'Client', resp: dict):
        self._client = client
        self.page: Page = Page(resp)

    def __iter__(self):
        while self.page.next_url:
            yield self.page

            resp = self._client._send_request(self.page.next_url)
            self.page = Page(resp)

        yield self.page


import cv2
import face_recognition
cap= cv2.VideoCapture('a5.mp4')
cascadePath = "lbpcascade_profileface.xml"
faceCascade = cv2.CascadeClassifier(cascadePath)
while(cap.isOpened()):
    ret, frame = cap.read()
    if ret == False:
        break
    img = cv2.resize(frame,(640,480))
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = faceCascade.detectMultiScale(gray)
    if len(faces)>0:
        for (x, y, w, h) in faces:
            cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)
        cv2.imshow('Video', img)
    k = cv2.waitKey(30) & 0xff
    if k==27:
        break
cap.release()
cv2.destroyAllWindows()


import allure

from lib.assertion import Assertions
from lib.my_requests import MyRequests

@allure.epic("Getting info about a user")
@allure.testcase(
    "https://docs.google.com/spreadsheets/d/1G0GwfdGZFxHw7pk2FUmShdH91QXZsEse65-bbTDL0GQ/edit#gid=1332729984",
    "Test cases to check getting info about a user")
class TestGettingUserInfo:
    """As these tests are created for the dummy service, which doesn't have any validation and doesn't save any new user,
    I have to use my previous experience and assume some validation errors, and I also decided not to create new user
    and use already existing users in dummy service"""

    @allure.title("Positive test: get info about existing user")
    def test_getting_info_about_exciting_user(self, get_user_list):
        """This test use user id, which is reserved in this service"""
        response = MyRequests.get(f"/users/{get_user_list['id']}")

        assert response.json()["data"] == get_user_list, \
            f"Info about user from response {get_user_list} is differ from request"
        Assertions.assert_basic_payload_params_status_code_header(response, 200, ["data", "support"],
                                                                  "application/json; charset=utf-8")

    @allure.title("Negative test: get info about deleted user")
    def test_getting_info_about_deleted_user(self, get_deleted_user):
        response = MyRequests.get(f"/users/{get_deleted_user}")

        Assertions.assert_code_status(response, 404)

    @allure.title("Negative test: get info about not existing user")
    def test_getting_info_about_not_exist_user(self):
        """Ids start counting from 1, so I suppose to use '0'"""
        response = MyRequests.get(f"/users/0")

        Assertions.assert_code_status(response, 404)


#!/usr/bin/env python3

import os
import sys
import requests
import json
from urllib.parse import urlparse

if len(sys.argv) != 2:
    print("Usage: ./fetch_scivis.py <dataset name>")
    print("The dataset name should be all lowercase and without spaces to match the website")
    sys.exit(1)

r = requests.get("https://klacansky.com/open-scivis-datasets/data_sets.json")
index = r.json()
meta = [x for x in index if x["name"].lower() == sys.argv[1]][0]
print(json.dumps(meta, indent=4))

script_path = os.path.dirname(os.path.realpath(__file__))
work_path = os.getcwd()

volume_path = urlparse(meta["url"])
meta["volume"] = os.path.normpath(work_path + "/" + os.path.basename(volume_path.path))

meta["camera"] = { "orbit": 5 }
meta["colormap"] = os.path.normpath(script_path + "/configs/paraview_cool_warm.png")
meta["image_size"] = [512, 512]

print("Data set Information")
print(json.dumps(meta, indent=4))

with open(sys.argv[1] + "_osp-icet.json", "w") as f:
    f.write(json.dumps(meta, indent=4))

if not os.path.isfile(meta["volume"]):
    print("Fetching volume from {}".format(meta["url"]))
    r = requests.get(meta["url"])
    data = bytes(r.content)
    with open(os.path.basename(meta["volume"]), "wb") as f:
        f.write(data)
else:
    print("File {} already exists, not re-downloading".format(meta["volume"]))


from django.db import models
import datetime

# Create your models here.
class Customer(models.Model):
	customer_name = models.CharField(max_length=128,
		blank=True, null=True,
		verbose_name='Nombre',
		help_text='Ingrese el Nombre Completo.')

	customer_address = models.CharField(max_length=64,
		blank=True, null=True,
		verbose_name='Dirección',
		help_text='Ingrese la dirección del Cliente.')

	customer_phone = models.CharField(max_length=24,
		blank=True, null=True,
		verbose_name='Teléfono',
		help_text='Ingrese el teléfono del Cliente.')

	""" Campos para auditar el cliente con respecto a la creaci[on y la actualización """
	date_created_customer = models.DateTimeField(auto_now_add=True)
	date_updated_customer = models.DateTimeField(auto_now=True)

	def save(self, *args, **kwargs):
		#Tomando la info del tiempo en ese instante
		date = datetime.datetime.now()

		self.date_updated_customer = date
		super (Customer, self).save(*args, **kwargs)

	def __str__(self):
		return self.customer_name

class Product(models.Model):
	product_name = models.CharField(max_length=128,
		blank=True, null=True,
		verbose_name='Nombre',
		help_text='Ingrese el Nombre del Producto.')

	product_price = models.DecimalField(max_digits=64,
		decimal_places=2,
		verbose_name= 'Precio',
		help_text='Precio del Producto')

	product_type = models.CharField(max_length=128,
		blank=True, null=True,
		verbose_name='Tipo de Producto',
		help_text='Ingrese el tipo de producto al que pertenece')

	product_description = models.TextField(max_length=400,
		verbose_name='Descripción de producto',
		help_text='Ingrese la Descripción del Producto')

	date_created_product = models.DateTimeField(auto_now_add=True)
	date_updated_product = models.DateTimeField()

	def save(self, *args, **kwargs):
		#Tomando la info del tiempo en ese instante
		date = datetime.datetime.now()

		self.date_updated_product = date
		super (Product, self).save(*args, **kwargs)

	def __str__(self):
		return self.product_name

class Stock(models.Model):
	stock_product_id = models.ForeignKey('Product')
	stock_quantity = models.IntegerField(max_length=24,
		verbose_name='Cantidad del producto',
		help_text='Ingrese la cantidad disponible del producto')

	date_created_stock = models.DateTimeField(auto_now_add=True)
	date_updated_stock = models.DateTimeField()

	def save(self, *args, **kwargs):
		#Tomando la info del tiempo en ese instante
		date = datetime.datetime.now()

		self.date_updated_stock = date
		super (Stock, self).save(*args, **kwargs)

class Order(models.Model):
	order_customer_id = models.ForeignKey('Customer')
	order_product_id = models.ForeignKey('Product')
	order_amount = models.IntegerField(max_length=10,
		verbose_name='Cantidad de productos',
		help_text='Ingrese la cantidad de productos en la orden')
	order_date = models.DateField(auto_now=True)

	date_created_order = models.DateTimeField(auto_now_add=True)
	date_updated_order = models.DateTimeField()

	def save(self, *args, **kwargs):
		#Tomando la info del tiempo en ese instante
		date = datetime.datetime.now()

		self.date_updated_order = date
		super (Order, self).save(*args, **kwargs)


# from data_accses_queries import category_data
# from data_accses_queries import transaction_data
# from data_accses_queries import user_data
# # print(category_data.get_categories())
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
from routes import transaction_routes, category_routes, user_routes
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
# print(transaction_data.get_transactions())
# # category_data.create_category('Salary')
# # transaction_data.create_transaction(1, 'CyberArk', 100, 'Salary', False)
# # print(transaction_data.get_transactions_by_category('Salary'))
# # transaction_data.delete_transaction(3)
# # category_data.delete_category('Salary')
# # print(user_data.get_balance(1))
# # user_data.update_balance(1, -5)
# print(transaction_data.sum_transactions_by_category())

app = FastAPI()
app.include_router(transaction_routes.router)
app.include_router(category_routes.router)
app.include_router(user_routes.router)

# app = FastAPI()

origins = [
    "http://localhost",
    "http://localhost:8000",
    "http://localhost:3000",
    "http://localhost:3001",
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# rest of the routes
if __name__ == "__main__":
    uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)


import discord
from .player import Song, queues, players, music

def add_song(video, guild_id, download):
    if download:
        webpage_url = video['webpage_url']
        SourceUrl = video['url']
    else:
        webpage_url = video['url']
        SourceUrl = None
    title = video['title']
    try:
        duration = video['duration']
    except:
        duration = 0
    song = Song(webpage_url, title, duration, SourceUrl, download)
    queues[guild_id].append(song)

async def can_call_command(ctx):
    if not await ctx_in_voice(ctx):
        return False
    if not await bot_in_ctx_voice(ctx):
        return False
    if not await bot_is_playing(ctx):
        return False
    else:
        return True

async def get_player(ctx):
    if (ctx.guild.id not in players):
        players[ctx.guild.id] = await ctx.message.author.voice.channel.connect()
    if ctx.guild.id not in queues:
        queues[ctx.guild.id] = []
    return players[ctx.guild.id]

async def disconnect_player(ctx):
    music[ctx.guild.id].cancel()
    players[ctx.guild.id].stop()
    await players[ctx.guild.id].disconnect()
    players.pop(ctx.guild.id)
    queues.pop(ctx.guild.id)

async def ctx_in_voice(ctx):
    if not ctx.message.author.voice:
        await send_embed(ctx, 'Вы не в голосовом канале', 0xFF0000)
        return False
    else:
        return True

async def bot_in_ctx_voice(ctx):
    if not ctx.guild.id in players or not players[ctx.guild.id].channel.id == ctx.message.author.voice.channel.id:
        await send_embed(ctx, 'Бот не находится в этом канале', 0xFF0000)
        return False
    else:
        return True

async def bot_is_playing(ctx):
    if not await bot_in_ctx_voice(ctx):
        return
    if len(queues[ctx.guild.id]) == 0 or not ctx.guild.id in queues:
        await send_embed(ctx, 'Музыка сейчас не играет', 0xFF0000)
        return False
    else:
        return True

async def send_embed(ctx, title, color):
    embed = discord.Embed(
        title=title, colour=color)
    await ctx.send(embed=embed)


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

import logging

import os
import fnmatch

import re

def _FindVersionFile(directory, match_list):
    for match_pattern in match_list:
        file_list = os.listdir(directory)
        file_list.sort(key=len)  # 文件名短的在前面，避免拷贝的副本在前面
        for file in file_list:
            if fnmatch.fnmatch(file, match_pattern):
                return file
    return ''

def _VersionStr(num_list):
    version = ''
    for num in num_list:
        version += '%s.' % num

    if not version:
        raise ValueError("version string is empty")

    return version[:-1]

def _IncreaseVersion(nums_list, index):
    if not nums_list or index <= 0:
        raise Exception('nums list is empty or index < 0')

    index = index - 1
    if index >= len(nums_list):
        index = len(nums_list) - 1

    nums_list[index] += 1
    for i in range(index+1, len(nums_list)):
        nums_list[i] = 0

class PropertiesFile:
    def __init__(self, path):
        self.path = path

    def TagNumDict(self):
        tag_num_dict = {}
        with open(self.path, 'r') as file:
            for line in file.readlines():
                line = line.strip()
                tag = line.split('=')[0]
                num = line.split('=')[1]

                if not num.isdigit():
                    raise ValueError("version number must be digit!")
                tag_num_dict[tag] = int(num)
        return tag_num_dict

    def WriteToFile(self, version_dict):
        with open(self.path, 'w', newline='\n') as file:
            for key in version_dict:
                line = '%s=%s\n' % (key, version_dict[key])
                file.write(line)

class PodspecFile:
    def __init__(self, path):
        self.path = path

    def _ParameterName(self, file_content):
        match = re.search(r'Pod::Spec.new\s*do\s*\|(.*?)\|', file_content)
        if match:
            return match.group(1)
        return ''

    def _VersionRegPattern(self, file_content):
        return self._ParameterName(file_content) + r"\.version\s*=\s*'(\d+(\.\d+)*)'"
        # return '('+self._ParameterName(file_content) + r"\.version\s*=\s*'(\d+(\.\d+)*)')"

    def TagNumDict(self):
        tag_num_dict = {}
        with open(self.path, mode='r', encoding='utf-8') as file:
            file_content = file.read()
            pattern = self._VersionRegPattern(file_content)
            match = re.search(pattern, file_content)
            if match:
                version_str = match.group(1)
                versions = version_str.split('.')
                v_list = ['x', 'y', 'z', 'm', 'n']
                for i in range(len(versions)):
                    tag_num_dict[v_list[i]] = int(versions[i])
                return tag_num_dict
        return tag_num_dict

    def WriteToFile(self, version_dict):
        # 写得丑陋且低效
        with open(self.path, mode='r+', encoding='utf-8') as file:
            file_content = file.read()
            pattern = self._VersionRegPattern(file_content)
            file.seek(0)
            file_content_lines = file.readlines()
            for line in file_content_lines:
                match = re.search(pattern, line)
                if match:
                    version_nums = list(version_dict.values())
                    updated_version_str = _VersionStr(version_nums)
                    updated_line = line.replace(
                        match.group(1), updated_version_str)
                    file_content = file_content.replace(line, updated_line)

                    file.seek(0)
                    file.write(file_content)
                    file.truncate()

class VersionProcessor:
    def __init__(self):
        files = ['version.properties', '*.podspec']
        self.file_path = _FindVersionFile('.', files)
        if self.file_path == '':
            print('Version file %s not found in current path.' % files)
            exit(1)
        logging.debug('version file path: ' + self.file_path)
        if self.file_path.endswith('.properties'):
            self.version_file = PropertiesFile(self.file_path)
        elif self.file_path.endswith('.podspec'):
            self.version_file = PodspecFile(self.file_path)

    def CurrentVersion(self):
        nums_list = list(self.version_file.TagNumDict().values())
        return _VersionStr(nums_list)

    def TagNumDict(self):
        return self.version_file.TagNumDict()

    def IncreaseVersionAndSave(self, version_index):
        tag_num_dict = self.version_file.TagNumDict()
        nums_list = list(tag_num_dict.values())
        if version_index <= 0:
            return _VersionStr(nums_list)

        _IncreaseVersion(nums_list, version_index)
        version_dict = dict(zip(tag_num_dict.keys(), nums_list))
        self.version_file.WriteToFile(version_dict)

        return _VersionStr(nums_list)

if __name__ == "__main__":
    handler = VersionProcessor()
    print(handler.CurrentVersion())
    print(handler.IncreaseVersionAndSave(3))


from fastapi import APIRouter, Depends, Response, Request
from typing import List, Optional, Union
from authenticator import authenticator
from jwtdown_fastapi.authentication import Token
from queries.posts import Error, PostIn, PostOut, PostRepository
from queries.users import UserOut

class AccountToken(Token):
    account: UserOut

router = APIRouter()

@router.get("/api/protected", response_model=bool)
async def get_protected(
    account_data: dict = Depends(authenticator.get_current_account_data),
):
    print(account_data)
    return True

@router.get("/token", response_model=AccountToken | None)
async def get_token(
    request: Request,
    user: UserOut = Depends(authenticator.try_get_current_account_data),
) -> AccountToken | None:
    if authenticator.cookie_name in request.cookies:
        return {
            "access_token": request.cookies[authenticator.cookie_name],
            "type": "Bearer",
            "account": user,
        }

@router.post("/api/posts", response_model=Union[PostOut, Error])
def create_post(
    post: PostIn,
    response: Response,
    repo: PostRepository = Depends(),
    account_data: dict = Depends(authenticator.get_current_account_data),
):
    response = repo.create_post(post)
    if not response:
        response.status_code = 400
    else:
        return response

@router.delete("/api/posts/{post_id}", response_model=bool)
def delete_post(
    post_id: int,
    response: Response,
    repo: PostRepository = Depends(),
    account_data: dict = Depends(authenticator.get_current_account_data),
) -> bool:
    response = repo.delete(post_id)
    if not response:
        response.status_code = 400
    return response

@router.put("/api/posts/{post_id}", response_model=Union[PostOut, Error])
def update_post(
    post_id: int,
    post: PostIn,
    response: Response,
    repo: PostRepository = Depends(),
    account_data: dict = Depends(authenticator.get_current_account_data),
) -> Union[PostOut, Error]:
    response = repo.update_post(post_id, post)
    if not response:
        response.status_code = 400
    return response

@router.get("/api/posts", response_model=Union[List[PostOut], Error])
def get_all_posts(
    repo: PostRepository = Depends(),
    account_data: dict = Depends(authenticator.get_current_account_data),
):
    return repo.get_all_posts()

@router.get("/api/posts/{post_id}", response_model=Optional[PostOut])
def get_one_post(
    post_id: int,
    response: Response,
    repo: PostRepository = Depends(),
    account_data: dict = Depends(authenticator.get_current_account_data),
) -> PostOut:
    post = repo.get_one_post(post_id)
    if not post:
        response.status_code = 400
    return post


import csv
import re
import string
import nltk
nltk.download('stopwords')
nltk.download('wordnet')
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer

comp = []
processed = []
out = [['Title','Description','Media','Price','Tax','SKU','Type','Vendor','Tags']]

with open('Barrera-Store-CSV.csv','r') as file:
    reader = csv.reader(file)
    for d in reader:
        comp.append(d)

for entry in comp:
    temp = entry
    e1 = re.findall('
.*', entry[2])
    if len(e1) > 0:
        e1 = e1[0]
        e1 = re.sub('
', '', e1)
        e1 = re.sub('
', '', e1)
    else:
        e1 = ''
    e2 = re.findall('

.*', entry[2])
    if len(e2) > 0:
        e2 = e2[0]
        e2 = re.sub('

', '', e2)
        e2 = re.sub('

', '', e2)
        e2 = re.sub('
','',e2)
    else:
        e2 = ''
    temp[2] = [e1,e2]
    temp[25] = re.sub('^\s+','',temp[25])
    temp[26] = re.sub('^\n+','',temp[26])
    temp[26] = re.sub('^\s+','',temp[26])
    if temp[0] != "":
        processed.append(temp)

#for x in processed[2]:
#    print(x)
#    print('----------------------------')

#print('----------------------------')
#print('----------------------------')

for p in processed:
    text = '
'+'\n'.join(p[2])+'
\n
ADDITIONAL INFO
\n

 Benefits	'+p[18]+'	\n
\n
\nFAQs	\n'+p[19]+'	\n
\n
\nSkin Type	\n'+p[22]+'	\n
\n
\nSize	\n'+p[23]+'	\n
\n
\nBrand	\n'+p[24]+'	\n
\n
\n
'
    tokens = nltk.word_tokenize('\n'.join(p[2]))
    stop = stopwords.words('english')
    exclude = ['','skin',"'s"]
    clean_tokens = [t.lower() for t in tokens if t.lower() not in string.punctuation and t.lower() not in stop and t.lower() not in exclude]
    lemmatizer = WordNetLemmatizer()
    lem_tokens = [lemmatizer.lemmatize(t) for t in clean_tokens]
    word_list = {word: sum([1 for w in lem_tokens if w == word]) for word in lem_tokens}
    tags = [k for k,v in word_list.items() if v > 1]
    temp = [p[1],'"{}"'.format(text.replace('\n','
')),p[28],p[10],"TRUE",p[9],"Non-Surgical",p[3],','.join(tags)]
    out.append(temp)
out.remove(out[1])
f = open('Barrera-Shopify-CSV.csv', 'w')
for x in out:
    f.write('/\c'.join(x))
    f.write('\n')
f.close()
print('complete')


import numpy as np
from typing import List, Tuple

class Zncc:
    """ZNCC based decoder

    ZNCC(Zero-mean Normalized Cross Correlation) based decoder can decode *arbitrary* structured light.

    Mirdehghan et al. show that the ZNCC-based decoder has
    almost the same performance as the native decoder [1] (see Figure 5).

    References
    ----------
    .. [1] Mirdehghan et al., "Optimal structured light a la carte." CVPR 2018.
    """

    def decode(self, imlist_code: List[np.ndarray], imlist_observe: List[np.ndarray]) -> Tuple[np.ndarray, np.ndarray]:
        """
        Parameters
        ----------
        imlist_code : List[np.ndarray]
          The projected patterns
        imlist_observe : List[np.ndarray]
          The images captured by the camera

        Returns
        -------
        img_index_x : np.ndarray
          index x-axis
        img_index_y : np.ndarray
          index y-axis
        """
        num = len(imlist_code)
        code = np.reshape(imlist_code, (num, -1))
        observe = np.reshape(imlist_observe, (num, -1))

        # Calculate ZNCC
        zncc = self.calculate_zncc(code, observe)

        # Get argmax
        ids = np.argmax(zncc, axis=0)

        index_y, index_x = np.unravel_index(ids, imlist_code[0].shape)

        dsize_observe = imlist_observe[0].shape
        img_index_y = np.reshape(index_y, dsize_observe)
        img_index_x = np.reshape(index_x, dsize_observe)

        return img_index_x, img_index_y

    @staticmethod
    def calculate_zncc(a: np.ndarray, b: np.ndarray) -> np.ndarray:
        """Calculate ZNCC (Zero-mean Normalized Cross-Correlation) for 1D or 2D array.

        Parameters
        ----------
        a : np.ndarray
           1D or 2D array. Shape should be ('N', 'any1').
        b : np.ndarray
           1D or 2D array. Shape should be ('N', 'any2').

        Returns
        -------
        output : np.ndarray
          Scalar or 1D array or 2D array of ZNCC value.
          Shape is ('any1', 'any2').

        Examples
        --------
        Simple 1D array case
        >>> a = np.random.rand(10)
        >>> calculate_zncc(a, a) # same array
        1.0
        >>> calculate_zncc(a, -a) # invert array
        -1.0
        >>> calculate_zncc(a, 0.8*a+1.0) # change amplitude and offset
        1.0
        Simple image case
        >>> img = np.random.rand(256, 256, 3)
        >>> calculate_zncc(img.flatten(), img.flatten())
        1.0

        2D array case
        >>> b = np.random.rand(10, 100)
        >>> c = np.random.rand(10, 200)
        >>> calculate_zncc(b, c).shape
        (100, 200)
        """
        # Subtract the average
        a = a - np.average(a, axis=0)
        b = b - np.average(b, axis=0)

        # Calculate the ZNCC
        aa_sum = np.expand_dims(np.sum(a*a, axis=0), -1)
        bb_sum = np.expand_dims(np.sum(b*b, axis=0), -1)
        output = ( a.T @ b ) / np.sqrt( aa_sum @ bb_sum.T )

        return output


from datetime import date
from pathlib import Path
import re
import sys
from typing import Tuple

from invoke import task

TOP_DIR = Path(__file__).parent.resolve()

def update_file(filename: str, sub_line: Tuple[str, str], strip: str = None):
    """Utility function for tasks to read, update, and write files"""
    with open(filename, "r") as handle:
        lines = [
            re.sub(sub_line[0], sub_line[1], line.rstrip(strip)) for line in handle
        ]

    with open(filename, "w") as handle:
        handle.write("\n".join(lines))
        handle.write("\n")

@task
def update_version(_, version=""):
    """Update package version to today's date using CalVer"""
    if version:
        if re.match(r"20[2-9][0-9]\.1?[0-9]\.[1-3]?[0-9].*", version) is None:
            sys.exit(
                f"Error: Passed version ({version}) does to match a date in the format "
                "YYYY.(M)M.(D)D."
            )
    else:
        # Use today's date
        today = date.today()
        version = f"{today.year}.{today.month}.{today.day}"

    update_file(
        TOP_DIR.joinpath("tools_optimade_client/__init__.py"),
        (r"__version__ = .+", f'__version__ = "{version}"'),
    )
    update_file(
        TOP_DIR.joinpath("setup.py"), (r"version=([^,]+),", f'version="{version}",')
    )

    print(f"Bumped version to {version} !")


"""**Plot georeferenced data (landuse, building, highway) using geopandas**."""
import matplotlib.pyplot as plt
import seaborn as sns
import geopandas as gpd

def plot_building(df_building, legend_box, fig_size, font_size, face_color,
                  destination):
    """Plot polygons for buildings.

    :param DataFrame df_building: building georeferenced data (geodataframe)
    :param tuple(float) legend_box: tuple of floats, eg (0.0, 0.05, 0.01, 0.7)
    :param tuple(int) fig_size: figure size
    :param int font_size: title font size
    :param str face_color: backgroud color (eg, white, black)
    :param str destination: plot destination path
    """
    fig, ax = plt.subplots(1, figsize=fig_size, facecolor=face_color)
    df_building.plot(column='buildings', categorical=True, legend=True,
                     ax=ax, linewidth=0.1, cmap='Dark2',
                     edgecolor="0.8")

    # ax.set_facecolor("whitesmoke")
    leg = ax.get_legend()
    leg.set_title("building")
    leg.set_bbox_to_anchor(legend_box)
    plt.axis("off")
    plt.title("Building infrastructure in Oldenburg", fontsize=font_size)
    plt.savefig(destination+"buildings.png", facecolor=fig.get_facecolor(),
                dpi=300)

def plot_landuses(df_building, df_landuse, legend_box, fig_size, font_size,
                  face_color, destination):
    """Plot polygons for landuse.

    :param DataFrame df_building: dbuilding georeferenced data (geodataframe)
    :param DataFrame df_landuse: landuse georeferenced data
    :param tuple(float) legend_box: tuple of floats, eg (0.0, 0.05, 0.01, 0.7)
    :param tuple(int) fig_size: figure size
    :param int font_size: title font size
    :param str face_color: backgroud color (eg, white, black)
    :param str destination: plot destination path
    """
    fig, ax = plt.subplots(1, figsize=fig_size, facecolor=face_color)
    base = df_landuse.plot(column='landuse', categorical=True,
                           legend=True, ax=ax, linewidth=0.1,
                           cmap='tab10', edgecolor="0.8")
    df_building.plot(ax=base, edgecolor="0.8", color='white', legend=True)

    # ax.set_facecolor("whitesmoke")
    leg = ax.get_legend()
    leg.set_title("landuse")
    leg.set_bbox_to_anchor(legend_box)
    plt.axis("off")
    plt.title("Land use in Oldenburg", fontsize=font_size)
    plt.savefig(destination+"landuse.png", facecolor=fig.get_facecolor(),
                dpi=300)

def plot_roads(df_highway, legend_box, fig_size, font_size, face_color,
               destination):
    """Plot lines (highway).

    :param DataFrame df_highway: highway georeferenced data (geodataframe)
    :param tuple(float) legend_box: tuple of floats, eg (0.0, 0.05, 0.01, 0.7)
    :param tuple(int) fig_size: figure size
    :param int font_size: title font size
    :param str face_color: backgroud color (eg, white, black)
    :param str destination: plot destination path
    """
    fig, ax = plt.subplots(1, figsize=fig_size, facecolor=face_color)
    df_highway.plot(column='highway', categorical=True, legend=True,
                    ax=ax, linewidth=1, cmap='tab10', edgecolor="0.8")

    # ax.set_facecolor("whitesmoke")
    leg = ax.get_legend()
    leg.set_title("highway")
    leg.set_bbox_to_anchor(legend_box)
    plt.title("Roads infrastructure in Oldenburg", fontsize=font_size)
    plt.axis("off")
    plt.savefig(destination+"highway.png", facecolor=fig.get_facecolor(),
                dpi=300)

if __name__ == "__main__":
    csv_file = "../data/02_urban_output_data/"
    buildings_shp = csv_file+"buildings/buildings.shp"
    landuse_shp = csv_file+"landuse/landuse.shp"
    highway_shp = csv_file+"highway/highway.shp"
    destination = "../data/04_Visualisation/"

    df_building = gpd.read_file(buildings_shp)
    df_highway = gpd.read_file(highway_shp)
    df_landuse = gpd.read_file(landuse_shp)
    classifications = ["commercial", "retail", "residential", "farmland",
                       "farmyard", "industrial"]
    df_landuse = df_landuse.loc[df_landuse["landuse"].isin(classifications)]

    sns.set_style("dark")
    sns.set_context(context=None, font_scale=1, rc=None)
    legend_box = (0.0, 0.05, 0.01, 0.7)
    font_size = 11
    fig_size = (6, 4)
    face_color = "white"

    plot_landuses(df_building, df_landuse, legend_box, fig_size, font_size,
                  face_color, destination)
    plot_roads(df_highway, legend_box, fig_size, font_size, face_color,
               destination)
    plot_building(df_building, legend_box, fig_size, font_size, face_color,
                  destination)


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

from grid import Grid
from grid_PAS import Grid as Grid_PAS

import plotting as pt
import plotting_tools as ptt

from scipy.io import loadmat

#===========================================================================================

windPath = '/home/michael/Documents/data/WINDS/'
PASpath = '/home/michael/Documents/data/IdealisedAmundsenSea/data/PAS_851/run/'

# Zonal and meridional limits.
W = -130; E = -90;
S = -76; N = -64;

# Get PAS bathymetry for background
grid = Grid_PAS(PASpath)
bathy = grid.bathy
bathy = ptt.maskBathyXY(bathy, grid, zi=0)
land = np.where(bathy<0, 0, 1)

# Get PAS grid and land subrange.
lonPAS, latPAS, land = grid.XYsubr([W+360,E+360], [S,N], land); lonPAS -= 360

# We want to show only xthe -1000m contour of bathy along the shelf break.
lonPASbathy, latPASbathy, bathy = grid.XYsubr([W+360,E+360], [-73,-70], bathy); lonPASbathy -= 360
#pt.plot1by1(bathy, X=lonPASbathy, Y=latPASbathy); quit()

# Extend land array southwards, to match wind data
Ny, Nx = latPAS.shape
latPAS_ = np.zeros((Ny+1,Nx))
latPAS_[1:,:] = latPAS; latPAS_[0,:] = -78
lonPAS_ = np.zeros((Ny+1,Nx))
lonPAS_[1:,:] = lonPAS; lonPAS_[0,:] = lonPAS[1,:]
land_ = np.zeros((Ny+1,Nx))
land_[1:,:] = land; land_[0,:] = 1

colors = ['white', 'cyan']; bounds = [0,0.5,1]
cmap = mpl.colors.ListedColormap(colors)
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)

#extent = [lonPAS[0,0], lonPAS[0,-1], latPAS[0,0], latPAS[-1,0]]
extent = [W, E, S, N]

# Load Pauls' wind data.
f = loadmat(windPath + 'paneldata.mat')['paneldata']

d = [1,1,1,1,4,1]
titles = ['reconstruction', 'external', 'internal', 'GHG', 'IPO', 'ozone']

for pi in range(6):

	lat = f[pi,0]['lat'][0,0]
	lon = f[pi,0]['lon'][0,0]
	u = f[pi,0]['u'][0,0]
	v = f[pi,0]['v'][0,0]

	xw = np.argmin(np.abs(lon[0,:]-W))
	xe = np.argmin(np.abs(lon[0,:]-E))
	ys = np.argmin(np.abs(lat[:,0]-S))
	yn = np.argmin(np.abs(lat[:,0]-N))

	lat = lat[ys:yn, xw:xe]
	lon = lon[ys:yn, xw:xe]
	u = u[ys:yn, xw:xe]
	v = v[ys:yn, xw:xe]

	latd = lat[::d[pi],::d[pi]]
	lond = lon[::d[pi],::d[pi]]
	ud = u[::d[pi],::d[pi]]
	vd = v[::d[pi],::d[pi]]

	# Colour in land.

	uav = np.mean(u, axis=1)
	uav = uav * 0.3*(E-W) / np.max(np.abs(uav)) + (W+E)/2
	zeros = np.zeros(uav.shape[0]) + (W+E)/2

	#plt.imshow(land[::-1], interpolation='none', cmap=cmap, norm=norm, extent=extent, aspect=2)
	plt.plot(uav, lat[:,0], color='r')
	plt.plot(zeros, lat[:,0], linestyle='dashed', color='r')
	plt.contourf(lonPAS_, latPAS_, land_, cmap=cmap)
	#plt.contourf(lonPAS, latPAS, land, cmap=cmap)
	plt.contour(lonPASbathy, latPASbathy, bathy, levels=[-1000], colors='k', linestyles='solid')
	plt.quiver(lond, latd, ud, vd)

	plt.title(titles[pi])
	plt.xlim([W, E]); plt.ylim([S, N])
	plt.show()


from django import forms
from dashboard.models import Data

class DataForm(forms.ModelForm):
    class Meta:
        model = Data
        fields = ['name','age','height','sex']
        labels = {
            "name":"이름",
            "age":"나이",
            "height":"키",
            "sex":"성별",
        }


# vim: ts=4 sw=4 et
# -*- coding: utf-8 -*-

# © 2021 The Board of Trustees of the Leland Stanford Junior University.
#
# This program 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, version 3.
#
# This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.

import functools
import logging
import re
from typing import *
import stanford.mais.account

# Set up logging
logger = logging.getLogger(__name__)
debug = logger.debug
info = logger.info

__all__ = (
    'validate',
    'AccountValidationResults',
)

# In __all__, we list `validate` first.  But in the code, we define the results
# class first.  That is so that we can reference the class name directly in
# `validate`.

class AccountValidationResults(NamedTuple):
    """Results of doing an account validation.

    This class contains the results of an account validation, called via
    :func:`validate`.

    .. note::
       Many of these properties are collections.  That means, if you want to
       use things like subscripting, you will want to convert to a
       more-specific type (such as :class:`list` before using it).
    """

    raw: Optional[str]
    """
    The raw input provided for validation.  This is only provided when
    a string was provided to :func:`validate`.
    """

    raw_set: Collection[str]
    """
    The raw input provided for validation.  If a string was provided to
    :func:`validate`, then this is the raw input after being split into a
    collection.  Otherwise, this will be the original list/set/tuple that was
    provided to :func:`validate`, but made into a set.

    The set union of `full`, `base`, `inactive`, and `unknown` is equal to
    this list.
    """

    full: Collection[str]
    """
    The set of active, full (or full-sponsored) SUNetIDs found in `raw_set`.
    """

    base: Collection[str]
    """
    The set of active, base (or base-sponsored) SUNetIDs found in `raw_set`.
    """

    inactive: Collection[str]
    """
    The set of inactive SUNetIDs found in `raw_set`.
    """

    unknown: Collection[str]
    """
    The set of entries from `raw_set` that are not SUNetIDs.
    """

@functools.singledispatch
def validate(
    raw: str,
    client: stanford.mais.account.AccountClient,
) -> AccountValidationResults:
    """Given a list of SUNetIDs; as a string or a list, tuple, or set; validate
    and check status.

    This takes a list of SUNetIDs, and returns a list of SUNetIDs which have
    been checked against the Accounts API for both activity and service level.
    The returned result shows which SUNetIDs are active full (or
    full-sponsored), active base (or base-sponsored), or inactive.

    If the input is a string, then the input string may be separated by commas,
    and/or whitespace, (where "whitespace" is a space, newline/linefeed, form
    feed, carriage return, tab/horizontal tab, or vertical tab character).  If
    the input is a list, tuple, or set; the function assumes that all
    whitespace etc. have been removed.

    .. note::
       "List, tuple, or set" is used instead of the generic "collection"
       because a :class:`str` is also a collection (of other :class:`str`).
       See `typing issue #256 <https://github.com/python/typing/issues/256>`_
       for the discussion around this issue.

    This is designed to catch most exceptions.  Exceptions related to
    validation (for example, attempting to validate an obviously-invalid
    SUNetID like `ab$#`) will result in the 'SUNetID' being added to the
    `unknown` list, instead of throwing an exception.  The only exceptions that
    should be expected from this function are ones related to API issues.

    :param raw: The list of SUNetIDs.  If a `str`, then the list may be comma- and/or whitespace-separated.

    :param client: An :class:`~stanford.mais.account.AccountClient` to connect to the Account API.

    :return: The results of the validation.  See the definition of :class:`~nero_wgcreator.account.validate.AccountValidationResults` for details.  If the input to this function is a string; that string will be in `raw`, and the parsed list will be in `raw_set`.  If the input to this function is not a string, then `raw` will be `None` and `raw_set` will be a copy of the input.

    :raises ChildProcessError: Something went wrong on the server side (a 400 or 500 error was returned).

    :raises PermissionError: You did not use a valid certificate, or do not have permissions to perform the operation.

    :raises requests.Timeout: The MaIS Workgroup API did not respond in time.
    """
    debug('In validate with str')
    debug(f"Validation input: {raw}")

    # Start by spliting on whitespace and comma.
    # NOTE: Repeated instances of whitespace/separators will make empty entries.
    raw_list = re.split(r'\s|,', raw)

    # Filter out all empty entries, and remove duplicates by using the set.
    debug(f"Split list pre-filter has {len(raw_list)} items.")
    raw_list_filtered = set(filter(
        lambda item: len(item)>0,
        raw_list
    ))

    # Validate the list entries.
    debug(f"Post-filter list has {len(raw_list_filtered)} items.")
    result = validate(raw_list_filtered, client)

    # Add in our raw string, and we're done!
    return AccountValidationResults(
        raw=raw,
        raw_set=result.raw_set,
        full=result.full,
        base=result.base,
        inactive=result.inactive,
        unknown=result.unknown,
    )

@validate.register(list)
@validate.register(tuple)
@validate.register(set)
def _(
    raw: Union[List[str], Tuple[str], Set[str]],
    client: stanford.mais.account.AccountClient,
) -> AccountValidationResults:
    """
    (This is a single-dispatch function.  See the documentation above!
    """
    debug('In validate with list/tuple/set')
    debug('Input: ' + ','.join(raw))
    debug(f"Input has {len(raw)} items.")

    # Limit our accounts to only people
    people = client.only_people()

    # If we were not given a set, then convert it into a set.
    if not isinstance(raw, set):
        raw = set(raw)

    # Components of the output
    full = set()
    base = set()
    inactive = set()
    unknown = set()

    for sunetid in raw:
        # Catch unknown entries
        try:
            account = people.get(sunetid)
            debug(f"Account {sunetid} exists.")
        except (ValueError, IndexError, KeyError):
            debug(f"Account {sunetid} not found.")
            unknown.add(sunetid)
            continue

        # Overwrite the input SUNetID with the normalized one.
        sunetid = account.sunetid

        # Next, catch inactives
        if account.is_active is False:
            debug(f"Account {sunetid} NOT active.")
            inactive.add(sunetid)
            continue

        # Finally, sort into full or base
        if account.is_full:
            debug(f"Account {sunetid} is FULL")
            full.add(sunetid)
        else:
            debug(f"Account {sunetid} is base")
            base.add(sunetid)

    # Return the structure
    debug(f"Validation results: full={len(full)} base={len(base)} inactive={len(inactive)} unknown={len(unknown)}")
    return AccountValidationResults(
        raw=None,
        raw_set=raw,
        full=full,
        base=base,
        inactive=inactive,
        unknown=unknown,
    )


# -*- coding: utf-8 -*-
"""
Created on Mon Jun 10 14:09:23 2019

@author: TRAORE Cheick Amed
"""

"Algorithme de factorisation d'entiers"
"Précondition l'entier doit être composé"
#import prime
from prime import erastothene

def factorisation(Nl):
    k=2
    #global tab
    tab=[]
    while k<=int(Nl**0.5):
        if Nl%k==0 and erastothene(k):
            tab=tab+[k]
        k=k+1
    #print(tab)
    #if tab[0]==2:
     #   k2=tab[1]
    #else:
     #   k2=tab[0]
    #k1=int(Nl/k2)
    #return k1,k2
    k=len(tab)
   # print(k,len(tab))
    k=k//2
   # print(k)
    k2=tab[k]
    k1=Nl//k2
    return k1,k2


#!/usr/bin/env python
from .abstract_window import AbstractWindow
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QImage, QTextCursor, QTextBlockFormat

class QtNotebookWindow(AbstractWindow):
    """
    Simple window that is the same as matplotlib figure window
    """
    parent_notebook = None
    scale_notebook = (0.5, 0.5)

    def __init__(self, *args, **kwargs):
        # Create Figure
        if self.parent_notebook is not None:
            size = self.parent_notebook.frameSize()
            min_size = 1
            dpi = 100.0
            kwargs['figsize'] = (max(min_size, self.scale_notebook[0] * (size.width() / dpi)),
                    max(min_size, self.scale_notebook[1] * (size.height() / dpi)))
            kwargs['dpi'] = dpi
        self.show_count = 0
        self.buf = None
        self.figure = plt.figure(*args, **kwargs)
        self.canvas = FigureCanvas(self.figure)
        self.canvas.mpl_connect('resize_event', self.tight_layout)

    def tight_layout(self, event):
        try:
            self.figure.tight_layout()
        except:
            pass

    def show(self):
        if self.parent_notebook is None:
            print("No parent notebook to print the image to")
            return
        self.figure.tight_layout()
        self.canvas.draw()
        size = self.canvas.size()
        self.buf, (width, height) = self.canvas.print_to_buffer()
        image = QImage(self.buf, width, height, QImage.Format_ARGB32)
        self.parent_notebook.insertImage(image, 'figure_' + str(self.figure.number) + '_' + str(self.show_count))
        self.parent_notebook.resetFontSize()
        self.show_count = self.show_count + 1

    def gcf(self):
        return self.figure


import requests
import pandas as pd
import json
from pandas import DataFrame

def issues(repo):
    raw=requests.get('https://api.github.com/repos/'+ repo + '/issues')
    df=pd.DataFrame(raw.json())
    df_user=df.loc[:,['user']]
    names=[]
    i=0
    while i<len(df_user):
        names.append(df_user.loc[i][0].get('login'))
        i=i+1

    df_name=DataFrame(names,columns=['user_name'])

    issues_df=df.loc[:,['number','title']].join(df_name)
    print(issues_df)

    return issues_df

issues("numpy/numpy")


import numpy as np
import cv2
from ppdet.core.workspace import create
from kkdetection.bytetrack import BYTETracker
from kkdetection.ppdet.detector import Detector
from kkdetection.ppdet.dataset import VideoDataset
from kkannotation.streamer import Recorder
from kkannotation.util.image import draw_annotation
from kkdetection.util.image import xyxy_to_xywh
from kkdetection.util.com import get_args

if __name__ == "__main__":
    args     = get_args()
    detector = Detector(**args.autofix())
    dataset = VideoDataset()
    dataset.set_data(args.get("video"), start_frame_id=0, max_frames=10, step=2)
    recorder = Recorder("./output_tracking.mp4", fps=dataset.streamer.get_fps(), width=dataset.streamer.shape()[1], height=dataset.streamer.shape()[0])
    tracker  = BYTETracker(
        dataset.streamer.shape()[0], dataset.streamer.shape()[1],
        thre_bbox_high=0.8, thre_bbox_low=0.2,
        thre_iou_high=0.8, thre_iou_low=0.8, thre_iou_new=0.8,
        max_time_lost=50
    )
    target_class_id = args.get("target", int, 0)
    dataloader = create("TestReader")(dataset, 0)
    outputs     = detector.predict_dataloader(dataloader)
    outputs     = [x["bbox"] for x in outputs]
    list_bboxes = [x[x[:, 0] == target_class_id][:, 2:].astype(float) for x in outputs]
    list_scores = [x[x[:, 0] == target_class_id][:, 1 ].astype(float) for x in outputs]
    tracks      = tracker.tracking(list_bboxes, list_scores)
    for i_frame, dict_output in enumerate(tracks):
        frame = dataset.streamer[i_frame]
        for track_id, bbox in dict_output.items():
            frame = draw_annotation(frame, xyxy_to_xywh([int(x) for x in bbox]), catecory_name=str(track_id), color_id=track_id)
        if args.get("is_show", None, False):
            cv2.imshow(__name__, frame)
            cv2.waitKey(0)
        if recorder is not None:
            recorder.write(frame)
    recorder.close()


import copy
from argparse import ArgumentParser, BooleanOptionalAction
from functools import partial
from typing import Optional

import torch
import torch.nn.functional as F
import torch_optimizer as optim
from pl_bolts.callbacks.knn_online import KNNOnlineEvaluator
from pl_bolts.optimizers import linear_warmup_decay
from pytorch_lightning import Trainer, LightningModule, seed_everything
from pytorch_lightning.callbacks import LearningRateMonitor, ModelCheckpoint
from pytorch_lightning.loggers import TensorBoardLogger
from torch import nn
from torchmetrics import Accuracy

from models import SimCLRMaskedViT, PosReconHead
from utils.criteria import multi_view_info_nce_loss, multi_view_cov_reg_loss
from utils.datamodules import build_imagenet
from utils.lr_wt_decay import param_groups_lrd, exclude_from_wt_decay
from utils.transforms import SimCLRPretrainPostTransform, imagenet_normalization, MultiCropPretrainPreTransform

class RandMaskedSimCLR(LightningModule):
    def __init__(
            self,
            num_samples: int,
            num_nodes: int = 1,
            gpus: int = 1,
            batch_size: int = 128,
            max_epochs: int = 100,
            dataset: str = "imagenet",
            num_classes: int = 1000,
            size_crops: tuple[int, ...] = (224,),
            num_crops: tuple[int, ...] = (2,),
            gaussian_blur: bool = True,
            jitter_strength: float = 1.,
            img_size: int = 224,
            patch_size: int = 16,
            in_chans: int = 3,
            embed_dim: int = 384,
            depth: int = 12,
            num_heads: int = 6,
            mlp_ratio: int = 4,
            mlp_drop_rate: float = 0.,
            attention_drop_rate: float = 0.,
            drop_path_rate: float = 0.,
            layer_decay: float = 1.,
            weight_sharing: Optional[str] = None,
            position: bool = True,
            shuffle: bool = False,
            mask_ratio: float = 0.75,
            ema_momentum: float = 0.,
            mask_ratio_sg: float = 0.75,
            proj_dim: int = 128,
            temperature: float = 0.1,
            cov_reg_norm: bool = False,
            cov_reg_coeff: float = 0.,
            pos_recon_depth: int = 0,
            pos_recon_num_heads: int = 6,
            pos_recon_coeff: float = 0.,
            pos_recon_loss: str = "mse",
            optimizer: str = "adamw",
            learning_rate: float = 1e-3,
            weight_decay: float = 0.05,
            exclude_bn_bias: bool = False,
            warmup_epochs: int = 10,
            **kwargs
    ):
        super(RandMaskedSimCLR, self).__init__()
        self.save_hyperparameters()

        # Training
        self.num_samples = num_samples
        self.num_nodes = num_nodes
        self.gpus = gpus
        self.batch_size = batch_size
        self.max_epochs = max_epochs
        # compute iters per epoch
        global_batch_size = num_nodes * gpus * batch_size if gpus > 0 else batch_size
        self.train_iters_per_epoch = num_samples // global_batch_size

        # Data
        self.dataset = dataset
        self.num_classes = num_classes
        self.size_crops = size_crops
        self.num_crops = num_crops
        self.gaussian_blur = gaussian_blur
        self.jitter_strength = jitter_strength

        # ViT params
        self.img_size = img_size
        self.patch_size = patch_size
        self.in_chans = in_chans
        self.embed_dim = embed_dim
        self.depth = depth
        self.num_heads = num_heads
        self.mlp_ratio = mlp_ratio
        self.weight_sharing = weight_sharing
        # Regularization
        self.mlp_drop_rate = mlp_drop_rate
        self.attention_drop_rate = attention_drop_rate
        self.drop_path_rate = drop_path_rate
        self.layer_decay = layer_decay

        # FCLR params
        self.position = position
        self.shuffle = shuffle
        self.mask_ratio = mask_ratio
        self.ema_momentum = ema_momentum
        self.mask_ratio_sg = mask_ratio_sg
        self.proj_dim = proj_dim
        self.temperature = temperature

        # CovReg
        self.cov_reg_norm = cov_reg_norm
        self.cov_reg_coeff = cov_reg_coeff

        # PosRecon
        self.pos_recon_depth = pos_recon_depth
        self.pos_recon_num_heads = pos_recon_num_heads
        self.pos_recon_coeff = pos_recon_coeff
        self.pos_recon_loss = pos_recon_loss

        # Optimizer
        self.optim = optimizer
        self.learning_rate = learning_rate
        self.weight_decay = weight_decay
        self.exclude_bn_bias = exclude_bn_bias
        self.warmup_epochs = warmup_epochs

        # Transforms
        if dataset == "imagenet":
            normalization = imagenet_normalization()
        self.normalization = normalization
        self.transform = SimCLRPretrainPostTransform(
            img_size=img_size,
            gaussian_blur=gaussian_blur,
            jitter_strength=jitter_strength,
            normalize=normalization,
        )

        # Modules
        self.siamese_net = SimCLRMaskedViT(
            img_size,
            patch_size,
            in_chans,
            embed_dim,
            depth,
            num_heads,
            mlp_ratio,
            proj_dim,
            mlp_drop_rate,
            attention_drop_rate,
            drop_path_rate,
            norm_layer=partial(nn.LayerNorm, eps=1e-6),
            weight_sharing=weight_sharing,
        )
        if ema_momentum > 0:
            self.siamese_net_sg = copy.deepcopy(self.siamese_net)
        if pos_recon_coeff > 0:
            self.pos_recon_head = PosReconHead(
                embed_dim,
                pos_recon_depth,
                pos_recon_num_heads
            )
        if pos_recon_loss in {'mse', 'l2'}:
            self.pos_recon_criterion = nn.MSELoss()
        elif pos_recon_loss in {'mae', 'l1'}:
            self.pos_recon_criterion = nn.L1Loss()
        elif pos_recon_loss == 'smooth_l1':
            self.pos_recon_criterion = nn.SmoothL1Loss()
        else:
            raise NotImplementedError(f"Unknown PosRecon loss: {pos_recon_loss}")
        self.classifier = nn.Linear(embed_dim, num_classes)

        # Online metrics
        self.train_acc_top_1 = Accuracy(top_k=1)
        self.train_acc_top_5 = Accuracy(top_k=5)
        self.val_acc_top_1 = Accuracy(top_k=1, compute_on_step=False)
        self.val_acc_top_5 = Accuracy(top_k=5, compute_on_step=False)

    def on_train_batch_end(self, outputs, batch, batch_idx):
        if self.ema_momentum > 0:
            for online_p, target_p in zip(self.siamese_net.parameters(),
                                          self.siamese_net_sg.parameters()):
                em = self.ema_momentum
                target_p.data = target_p.data * em + online_p.data * (1.0 - em)

    def forward(self, x):
        x = self.normalization(x)
        x, _ = self.siamese_net(x)

        return x

    def forward_multi_crop(self, img):
        # Concatenate crop with the same size and mask ratio, augment, and forward
        end_indices = torch.tensor(self.num_crops).cumsum(0)
        start_indices = torch.cat((torch.tensor([0]), end_indices[:-1]))
        for i, (start_index, end_index) in enumerate(zip(start_indices, end_indices)):
            # Assume global crop at first
            mask_ratio = self.mask_ratio if i == 0 else 0.
            img_ = torch.cat([
                self.transform(i) for i in img[start_index:end_index]
            ])
            yield self.siamese_net(img_, self.position, self.shuffle, mask_ratio)

    def position_reconstruction(self, patch_embed, visible_idx):
        pos_embed = self.siamese_net.pos_embed.expand(patch_embed.size(0), -1, -1)
        if visible_idx is not None:
            pos_embed = pos_embed.gather(1, visible_idx)
        pos_embed_pred = self.pos_recon_head(patch_embed)
        loss_pos_recon = self.pos_recon_criterion(pos_embed_pred, pos_embed)

        return loss_pos_recon

    def shared_step(self, img):
        batch_size, *_ = img[0].size()
        patch_embed, visible_idx, proj = [], [], []
        for patch_embed_, visible_idx_, proj_ in self.forward_multi_crop(img):
            patch_embed.append(patch_embed_)
            visible_idx.append(visible_idx_)
            proj.append(proj_.view(-1, batch_size, self.proj_dim))
        reps = torch.cat([pe[:, 0, :] for pe in patch_embed])
        patch_embed = patch_embed[0][:, 1:, :]
        visible_idx = visible_idx[0]
        proj = torch.cat(proj).transpose(0, 1)

        if self.ema_momentum > 0:
            proj_sg = []
            with torch.no_grad():
                for _, _, proj_ in self.forward_multi_crop(img):
                    proj_sg.append(proj_.view(-1, batch_size, self.proj_dim))
            proj_sg = torch.cat(proj_sg).transpose(0, 1)
            proj = torch.cat((proj, proj_sg))

        loss_clr = multi_view_info_nce_loss(proj, self.temperature)

        loss_cov_reg = multi_view_cov_reg_loss(proj, self.cov_reg_norm)
        loss = loss_clr + self.cov_reg_coeff * loss_cov_reg

        loss_pos_recon = 0.
        if self.pos_recon_coeff > 0:
            loss_pos_recon = self.position_reconstruction(patch_embed, visible_idx)
            loss += self.pos_recon_coeff * loss_pos_recon

        return reps, proj, {
            "clr": loss_clr,
            "cov_reg": loss_cov_reg,
            "pos_recon": loss_pos_recon,
            "all": loss,
        }

    def linear_probe(self, reps, labels, acc_top_1_fn, acc_top_5_fn):
        labels = labels.repeat(reps.size(0) // labels.size(0))
        logits = self.classifier(reps)
        loss = F.cross_entropy(logits, labels)
        acc_top_1 = acc_top_1_fn(logits.softmax(-1), labels)
        acc_top_5 = acc_top_5_fn(logits.softmax(-1), labels)

        return loss, acc_top_1, acc_top_5

    def training_step(self, batch, batch_idx):
        img, labels = batch
        reps, proj, losses = self.shared_step(img)

        loss_xent, acc_top_1, acc_top_5 = self.linear_probe(
            reps.detach(), labels, self.train_acc_top_1, self.train_acc_top_5
        )

        self.log_dict({
            'loss/clr/train': losses["clr"],
            'loss/cov_reg/train': losses["cov_reg"],
            'loss/pos_recon/train': losses["pos_recon"],
            'loss/pretrain/train': losses["all"],
            'loss/linear_probe/train': loss_xent,
            'acc/linear_probe_top_1/train': acc_top_1,
            'acc/linear_probe_top_5/train': acc_top_5,
            'norm/reps': reps.norm(dim=-1).mean(),
            'norm/proj': proj.norm(dim=-1).mean(),
        }, sync_dist=True)
        return losses["all"] + loss_xent

    def validation_step(self, batch, batch_idx):
        img, labels = batch
        reps, proj, losses = self.shared_step(img)

        loss_xent, acc_top_1, acc_top_5 = self.linear_probe(
            reps.detach(), labels, self.val_acc_top_1, self.val_acc_top_5
        )

        self.log_dict({
            'loss/clr/val': losses["clr"],
            'loss/cov_reg/val': losses["cov_reg"],
            'loss/pos_recon/val': losses["pos_recon"],
            'loss/pretrain/val': losses["all"],
            'loss/linear_probe/val': loss_xent,
            'acc/linear_probe_top_1/val': acc_top_1,
            'acc/linear_probe_top_5/val': acc_top_5,
        }, sync_dist=True)
        return losses["all"] + loss_xent

    def configure_optimizers(self):
        param_groups = param_groups_lrd(
            self.siamese_net,
            lr=self.learning_rate,
            weight_decay=self.weight_decay,
            exclude_1d_params=self.exclude_bn_bias,
            no_weight_decay_list=("pos_embed", "cls_token"),
            layer_decay=self.layer_decay
        )
        if self.exclude_bn_bias:
            param_groups += exclude_from_wt_decay(self.classifier, self.weight_decay)
            if self.pos_recon_coeff > 0:
                param_groups += exclude_from_wt_decay(self.pos_recon_head, self.weight_decay)
        else:
            param_groups += [
                {"params": self.classifier.parameters(), "weight_decay": self.weight_decay}
            ]
            if self.pos_recon_coeff > 0:
                param_groups += [
                    {"params": self.pos_recon_head.parameters(), "weight_decay": self.weight_decay}
                ]

        if self.optim == "lars":
            optimizer = optim.LARS(param_groups, lr=self.learning_rate, momentum=0.9)
        elif self.optim == "adam":
            optimizer = torch.optim.Adam(param_groups, lr=self.learning_rate)
        elif self.optim == "lamb":
            optimizer = optim.Lamb(param_groups, lr=self.learning_rate)
        elif self.optim == "adamw":
            optimizer = torch.optim.AdamW(param_groups, lr=self.learning_rate)

        warmup_steps = self.train_iters_per_epoch * self.warmup_epochs
        total_steps = self.train_iters_per_epoch * self.max_epochs

        scheduler = {
            "scheduler": torch.optim.lr_scheduler.LambdaLR(
                optimizer,
                linear_warmup_decay(warmup_steps, total_steps, cosine=True),
            ),
            "interval": "step",
            "frequency": 1,
        }

        return [optimizer], [scheduler]

    @staticmethod
    def add_model_specific_args(parent_parser):
        parser = ArgumentParser(parents=[parent_parser], add_help=False)

        # training params
        parser.add_argument("--num_nodes", default=1, type=int,
                            help="number of nodes for training")
        parser.add_argument("--gpus", default=1, type=int,
                            help="number of gpus to train on")
        parser.add_argument("--max_epochs", default=100, type=int,
                            help="number of total epochs to run")
        parser.add_argument("--max_steps", default=-1, type=int,
                            help="max steps")
        parser.add_argument("--batch_size", default=128, type=int,
                            help="batch size per gpu")
        parser.add_argument("--num_workers", default=8, type=int,
                            help="num of workers per GPU")
        parser.add_argument("--fast_dev_run", default=False, type=int)
        parser.add_argument("--fp16", default=False, action='store_true',
                            help="use fp16")

        # transform params
        parser.add_argument("--dataset", type=str, default="imagenet",
                            help="dataset")
        parser.add_argument("--lmdb_25pct", default=False, action='store_true',
                            help="use dedicated 25%% LMDB dataset")
        parser.add_argument("--lmdb", default=False, action='store_true',
                            help="use LMDB dataset")
        parser.add_argument("--data_dir", type=str, default="dataset",
                            help="path to dataset")
        parser.add_argument("--sample_pct", type=int, default=100,
                            help="%% of samples for training (only for ablation)")
        parser.add_argument("--size_crops", default=(224,), type=int, nargs="+",
                            help="crop resolution")
        parser.add_argument("--num_crops", default=(2,), type=int, nargs="+",
                            help="number of crops")
        parser.add_argument("--min_scale_crops", default=(0.08,), type=float, nargs="+",
                            help="RandResizeCrop minimum scales")
        parser.add_argument("--max_scale_crops", default=(1.,), type=float, nargs="+",
                            help="RandResizeCrop maximum scales")
        parser.add_argument("--gaussian_blur", default=True,
                            action=BooleanOptionalAction, help="add gaussian blur")
        parser.add_argument("--jitter_strength", type=float, default=1.0,
                            help="jitter strength")

        # model params
        parser.add_argument("--img_size", default=224, type=int,
                            help="input image size")
        parser.add_argument("--patch_size", default=16, type=int,
                            help="patch size")
        parser.add_argument("--in_chans", default=3, type=int,
                            help="number of in channels")
        parser.add_argument("--embed_dim", default=384, type=int,
                            help="embedding dimension")
        parser.add_argument("--depth", default=12, type=int,
                            help="number of Transformer blocks")
        parser.add_argument("--num_heads", default=6, type=int,
                            help="number of self-attention heads")
        parser.add_argument("--mlp_ratio", default=4, type=int,
                            help="Ratio of embedding dim to MLP dim")
        parser.add_argument("--weight_sharing", default=None, type=str,
                            help="ALBERT-style weight sharing, "
                                 "choose from None, attn, ffn, or all")
        # regularization
        parser.add_argument("--layer_decay", default=1., type=float,
                            help="layer-wise decay")
        parser.add_argument("--mlp_drop_rate", default=0.0, type=float,
                            help="mlp dropout rate")
        parser.add_argument("--attention_drop_rate", default=0.0, type=float,
                            help="attention dropout rate")
        parser.add_argument("--drop_path_rate", default=0.0, type=float,
                            help="path dropout rate")
        # FCLR
        parser.add_argument("--position", default=True, action=BooleanOptionalAction,
                            help="add positional embedding or not")
        parser.add_argument("--shuffle", default=False, action='store_true',
                            help="shuffle positional embedding or not")
        parser.add_argument("--mask_ratio", default=0.75, type=float,
                            help="mask ratio of patches")
        parser.add_argument("--ema_momentum", default=0., type=float,
                            help="ema momentum")
        parser.add_argument("--mask_ratio_sg", default=0.75, type=float,
                            help="mask ratio of patches on target branch")
        parser.add_argument("--proj_dim", default=128, type=int,
                            help="projection head output dimension")
        parser.add_argument("--temperature", default=0.1, type=float,
                            help="temperature parameter in InfoNCE loss")
        # CovReg
        parser.add_argument("--cov_reg_norm", default=True, action=BooleanOptionalAction,
                            help="use correlation instead of covariance")
        parser.add_argument("--cov_reg_coeff", default=0., type=float,
                            help="coefficient on covariance regularization loss")
        # PosRecon
        parser.add_argument("--pos_recon_depth", default=0, type=int,
                            help="depth of PosRecon head, 0 for linear layer")
        parser.add_argument("--pos_recon_num_heads", default=6, type=int,
                            help="number of attention heads in PosRecon head")
        parser.add_argument("--pos_recon_coeff", default=0., type=float,
                            help="coefficient on position reconstruction loss")
        parser.add_argument("--pos_recon_loss", default='mse', type=str,
                            help="type of position reconstruction loss")

        # Optimizer
        parser.add_argument("--optimizer", default="adamw", type=str,
                            help="choose between adamw/lars")
        parser.add_argument("--learning_rate", default=1e-3, type=float,
                            help="base learning rate")
        parser.add_argument("--weight_decay", default=0.05, type=float,
                            help="weight decay")
        parser.add_argument("--exclude_bn_bias", default=True,
                            action=BooleanOptionalAction,
                            help="exclude bn/ln/bias from weight decay")
        parser.add_argument("--warmup_epochs", default=10, type=int,
                            help="number of warmup epochs")

        return parser

if __name__ == '__main__':
    seed_everything(0)
    parser = ArgumentParser()
    parser.add_argument("--version", default=None, type=str)
    parser.add_argument("--log_path", default="lightning_logs", type=str)
    parser.add_argument("--resume_ckpt_path", default=None, type=str)
    parser.add_argument("--track_grad", default=True, action=BooleanOptionalAction)
    parser.add_argument("--knn_probe", default=False, action='store_true')
    parser = RandMaskedSimCLR.add_model_specific_args(parser)
    args = parser.parse_args()

    if args.dataset == "imagenet":
        dm = build_imagenet(args.sample_pct, args.lmdb, args.lmdb_25pct)
    else:
        raise NotImplementedError(f"Unimplemented dataset: {args.dataset}")
    dm = dm(data_dir=args.data_dir,
            batch_size=args.batch_size,
            num_workers=args.num_workers)
    args.num_samples = dm.num_samples
    args.num_classes = dm.num_classes

    dm.train_transforms = dm.val_transforms = MultiCropPretrainPreTransform(
        args.size_crops, args.num_crops, args.min_scale_crops, args.max_scale_crops
    )

    model = RandMaskedSimCLR(**args.__dict__)

    logger = TensorBoardLogger(args.log_path, name="pretrain", version=args.version)
    lr_monitor = LearningRateMonitor(logging_interval="step")
    model_checkpoint = ModelCheckpoint(save_last=True, monitor="loss/pretrain/val")

    callbacks = [model_checkpoint]
    if args.knn_probe:
        callbacks.append(KNNOnlineEvaluator())
    callbacks.append(lr_monitor)

    if args.gpus > 1:
        if args.ema_momentum > 0:
            strategy = "ddp"
        else:
            strategy = "ddp_find_unused_parameters_false"
    else:
        strategy = None

    trainer = Trainer(
        max_epochs=args.max_epochs,
        max_steps=args.max_steps,
        devices=args.gpus if args.gpus > 0 else None,
        num_nodes=args.num_nodes,
        accelerator="gpu" if args.gpus > 0 else None,
        strategy=strategy,
        sync_batchnorm=True if args.gpus > 1 else False,
        track_grad_norm=2 if args.track_grad else -1,
        precision=16 if args.fp16 else 32,
        callbacks=callbacks,
        logger=logger,
        fast_dev_run=args.fast_dev_run,
    )

    trainer.fit(model, datamodule=dm, ckpt_path=args.resume_ckpt_path)