import copy
import random as rnd
from queue import PriorityQueue

import numpy as np

from common import (Agent, Target, at6, manhattanDistance, minInRange,
                    minOutRange, numActions, targetInRange, withinRange5)

# from improvedMAST import improvementMAST

'''
    This Improved Agent is the same as our Improved Agent for the stationary target. It simply factors in the extra clue of whether
    the target is within a distance of 5 by limiting its search scope to determine the next cell to search in the same way that
    it did for the other agents.
'''

def improvedMAMTWithClue(agent, target):
    highest = 0
    r = c = 0

    for row in agent.map:
        for cell in row:
            cell.score = cell.probability * \
                (1 - cell.falseNegativeProbability)
            if cell.score > highest:
                highest = cell.score
                r, c = cell.row, cell.col

    while agent.hasFoundTarget == False:
        minScore = agent.dim ** 4
        prevr = r
        prevc = c

        numChecks = int(agent.map[r][c].falseNegativeProbability * 10.0)
        for check in range(numChecks):
            searchResult = agent.searchCell(r, c, target)
            #print('searched cell: ', (prevr,prevc))
            #print('Target Position: ', target.position)

            if searchResult == False:
                target.move()
                withinFive = targetInRange(agent, target, prevr, prevc)
                #print('target in range? ', withinFive)
                scale = 1 - agent.map[r][c].probability + \
                    agent.map[r][c].probability * \
                    agent.map[r][c].falseNegativeProbability
                agent.map[r][c].probability = agent.map[r][c].probability * \
                    agent.map[r][c].falseNegativeProbability
                i = 0
                while i < agent.dim:
                    j = 0
                    while j < agent.dim:
                        if prevr == i and prevc == j:
                            j += 1
                            continue
                        # probabilities/scores are updated here
                        agent.map[i][j].probability = agent.map[i][j].probability / scale
                        agent.map[i][j].score = agent.map[i][j].probability * \
                            (1 - agent.map[i][j].falseNegativeProbability)
                        dist = manhattanDistance((prevr, prevc), (i, j))
                        agent.map[i][j].score = (1 + float(dist)) / (
                            agent.map[i][j].probability * (1 - agent.map[i][j].falseNegativeProbability))
                        j = j + 1
                    i = i + 1
                if check == numChecks - 1:
                    if withinFive:
                        minScore, r, c = minInRange(agent, prevr, prevc)
                    else:
                        minScore, r, c = minOutRange(agent, prevr, prevc)
                    numActions((prevr, prevc), (r, c), agent)
            else:
                break
    return agent.numMoves

def improvedMAMTWithoutClue(agent, target):
    highest = 0
    r = c = 0
    for row in agent.map:
        for cell in row:
            cell.score = cell.probability * (1 - cell.falseNegativeProbability)
            # dist = float(manhattanDistance((r,c), (i,j)))
            # agent.map[i][j].score = dist / agent.map[i][j].score
            if cell.score > highest:
                highest = cell.score
                r, c = cell.row, cell.col

    while (agent.hasFoundTarget == False):
        minScore = agent.dim**4
        prevr = r
        prevc = c
        numChecks = int(agent.map[r][c].falseNegativeProbability * 10.0)
        for check in range(0, numChecks):
            searchResult = agent.searchCell(r, c, target)
            if searchResult == False:
                target.move()
                scale = 1 - agent.map[r][c].probability + \
                    agent.map[r][c].probability * \
                    agent.map[r][c].falseNegativeProbability
                agent.map[r][c].probability = agent.map[r][c].falseNegativeProbability * \
                    agent.map[r][c].probability
                i = 0
                while i < agent.dim:
                    j = 0
                    while j < agent.dim:
                        if i == prevr and j == prevc:
                            j += 1
                            continue
                        agent.map[i][j].probability = agent.map[i][j].probability / scale
                        dist = manhattanDistance((prevr, prevc), (i, j))
                        agent.map[i][j].score = (1 + float(dist)) / (
                            agent.map[i][j].probability * (1 - agent.map[i][j].falseNegativeProbability))
                        if check == numChecks - 1 and minScore > agent.map[i][j].score:
                            minScore = agent.map[i][j].score
                            r = i
                            c = j
                        j = j + 1
                    i = i + 1
                if check == numChecks - 1:
                    numActions((prevr, prevc), (r, c), agent)
            else:
                break

    return agent.numMoves


from Mesh import *
from Jacobi import *
from Advec1D import *

import matplotlib.pyplot as plt
from matplotlib import animation

# Parameters definition
NODETOL = 1e-10
# domain extension
xmin = 0.0
xmax = 6.28
# Subdomains
K = 10
# Vertices
Nv = K+1
'''
return number of vertex, equi-spaced grid points, elements to vertex
VX are the points in the mesh and EToV is a Kx2 matrix, the first row
is the vertex index to the left of each element K and the second row
is the vertex index to the right of each element K.
'''
VX, EToV = MeshGen1D(xmin,xmax,K)
# Aproximation order
N=1
# number of points
Np = N+1
# Number of points per face
Nfp = 1
# Number of faces
Nfaces=2
# Jacobi Gauss Lobatto points
r = jacobi_gauss_lobatto_points(1,1,N)
# Vandermonde Matrix
V = vandermonde_matrix_1d(N, r)
# Matrix derivatives
Dr = gradient_matrix_1d(N, r, V)
# M = inv(dot(V,Trans(V)))
# print dot(M,Dr)
# LIFT = Lift1D()
Emat = zeros((Np,Nfaces*Nfp))
Emat[0,0] = 1.0
Emat[Np-1,1] = 1.0
#print Emat
LIFT = dot(V,(dot(Trans(V),Emat)))
va = Trans(EToV)[0]
vb = Trans(EToV)[1]
x1 = dot(ones((N+1,1)),array([VX[:len(va)]]))
x2 = 0.5*dot(Trans(array([r+1])),array([vec(VX,vb)-vec(VX,va)]))
x = x1+x2
rx,J = GeometricFactors1D(x,Dr)
fmask1 = nonzero(abs(r+1) < NODETOL)
fmask2 = nonzero(abs(r-1) < NODETOL)
Fmask  = array([fmask1[0][0],fmask2[0][0]])

Fx = getm(x,Fmask)
#nx = Normals1D()

nx = zeros((Nfp*Nfaces, K))
nx[0] = -1.0
nx[Nfp*Nfaces-1] = 1.0
Fscale = 1./getm(J,Fmask);
EToE, EToF = Connect1D(EToV,Nfaces,K,Nv)

vmapM, vmapP, vmapI, mapI, vmapB, mapB, mapO = BuildMaps1D(K,Np,Nfp,Nfaces,EToE,EToF,Fmask,x,NODETOL)

u = sin(x)

FinalTime = 30.
data = Advec1D(Np,K,x,rx,nx,Dr,u,LIFT,Fscale,Nfp,Nfaces,vmapM,vmapP,vmapI,mapI,mapO,FinalTime)

# Create animation
fig = plt.figure()
ax = plt.axes(xlim=(xmin, xmax), ylim=(-2, 2))
line, = ax.plot([], [], 'bo')

def animate(i):
    t = x.ravel()
    y = data[i].ravel()
    line.set_data(t, y)
    return line,

anim = animation.FuncAnimation(fig, animate,
                               frames=len(data), interval=100, blit=True)

anim.save('basic_animation.mp4', fps=5, extra_args=['-vcodec', 'libx264'])

plt.show()


__author__ = 'Ben'

from string import Template

def main():
    number_of_instances = int(input())
    result = ""
    result_line = Template('Case #$n: $res\n')

    for instance in range(1, number_of_instances + 1):
        row1 = int(input())
        for r1 in range(1, 5):
            temp = input()
            if row1 == r1:
                row1_content = set(temp.split())

        row2 = int(input())
        for r2 in range(1, 5):
            temp = input()
            if row2 == r2:
                row2_content = set(temp.split())

        intersection_set = row1_content.intersection(row2_content)
        if len(intersection_set) == 0:
            result += result_line.substitute(n=instance, res='Volunteer cheated!')
        elif len(intersection_set) > 1:
            result += result_line.substitute(n=instance, res='Bad magician!')
        else:
            result += result_line.substitute(n=instance, res=intersection_set.pop())

    print(result)

if __name__ == "__main__":
    main()


"""Item crud client."""
import json
import logging
import operator
from datetime import datetime
from typing import List, Optional, Set, Type, Union
from urllib.parse import unquote_plus, urlencode, urljoin

import attr
import geoalchemy2 as ga
import sqlalchemy as sa
import stac_pydantic
from fastapi import HTTPException
from pydantic import ValidationError
from shapely.geometry import Polygon as ShapelyPolygon
from shapely.geometry import shape
from sqlakeyset import get_page
from sqlalchemy import func
from sqlalchemy.orm import Session as SqlSession
from stac_fastapi.types.config import Settings
from stac_fastapi.types.core import BaseCoreClient
from stac_fastapi.types.errors import NotFoundError
from stac_fastapi.types.search import BaseSearchPostRequest
from stac_fastapi.types.stac import Collection, Collections, Item, ItemCollection
from stac_pydantic.links import Relations
from stac_pydantic.shared import MimeTypes

from stac_fastapi.sqlalchemy import serializers
from stac_fastapi.sqlalchemy.extensions.query import Operator
from stac_fastapi.sqlalchemy.models import database
from stac_fastapi.sqlalchemy.session import Session
from stac_fastapi.sqlalchemy.tokens import PaginationTokenClient

logger = logging.getLogger(__name__)

NumType = Union[float, int]

@attr.s
class CoreCrudClient(PaginationTokenClient, BaseCoreClient):
    """Client for core endpoints defined by stac."""

    session: Session = attr.ib(default=attr.Factory(Session.create_from_env))
    item_table: Type[database.Item] = attr.ib(default=database.Item)
    collection_table: Type[database.Collection] = attr.ib(default=database.Collection)
    item_serializer: Type[serializers.Serializer] = attr.ib(
        default=serializers.ItemSerializer
    )
    collection_serializer: Type[serializers.Serializer] = attr.ib(
        default=serializers.CollectionSerializer
    )

    @staticmethod
    def _lookup_id(
        id: str, table: Type[database.BaseModel], session: SqlSession
    ) -> Type[database.BaseModel]:
        """Lookup row by id."""
        row = session.query(table).filter(table.id == id).first()
        if not row:
            raise NotFoundError(f"{table.__name__} {id} not found")
        return row

    def all_collections(self, **kwargs) -> Collections:
        """Read all collections from the database."""
        base_url = str(kwargs["request"].base_url)
        with self.session.reader.context_session() as session:
            collections = session.query(self.collection_table).all()
            serialized_collections = [
                self.collection_serializer.db_to_stac(collection, base_url=base_url)
                for collection in collections
            ]
            links = [
                {
                    "rel": Relations.root.value,
                    "type": MimeTypes.json,
                    "href": base_url,
                },
                {
                    "rel": Relations.parent.value,
                    "type": MimeTypes.json,
                    "href": base_url,
                },
                {
                    "rel": Relations.self.value,
                    "type": MimeTypes.json,
                    "href": urljoin(base_url, "collections"),
                },
            ]
            collection_list = Collections(
                collections=serialized_collections or [], links=links
            )
            return collection_list

    def get_collection(self, collection_id: str, **kwargs) -> Collection:
        """Get collection by id."""
        base_url = str(kwargs["request"].base_url)
        with self.session.reader.context_session() as session:
            collection = self._lookup_id(collection_id, self.collection_table, session)
            return self.collection_serializer.db_to_stac(collection, base_url)

    def item_collection(
        self,
        collection_id: str,
        bbox: Optional[List[NumType]] = None,
        datetime: Optional[str] = None,
        limit: int = 10,
        token: str = None,
        **kwargs,
    ) -> ItemCollection:
        """Read an item collection from the database."""
        base_url = str(kwargs["request"].base_url)
        with self.session.reader.context_session() as session:
            # Look up the collection first to get a 404 if it doesn't exist
            _ = self._lookup_id(collection_id, self.collection_table, session)
            query = (
                session.query(self.item_table)
                .join(self.collection_table)
                .filter(self.collection_table.id == collection_id)
                .order_by(self.item_table.datetime.desc(), self.item_table.id)
            )
            # Spatial query
            geom = None
            if bbox:
                bbox = [float(x) for x in bbox]
                if len(bbox) == 4:
                    geom = ShapelyPolygon.from_bounds(*bbox)
                elif len(bbox) == 6:
                    """Shapely doesn't support 3d bounding boxes so use the 2d portion"""
                    bbox_2d = [bbox[0], bbox[1], bbox[3], bbox[4]]
                    geom = ShapelyPolygon.from_bounds(*bbox_2d)
            if geom:
                filter_geom = ga.shape.from_shape(geom, srid=4326)
                query = query.filter(
                    ga.func.ST_Intersects(self.item_table.geometry, filter_geom)
                )

            # Temporal query
            if datetime:
                # Two tailed query (between)
                dts = datetime.split("/")
                # Non-interval date ex. "2000-02-02T00:00:00.00Z"
                if len(dts) == 1:
                    query = query.filter(self.item_table.datetime == dts[0])
                # is there a benefit to between instead of >= and <= ?
                elif dts[0] not in ["", ".."] and dts[1] not in ["", ".."]:
                    query = query.filter(self.item_table.datetime.between(*dts))
                # All items after the start date
                elif dts[0] not in ["", ".."]:
                    query = query.filter(self.item_table.datetime >= dts[0])
                # All items before the end date
                elif dts[1] not in ["", ".."]:
                    query = query.filter(self.item_table.datetime <= dts[1])

            count = None
            if self.extension_is_enabled("ContextExtension"):
                count_query = query.statement.with_only_columns(
                    [func.count()]
                ).order_by(None)
                count = query.session.execute(count_query).scalar()
            token = self.get_token(token) if token else token
            page = get_page(query, per_page=limit, page=(token or False))
            # Create dynamic attributes for each page
            page.next = (
                self.insert_token(keyset=page.paging.bookmark_next)
                if page.paging.has_next
                else None
            )
            page.previous = (
                self.insert_token(keyset=page.paging.bookmark_previous)
                if page.paging.has_previous
                else None
            )

            links = [
                {
                    "rel": Relations.self.value,
                    "type": "application/geo+json",
                    "href": str(kwargs["request"].url),
                },
                {
                    "rel": Relations.root.value,
                    "type": "application/json",
                    "href": str(kwargs["request"].base_url),
                },
                {
                    "rel": Relations.parent.value,
                    "type": "application/json",
                    "href": str(kwargs["request"].base_url),
                },
            ]
            if page.next:
                links.append(
                    {
                        "rel": Relations.next.value,
                        "type": "application/geo+json",
                        "href": f"{kwargs['request'].base_url}collections/{collection_id}/items?token={page.next}&limit={limit}",
                        "method": "GET",
                    }
                )
            if page.previous:
                links.append(
                    {
                        "rel": Relations.previous.value,
                        "type": "application/geo+json",
                        "href": f"{kwargs['request'].base_url}collections/{collection_id}/items?token={page.previous}&limit={limit}",
                        "method": "GET",
                    }
                )

            response_features = []
            for item in page:
                response_features.append(
                    self.item_serializer.db_to_stac(item, base_url=base_url)
                )

            context_obj = None
            if self.extension_is_enabled("ContextExtension"):
                context_obj = {
                    "returned": len(page),
                    "limit": limit,
                    "matched": count,
                }

            return ItemCollection(
                type="FeatureCollection",
                features=response_features,
                links=links,
                context=context_obj,
            )

    def get_item(self, item_id: str, collection_id: str, **kwargs) -> Item:
        """Get item by id."""
        base_url = str(kwargs["request"].base_url)
        with self.session.reader.context_session() as session:
            db_query = session.query(self.item_table)
            db_query = db_query.filter(self.item_table.collection_id == collection_id)
            db_query = db_query.filter(self.item_table.id == item_id)
            item = db_query.first()
            if not item:
                raise NotFoundError(f"{self.item_table.__name__} {item_id} not found")
            return self.item_serializer.db_to_stac(item, base_url=base_url)

    def get_search(
        self,
        collections: Optional[List[str]] = None,
        ids: Optional[List[str]] = None,
        bbox: Optional[List[NumType]] = None,
        datetime: Optional[Union[str, datetime]] = None,
        limit: Optional[int] = 10,
        query: Optional[str] = None,
        token: Optional[str] = None,
        fields: Optional[List[str]] = None,
        sortby: Optional[str] = None,
        intersects: Optional[str] = None,
        **kwargs,
    ) -> ItemCollection:
        """GET search catalog."""
        # Parse request parameters
        base_args = {
            "collections": collections,
            "ids": ids,
            "bbox": bbox,
            "limit": limit,
            "token": token,
            "query": json.loads(unquote_plus(query)) if query else query,
        }

        if datetime:
            base_args["datetime"] = datetime

        if intersects:
            base_args["intersects"] = json.loads(unquote_plus(intersects))

        if sortby:
            # https://github.com/radiantearth/stac-spec/tree/master/api-spec/extensions/sort#http-get-or-post-form
            sort_param = []
            for sort in sortby:
                sort_param.append(
                    {
                        "field": sort[1:],
                        "direction": "asc" if sort[0] == "+" else "desc",
                    }
                )
            base_args["sortby"] = sort_param

        if fields:
            includes = set()
            excludes = set()
            for field in fields:
                if field[0] == "-":
                    excludes.add(field[1:])
                elif field[0] == "+":
                    includes.add(field[1:])
                else:
                    includes.add(field)
            base_args["fields"] = {"include": includes, "exclude": excludes}

        # Do the request
        try:
            search_request = self.post_request_model(**base_args)
        except ValidationError:
            raise HTTPException(status_code=400, detail="Invalid parameters provided")
        resp = self.post_search(search_request, request=kwargs["request"])

        # Pagination
        page_links = []
        for link in resp["links"]:
            if link["rel"] == Relations.next or link["rel"] == Relations.previous:
                query_params = dict(kwargs["request"].query_params)
                if link["body"] and link["merge"]:
                    query_params.update(link["body"])
                link["method"] = "GET"
                link["href"] = f"{link['href']}?{urlencode(query_params)}"
                link["body"] = None
                link["merge"] = False
                page_links.append(link)
            else:
                page_links.append(link)
        resp["links"] = page_links
        return resp

    def post_search(
        self, search_request: BaseSearchPostRequest, **kwargs
    ) -> ItemCollection:
        """POST search catalog."""
        base_url = str(kwargs["request"].base_url)
        with self.session.reader.context_session() as session:
            token = (
                self.get_token(search_request.token) if search_request.token else False
            )
            query = session.query(self.item_table)

            # Filter by collection
            count = None
            if search_request.collections:
                query = query.join(self.collection_table).filter(
                    sa.or_(
                        *[
                            self.collection_table.id == col_id
                            for col_id in search_request.collections
                        ]
                    )
                )

            # Sort
            if search_request.sortby:
                sort_fields = [
                    getattr(
                        self.item_table.get_field(sort.field),
                        sort.direction.value,
                    )()
                    for sort in search_request.sortby
                ]
                sort_fields.append(self.item_table.id)
                query = query.order_by(*sort_fields)
            else:
                # Default sort is date
                query = query.order_by(
                    self.item_table.datetime.desc(), self.item_table.id
                )

            # Ignore other parameters if ID is present
            if search_request.ids:
                id_filter = sa.or_(
                    *[self.item_table.id == i for i in search_request.ids]
                )
                items = query.filter(id_filter).order_by(self.item_table.id)
                page = get_page(items, per_page=search_request.limit, page=token)
                if self.extension_is_enabled("ContextExtension"):
                    count = len(search_request.ids)
                page.next = (
                    self.insert_token(keyset=page.paging.bookmark_next)
                    if page.paging.has_next
                    else None
                )
                page.previous = (
                    self.insert_token(keyset=page.paging.bookmark_previous)
                    if page.paging.has_previous
                    else None
                )

            else:
                # Spatial query
                geom = None
                if search_request.intersects is not None:
                    geom = shape(search_request.intersects)
                elif search_request.bbox:
                    if len(search_request.bbox) == 4:
                        geom = ShapelyPolygon.from_bounds(*search_request.bbox)
                    elif len(search_request.bbox) == 6:
                        """Shapely doesn't support 3d bounding boxes we'll just use the 2d portion"""
                        bbox_2d = [
                            search_request.bbox[0],
                            search_request.bbox[1],
                            search_request.bbox[3],
                            search_request.bbox[4],
                        ]
                        geom = ShapelyPolygon.from_bounds(*bbox_2d)

                if geom:
                    filter_geom = ga.shape.from_shape(geom, srid=4326)
                    query = query.filter(
                        ga.func.ST_Intersects(self.item_table.geometry, filter_geom)
                    )

                # Temporal query
                if search_request.datetime:
                    # Two tailed query (between)
                    dts = search_request.datetime.split("/")
                    # Non-interval date ex. "2000-02-02T00:00:00.00Z"
                    if len(dts) == 1:
                        query = query.filter(self.item_table.datetime == dts[0])
                    # is there a benefit to between instead of >= and <= ?
                    elif dts[0] not in ["", ".."] and dts[1] not in ["", ".."]:
                        query = query.filter(self.item_table.datetime.between(*dts))
                    # All items after the start date
                    elif dts[0] not in ["", ".."]:
                        query = query.filter(self.item_table.datetime >= dts[0])
                    # All items before the end date
                    elif dts[1] not in ["", ".."]:
                        query = query.filter(self.item_table.datetime <= dts[1])

                # Query fields
                if search_request.query:
                    for field_name, expr in search_request.query.items():
                        field = self.item_table.get_field(field_name)
                        for op, value in expr.items():
                            if op == Operator.gte:
                                query = query.filter(operator.ge(field, value))
                            elif op == Operator.lte:
                                query = query.filter(operator.le(field, value))
                            else:
                                query = query.filter(op.operator(field, value))

                if self.extension_is_enabled("ContextExtension"):
                    count_query = query.statement.with_only_columns(
                        [func.count()]
                    ).order_by(None)
                    count = query.session.execute(count_query).scalar()
                page = get_page(query, per_page=search_request.limit, page=token)
                # Create dynamic attributes for each page
                page.next = (
                    self.insert_token(keyset=page.paging.bookmark_next)
                    if page.paging.has_next
                    else None
                )
                page.previous = (
                    self.insert_token(keyset=page.paging.bookmark_previous)
                    if page.paging.has_previous
                    else None
                )

            links = []
            if page.next:
                links.append(
                    {
                        "rel": Relations.next.value,
                        "type": "application/geo+json",
                        "href": f"{kwargs['request'].base_url}search",
                        "method": "POST",
                        "body": {"token": page.next},
                        "merge": True,
                    }
                )
            if page.previous:
                links.append(
                    {
                        "rel": Relations.previous.value,
                        "type": "application/geo+json",
                        "href": f"{kwargs['request'].base_url}search",
                        "method": "POST",
                        "body": {"token": page.previous},
                        "merge": True,
                    }
                )

            response_features = []
            filter_kwargs = {}

            for item in page:
                response_features.append(
                    self.item_serializer.db_to_stac(item, base_url=base_url)
                )

            # Use pydantic includes/excludes syntax to implement fields extension
            if self.extension_is_enabled("FieldsExtension"):
                if search_request.query is not None:
                    query_include: Set[str] = set(
                        [
                            k
                            if k in Settings.get().indexed_fields
                            else f"properties.{k}"
                            for k in search_request.query.keys()
                        ]
                    )
                    if not search_request.fields.include:
                        search_request.fields.include = query_include
                    else:
                        search_request.fields.include.union(query_include)

                filter_kwargs = search_request.fields.filter_fields
                # Need to pass through `.json()` for proper serialization
                # of datetime
                response_features = [
                    json.loads(stac_pydantic.Item(**feat).json(**filter_kwargs))
                    for feat in response_features
                ]

        context_obj = None
        if self.extension_is_enabled("ContextExtension"):
            context_obj = {
                "returned": len(page),
                "limit": search_request.limit,
                "matched": count,
            }

        return ItemCollection(
            type="FeatureCollection",
            features=response_features,
            links=links,
            context=context_obj,
        )


from os import linesep
import googletrans

translator = googletrans.Translator()

read_file_path = r'9.영어로된 문서를 한글로 자동 번역\english.txt'
write_file_path = r'9.영어로된 문서를 한글로 자동 번역\korean.txt'

with open(read_file_path) as f :
    readLines = f.readlines()

for lines in readLines:
    result1 = translator.translate(lines, dest='ko', src='en')
    print(result1.text)
    with open(write_file_path, 'a', encoding='UTF8') as f:
        f.write(result1.text + '\n')

9.영어로된 문서를 한글로 자동 번역/main9-4.py


import numpy as np

class EllipticCurve():
    def __init__(self, a, b, p = np.inf):
        """
            This class represents an elliptic curve of the form y^2 = x^3 + ax + b

            Parameters
            ----------
            a : int
                The value of a in the equation
            b : int
                The value of b in the equation
            p : int
                The prime number used to define the field

            a and b must be such that 4a^3 + 27b^2 != 0
        """
        self.a = a
        self.b = b
        self.p = p

        if self.is_singular():
            raise ValueError("The function is singular at this point")

    def is_singular(self):
        """
            This function checks if the function is singular. A function is singular if 4a^3 + 27b^2 = 0
        """
        if 4*self.a**3 + 27*self.b**2 == 0:
            return True
        return False

    def f(self, x, y):
        """
            This function returns the value of the function at the point (x, y)
        """
        z = y**2 - (x**3 + self.a*x + self.b)
        return z

    def y(self, x):
        """
            This function returns the y-coordinates of the points on the curve with the given x-coordinate
        """
        return np.sqrt((x**3 + self.a*x + self.b))

    def add(self, p: tuple, q: tuple):
        """
            This function adds two points on the curve

            Parameters
            ----------
            p : tuple
                The first point on the curve
            q : tuple
                The second point on the curve
        """

        # Compute the slope of the line between p and q
        if p[0] == q[0] and p[1] == q[1]:
            # Doubling of points.
            if p[0] == 0:
                return (np.inf, np.inf)
            m = (3*p[0]**2 + self.a)/(2*p[1])
        if p[0] == q[0]:
            # Point negation, so the line is vertical. The slope is infinite. return the additive identity (O,O).
            return (np.inf, np.inf)
        if p == (np.inf, np.inf):
            # Point at infinity (O,O) + (x, y) = (x, y)
            return q
        if q == (np.inf, np.inf):
            # Point at infinity (x, y) + (O,O) = (x, y)
            return p
        else:
            # Addition for two distinct points is the negation of the intersection point of the line between p and q and the curve
            m = (q[1] - p[1])/(q[0] - p[0])

        # Compute the x-coordinate of the point r
        x = m**2 - p[0] - q[0]
        # Compute the y-coordinate of the point r
        y = m*(p[0] - x) - p[1]

        # If the x-coordinate is greater than the key size, then we need to reduce it modulo the key size
        if x > self.p:
            x = x % self.p

        return (x, y)

    def multiply(self, p: tuple, k: int):
        pi = p
        for i in range(k):
            pi = self.add(pi, p)
        return pi

    def dot(self, p:tuple, q:tuple, k:int):
        """
            This function performs the dotting operation between two points on the curve.

            Parameters
            ----------
            p : tuple
                The first point on the curve.
            q : tuple
                The second point on the curve. The point is used to determine the initial slope.
            k : int
                The number of times the point p is added to itself.
        """

        for i in range(k):
            q = self.add(q, p)
        return q


from setuptools import setup, find_packages

def parse_requirements(requirements):
    with open(requirements, "r") as req_file:
        return [line.strip('\n') for line in req_file if line.strip('\n')
                and not line.startswith('#')]

requires = parse_requirements("requirements.txt")

with open('README.md') as f:
    long_description = f.read()

setup(
    name="typesense_orm",
    packages=find_packages(),
    version="0.0.15",
    description="A typesense-server client using orm paradigm based on pydantic",
    long_description=long_description,
    long_description_content_type="text/markdown",
    author="Oleg Demianchenko",
    author_email="oleg.demianchenko@gmail.com",
    license="MIT",
    platforms="OS Independent",
    url="https://github.com/RedSnail/typesense_orm",
    python_requires='>=3.8',
    include_package_data=False,
    build_requires=["wheel"],
    install_requires=requires
)


import siliconcompiler
import os

def main():
    root = os.path.dirname(__file__)
    chip = siliconcompiler.Chip('mkFibOne')
    chip.input(f'{root}/FibOne.bsv')
    chip.set('option', 'frontend', 'bluespec')
    # default Bluespec clock pin is 'CLK'
    chip.clock(pin='CLK', period=5)
    chip.load_target("freepdk45_demo")
    chip.run()
    chip.summary()
    chip.show()

if __name__ == '__main__':
    main()


from __future__ import print_function
import argparse
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.optim.lr_scheduler import StepLR
from loaders import load
import time
import pandas
import sys
from ast import literal_eval
import numpy as np
from torch import autograd

import os
from tensorboardX import SummaryWriter

from uuid import uuid4

from tqdm.auto import tqdm
from helpers import add_argument, fstr, save_dict
import defaults

class Net(nn.Module):
    """ default pytorch example """
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, 3, 1)
        self.conv2 = nn.Conv2d(32, 64, 3, 1)
        self.dropout1 = nn.Dropout2d(0.25)
        self.dropout2 = nn.Dropout2d(0.5)
        self.fc1 = nn.Linear(9216, 128)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = F.relu(x)
        x = self.conv2(x)
        x = F.relu(x)
        x = F.max_pool2d(x, 2)
        x = self.dropout1(x)
        x = torch.flatten(x, 1)
        x = self.fc1(x)
        x = F.relu(x)
        x = self.dropout2(x)
        x = self.fc2(x)
        output = F.log_softmax(x, dim=1)
        return output

class Perturb(nn.Module):
    """ constant perturbation """
    def __init__(self, shape):
        super(Perturb, self).__init__()
        self.delta = nn.Parameter(torch.zeros(shape))

    def forward(self):
        return self.delta

def config(**kwargs):
    # Training settings
    parser = argparse.ArgumentParser(description='learning in games')
    train = parser.add_argument_group('train')
    test = parser.add_argument_group('test')
    run = parser.add_argument_group('run')

    add_argument(train, 'seed',             1, 'random seed', 'S')
    add_argument(train, 'dataset',         'mnist', 'dataset', choices=['mnist'])
    add_argument(train, 'batch_size',       200, 'input batch size for training', 'N')
    add_argument(train, 'test_batch_size',  1000, 'input batch size for testing', 'N')
    add_argument(train, 'epochs',           20, 'number of epochs to train', 'N')
    add_argument(train, 'lr1',              0.2, 'learning rate for classifier', 'LR')
    add_argument(train, 'lr2',              1.0, 'learning rate for adversary', 'LR')
    add_argument(train, 'lr_rate1',         1e-5, 'learning rate decay const for classifier', 'M')
    add_argument(train, 'lr_class1',       '1/t', 'learning rate decay function', 'FN', choices=['1/t','1/tlogt'] )
    add_argument(train, 'lr_rate2',         3e-6, 'learning rate decay const for adversary', 'M')
    add_argument(train, 'lr_class2',       '1/tlogt', 'learning rate decay function', 'FN', choices=['1/t','1/tlogt'] )
    add_argument(train, 'perturb_reg',      0.000001, 'regularization on adversarial perturbation', 'REG')

    add_argument(run, 'no_cuda',            False, 'disables CUDA training')
    add_argument(run, 'save_model',         True, 'For Saving the current Model')
    add_argument(run, 'log_interval',       10, 'how many batches to wait before logging training status', 'N')
    add_argument(run, 'datadir',           'data', 'directory of dataset')
    add_argument(run, 'storedir',           defaults.STORE_DIR, 'directory to store checkpoints')
    add_argument(run, 'epoch',              1, 'Epoch to resume running at')
    add_argument(run, 'log_smooth',         0.5, 'logging smoothness parameter')
    add_argument(run, 'last_iter',          -1, 'Last iteration')

    add_argument(test, 'adv_epsilon',       1., 'magnitude of adversarial perturbation')
    add_argument(test, 'adv_norm',         'inf', 'norm of adversarial perturbation', \
                 choices=['abs', 'l2','inf'])

    parser.set_defaults(**kwargs)
    try:
        # hack for detecting a jupyter lab notebook
        if get_ipython().__class__.__name__ == 'ZMQInteractiveShell':
            args = parser.parse_args('')
    except:
        args = parser.parse_args()
    return args

def init(args, device, shape, last_iter=-1):
    model = Net().to(device)
    perturb = Perturb(shape).to(device)

    def lr(t, mode='1/t'):
        if mode == '1/t': return t
        elif mode == '1/tlogt': return t*np.log(t+1)
        else: raise NotImplemented

    opt1 = optim.SGD(model.parameters(), lr=args.lr1 )
    lr1 = lambda t: args.lr1/(args.lr_rate1*lr(t, mode=args.lr_class1) + 1)
    sch1 = optim.lr_scheduler.LambdaLR(opt1, lr1, last_epoch=-1)#args.last_iter)

    opt2 = optim.SGD(perturb.parameters(), lr=args.lr2)
    lr2 = lambda t: args.lr2/(args.lr_rate2*lr(t, mode=args.lr_class2) + 1)
    sch2 = optim.lr_scheduler.LambdaLR(opt2, lr2, last_epoch=-1)#args.last_iter)

    return (model, perturb), (opt1, opt2), (sch1, sch2)

def loss(model, delta, batch):
    (data, target) = batch
    output = model(data + delta)
    return F.nll_loss(output, target)

def train(state, args, models, device, loader, optimizers, schedulers, logger):
    model, perturb = models
    model.train()

    iterator = tqdm(enumerate(loader), total=len(loader))

    f1_smooth = 0
    f2_smooth = 0
    for batch_idx, (data, target) in iterator:
        batch = data.to(device), target.to(device)
        data, target = batch

        optimizers[0].zero_grad()

        delta = perturb()
        f1 = loss(model, delta, batch)
        f1.backward()

        optimizers[0].step()
        optimizers[1].zero_grad()

        delta = perturb()
        perturb_norm = torch.sum(delta*delta)/2
        f2 = -loss(model, delta, batch) + args.perturb_reg*perturb_norm

        f2.backward()

        optimizers[1].step()

        f1_smooth = (1-args.log_smooth)*f1_smooth + args.log_smooth*f1
        f2_smooth = (1-args.log_smooth)*f2_smooth + args.log_smooth*f2

        out = {'loss0':f1, 'loss1':f2, 'loss_sum':f1+f2, 'norm_delta':perturb_norm}

        if batch_idx % args.log_interval == 0:
            logger.append(state['iter'], out)
            desc = (f'{args.loop_msg} | Loss: {f1_smooth:6.3f},{f2_smooth:6.3f} | norm(delta):{perturb_norm:8.5f} ||')
            iterator.set_description(desc)
            iterator.refresh()

        schedulers[0].step()
        schedulers[1].step()
        state['iter'] += 1

def test(state, args, model, device, test_loader, logger):
    model.eval()
    test_loss = 0
    correct = 0
    with torch.no_grad():
        iterator = tqdm(enumerate(test_loader), total=len(test_loader))
        for idx, (data, target) in iterator:
            data, target = data.to(device), target.to(device)
            output = model(data)
            test_loss += F.nll_loss(output, target, reduction='sum').item()  # sum up batch loss
            pred = output.argmax(dim=1, keepdim=True)  # get the index of the max log-probability
            correct += pred.eq(target.view_as(pred)).sum().item()
            desc = (f'Test | Loss: {test_loss:10.3f}, {correct}/{len(test_loader.dataset)}({correct/((idx+1)/test_loader.batch_size*len(test_loader.dataset))}%)')
            iterator.set_description(desc)
            iterator.refresh()

    test_loss /= len(test_loader.dataset)
    out = {'test_accuracy': correct/len(test_loader.dataset)}
    logger.append(state['iter'], out)
    return out

def test_adv(state, args, model, device, test_loader, logger=None, loop_msg='Adversarial Test'):
    model.eval()

    iterator = tqdm(enumerate(test_loader), total=len(test_loader))
    correct = 0
    adv_correct = 0
    for idx, (data, target) in iterator:
        data, target = data.to(device), target.to(device)
        perturb = torch.tensor(torch.zeros(*test_loader.shape), requires_grad=True, device=device)
        output = model(data + perturb)
        loss = F.nll_loss(output, target)
        pred = output.argmax(dim=1, keepdim=True)
        correct += pred.eq(target.view_as(pred)).sum().item()

        Dperturb_loss = autograd.grad(loss, perturb)[0]

        if args.adv_norm == 'infty':
            Dperturb_loss = torch.sign(Dperturb_loss)
        elif args.adv_norm == 'l2':
            Dperturb_loss /= torch.norm(Dperturb_loss)
            Dperturb_loss *= torch.norm(torch.ones(*Dperturb_loss.shape))
        elif args.adv_norm == 'noise':
            Dperturb_loss = torch.rand_like(Dperturb_loss)
        else:
            raise NotImplemented()

        adv_data = data + args.adv_epsilon*Dperturb_loss
        adv_output = model(adv_data)
        adv_pred = adv_output.argmax(dim=1, keepdim=True)
        adv_correct += adv_pred.eq(target.view_as(adv_pred)).sum().item()

        desc = (f'Test ({args.adv_epsilon:.2f}-{args.adv_norm}) | Loss: {loss:8.3f}, {adv_correct}/{len(test_loader.dataset)}')
        iterator.set_description(desc)

    accuracy = correct/len(test_loader.dataset)
    adv_accuracy = adv_correct/len(test_loader.dataset)
    out = {'test_accuracy': accuracy, 'adv_accuracy': adv_accuracy, 'adv_data': adv_data}
    if logger: logger.append(state['iter'], out)
    return out

class Logger():
    def __init__(self, writer=None):
        self.df = pandas.DataFrame()
        self.writer = writer

    def append(self, iter, other):
        self.df = self.df.append(other, ignore_index=True)
        if self.writer:
            for arg,val in other.items():
                self.writer.add_scalar(arg, val, iter)
    def to_pickle(self, path):
        self.df.to_pickle(path)

def eval(exp_dir, epoch):
    with open(os.path.join(exp_dir, 'args.txt'), 'r') as f:
        kwargs = literal_eval(f.readline())
        args = config(**kwargs)
    logger = Logger()
    print(f"lr1={args.lr1} lr2={args.lr2}")
    (train_loader, test_loader), device = load(args)
    models, optimizers = init(args, device, shape=train_loader.shape)
    state = {"iter": np.nan}
    save_model = os.path.join(exp_dir, f'save{epoch:03d}.pt')
    save_perturb = os.path.join(exp_dir, f'save_perturb{epoch:03d}.pt')
    out = {}
    try:
        models[0].load_state_dict(torch.load(save_model))
        models[1].load_state_dict(torch.load(save_perturb))
        out = test(state, args, models[0], device, test_loader, logger)
        delta = [_ for _ in models[1].parameters()][0]
        img = torchvision.utils.make_grid(delta, normalize=True)
        torchvision.utils.save_image(img, os.path.join(exp_dir, f'perturb{epoch:03d}.png'))
    except:
        print("model not found")
    return dict(lr1=args.lr1, lr2=args.lr2, **out)

def main(exp_id=str(uuid4())):
    state = dict(iter=0, start_time=time.time())
    args = config(exp_id=exp_id)

    # try to make the store dir (if it doesn't exist)
    exp_dir = os.path.join(args.storedir, exp_id)
    try:
        os.makedirs(exp_dir)
    except OSError as e:
        print("Directory exists ({e.message})")

    writer = SummaryWriter(exp_dir)
    logger = Logger(writer)

    (train_loader, test_loader), device = load(args)
    models, optimizers, schedulers = init(args, device, shape=train_loader.shape, last_iter=args.last_iter)

    for epoch in range(1, args.epochs + 1):
        args.epoch = epoch
        args.last_iter = epoch*len(train_loader)
        args.loop_msg = fstr(defaults.LOOP_MSG, args=args)

        train(state, args, models, device, train_loader, optimizers, schedulers, logger)
        test(state, args, models[0], device, test_loader, logger)

        logger.to_pickle(os.path.join(args.storedir, exp_id, 'store.pkl'))
        if args.save_model:
            for model, savefile in zip(models, defaults.SAVE_FILES):
                torch.save(model.state_dict(), os.path.join(exp_dir, fstr(savefile, args=args)))
            save_dict(vars(args), os.path.join(exp_dir, defaults.ARG_FILE))

if __name__ == '__main__':
    main()


import cv2 as cv
import numpy as np

import padding

XSIZE = 64
YSIZE = 64
MAX_HEIGHT = 965
MAX_WIDTH = 997

def get_video_flow_stacks(video_list):
    stacked_videos = []
    index = 1
    print(str(len(video_list)) + "amount of videos")
    for val in video_list:
        print(str(index) + " out of " + str(len(video_list)))
        index = index + 1
        cap = cv.VideoCapture("data/TV-HI/"+val) #get the feed of the video_list
        middle_frame = int(cap.get(cv.CAP_PROP_FRAME_COUNT) / 2)
        ret, first_frame = cap.read()
        prev_gray = cv.cvtColor(first_frame, cv.COLOR_BGR2GRAY) # set the first frame to gray scale and use it for the first optical flow comparison
        # prev_gray = padding.add_padding(prev_gray, MAX_HEIGHT, MAX_WIDTH, gray=True)
        prev_gray = padding.pad_and_resize(prev_gray, YSIZE, XSIZE, gray=True)
        # prev_gray = cv.resize(prev_gray, (XSIZE, YSIZE), interpolation=cv.INTER_NEAREST)
        counter = 1
        stacked_frames = []

        while (cap.isOpened()):
            ret, frame = cap.read()
            if frame is not None:
                # cv.imshow("input", frame)
                gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) #gray scale of the next frame
                # gray = cv.resize(gray, (XSIZE, YSIZE), interpolation=cv.INTER_NEAREST)
                # gray = padding.add_padding(gray, MAX_HEIGHT, MAX_WIDTH, gray=True)
                gray = padding.pad_and_resize(gray, YSIZE, XSIZE, gray=True)

                if counter >= middle_frame - 10 and counter <= middle_frame + 9:
                    flow = cv.calcOpticalFlowFarneback(prev_gray, gray, None, 0.5, 3, 15, 3, 5, 1.2, 0)
                    horz = cv.normalize(flow[..., 0], None, 0, 255, cv.NORM_MINMAX)
                    vert = cv.normalize(flow[..., 1], None, 0, 255, cv.NORM_MINMAX)
                    horz = horz.astype('uint8')
                    vert = vert.astype('uint8')
                    # cv.imshow('Horizontal Component', horz)
                    # cv.imshow('Vertical Component', vert)
                    stacked_frames.append(horz/255)
                    stacked_frames.append(vert/255)

                # Updates previous frame
                prev_gray = gray
                counter = counter + 1
            else:
                cap.release()

        frame_stack = np.asarray(stacked_frames)
        frame_stack = np.transpose(frame_stack, (1,2,0))
        stacked_videos.append(frame_stack)

    return stacked_videos

def get_middle_frames(video_list):
    image_list = []
    index = 1
    print(str(len(video_list)) + "amount of videos")
    for val in video_list:
        print(str(index) + " out of " + str(len(video_list)))
        index = index + 1

        cap = cv.VideoCapture("data/TV-HI/" + val)
        middle_frame = int(cap.get(cv.CAP_PROP_FRAME_COUNT) / 2)
        counter = 1
        while (cap.isOpened()):
            ret, frame = cap.read()
            # frame = padding.add_padding(frame, MAX_HEIGHT, MAX_WIDTH)
            frame = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
            frame = padding.pad_and_resize(frame, YSIZE, XSIZE, gray=True)
            if frame is not None:
                if counter == middle_frame:
                    # cv.imshow('Testing', frame)
                    image_list.append(frame)
                    cap.release()
                    # cv.waitKey(0)
            counter = counter + 1

    return np.asarray(image_list)


import requests
import csv
from pprint import pprint

# HEART RATE ON THIS DAY
def get_heartrate(user_id, access_token):
    heart_rate_request = requests.get('https://api.fitbit.com/1/user/' + user_id + '/activities/heart/date/2020-08-16/2020-08-31.json',
                                     headers={'Authorization': 'Bearer ' + access_token})
    if (heart_rate_request.status_code != 200):
        print('Error fetching heartrate request. Need a new access token')
    else:
        # pprint(heart_rate_request.json()['activities-heart'])
        data = heart_rate_request.json()['activities-heart']
        # d = data[0]
        # print(d['dateTime'])
        # print(d['value']['restingHeartRate'])

        # extract heart rate values to new csv file
        with open("./csv/heartrate.csv", "w", newline='') as csv_file:
            writer = csv.writer(csv_file, delimiter=',')
            for line in data:
                # print(line['value']['restingHeartRate'])
                writer.writerow([line['dateTime'], line['value']['restingHeartRate']])


data = [int(row) for row in open("input1.txt").read().split(",")]

def parse_op(value):
    opcode = value % 100
    p1 = (value // 100) % 10
    p2 = (value // 1000) % 10
    p3 = (value // 10000) % 10
    return opcode, p1, p2, p3

def get_increment(opcode):
    if opcode in [1, 2, 7, 8]:
        return 4
    elif opcode in [3, 4]:
        return 2
    elif opcode in [5, 6]:
        return 3
    raise NotImplementedError(f"Unknown Opcode {opcode}")

def get_value(mode, index, data, inputs):
    if mode == 0:
        return data[index]
    elif mode == 1:
        return index
    raise NotImplementedError("Unknown parameter mode")

def process(index, data, inputs, outputs):
    op, m1, m2, m3 = parse_op(data[index])

    try:
        p1 = get_value(m1, data[index + 1], data, inputs)
    except:
        p1 = None

    try:
        p2 = get_value(m2, data[index + 2], data, inputs)
    except:
        p2 = None

    try:
        p3 = get_value(m3, data[index + 3], data, inputs)
    except:
        p3 = None

    if op == 99:
        return None, data, inputs, outputs
    elif op == 1:
        data[data[index + 3]] = p1 + p2
    elif op == 2:
        data[data[index + 3]] =  p1 *   p2
    elif op == 3:
        data[data[index + 1]] = next(inputs)
    elif op == 4:
        outputs.append(p1)
    elif op == 5:
        if p1 != 0:
            return p2, data, inputs, outputs
    elif op == 6:
        if p1 == 0:
            return p2, data, inputs, outputs
    elif op == 7:
        if p1 < p2:
            data[data[index + 3]] = 1
        else:
            data[data[index + 3]] = 0
    elif op == 8:
        if p1 == p2:
            data[data[index + 3]] = 1
        else:
            data[data[index + 3]] = 0

    return index + get_increment(op), data, inputs, outputs

def constant_inputs(x):
    while True:
        yield x

def part1(data):
    index = 0
    inputs = constant_inputs(1)
    outputs = []
    while index is not None:
        index, data, inputs, outputs = process(index, data, inputs, outputs)

    print(outputs[-1])

def part2(data):
    index = 0
    inputs = constant_inputs(5)
    outputs = []
    while index is not None:
        index, data, inputs, outputs = process(index, data, inputs, outputs)

    print(outputs[-1])

part1(data[:])
part2(data[:])


import pygame
import random

pygame.init()

# Set up the game window
width = 1200
height = 700
game_display = pygame.display.set_mode((width, height))
pygame.display.set_caption('Snake Game')

# Set up some colors
white = (255, 255, 255)
black = (0, 0, 0)
red = (255, 0, 0)
food_amount = 3

# Set up the snake block size and speed
block_size = 20
clock = pygame.time.Clock()
snake_speed = 30

# Set up the font for the score display
font = pygame.font.SysFont(None, 25)
font2 = pygame.font.SysFont(None, 15)

# Define a function to display the score
def score(score):
    text = font.render("Score: "+str(score), True, black)
    game_display.blit(text, [0, 0])

# Define a function to display the math question on the top of the game window
def math_question(first_num, second_num, operator):
    text = font.render(str(first_num) + " " + operator + " " + str(second_num) + " = ?", True, black)
    game_display.blit(text, [0, 20])

# Define the main game loop
def game_loop():
    game_over = False
    game_close = False

    # Set up the initial position and length of the snake
    x1 = 600
    y1 = 300
    x1_change = 0
    y1_change = 0
    snake_list = []
    length_of_snake = 1

    # Set up the initial position of the food
    food_positions = []

    # Set up the math question
    first_num = random.randint(1, 10)
    second_num = random.randint(1, 10)
    food_x = round(random.randrange(0, width - block_size) / 20.0) * 20.0
    food_y = round(random.randrange(0, height - block_size) / 20.0) * 20.0

    operator = random.choice(["+", "-", "*"])
    if operator == "+":
        correct_answer = first_num + second_num
    elif operator == "-":
        correct_answer = first_num - second_num
    else:
        correct_answer = first_num * second_num

    food_positions.append((food_x, food_y, font.render(str(correct_answer), True, black), 'good'))

    for i in range(food_amount):  # generate 2 foods
        food_x = round(random.randrange(0, width - block_size) / 20.0) * 20.0
        food_y = round(random.randrange(0, height - block_size) / 20.0) * 20.0
        food_number = random.randrange(correct_answer - 5, correct_answer + 5, 1)
        if food_number == correct_answer:
            food_number = correct_answer + 1
        food_text = font.render(str(food_number), True, black)
        food_positions.append((food_x, food_y, food_text, 'bad'))

    # Main game loop
    while not game_over:
        # If the game is over, display the final score and wait for the user to quit the game
        while game_close == True:
            game_display.fill(white)
            score(length_of_snake - 1)

            message("Przegrałeś! Wciśnij Q aby wyjść lub C aby grać dalej", red)
            pygame.display.update()

            # Wait for user input to either quit or restart the game
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_q:
                        game_over = True
                        game_close = False
                    if event.key == pygame.K_c:
                        game_loop()

        # Main event loop
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_over = True
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    x1_change = -block_size
                    y1_change = 0
                elif event.key == pygame.K_RIGHT:
                    x1_change = block_size
                    y1_change = 0
                elif event.key == pygame.K_UP:
                    y1_change = -block_size
                    x1_change = 0
                elif event.key == pygame.K_DOWN:
                    y1_change = block_size
                    x1_change = 0

        # If the snake hits the boundaries of the game window, end the game
        if x1 >= width or x1 < 0 or y1 >= height or y1 < 0:
            game_close = True

        # Update the position of the snake and the length of the snake if it eats the food
        x1 += x1_change
        y1 += y1_change
        game_display.fill(white)

        if not food_positions:
            # Set up the math question
            first_num = random.randint(1, 10)
            second_num = random.randint(1, 10)
            food_x = round(random.randrange(0, width - block_size) / 20.0) * 20.0
            food_y = round(random.randrange(0, height - block_size) / 20.0) * 20.0
            operator = random.choice(["+", "-", "*"])
            if operator == "+":
                correct_answer = first_num + second_num
            elif operator == "-":
                correct_answer = first_num - second_num
            else:
                correct_answer = first_num * second_num

            # Add the correct answer to the food positions
            food_positions.append((food_x, food_y, font.render(str(correct_answer), True, black), 'good'))

            picked_numbers = [correct_answer]
            for i in range(food_amount):
                food_x = round(random.randrange(0, width - block_size) / 20.0) * 20.0
                food_y = round(random.randrange(0, height - block_size) / 20.0) * 20.0
                food_number = random.randrange(correct_answer - 5, correct_answer + 5, 1)
                if food_number in picked_numbers:
                    food_number = correct_answer + 1
                picked_numbers.append(food_number)
                food_text = font.render(str(food_number), True, black)
                food_positions.append((food_x, food_y, food_text, 'bad'))

            picked_numbers.clear()

        # Draw all the food items
        for food in food_positions:
            pygame.draw.rect(game_display, red, [food[0], food[1], block_size, block_size])
            food_text_rect = food[2].get_rect(center=(food[0] + block_size / 2, food[1] + block_size / 2))
            game_display.blit(food[2], food_text_rect)

        # If the snake eats a food item, remove it from the list and increase the length of the snake
        for food in food_positions:
            if x1 == food[0] and y1 == food[1] and food[3] == 'bad':
                game_close = True
                break
            if x1 == food[0] and y1 == food[1]:
                food_positions.clear()
                length_of_snake += 1

        snake_head = []
        snake_head.append(x1)
        snake_head.append(y1)
        snake_list.append(snake_head)
        if len(snake_list) > length_of_snake:
            del snake_list[0]

        # If the snake hits itself, end the game
        for x in snake_list[:-1]:
            if x == snake_head:
                game_close = True

        # Draw the snake
        for x in snake_list:
            pygame.draw.rect(game_display, black, [x[0], x[1], block_size, block_size])

        # Update the score and the display
        score(length_of_snake - 1)
        math_question(first_num, second_num, operator)

        pygame.display.update()

        # Update the clock and the snake speed
        clock.tick(snake_speed)

    # Quit the game and the Pygame library
    pygame.quit()
    quit()

def message(msg, color):
    screen_text = font.render(msg, True, color)
    game_display.blit(screen_text, [width / 2 - 200, height / 2])

# Call the main game loop
game_loop()


import json
import requests
import os

def get_task_job_delete(url,path):
    res = requests.get(url)
    jobs = json.loads(res.text)["jobs"]

    for job in jobs:
        if job["state"] == "FINISHED":
            os.remove(path + "/" + job["jid"])

if __name__ == '__main__':
    url = "http://10.0.1.12:59696/jobs/overview"
    get_task_job_delete(url,"/opt/appShare/flink-history")


# -*- coding: utf-8 -*-
"""
Created on Tue Sep 28 14:59:51 2021

@author: Bruno
"""
#CONFIGURAÇÔES
# Sempre usar no cabeçalho (préambulo) matplotlib e scypi
# Os erros aqui no cabeçalho são devidos ao não uso dos pacotes durante o código,
# um dos erros permite identificar funções onde não especifiquei de qual pacote vem e
# o outro apenas alerta que o pacote não foi usado.

from scipy import *
from matplotlib import *
import numpy as np
import matplotlib.pyplot as plt
import math as mt
import scipy.linalg as sl

# --------------------------- Exercício 4.1 -------------------------------------------------------

M = np.array([[1,2,3],
              [4,5,6],
              [7,8,9],
              [10,11,12]])

M1 = np.arange(13)
M1 = M1[1:]
M2 = M1.reshape(np.shape(M))

for i in np.arange(4):
     for j in np.arange(3):
         if M[i,j] != M2[i,j]:
             print("As matrizes são diferentes")
             break
         if i == 3 and j ==2 and M[i,j] == M2[i,j]:
             print("As matrizes são identicas")

print(M[2,:])
print(M[2:])


import time
from qtsp_subtree.src import TSP_utilities
from qtsp_subtree.src.forest_tsp_solver import ForestTSPSolver
import numpy as np
import pdb
import csv
import sys
import random

def run_testing_sequence(number_of_nodes=3, is_random=False):
    file_time = time.time()
    results_file = open("phase_3_results_" + str(file_time) + ".csv", 'w')
    angles_file = open("phase_3_angles_" + str(file_time) + ".csv", 'w')

    results_file.write("steps,tol,time,valid_prob,best_valid,optimal_cost,forest_cost,best_sol_prob\n")
    csv_writer = csv.writer(results_file)
    csv_writer_angles = csv.writer(angles_file)
    possible_steps = [3, 2, 1]
    possible_xtol = [1e-4, 1e-3, 1e-2]
    if is_random:
        np.random.seed(17638)
        random.seed(17638)
        while True:
            nodes_array = TSP_utilities.create_nodes_array(3)
            # nodes_array = np.array([[0,0], [0,7], [0,14]])
            steps = random.choice(possible_steps)
            xtol = random.choice(possible_xtol)
            run_single_tsp(nodes_array, csv_writer, csv_writer_angles, steps, xtol)
    else:
        for steps in possible_steps:
            for xtol in possible_xtol:
                for i in range(10):
                    run_single_tsp(nodes_array, csv_writer, csv_writer_angles, steps, xtol)
    results_file.close()

def run_single_tsp(nodes_array, csv_writer, csv_writer_angles, steps, xtol, all_ones=-2):
    params = [steps, xtol]
    print(steps, xtol)
    ftol = xtol
    start_time = time.time()
    forest_solver = ForestTSPSolver(nodes_array, steps=steps, xtol=xtol, ftol=ftol, all_ones_coefficient=all_ones)

    [betas, gammas] = forest_solver.find_angles()
    print(betas)
    print(gammas)

    forest_solver.betas = betas
    forest_solver.gammas = gammas
    results = forest_solver.get_results()
    end_time = time.time()
    calculation_time = end_time - start_time
    metrics = calculate_metrics(results, calculation_time)

    brute_force_solution = TSP_utilities.solve_tsp_brute_force(nodes_array)
    cost_matrix = TSP_utilities.get_tsp_matrix(nodes_array)
    optimal_cost = TSP_utilities.calculate_cost(cost_matrix, brute_force_solution)

    solution = forest_solver.get_solution()
    forest_cost = TSP_utilities.calculate_cost(cost_matrix, solution)
    best_solution_probability = results[0][1]

    row = params + metrics + [optimal_cost, forest_cost, best_solution_probability]
    print(row)
    [print(el) for el in forest_solver.create_cost_operators()]
    if csv_writer is not None:
        csv_writer.writerow(row)
        csv_writer_angles.writerow(row)
        csv_writer_angles.writerow(betas)
        csv_writer_angles.writerow(gammas)
        csv_writer_angles.writerow("\n")
    sys.stdout.flush()

def check_if_solution_is_valid(solution):
    solution = list(solution)
    number_of_nodes = int(np.sqrt(len(solution)))
    time_groups = [solution[number_of_nodes*i:number_of_nodes*(i+1)] for i in range(number_of_nodes)]
    for group in time_groups:
        if np.sum(group) != 1:
            return False
        if time_groups.count(group) != 1:
            return False
    return True

def calculate_metrics(results, calculation_time):
    valid_results_probability = 0
    for entry in results:
        if check_if_solution_is_valid(entry[0]):
            valid_results_probability += entry[1]

    best_result = results[0][0]
    best_result_valid = check_if_solution_is_valid(best_result)
    return [calculation_time, valid_results_probability, best_result_valid]

def main():
    run_testing_sequence(number_of_nodes=3, is_random=True)
    # nodes_array = np.array([[0,0], [0, 5], [0, 10]])
    # run_single_tsp(nodes_array, None, 3, 1e-4, 2)

if __name__ == '__main__':
    main()


from flask import render_template, session, current_app, abort, jsonify, request, g

from info import constants
from info.models import User, News, Category
from info.response_code import RET
from info.utils.common import user_login_data
from . import index_blu

@index_blu.route('/')
@user_login_data
def index():
    # 获取到当前登录用户的id
    # 从session中获取
    # user_id = session.get('user_id')
    # user = None
    # if user_id:
    #     try:
    #         user = User.query.get(user_id)
    #     except Exception as e:
    #         current_app.logger.error(e)
    # 使用g变量获取用户登陆信息
    user = g.user
    # 右侧新闻排行
    clicks_news = []
    # 按照点击量排序查询出点击最高的前10条新闻
    try:
        clicks_news = News.query.order_by(News.clicks.desc()).limit(constants.CLICK_RANK_MAX_NEWS).all()
    except Exception as e:
        current_app.logger.error(e)
    # 将对象字典添加到列表中
    # 获取新闻分类数据
    # 定义列表保存分类数据
    # category_id = []
    try:
        category_id = Category.query.filter(Category.id).all()  # 分类id
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='新闻分类查询错误')
    # 拼接内容
    # 返回数据
    data = {'user': user if user else None,
            'news_dict': clicks_news,
            'categories': category_id}
    # 返回给前端查询结果
    return render_template('news/index.html', data=data)

@index_blu.route('/news_list')
def news_list():
    """
    获取首页新闻数据
    :return:
    """
    # 1. 获取参数,并指定默认为最新分类,第一页,一页显示10条数据
    page = request.args.get('page', 1)   # 页数，不传即获取第1页
    per_page = request.args.get('per_page',constants.HOME_PAGE_MAX_NEWS)  # 每页多少条数据，如果不传，默认10条
    cid = request.args.get('cid', 0)  # 分类id
    print(page, per_page, cid)
    # 校验
    if not all([page, per_page, cid]):
        return jsonify(errno=RET.PARAMERR, errmsg='新闻列表获取错误')
    # 整数化
    page = int(page)
    per_page = int(per_page)
    cid = int(cid)
    # 当前新闻状态
    filters = [News.status == 0]
    # 如果分类id不为1，那么添加分类id的过滤
    if cid != 1:
        filters.append(News.category_id == cid)
    # 3. 查询数据并分页，paginate一个方法
    try:
        paginate = News.query.filter(*filters).order_by(News.create_time.desc()).paginate(page, per_page, False)
        paginates = paginate.items
        news = [i.to_dict() for i in paginates]
        # 获取总页数
        total_page = paginate.pages
        # 当前页数
        current_page = paginate.page
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='新闻列表错误')
    # 2. 校验参数
	  # 默认选择最新数据分类
    # 3. 查询数据
    # 将模型对象列表转成字典列表
    data = {'total_page': total_page,
            'news_dict_list': news}
    #返回数据
    return jsonify(errno=RET.OK,errmsg='列表数据显示完成', currentPage= current_page, data = data)


class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        if not matrix or not matrix[0]:
            return matrix
        m, n = len(matrix), len(matrix[0])
        point_list = []
        for i in range(m):
            for j in range(n):
                if matrix[i][j] == 0:
                    point_list.append([i, j])

        for point in point_list:
            for j in range(n):
                matrix[point[0]][j] = 0
            for i in range(m):
                matrix[i][point[1]] = 0


import os
from urllib import parse

from linode_api4.errors import UnexpectedResponseError
from linode_api4.objects import (
    Base,
    DerivedBase,
    MappedObject,
    Property,
    Region,
)
from linode_api4.objects.networking import IPAddress

class NodeBalancerNode(DerivedBase):
    """
    The information about a single Node, a backend for this NodeBalancer’s configured port.

    API documentation: https://www.linode.com/docs/api/nodebalancers/#node-view
    """

    api_endpoint = (
        "/nodebalancers/{nodebalancer_id}/configs/{config_id}/nodes/{id}"
    )
    derived_url_path = "nodes"
    parent_id_name = "config_id"

    properties = {
        "id": Property(identifier=True),
        "config_id": Property(identifier=True),
        "nodebalancer_id": Property(identifier=True),
        "label": Property(mutable=True),
        "address": Property(mutable=True),
        "weight": Property(mutable=True),
        "mode": Property(mutable=True),
        "status": Property(),
        "tags": Property(mutable=True),
    }

    def __init__(self, client, id, parent_id, nodebalancer_id=None, json=None):
        """
        We need a special constructor here because this object's parent
        has a parent itself.
        """
        if not nodebalancer_id and not isinstance(parent_id, tuple):
            raise ValueError(
                "NodeBalancerNode must either be created with a nodebalancer_id or a tuple of "
                "(config_id, nodebalancer_id) for parent_id!"
            )

        if isinstance(parent_id, tuple):
            nodebalancer_id = parent_id[1]
            parent_id = parent_id[0]

        DerivedBase.__init__(self, client, id, parent_id, json=json)

        self._set("nodebalancer_id", nodebalancer_id)

class NodeBalancerConfig(DerivedBase):
    """
    The configuration information for a single port of this NodeBalancer.

    API documentation: https://www.linode.com/docs/api/nodebalancers/#config-view
    """

    api_endpoint = "/nodebalancers/{nodebalancer_id}/configs/{id}"
    derived_url_path = "configs"
    parent_id_name = "nodebalancer_id"

    properties = {
        "id": Property(identifier=True),
        "nodebalancer_id": Property(identifier=True),
        "port": Property(mutable=True),
        "protocol": Property(mutable=True),
        "algorithm": Property(mutable=True),
        "stickiness": Property(mutable=True),
        "check": Property(mutable=True),
        "check_interval": Property(mutable=True),
        "check_timeout": Property(mutable=True),
        "check_attempts": Property(mutable=True),
        "check_path": Property(mutable=True),
        "check_body": Property(mutable=True),
        "check_passive": Property(mutable=True),
        "ssl_cert": Property(mutable=True),
        "ssl_key": Property(mutable=True),
        "ssl_commonname": Property(),
        "ssl_fingerprint": Property(),
        "cipher_suite": Property(mutable=True),
        "nodes_status": Property(),
        "proxy_protocol": Property(mutable=True),
    }

    @property
    def nodes(self):
        """
        This is a special derived_class relationship because NodeBalancerNode is the
        only api object that requires two parent_ids

        Returns a paginated list of NodeBalancer nodes associated with this Config.
        These are the backends that will be sent traffic for this port.

        API documentation: https://www.linode.com/docs/api/nodebalancers/#nodes-list

        :returns: A paginated list of NodeBalancer nodes.
        :rtype: PaginatedList of NodeBalancerNode
        """
        if not hasattr(self, "_nodes"):
            base_url = "{}/{}".format(
                NodeBalancerConfig.api_endpoint,
                NodeBalancerNode.derived_url_path,
            )
            result = self._client._get_objects(
                base_url,
                NodeBalancerNode,
                model=self,
                parent_id=(self.id, self.nodebalancer_id),
            )

            self._set("_nodes", result)

        return self._nodes

    def node_create(self, label, address, **kwargs):
        """
        Creates a NodeBalancer Node, a backend that can accept traffic for this
        NodeBalancer Config. Nodes are routed requests on the configured port based
        on their status.

        API documentation: https://www.linode.com/docs/api/nodebalancers/#node-create

        :param address: The private IP Address where this backend can be reached.
                        This must be a private IP address.
        :type address: str

        :param label: The label for this node. This is for display purposes only.
                      Must have a length between 2 and 32 characters.
        :type label: str

        :returns: The node which is created successfully.
        :rtype: NodeBalancerNode
        """
        params = {
            "label": label,
            "address": address,
        }
        params.update(kwargs)

        result = self._client.post(
            "{}/nodes".format(NodeBalancerConfig.api_endpoint),
            model=self,
            data=params,
        )
        self.invalidate()

        if not "id" in result:
            raise UnexpectedResponseError(
                "Unexpected response creating node!", json=result
            )

        # this is three levels deep, so we need a special constructor
        n = NodeBalancerNode(
            self._client, result["id"], self.id, self.nodebalancer_id, result
        )
        return n

    def load_ssl_data(self, cert_file, key_file):
        """
        A convenience method that loads a cert and a key from files and sets them
        on this object.  This can make enabling ssl easier (instead of you needing
        to load the files yourself).

        This does *not* change protocol/port for you, or save anything.  Once this
        is called, you must still call `save()` on this object for the changes to
        take effect.

        :param cert_file: A path to the file containing the public certificate
        :type cert_file: str
        :param key_file: A path to the file containing the unpassphrased private key
        :type key_file: str
        """
        # access a server-loaded field to ensure this object is loaded from the
        # server before setting values.  Failing to do this can cause an unloaded
        # object to overwrite these values on a subsequent load, which happens to
        # occur on a save()
        _ = self.ssl_fingerprint

        # we're disabling warnings here because these attributes are defined dynamically
        # through linode.objects.Base, and pylint isn't privy
        if os.path.isfile(os.path.expanduser(cert_file)):
            with open(os.path.expanduser(cert_file)) as f:
                self.ssl_cert = f.read()

        if os.path.isfile(os.path.expanduser(key_file)):
            with open(os.path.expanduser(key_file)) as f:
                self.ssl_key = f.read()

class NodeBalancer(Base):
    """
    A single NodeBalancer you can access.

    API documentation: https://www.linode.com/docs/api/nodebalancers/#nodebalancer-view
    """

    api_endpoint = "/nodebalancers/{id}"
    properties = {
        "id": Property(identifier=True),
        "label": Property(mutable=True),
        "hostname": Property(),
        "client_conn_throttle": Property(mutable=True),
        "status": Property(),
        "created": Property(is_datetime=True),
        "updated": Property(is_datetime=True),
        "ipv4": Property(relationship=IPAddress),
        "ipv6": Property(),
        "region": Property(slug_relationship=Region),
        "configs": Property(derived_class=NodeBalancerConfig),
        "transfer": Property(),
        "tags": Property(),
    }

    # create derived objects
    def config_create(self, **kwargs):
        """
        Creates a NodeBalancer Config, which allows the NodeBalancer to accept traffic
        on a new port. You will need to add NodeBalancer Nodes to the new Config before
        it can actually serve requests.

        API documentation: https://www.linode.com/docs/api/nodebalancers/#config-create

        :returns: The config that created successfully.
        :rtype: NodeBalancerConfig
        """
        params = kwargs

        result = self._client.post(
            "{}/configs".format(NodeBalancer.api_endpoint),
            model=self,
            data=params,
        )
        self.invalidate()

        if not "id" in result:
            raise UnexpectedResponseError(
                "Unexpected response creating config!", json=result
            )

        c = NodeBalancerConfig(self._client, result["id"], self.id, result)
        return c

    def config_rebuild(self, config_id, nodes, **kwargs):
        """
        Rebuilds a NodeBalancer Config and its Nodes that you have permission to modify.
        Use this command to update a NodeBalancer’s Config and Nodes with a single request.

        API documentation: https://www.linode.com/docs/api/nodebalancers/#config-rebuild

        :param config_id: The ID of the Config to access.
        :type config_id: int

        :param nodes: The NodeBalancer Node(s) that serve this Config.
        :type nodes: [{ address: str, id: int, label: str, mode: str, weight: int }]

        :returns: A nodebalancer config that rebuilt successfully.
        :rtype: NodeBalancerConfig
        """
        params = {
            "nodes": nodes,
        }
        params.update(kwargs)

        result = self._client.post(
            "{}/configs/{}/rebuild".format(
                NodeBalancer.api_endpoint, parse.quote(str(config_id))
            ),
            model=self,
            data=params,
        )

        if not "id" in result:
            raise UnexpectedResponseError(
                "Unexpected response rebuilding config!", json=result
            )

        return NodeBalancerConfig(self._client, result["id"], self.id, result)

    def statistics(self):
        """
        Returns detailed statistics about the requested NodeBalancer.

        API documentation: https://www.linode.com/docs/api/nodebalancers/#nodebalancer-statistics-view

        :returns: The requested stats.
        :rtype: MappedObject
        """
        result = self._client.get(
            "{}/stats".format(NodeBalancer.api_endpoint), model=self
        )

        if not "title" in result:
            raise UnexpectedResponseError(
                "Unexpected response generating stats!", json=result
            )
        return MappedObject(**result)


def anagrams(self, strs):
    hashmap = {}

    for string in strs:
        string = ''.join(sorted(string))
        hashmap[string] = hashmap.get(string, 0) + 1

    result = []
    for string in strs:
        sortedString = ''.join(sorted(string))
        if sortedString in hashmap and hashmap[sortedString] > 1:
            result.append(string)
    return result

class Solution:
    """
    @param strs: A list of strings
    @return: A list of strings
    """

    def anagrams(self, strs):
        # write your code here
        words_dict = {}
        key_to_dict = {}

        for word in strs:
            word_dict = {}
            for c in word:
                word_dict[c] = word_dict.get(c, 0) + 1

            is_found = False
            for key in key_to_dict:
                if key_to_dict[key] == word_dict:
                    is_found = True
                    words_dict[key].append(word)
                    break
            if not is_found:
                key_to_dict[word] = word_dict
                words_dict[word] = [word]

        results = []

        for key in words_dict:
            if len(words_dict[key]) < 2:
                continue
            for word in words_dict[key]:
                results.append(word)
        return results


from concurrent.futures import thread
import socket
import sys
from time import sleep
import webbrowser
from threading import Thread

from model import wallet
from model.blockchain import Blockchain
from network import p2p_server
from server import server

def get_ip_address():
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(('254.254.254.254', 1))
        return s.getsockname()[0]
    except:
        return '127.0.0.1'

if __name__ == '__main__':
    http_port = None
    p2p_port = None
    try:
        http_port = int(sys.argv[1])
        p2p_port = int(sys.argv[2])
    except:
        if http_port is None:
            http_port = 5000
        if p2p_port is None:
            p2p_port = 6000

    ip = get_ip_address()
    blockchain = Blockchain()
    p2p_thread = Thread(target=p2p_server.init, args=[ip, p2p_port, blockchain])
    p2p_thread.daemon = True
    p2p_thread.start()

    http_thread = Thread(target=server.run, args=[ip, http_port, p2p_port, blockchain])
    http_thread.start()

    sleep(2)

    webbrowser.open(f'http://{ip}:{http_port}')


import io

import pytest
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.core.files.base import File
from PIL import Image
from variations import processors

from app.models import DummyResource
from paper_uploads import helpers, validators

class TestGetFilename:
    def test_camelcase(self):
        assert helpers.get_filename("/tmp/folder/File Name.JpEg") == "File Name"

    def test_no_extension(self):
        assert helpers.get_filename("/tmp/file") == "file"

class TestGetExtensions:
    def test_camelcase(self):
        assert helpers.get_extension("/tmp/folder/File Name.JpEg") == "JpEg"

    def test_no_extension(self):
        assert helpers.get_extension("/tmp/file") == ""

class TestBuildVariations:
    variations = None

    def setup_method(self):
        from paper_uploads.conf import settings

        old_setting = settings.VARIATION_DEFAULTS
        settings.VARIATION_DEFAULTS = dict(
            size=(640, 480),
            jpeg=dict(
                quality=92,
                progressive=True
            ),
            webp=dict(
                lossless=True,
                quality=90,
            ),
            postprocessors=[
                processors.ColorOverlay("#FF0000", overlay_opacity=0.25),
            ],
        )

        self.variations = helpers.build_variations(
            dict(
                desktop=dict(
                    size=(1600, 0),
                    clip=False,
                    postprocessors=[],
                    jpeg=dict(
                        quality=80,
                    ),
                ),
                tablet=dict(
                    size=(1024, 0),
                    clip=False,
                    versions={"webp", "2x"},
                    jpeg=dict(
                        quality=75,
                    ),
                ),
                tablet_webp=dict(
                    size=(1200, 0),
                    clip=False,
                    format="WEBP",
                    webp=dict(
                        quality=60,
                    ),
                ),
                mobile=dict(
                    size=(640, 0),
                    clip=False,
                ),
                micro=dict(
                    name="square",  # overriden name
                    size=(200, 200),
                    versions={"2x"},
                ),
            )
        )

        # restore option
        settings.VARIATION_DEFAULTS = old_setting

    def test_count(self):
        # 3 normal variations + 3 implicit for `tablet`
        assert len(self.variations) == 8

    def test_overriden_name(self):
        assert "square" in self.variations
        assert "square_2x" in self.variations
        assert "micro" not in self.variations
        assert "micro_2x" not in self.variations

    def test_size_overriden(self):
        assert self.variations["desktop"].size == (1600, 0)
        assert self.variations["tablet"].size == (1024, 0)
        assert self.variations["mobile"].size == (640, 0)

    def test_extra_context_replaced(self):
        assert self.variations["desktop"].extra_context["jpeg"] == {
            "quality": 80,
        }
        assert self.variations["tablet"].extra_context["jpeg"] == {
            "quality": 75,
        }
        assert self.variations["mobile"].extra_context["jpeg"] == {
            "quality": 92,
            "progressive": True,
        }

    def test_postprocessors_replaced(self):
        assert self.variations["desktop"].postprocessors == []
        assert isinstance(
            self.variations["tablet"].postprocessors[0], processors.ColorOverlay
        )
        assert isinstance(
            self.variations["mobile"].postprocessors[0], processors.ColorOverlay
        )

    def test_names(self):
        assert self.variations["desktop"].name == "desktop"
        assert self.variations["tablet"].name == "tablet"
        assert self.variations["mobile"].name == "mobile"
        assert self.variations["tablet_webp"].name == "tablet_webp"
        assert self.variations["tablet_2x"].name == "tablet_2x"
        assert self.variations["tablet_webp_2x"].name == "tablet_webp_2x"
        assert self.variations["square"].name == "square"
        assert self.variations["square_2x"].name == "square_2x"

    def test_retina_size(self):
        assert self.variations["tablet_2x"].size == (2048, 0)
        assert self.variations["tablet_webp_2x"].size == (2048, 0)
        assert self.variations["square"].size == (200, 200)
        assert self.variations["square_2x"].size == (400, 400)

    def test_webp_format(self):
        assert self.variations["tablet_2x"].format == "AUTO"
        assert self.variations["tablet_webp"].format == "WEBP"
        assert self.variations["tablet_webp_2x"].format == "WEBP"

    def test_explicit_overwrite_version(self):
        assert self.variations["tablet_webp"].size == (1200, 0)
        assert self.variations["tablet_webp"].extra_context["webp"]["quality"] == 60

    def test_invalid_versions(self):
        with pytest.raises(ValueError):
            helpers.build_variations(dict(
                demo=dict(
                    versions={"2x", "7x", "png"}
                )
            ))

class TestIterateVariationNames:
    def test_plain(self):
        names = helpers.iterate_variation_names(dict(
            desktop=dict(
                size=(200, 300)
            ),
            mobile=dict(
                size=(200, 300)
            ),
        ))
        assert set(names) == {"desktop", "mobile"}

    def test_webp(self):
        names = helpers.iterate_variation_names(dict(
            desktop=dict(
                size=(200, 300),
                versions={"webp"}
            ),
            mobile=dict(
                size=(200, 300)
            ),
        ))
        assert set(names) == {"desktop", "desktop_webp", "mobile"}

    def test_retina(self):
        names = helpers.iterate_variation_names(dict(
            desktop=dict(
                size=(200, 300),
                versions={"2x"}
            ),
            mobile=dict(
                size=(200, 300)
            ),
        ))
        assert set(names) == {"desktop", "desktop_2x", "mobile"}

    def test_mixed(self):
        names = helpers.iterate_variation_names(dict(
            desktop=dict(
                size=(200, 300),
                versions={"webp", "2x"}
            ),
            mobile=dict(
                size=(200, 300),
                versions={"2x", "3x"}
            ),
        ))
        assert set(names) == {
            "desktop", "desktop_webp", "desktop_2x", "desktop_webp_2x",
            "mobile", "mobile_2x", "mobile_3x"
        }

class TestImplicitVariations:
    variations = None

    def setup_method(self):
        self.variations = helpers.build_variations(
            dict(
                tablet=dict(
                    upscale=True,
                    anchor="br",
                    versions={"webp", "2x", "3x", "4x"},
                ),
            )
        )

    def test_count(self):
        # 1 normal variations + 7 implicit for `tablet`
        assert len(self.variations) == 8

    def test_names(self):
        assert self.variations["tablet"].name == "tablet"
        assert self.variations["tablet_webp"].name == "tablet_webp"
        assert self.variations["tablet_2x"].name == "tablet_2x"
        assert self.variations["tablet_3x"].name == "tablet_3x"
        assert self.variations["tablet_4x"].name == "tablet_4x"
        assert self.variations["tablet_webp_2x"].name == "tablet_webp_2x"
        assert self.variations["tablet_webp_3x"].name == "tablet_webp_3x"
        assert self.variations["tablet_webp_4x"].name == "tablet_webp_4x"

    def test_shared_params(self):
        for variation in self.variations.values():
            assert variation.upscale is True
            assert variation.anchor == (1, 1)

@pytest.mark.django_db
class TestGetResourceModelTrees:
    def test_concrete_count(self):
        trees = helpers.get_resource_model_trees()
        assert len(trees) == 11

    def test_proxy_count(self):
        trees = helpers.get_resource_model_trees(include_proxy=True)
        assert len(trees) == 11

    def test_concrete_heights(self):
        trees = helpers.get_resource_model_trees()
        tree_heights = [tree.height for tree in trees]
        height_map = {
            value: len([item for item in tree_heights if item == value])
            for value in set(tree_heights)
        }
        assert height_map == {0: 10, 1: 1}

    def test_proxy_heights(self):
        trees = helpers.get_resource_model_trees(include_proxy=True)
        tree_heights = [tree.height for tree in trees]
        height_map = {
            value: len([item for item in tree_heights if item == value])
            for value in set(tree_heights)
        }
        assert height_map == {0: 8, 1: 2, 2: 1}

@pytest.mark.django_db
class TestGetCollectionTrees:
    # Дерево всегда начинается с Collection, поэтому тестируются
    # элементы, начиная со второгь уровня.

    def test_concrete_count(self):
        trees = helpers.get_collection_trees()
        assert len(trees[0].children) == 1

    def test_proxy_count(self):
        trees = helpers.get_collection_trees(include_proxy=True)
        assert len(trees[0].children) == 6

    def test_concrete_heights(self):
        trees = helpers.get_collection_trees()
        tree_heights = [tree.height for tree in trees[0].children]
        height_map = {
            value: len([item for item in tree_heights if item == value])
            for value in set(tree_heights)
        }
        assert height_map == {0: 1}

    def test_proxy_heights(self):
        trees = helpers.get_collection_trees(include_proxy=True)
        tree_heights = [tree.height for tree in trees[0].children]
        height_map = {
            value: len([item for item in tree_heights if item == value])
            for value in set(tree_heights)
        }
        assert height_map == {0: 5, 1: 1}

@pytest.mark.django_db
def test_get_instance():
    resource = DummyResource.objects.create(id=1)

    assert helpers.get_instance("app", "dummyresource", 1) == resource
    assert helpers.get_instance("app", "dummyresource", 1, using="default") == resource

    with pytest.raises(ObjectDoesNotExist):
        assert helpers.get_instance("app", "dummyresource", 2)

def test_run_validators():
    with File(io.BytesIO(), name="file.jpeg") as file:
        with Image.new("RGB", (640, 480)) as img:
            img.save(file, format="JPEG")

        try:
            helpers.run_validators(
                file,
                [
                    validators.ExtensionValidator(["jpg"]),
                    validators.ImageMinSizeValidator(800, 600),
                    validators.ImageMaxSizeValidator(1024, 800),
                ],
            )
        except ValidationError as exc:
            assert len(exc.messages) == 2
            assert (
                "has an invalid extension. Valid extension(s): jpg" in exc.messages[0]
            )
            assert (
                "is too small. Image should be at least 800x600 pixels."
                in exc.messages[1]
            )