import numpy as np
import pandas as pd

from .weight_base import WeightBase

class WeiAge(WeightBase):
    """
    Calculates weights which will make
    the age distribution uniform
    """
    name = 'wei_age'

    def __init__(self,
                 data: pd.DataFrame):
        super(WeiAge, self).__init__(
            data,
        )

    def calculate(self) -> np.ndarray:
        values = self._data.age

        ages, counts = np.unique(
            values,
            return_counts=True
        )
        n_rows = len(self._data)
        n_categories = len(ages)

        wei = np.zeros(len(self._data))

        for age, count in zip(ages, counts):
            wei[values == age] = n_rows / (
                    (values == age).astype(int).sum() * n_categories
            )

        return wei


"Sample code to get hardware information."
from ctypes import (
    c_short,
    c_char_p,
    byref,
)

from thorlabs_kinesis import benchtop_stepper_motor as bsm

if __name__ == "__main__":
    serial_no = c_char_p(bytes("40875459", "utf-8"))
    channel = c_short(1)

    if bsm.SBC_Open(serial_no) == 0:
        print("Is channel valid ", bsm.SBC_IsChannelValid(serial_no, channel))

        hw_info = bsm.TLI_HardwareInformation()  # container for hw info
        err = bsm.SBC_GetHardwareInfoBlock(serial_no, channel, byref(hw_info))
        if err == 0:
            print("Serial No: ", hw_info.serialNumber)
            print("Model No: ", hw_info.modelNumber)
            print("Firmware Version: ", hw_info.firmwareVersion)
            print("Number of  Channels: ", hw_info.numChannels)
            print("Type: ", hw_info.type)
        else:
            print(f"Error getting HW Info Block. Error Code: {err}")

        bsm.SBC_Close(serial_no)


"""remove_product_rating_score

Revision ID: 177cf327b079
Revises: acf2fa2bcf67
Create Date: 2023-05-26 14:43:55.049871

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = "177cf327b079"
down_revision = "acf2fa2bcf67"
branch_labels = None
depends_on = None

def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column("product_rating", "score")
    # ### end Alembic commands ###

def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column(
        "product_rating",
        sa.Column("score", sa.INTEGER(), autoincrement=False, nullable=False),
    )
    # ### end Alembic commands ###


class Solution(object):
    # O(n**2)
    def shortestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        i, j = 0, len(s)-1
        while j >= 0:
            if s[i] == s[j]:
                i += 1
            j -= 1
        if i == len(s):
            return s
        mid = s[:i]
        suffix = s[i:]
        return suffix[::-1]+self.shortestPalindrome(mid)+suffix

    # KMP <=> O(n)
    def shortestPalindrome_kmp(self, s):
        tmp = s + '#' + s[::-1]
        tbl = self.getTable(tmp)
        return s[tbl[-1]:][::-1] + s

    def getTable(self, s):
        tbl = [0]*len(s)
        idx = 0
        for i in range(1, len(s)):
            if s[idx] == s[i]:
                tbl[i] = tbl[i-1]+1
                idx += 1
            else:
                idx = tbl[i-1]
                while idx > 0 and s[idx] != s[i]:
                    idx = tbl[idx-1]
                if s[idx] == s[i]:
                    idx += 1
                tbl[i] = idx
        return tbl

    def test(self):
        testCases = [
            'aacecaaa',
            'abcd',
            'aacecabccaa',
        ]
        for s in testCases:
            print('s: %s' % (s))
            result = self.shortestPalindrome(s)
            res = self.shortestPalindrome_kmp(s)
            print('result: %s' % result)
            print('res: %s' % res)
            print('-='*20+'-')

if __name__ == '__main__':
    Solution().test()


from __future__ import annotations
import math
from typing import TYPE_CHECKING
from adapter.path_adapter import PathAdapter, PathAttributeID
from adapter.straight_adapter import StraightAdapter
from common.image_manager import ImageID
from entity_base.image.image_state import ImageState
from models.path_models.path_segment_state.abstract_segment_state import AbstractSegmentState, SerializedSegmentStateState
from models.path_models.path_segment_state.arc_segment_state import ArcSegmentState
from models.path_models.path_segment_state.bezier_segment_state import BezierSegmentState
from models.path_models.path_segment_state.segment_type import SegmentType
from models.path_models.path_segment_state.straight_segment_state import StraightSegmentState
from models.path_models.segment_direction import SegmentDirection
from entities.root_container.field_container.segment.arc_segment_entity import ArcSegmentEntity
from entities.root_container.field_container.segment.bezier_segment_entity import BezierSegmentEntity
from entities.root_container.field_container.segment.straight_segment_entity import StraightSegmentEntity
from models.project_history_interface import ProjectHistoryInterface
from services.constraint_solver_service import ConstraintSolver
from utility.format_functions import formatDegrees, formatInches
from utility.math_functions import distanceTuples, thetaFromPoints
if TYPE_CHECKING:
    from entities.root_container.field_container.field_entity import FieldEntity
    from models.path_models.path_node_model import PathNodeModel
    from models.path_models.path_model import PathModel
    from entity_base.entity import Entity

from models.path_models.path_element_model import PathElementModel, SerializedPathElementState

class SerializedPathSegmentState(SerializedPathElementState):

    def __init__(self, direction: SegmentDirection, states: dict[SegmentType, SerializedSegmentStateState], current: SegmentType):
        self.direction = direction
        self.states = states
        self.current = current

    def _deserialize(self, pathModel: PathModel) -> 'PathNodeModel':
        segment = PathSegmentModel(pathModel)
        segment.direction = self.direction

        segment.states = {}
        for key, value in self.states.items():
            segment.states[key] = value.deserialize(segment)

        segment.currentStateType = self.current

        segment.generateUI()
        return segment

    def makeAdapterDeserialized(self):
        for state in self.states.values():
            state.adapter.makeDeserialized()

class PathSegmentModel(PathElementModel):

    def makeAdapterSerialized(self):
        for state in self.states.values():
            state.adapter.makeSerialized()

    def _serialize(self) -> SerializedPathSegmentState:
        sStates: dict[SegmentType, SerializedSegmentStateState] = {}
        for key, value in self.states.items():
            sStates[key] = value.serialize()

        return SerializedPathSegmentState(self.direction, sStates, self.currentStateType)

    def __init__(self, pathModel: PathModel):
        super().__init__(pathModel)

        self.direction = SegmentDirection.FORWARD

        self.states: dict[SegmentType, AbstractSegmentState] = {
            SegmentType.STRAIGHT: StraightSegmentState(self),
            SegmentType.ARC: ArcSegmentState(self),
            SegmentType.BEZIER: BezierSegmentState(self)
        }

        self.currentStateType = SegmentType.STRAIGHT
        self.bConstraints = None # before theta constraint solver
        self.aConstraints = None # after theta constraint solver

        self.generateUI()

    """
    UPDATE methods that update values based on model state
    """

    # update thetas based on segment states and segment direction
    def updateThetas(self):

        # need to recompute state thetas first
        self.getState().onUpdate()

        self.START_THETA = self.getState().getStartTheta()
        self.END_THETA = self.getState().getEndTheta()

        # if segment is reversed, flip thetas
        if self.getDirection() == SegmentDirection.REVERSE:
            self.START_THETA = (self.START_THETA + math.pi) % (2 * math.pi)
            self.END_THETA = (self.END_THETA + math.pi) % (2 * math.pi)

        self.getAdapter().set(PathAttributeID.THETA1, self.START_THETA, formatDegrees(self.START_THETA))
        self.getAdapter().set(PathAttributeID.THETA2, self.END_THETA, formatDegrees(self.END_THETA))

    # called when the distance of the segment is changed
    def updateDistance(self):
        self.DISTANCE = distanceTuples(self.getPrevious().getPosition(), self.getNext().getPosition())
        # if segment is reversed, negate distance
        if self.getDirection() == SegmentDirection.REVERSE:
            self.DISTANCE *= -1

        self.getAdapter().set(PathAttributeID.DISTANCE, self.DISTANCE, formatInches(self.DISTANCE))

    # Update adapter for endpoint position
    def updateEndpointPosition(self, node: PathNodeModel):

        # new endpoint position
        pos = node.getPosition()

        # update the correct endpoint
        if self.getPrevious() == node:
            x, y = PathAttributeID.X1, PathAttributeID.Y1
        else:
            x, y = PathAttributeID.X2, PathAttributeID.Y2

        # set adapter
        self.getAdapter().set(x, pos[0], formatInches(pos[0]))
        self.getAdapter().set(y, pos[1], formatInches(pos[1]))

    """
    CALLBACK METHODS FOR WHEN THINGS NEED TO BE UPDATED
    """

    def onInit(self):
        self.updateThetas()
        self.updateDistance()
        self.updateEndpointPosition(self.getPrevious())
        self.updateEndpointPosition(self.getNext())

        self.getPrevious().onThetaChange()
        self.getNext().onThetaChange()

    def onInitSegmentOnly(self):
        self.updateThetas()
        self.updateDistance()
        self.updateEndpointPosition(self.getPrevious())
        self.updateEndpointPosition(self.getNext())

    # called when a node attached to segment is moved
    def onNodePositionChange(self, node: PathNodeModel = None):
        # assert that node is attached to segment
        assert(node is None or node == self.getPrevious() or node == self.getNext())

        # update segment start/end thetas
        self.updateThetas()
        self.getPrevious().onThetaChange()
        self.getNext().onThetaChange()

        # update segment distance
        self.updateDistance()

        if node is None:
            self.updateEndpointPosition(self.getPrevious())
            self.updateEndpointPosition(self.getNext())
            self.getPrevious().onThetaChange()
            self.getNext().onThetaChange()
        else:
            # update endpoint that changed
            self.updateEndpointPosition(node)
            # update the other endpoint's angle
            self.getOther(node).onThetaChange()

        # redraw segment ui. No need to update segment model as
        # segment endpoint positions are just refs to node models
        self.recomputeUI()

    """
    SETTER METHODS THAT MODIFY MODEL AND THEN SEND NOTIF TO UPDATE UI
    """

    def setState(self, type: SegmentType):

        assert(type in self.states)
        self.currentStateType = type

        # callback for state change
        self.getState().onSwitchToState()

        self.onInit()

        # regenerate ui with new state
        self.generateUI()
        self.recomputeUI()

        command = self.path.getCommandFromPath(self)
        command.setNewAdapter(self.getAdapter())
        command.rebuild()
        command.ui.recomputeEntity()

        # absolutely atrocious code to dig through interactor shit to
        # sustain menu across changing segment entity
        self.ui.interactor.removeAllEntities()
        self.ui.interactor.addEntity(self.ui)

    def toggleDirection(self):
        if self.direction == SegmentDirection.FORWARD:
            self.direction = SegmentDirection.REVERSE
        else:
            self.direction = SegmentDirection.FORWARD
        self.getState()._updateIcon()

        self.updateThetas()
        self.getPrevious().onThetaChange()
        self.getNext().onThetaChange()

    """
    GETTER METHODS THAT READ FROM MODEL. DO NOT MODIFY MODEL OR SEND NOTIFICATIONS
    """

    def getState(self) -> AbstractSegmentState:
        return self.states[self.currentStateType]

    def getStraightState(self) -> StraightSegmentState:
        return self.states[SegmentType.STRAIGHT]

    def getArcState(self) -> ArcSegmentState:
        return self.states[SegmentType.ARC]

    def getBezierState(self) -> BezierSegmentState:
        return self.states[SegmentType.BEZIER]

    def getAdapter(self) -> PathAdapter:
        return self.getState().getAdapter()

    def getPrevious(self) -> PathNodeModel:
        return super().getPrevious()

    def getNext(self) -> PathNodeModel:
        return super().getNext()

    def getBeforePos(self) -> tuple:
        return self.getPrevious().getPosition()

    def getAfterPos(self) -> tuple:
        return self.getNext().getPosition()

    def getStartTheta(self) -> float:
        return self.START_THETA

    def getEndTheta(self) -> float:
        return self.END_THETA

    def getDirection(self) -> SegmentDirection:
        return self.direction

    def getType(self) -> SegmentType:
        return self.getState().getType()

    def getCenterInches(self) -> tuple:
        return self.getState()._defineCenterInches()

    def getOther(self, node: PathNodeModel) -> PathNodeModel:
        if node == self.getPrevious():
            return self.getNext()
        elif node == self.getNext():
            return self.getPrevious()
        else:
            raise Exception("Node not attached to segment")

    # initialize constraint solver for snapping to before node with angle (arc/bezier)
    def initBeforeThetaConstraints(self):
        self.bConstraints = ConstraintSolver(self.field)

        prevNode = self.getPrevious()

        # snap to cardinal directions for itself
        self.bConstraints.addCardinalConstraints(prevNode)

        # if segment before prevNode exists, snap to segment end angle
        prevSegment = prevNode.getPrevious()
        if prevSegment is not None:
            prevAngle = prevSegment.getEndTheta()
            self.bConstraints.addAngleConstraint(prevNode, prevAngle)

    # initialize constraint solver for snapping to after node with angle (arc/bezier)
    def initAfterThetaConstraints(self):
        self.aConstraints = ConstraintSolver(self.field)

        prevNode = self.getPrevious()

        # snap to cardinal directions for itself
        self.aConstraints.addCardinalConstraints(prevNode)

        # if segment before prevNode exists, snap to segment end angle
        prevSegment = prevNode.getPrevious()
        if prevSegment is not None:
            prevAngle = prevSegment.getEndTheta()
            self.aConstraints.addAngleConstraint(prevNode, prevAngle)

    # given a hypothetical start theta, return the "snapped" version if close enough
    # return None if no snapping
    def getConstrainedStartTheta(self, startTheta: float) -> float | None:
        snappedTheta = self.bConstraints.constrainAngle(startTheta)

        if snappedTheta is None:
            # nothing to snap
            return None
        else:
            # can snap
            return snappedTheta

    # given a hypothetical start theta, return the "snapped" version if close enough
    # return None if no snapping
    def getConstrainedEndTheta(self, endTheta: float) -> float | None:
        snappedTheta = self.aConstraints.constrainAngle( endTheta)

        if snappedTheta is None:
            # nothing to snap
            return None
        else:
            # can snap
            return snappedTheta

    """
    PRIVATE METHODS
    """

    def _generateUI(self, fieldEntity: FieldEntity) -> Entity:
        if self.getType() == SegmentType.STRAIGHT:
            return StraightSegmentEntity(fieldEntity, self)
        elif self.getType() == SegmentType.ARC:
            return ArcSegmentEntity(fieldEntity, self)
        elif self.getType() == SegmentType.BEZIER:
            return BezierSegmentEntity(fieldEntity, self)
        else:
            raise Exception("Invalid segment type")

    def __str__(self) -> str:
        return f"PathSegmentModel"


import argparse
import mmread_utils as mmu
import pickle as pkl

def parse_annots(fn):
    """
    Columns are:
    * 0 - run_barcode
    * 1 - cell_ontology_class
    * 17 - tissue
    """

    annots_dict = {}
    for i, line in enumerate(open(fn)):
        if i == 0: continue

        line = line.split(',')
        if len(line[1]) == 0:
            continue
        ## Combine cell types with spaces in them
        elif line[1][0] == '"':
            annot = [line[1]]
            idx = 2
            while line[idx][-1] != '"':
                annot.append(line[idx])
                idx += 1
            annot.append(line[idx])
            annot = ';'.join(annot)
            annot = annot[1:-1]
        else:
            annot = line[1]
            idx = 1

        re_rep = r"\s+"
        cell_type = (f'{re.subn(re_rep, "_", line[idx+16])[0]}:'
        f'{re.subn(re_rep, "_", annot)[0]}')
        annots_dict[line[0]] = cell_type

    return(annots_dict)

def load_sj_genes_num(gd):
    """
    Return dictionary structure:
    sj (chrom, start_pos, end_pos, strand):
        {gene_ids}
    """
    sj_list = f'{gd}/sjdbList.fromGTF.out.tab'

    sj_genes_dict = {}
    for line in open(sj_list, 'r'):
        line = line.strip().split('\t')
        # Fix chromosome
        line[0] = line[0].strip('chr')
        if line[0] == 'X':
            line[0] = '23'
        elif line[0] == 'Y':
            line[0] = '24'
        elif line[0][0] in {'M', 'm'}:
            line[0] = '25'
        elif not re.match(r'^[0-9]+$', line[0]):
            continue
        # Fix sign
        line[3] = '1' if line[3] == '+' else '2'
        idx = tuple(map(int, line[:4]))
        sj_genes_dict[idx] = set(map(int, line[4].split(',')))

    return(sj_genes_dict)

################################################################################
def get_args():
    parser = argparse.ArgumentParser(description='')

    parser.add_argument('-i')
    parser.add_argument('-o')
    parser.add_argument('-gd')
    parser.add_argument('-annots')

    return(parser.parse_args())

def main():
    args = get_args()

    annots_dict = parse_annots(args.annots)

    ## Load gene counts
    all_counts_gene_orig, mtx_fns_gene = mmu.load_all_gene_counts(args.i)

    ## Load SJ counts
    sj_annots = load_sj_genes_num(args.gd)
    all_sjs, sj_lists = mmu.get_all_sjs(args.i, sj_annots)
    all_counts_sj, mtx_fns_sj = mmu.load_all_sj_counts(args.i, all_sjs,
        sj_lists)

    ## Make sure both mats are in CSR format
    all_counts_sj = all_counts_sj.tocsr()
    all_counts_gene_orig = all_counts_gene_orig.tocsr()

    ## Need to add on to the mats so there's 1:1 sj:gene
    ##  (some SJs have multiple genes)
    all_counts_sj, all_counts_gene, sj_ord, g_idx = mmu.adjust_mats(
        all_counts_sj, all_counts_gene_orig, all_sjs, sj_annots)

    ## Split up gene and SJ counts
    genes_dict, _ = mmu.split_counts_mat(all_counts_gene, mtx_fns_gene,
        annots_dict)
    sj_dict, _ = mmu.split_counts_mat(all_counts_sj, mtx_fns_sj, annots_dict)
    genes_dict_orig, cell_bcs = mmu.split_counts_mat(all_counts_gene_orig, mtx_fns_gene,
        annots_dict)

    pkl.dump([sj_dict, genes_dict, sj_ord, genes_dict_orig, g_idx, cell_bcs],
        open(args.o, 'wb'))

if __name__ == '__main__':
    main()


class Produto:
    def __init__(self, nome, valor):
        self.nome = nome
        self.valor = valor

class CarrinhoCompras:
    def __init__(self, ):
        self.produtos = []

    def inserir_produto(self, produto):
        self.produtos.append(produto)

    def lista_produtos(self):
        for produto in self.produtos:
            print(f'{produto.nome}: R${produto.valor}')

    def soma_total(self):
        total = 0
        for produto in self.produtos:
            total += produto.valor
        return f'R${total}'

carrinho = CarrinhoCompras()
p1 = Produto('Boné', 50)
p2 = Produto('Tênis', 100)
p3 = Produto('Camiseta', 39)
carrinho.inserir_produto(p1)
carrinho.inserir_produto(p2)
carrinho.inserir_produto(p3)
carrinho.lista_produtos()
print(carrinho.soma_total())


from sklearn.linear_model import LassoCV

def run(x_train, y_train, x_test, y_test, eps, n_alphas, alphas, fit_intercept, normalize, precompute, max_iter, tol, copy_X, cv, verbose, n_jobs,
        positive, random_state, selection):
    reg = LassoCV(eps=eps,
                  n_alphas=n_alphas,
                  alphas=alphas,
                  fit_intercept=fit_intercept,
                  normalize=normalize,
                  precompute=precompute,
                  max_iter=max_iter,
                  tol=tol,
                  copy_X=copy_X,
                  cv=cv,
                  verbose=verbose,
                  n_jobs=n_jobs,
                  positive=positive,
                  random_state=random_state,
                  selection=selection).fit(x_train, y_train)
    return {'train_predict': reg.predict(x_train).tolist(),
            'test_predict': reg.predict(x_test).tolist(),
            'train_score': reg.score(x_train, y_train),
            'test_score': reg.score(x_test, y_test),
            'alpha_': reg.alpha_,
            'coef_': reg.coef_.tolist(),
            'intercept_': reg.intercept_,
            'mse_path_': reg.mse_path_.tolist(),
            'alphas_': reg.alphas_.tolist(),
            'dual_gap_': reg.dual_gap_.tolist(),
            'n_iter_': reg.n_iter_}


#%%
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
import matplotlib.ticker as ticker
from matplotlib import rcParams
import numpy as np
from highlight_text import fig_text
import pandas as pd

from PIL import Image
import urllib
import os

df = pd.read_csv("success_rate_2022_2023.csv", index_col = 0)
df = (
        df
        .sort_values(by = ["variable", "value"], ascending = True)
        .reset_index(drop = True)
)

fig = plt.figure(figsize=(6.5, 10), dpi = 200, facecolor="#EFE9E6")
ax = plt.subplot(111, facecolor = "#EFE9E6")

# Adjust spines
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)

ax.grid(True, color = "lightgrey", ls = ":")

# Define the series
teams = list(df["team_id"].unique())
Y = np.arange(len(teams))
X_xg = df[df["variable"] == "2022_success_rate"]["value"]
X_goals = df[df["variable"] == "2023_success_rate"]["value"]

# Fix axes limits
ax.set_ylim(-.5, len(teams) - .5)
ax.set_xlim(
    min(X_goals.min(), X_xg.min(), 35),
    max(X_goals.max(), X_xg.max(), 55)
)

# Scatter plots
ax.scatter(X_xg, Y, color = "#74959A", s = 200, alpha = 1, zorder = 3)
ax.scatter(X_goals, Y, color = "#495371", s = 200, alpha = 1, zorder = 3)
ax.scatter(X_xg, Y, color = "none", ec = "#74959A", s = 180, lw = 2.5, zorder = 3)
ax.scatter(X_goals, Y, color = "none", ec = "#495371", s = 180, lw = 2.5, zorder = 3)

# Add line chart between points and difference annotation
for index in Y:
    difference = X_xg.iloc[index] - X_goals.iloc[index]
    if difference > 0:
        color = "#74959A"
        x_adj = -1.75
        anot_position = X_xg.iloc[index]
        anot_aux_sign = "-"
    else:
        color = "#495371"
        x_adj = 1.75
        anot_position = X_goals.iloc[index]
        anot_aux_sign = "+"

    ax.annotate(
        xy = (anot_position, index),
        text = f"{anot_aux_sign} {abs(difference):.1f}",
        xytext = (13, -2),
        textcoords = "offset points",
        size = 8,
        color = color,
        weight = "bold"
    )

    if abs(difference) < 1.3:
        continue
    if abs(difference) < -1.1:
        continue
    ax.plot(
        [X_xg.iloc[index] + x_adj, X_goals.iloc[index] + x_adj*(-1)],
        [index, index],
        lw = 1,
        color = color,
        zorder = 2
    )

DC_to_FC = ax.transData.transform
FC_to_NFC = fig.transFigure.inverted().transform

# Native data to normalized data coordinates
DC_to_NFC = lambda x: FC_to_NFC(DC_to_FC(x))

logos_folder = "nfl_logos/"
# Modify the loop to fetch logos from the local folder
for index, team_id in enumerate(teams):
    ax_coords = DC_to_NFC([33, index - 0.55])
    logo_ax = fig.add_axes([ax_coords[0], ax_coords[1], 0.04, 0.04], anchor="C")

    # Use the local path to the logos folder
    logo_path = f"{logos_folder}{team_id:.0f}.png"

    try:
        # Check if the file exists before opening
        with Image.open(logo_path) as club_icon:
            logo_ax.imshow(club_icon.convert("LA"))
            logo_ax.axis("off")
    except FileNotFoundError:
        print(f"Logo not found for team ID {team_id}")

# Remove tick labels
ax.yaxis.set_major_locator(ticker.MultipleLocator(1))
false_ticks = ax.set_yticklabels([])

fig_text(
    x = 0.15, y = .9,
    s = "Through 10 weeks, only 3 NFL Teams\nhave outperformed their <2022> \noffensive success rate in <2023>",
    highlight_textprops = [
        {"color":"#74959A"},
        {"color": "#495371"}
    ],
    va = "bottom", ha = "left",
    fontsize = 14, color = "black", weight = "bold"
)
fig_text(
	x = 0.15, y = .885,
    s = "Source: rbsdm.com | Viz by Ray Carpenter | inspired by a viz by @sonofacorner",
	va = "bottom", ha = "left",
	fontsize = 8, color = "#4E616C"
)

# # ---- The League's logo
league_icon = Image.open("nfl_logos/NFL.png")
league_ax = fig.add_axes([0.055, 0.89, 0.065, 0.065], zorder=1)
league_ax.imshow(league_icon)
league_ax.axis("off")

plt.savefig(
	"06202022_bundelsiga_xg.png",
	dpi = 500,
	facecolor = "#EFE9E6",
	bbox_inches="tight",
    edgecolor="none",
	transparent = False
)

plt.savefig(
	"06202022_bundelsiga_xg_tr.png",
	dpi = 500,
	facecolor = "none",
	bbox_inches="tight",
    edgecolor="none",
	transparent = True
)


#!/bin/python3

import os
import sys

#
# Complete the gradingStudents function below.
#
def gradingStudents(grades):
    l=[]
    for i in grades:
        if i<38:
            l.append(i)
        elif i%5==1 or i%5==2 or i%5==0:
            l.append(i)
        elif i%5==3:
            l.append(i+2)
        elif i%5==4:
            l.append(i+1)
    return l

if __name__ == '__main__':
    f = open(os.environ['OUTPUT_PATH'], 'w')

    n = int(input())

    grades = []

    for _ in range(n):
        grades_item = int(input())
        grades.append(grades_item)

    result = gradingStudents(grades)

    f.write('\n'.join(map(str, result)))
    f.write('\n')

    f.close()


 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
 #   You may obtain a copy of the License at

 #       http://www.apache.org/licenses/LICENSE-2.0

 #   Unless required by applicable law or agreed to in writing, software
 #   distributed under the License is distributed on an "AS IS" BASIS,
 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 #   See the License for the specific language governing permissions and
 #   limitations under the License.

from astropy import units as u
from astropy import coordinates

from astroquery.irsa_dust import IrsaDust
from astropy.coordinates import Angle,ICRS,SkyCoord

import math
import os.path
import sys

import requests

def timeFix(s,m,h): #fixes time to ensure it stays within normal range (0-60)
	if(s>=60 or m>=60):
		while(s>=60 or m>=60):
			if s >= 60:
				m+=1
				s-=60
			if m >= 60:
				h+=1
				m-=60
	elif(s<0 or m<0):
		while(s<0 or m<0):
			if s < 0:
				m-=1
				s+=60
			if m < 0:
				h-=1
				m+=60
	return s,m,h;

def fourCoord(dam,ra,dec,coord):
	ds = dam*4

	#e
	ds/=math.cos(math.radians(dec.degree))
	h = ra.hms.h
	m = ra.hms.m
	s = ra.hms.s+ds
	(s,m,h) = timeFix(s,m,h)
	rad = Angle((h,m,s), unit = u.hour)
	rad = Angle(rad.to_string(unit=u.hour),u.hour)
	coord[1] = rad.to_string()+" "+dec.to_string()

	#n
	decli = dec.arcminute+dam
	decl = Angle(decli,u.arcminute)
	decl = Angle(decl.to_string(unit=u.degree),u.degree)
	coord[0] = ra.to_string()+" "+decl.to_string()

	#w
	ds=ds*(-1)
	ds/=math.cos(math.radians(dec.degree))
	h = ra.hms.h
	m = ra.hms.m
	s = ra.hms.s+ds
	(s,m,h) = timeFix(s,m,h)
	rad = Angle((h,m,s), unit = u.hour)
	rad = Angle(rad.to_string(unit=u.hour),u.hour)
	coord[3] = rad.to_string()+" "+dec.to_string()

	#s
	decli = dec.arcminute-dam
	decl = Angle(decli,u.arcminute)
	decl = Angle(decl.to_string(unit=u.degree),u.degree)
	coord[2] = ra.to_string()+" "+decl.to_string()

	#print(coord)
	return coord; #performs transformation of initial coord into cardinal coordinates

def tableFill(dam, ra, dec, appender,nme):
	t = Table(None)
	Am = Column(name = 'Arcminute')
	North = Column(name = 'North')
	East = Column(name = 'East')
	South = Column(name = 'South')
	West = Column(name = 'West')
	t.add_columns([Am,North, East, South, West])
	tA_v = []
	curVal = [None] *4 #n = 0, e = 1, s = 2, w = 3
	coord = [None] *4 #n = 0, e = 1, s = 2, w = 3
	#get values for each arcminute
	for j in range(0,dam+1):
		fourCoord(j, ra, dec, coord)
		t.add_row()
		t[j][0]=j
		for i in range(0,4):
			C = coordinates.SkyCoord(coord[i])
			table = IrsaDust.get_extinction_table(C.fk5, show_progress = False)
			curVal[i] = (table['A_SandF'][2])
			t[j][i+1] = curVal[i]
			curVal = curVal[:]
		tA_v.append(curVal)

	t.add_row()
	for i in range(0,5): #this adds a blank line to the table to separate queries
		t[j+1][i] = None
	n = [nme]
	namesTable = Table([n], names=('n'))
	final_name = namesTable.to_pandas()
	final_vals = t.to_pandas()
	from pandas import ExcelWriter
	with open('A_v Values.csv', appender) as f:
		final_name.to_csv(f, header =False, index = False)
	appender = 'a'
	with open('A_v Values.csv', appender) as f:
		final_vals.to_csv(f, header =True, index = False, sep = ',')
	return(tA_v)#gets the data from IRSA database and stores A_v in array

def grabImage(ra,dec):
	imagelist = IrsaDust.get_image_list(SkyCoord(ra,dec).fk5, image_type="100um", radius=2*u.degree)
	image_file = download_file(imagelist[0],cache=True)
	image_data.append(fits.getdata(image_file, ext=0)) #gets image from IRSA database

def PicSaver(image_data,gals,goPics):

	go = int(goPics)
	iend = go
	sz1 = (int(len(gals))//go)+1
	sz2 = (int(len(gals))-(go*(sz1-1)))
	if go==1:
		sz1 = sz1-1
	for j in range(0,sz1):
		if go == 1:
			plt.figure(1)
			plt.title(gals[j])
			plt.imshow(image_data[j],cmap='gray')
			plt.colorbar()
			plt.savefig(os.path.join('Pictures',(gals[j]+".png")))
			plt.clf()
		else:
			if j==sz1-1: #if last set
				iend = sz2
			if iend == 1: #if only one plot remains
				plt.figure(1)
				plt.title(gals[len(gals)-1])
				plt.imshow(image_data[len(image_data)-1],cmap='gray')
				plt.colorbar()
				plt.savefig(os.path.join('Pictures',(gals[len(gals)-1]+".png")))
				plt.clf()
			elif iend == 0:
				plt.clf()
				return
			else:
				f, axarr = plt.subplots(1,iend)
				for i in range(go*(j),((j)*go)+iend):
					im = axarr[i-(go*j)].imshow(image_data[i],cmap='gray')
					axarr[i-(go*(j))].set_title(gals[i])
				f.subplots_adjust(right=0.8)
				cbar_ax = f.add_axes([0.85, 0.15, 0.05, 0.7])
				f.colorbar(im,cax = cbar_ax)
				f.savefig(os.path.join('Pictures',(gals[go*(j)]+".png")))
				plt.clf()

	#-----Saves Graphs and Data To The Directory-----# #saves all images in .png files

def GraphMaker(A_v,gals,majAxis,goGraphs):

	go = int(goGraphs)
	iend = go
	sz1 = (int(len(gals))//go)+1
	sz2 = (int(len(gals))-(go*(sz1-1)))
	if go==1:
		sz1 = sz1-1
	for j in range(0,sz1):
		if go == 1:
			plt.clf()
			plt.figure(1)
			plt.plot(x,A_v[j][:,0], color = "blue", marker = ".", label = "North")
			plt.plot(x, A_v[j][:,1], color = "red", marker = ".", label = "East")
			plt.plot(x, A_v[j][:,2], color = "green", marker = ".", label = "South")
			plt.plot(x, A_v[j][:,3], color = "black", marker = ".", label = "West")
			#plt.axvline(x=majAxis[j])
			plt.xlabel("Arcminutes from Center of Galaxy")
			plt.ylabel("A_v Value")
			plt.legend(loc='center right', shadow=True)
			plt.suptitle("A_v Values by Arcminute")
			plt.title(gals[j])
			plt.savefig(os.path.join('Graphs',(gals[j]+" Graph.png")))
			plt.clf()
		else:
			if j==sz1-1:
				iend = sz2
			if iend == 1:
				plt.clf()
				plt.figure(1)
				plt.plot(x,A_v[len(gals)-1][:,0], color = "blue", marker = ".", label = "North")
				plt.plot(x, A_v[len(gals)-1][:,1], color = "red", marker = ".", label = "East")
				plt.plot(x, A_v[len(gals)-1][:,2], color = "green", marker = ".", label = "South")
				plt.plot(x, A_v[len(gals)-1][:,3], color = "black", marker = ".", label = "West")
				#plt.axvline(x=majAxis[j])
				plt.xlabel("Arcminutes from Center of Galaxy")
				plt.ylabel("A_v Value")
				plt.legend(loc='center right', shadow=True)
				plt.suptitle("A_v Values by Arcminute")
				plt.title(gals[len(gals)-1])
				plt.savefig(os.path.join('Graphs',(gals[len(gals)-1]+" Graph.png")))
				plt.clf()
			elif iend == 0:
				plt.clf()
				return
			else:
				f, axarr = plt.subplots(nrows = 1,ncols = iend, sharey = True, sharex = True,figsize = (20,10))
				f.text(.5,.04, 'Arcminutes From Center of Galaxy',ha='center',fontsize = 20)
				f.text(.08,.5, 'A_V Value',va='center', rotation='vertical',fontsize = 20)
				for i in range(go*(j),((j)*go)+iend):
					no, = axarr[i-(go*j)].plot(x, A_v[i][:,0], color = "blue", marker = ".", label = "North")
					ea, = axarr[i-(go*j)].plot(x, A_v[i][:,1], color = "red", marker = ".", label = "East")
					so, = axarr[i-(go*j)].plot(x, A_v[i][:,2], color = "green", marker = ".", label = "South")
					we, = axarr[i-(go*j)].plot(x, A_v[i][:,3], color = "black", marker = ".", label = "West")
					#axarr[i-(go*j)].axvline(x=majAxis[i])
					axarr[i-(go*(j))].set_title(gals[i], fontsize = 20)
				plt.figlegend((no,ea,so,we),("North","East","South","West"),loc='center right', shadow=True, prop={'size':20})
				plt.suptitle("A_v Values by Arcminute", fontsize = 20)
				f.savefig(os.path.join('Graphs',(gals[go*(j)]+" Graph.png")))
				plt.clf()

	#-----Saves Graphs and Data To The Directory-----# #saves all images in .png files

# def getAxis(name,link,majAxis,minAxis,ra, dec):
	# inputs = {'objname': name,
	# 			'extend': 'no',
	# 			'hconst': '73',
	# 			'omegam': '0.27',
	# 			'omegav': '0.73',
	# 			'corr_z': '1',
	# 			'out_csys': 'Equatorial',
	# 			'out_equinox': 'J2000.0',
	# 			'obj_sort': "RA or Longitude",
	# 			'of': 'pre_text',
	# 			'zv_breaker': '30000.0',
	# 			'list_limit': '5',
	# 			'img_stamp': 'YES'}
	# page = requests.get(link, params = inputs)
	# from bs4 import BeautifulSoup
	# soup = BeautifulSoup(page.content, 'html.parser')
	# #-------Get Velocities-----#
	# velocities = soup.find_all('pre')[5]
	# Helio = list(velocities.children)[2]
	# VGS = list(velocities.children)[16]
	# Helio = Helio.lstrip('\n')
	# VGS = VGS.lstrip('\n')
	# Hvals = [int(s) for s in Helio.split() if s.isdigit()]
	# VGSVals = [int(s) for s in VGS.split() if s.isdigit()]
	# #-----End Get Velocities-----#
	# #-----Get Diameters-----#
	# diameters = soup.find_all('table')[22]
	# diameters = diameters.find_all('tr')[2]
	# major = diameters.find_all('td')[1].get_text()
	# minor = diameters.find_all('td')[2].get_text()
	# #-----End Get Diameters-----#
	# write_file = 'Data.csv'
	# fix = False
	# fix2 = False
	# if(major != "..."):
	# 	major = float(major)/60
	# 	majAxis.append(major)
	# else:
	# 	major = "None"
	# 	fix = True
	# 	majAxis.append(None)
	# if(minor != "..."):
	# 	minor = float(minor)/60
	# 	minAxis.append(minor)
	# else:
	# 	minor = "None"
	# 	fix2 = True
	# 	minAxis.append(None)
	# with open(write_file, 'a') as output:
	# 	if(fix and fix2):
	# 		output.write(name + ',' + ra.to_string() + ',' + dec.to_string() + ',' + str(Hvals[0]) + ',' + str(Hvals[1]) + ',' + str(VGSVals[0]) + ',' + str(VGSVals[1]) + ',' + major + ',' + minor + '\n')
	# 	elif(fix == True and fix2 == False):
	# 		output.write(name + ',' + ra.to_string() + ',' + dec.to_string() + ',' + str(Hvals[0]) + ',' + str(Hvals[1]) + ',' + str(VGSVals[0]) + ',' + str(VGSVals[1]) + ',' + major + ',' + '%.3f' %minor + '\n')
	# 	elif(fix == False and fix2 == True):
	# 		output.write(name + ',' + ra.to_string() + ',' + dec.to_string() + ',' + str(Hvals[0]) + ',' + str(Hvals[1]) + ',' + str(VGSVals[0]) + ',' + str(VGSVals[1]) + ',' + '%.3f' %major + ',' + minor + '\n')
	# 	else: output.write(name + ',' + ra.to_string() + ',' + dec.to_string() + ',' + str(Hvals[0]) + ',' + str(Hvals[1]) + ',' + str(VGSVals[0]) + ',' + str(VGSVals[1]) + ',' + '%.3f' %major + ',' + '%.3f' %minor + '\n')

from astropy.coordinates import name_resolve

#-----SETUP-----#
c3 = None
link = "https://ned.ipac.caltech.edu/cgi-bin/objsearch?"
gals = []
start_coord = []
print("\nWelcome to A_v Calculator!\n")
print("Created by: Tate Walker for Dr. Peter Brown at Texas A&M University\n")
can_read = False
while can_read == False:
	choice = input("Enter [1] to enter galaxies by hand. Enter [2] to import a .txt file of names. Enter [q] to quit.\n")
	if choice == '1':
		galaxies = input("Enter galaxies separated by commas: Ex. M82, M83\n")
		for x in galaxies.split(','):
			gals.append(x.strip())
		can_read = True
	elif choice == '2':
		file = input("What is the name of the file? Ex. galaxies.txt\n")
		with open(file) as inp:
			gals = inp.read().splitlines()
		can_read = True
		choice == '2'
	elif choice == 'q':sys.exit()
	else: print("Please enter either [1], [2], or [q]\n\n")

c1 = input("Do you want to get A_v values? [y] [n] \n") #option to get values
if c1 == 'y':
	c3 = input("Do you want to graph these values? [y] [n] \n") #option to graph
	if c3 == 'y': goGraphs = input("How many graphs per file?\n")
c2 = input("Do you want to get pictures of each galaxy? [y] [n] \n") #option to get pictures
if c2 == 'y':goPics = input("How many pictures per file?\n")

if c1 == 'y':
	dam = input("How many arcminutes?\n") #dam = delta arcminutes
	dam = int(dam)

elif c1 and c2 == 'n':
	print("Those are all the options, please come back if you change your mind.")
	sys.exit()

for i in range(0,len(gals)):
	tcoord=SkyCoord.from_name(gals[i],frame ='icrs') #gets coordinate from name given and stores in temporary SkyCoord
	start_coord.append(tcoord) #puts temporary SkyCoord in a list

from astropy.table import Table
from astropy.table import Column

#-----SETUP-----#

#------MAIN FUNCTION-----#

from astropy.utils.data import download_file
from astropy.io import fits
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
import numpy as np
image_data = []
A_v = []
majAxis = []
minAxis = []
ra = Angle(start_coord[0].ra.hour,unit = u.hour) #gets radius of 1st coordinate as an angle (needed for things to work)
dec = start_coord[0].dec #dont need an angle for some reason but it works

appender = 'w' #lets us overwrite a file or make a new one
nme = gals[0]

import itertools
import threading
import time
import sys

done = False
#here is the animation
def animate():
    for c in itertools.cycle(['|', '/', '-', '\\']):
        if done:
            break
        sys.stdout.write('\rloading ' + c)
        sys.stdout.flush()
        time.sleep(0.1)
    print(chr(27) + "[2J")
    sys.stdout.write('\rDone!')

print(chr(27) + "[2J")
threader = threading.Thread(target=animate)
threader.start()
if c1 == 'y':A_v.append(tableFill(dam,ra,dec,appender,nme)) #runs the main functionality and returns the data of a galaxy
if c2 == 'y':grabImage(ra,dec) #gets image data and stores in list
appender = 'a' #lets us append a file instead of overwriting
for i in range(1,len(start_coord)):
	nme = gals[i]
	ra = Angle(start_coord[i].ra.hour,unit = u.hour)
	dec = start_coord[i].dec
	if c1 == 'y':A_v.append(tableFill(dam,ra,dec,appender,nme))
	if c2 == 'y':grabImage(ra,dec)
if c2 == 'y':PicSaver(image_data,gals,goPics) #saves all images in .png files, don't mess with this
if c3 == 'y':
	x = np.arange(dam+1) #creates array of size dam+1 to store values
	A_v = np.array(A_v) #numpy array needed to graph
	# write_file = 'Data.csv'
	# with open(write_file, 'w') as output:
	# 	output.write("Name, Ra, Dec, Heliocentric Velocity (km/s), Uncertainty (km/s), VGS Velocity (km/s), Uncertainty (km/s), Apparent Major Axis (arcmin), Apparent Minor Axis (arcmin)\n")
	# for i in range(0,len(gals)):
	# 	nme = gals[i]
	# 	ra = Angle(start_coord[i].ra.hour,unit = u.hour)
	# 	dec = start_coord[i].dec
	# 	getAxis(nme,link,majAxis,minAxis,ra,dec)
	GraphMaker(A_v,gals,majAxis,goGraphs)
done = True
time.sleep(3)
print(chr(27) + "[2J")
print("All pictures and graphs are saved in the project directory if selected. The A_v values are stored in the .csv file if calculated\n")
print("Thank you for using this program!\n")


from __future__ import division
import os
import sys
import subprocess
import threading
import json
import numpy as np
import ast
import tempfile

# Assumes spice.jar is in the same directory as spice.py.  Change as needed.
SPICE_JAR = 'SPICE-1.0/spice-1.0.jar'
TEMP_DIR = 'tmp'
CACHE_DIR = 'cache'

class Spice:
    """
    Main Class to compute the SPICE metric
    """

    def float_convert(self, obj):
        try:
          return float(obj)
        except:
          return np.nan

    def compute_score(self, gts, res):
        assert(sorted(gts.keys()) == sorted(res.keys()))
        imgIds = sorted(gts.keys())

        # Prepare temp input file for the SPICE scorer
        input_data = []
        for id in imgIds:
            hypo = res[id]
            ref = gts[id]

            # Sanity check.
            assert(type(hypo) is list)
            assert(len(hypo) == 1)
            assert(type(ref) is list)
            assert(len(ref) >= 1)

            input_data.append({
              "image_id" : id,
              "test" : hypo[0],
              "refs" : ref
            })

        cwd = os.path.dirname(os.path.abspath("__file__"))
        temp_dir=os.path.join(cwd, TEMP_DIR)
        if not os.path.exists(temp_dir):
          os.makedirs(temp_dir)
        in_file = tempfile.NamedTemporaryFile(delete=False, dir=temp_dir, mode='w')
        json.dump(input_data, in_file, indent=2)
        in_file.close()

        # Start job
        out_file = tempfile.NamedTemporaryFile(delete=False, dir=temp_dir, mode='w')
        out_file.close()
        cache_dir=os.path.join(cwd, CACHE_DIR)
        if not os.path.exists(cache_dir):
          os.makedirs(cache_dir)
        spice_cmd = ['java', '-jar', '-Xmx8G', SPICE_JAR, in_file.name,
          '-cache', cache_dir,
          '-out', out_file.name,
          '-subset',
          '-silent'
        ]
        subprocess.check_call(spice_cmd,
            cwd=os.path.dirname(os.path.abspath("__file__")))

        # Read and process results
        with open(out_file.name) as data_file:
          results = json.load(data_file)
        os.remove(in_file.name)
        os.remove(out_file.name)

        imgId_to_scores = {}
        spice_scores = []
        for item in results:
          imgId_to_scores[item['image_id']] = item['scores']
          spice_scores.append(self.float_convert(item['scores']['All']['f']))
        average_score = np.mean(np.array(spice_scores))
        scores = []
        for image_id in imgIds:
          # Convert none to NaN before saving scores over subcategories
          score_set = {}
          for category,score_tuple in imgId_to_scores[image_id].items():
            score_set[category] = {k: self.float_convert(v) for k, v in score_tuple.items()}
          scores.append(score_set)
        return average_score, scores

    def method(self):
        return "SPICE"
#!/usr/bin/env python
#
# File Name : ptbtokenizer.py
#
# Description : Do the PTB Tokenization and remove punctuations.
#
# Creation Date : 29-12-2014
# Last Modified : Thu Mar 19 09:53:35 2015
# Authors : Hao Fang <hfang@uw.edu> and Tsung-Yi Lin <tl483@cornell.edu>

import os
import sys
import subprocess
import tempfile
import itertools

# path to the stanford corenlp jar
STANFORD_CORENLP_3_4_1_JAR = 'stanford-corenlp-3.4.1.jar'

# punctuations to be removed from the sentences
PUNCTUATIONS = ["''", "'", "``", "`", "-LRB-", "-RRB-", "-LCB-", "-RCB-", \
        ".", "?", "!", ",", ":", "-", "--", "...", ";"]

class PTBTokenizer:
    """Python wrapper of Stanford PTBTokenizer"""

    def tokenize(self, captions_for_image):
        cmd = ['java', '-cp', STANFORD_CORENLP_3_4_1_JAR, \
                'edu.stanford.nlp.process.PTBTokenizer', \
                '-preserveLines', '-lowerCase']

        # ======================================================
        # prepare data for PTB Tokenizer
        # ======================================================
        final_tokenized_captions_for_image = {}
        image_id = [k for k, v in captions_for_image.items() for _ in range(len(v))]
        sentences = '\n'.join([c['caption'].replace('\n', ' ') for k, v in captions_for_image.items() for c in v])

        # ======================================================
        # save sentences to temporary file
        # ======================================================
        path_to_jar_dirname=os.path.dirname(os.path.abspath("__file__"))
        tmp_file = tempfile.NamedTemporaryFile(delete=False, dir=path_to_jar_dirname, mode='w')
        tmp_file.write(sentences)
        tmp_file.close()

        # ======================================================
        # tokenize sentence
        # ======================================================
        cmd.append(os.path.basename(tmp_file.name))
        p_tokenizer = subprocess.Popen(cmd, cwd=path_to_jar_dirname, \
                stdout=subprocess.PIPE)
        token_lines = p_tokenizer.communicate(input=sentences.rstrip())[0]
        lines = token_lines.decode().split('\n')
        # remove temp file
        os.remove(tmp_file.name)

        # ======================================================
        # create dictionary for tokenized captions
        # ======================================================
        for k, line in zip(image_id, lines):
            if not k in final_tokenized_captions_for_image:
                final_tokenized_captions_for_image[k] = []
            tokenized_caption = ' '.join([w for w in line.rstrip().split(' ') \
                    if w not in PUNCTUATIONS])
            final_tokenized_captions_for_image[k].append(tokenized_caption)

        return final_tokenized_captions_for_image


# 875. Koko Eating Bananas
# source: https://leetcode.com/problems/koko-eating-bananas/
class Solution(object):

    def minEatingSpeed(self, piles, H):
        left, right = 0, max(piles)
        while left < right: # O(lgn) for binary search, totally O(NlgN)
            mid = (left + right) / 2
            # print(left, right, mid)
            if self.whether(piles, H, mid): # this will take O(n)
                right = mid
            else:
                left = mid + 1
        return left

    def whether(self, piles, H, K):
        # print(K)
        total = [ (bananas+K-1)//K for bananas in piles]
        return sum(total) <= H


# Create your views here.
from bet_data_fetcher.models import *
from django.conf import settings
from django.core.cache import cache
from exceptions import *
import logging

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

def _fetch_data_from_sites():
    """ Fetches data from site classes in bet_sites.
    Supposed to iterate through to fetch
    """
    from bet_sites import StanJamer
    data = StanJamer().get_data()
    if reduce(lambda x, y: bool(x) or bool(y), data.values()):
        logger.info("Fetched data from StanJamer")
        return data
    else:
        #TODO: try other class
        return data

def _map_data_to_obj(data):
    def match_bet_values(bet_value_arr, bet_obj):
        bet_val_objs = BetValue.objects.filter(bet=bet_obj)
        logger.debug("Found %d bet values objects for %s bet" % (len(bet_val_objs), str(bet_obj)))
        for bet_val_dict in bet_value_arr:
            for bet_val_obj in bet_val_objs:
                if bet_val_obj.name == bet_val_dict['name']:
                    bet_val_dict['bet_val_obj'] = bet_val_obj
                    break
            if not bet_val_dict.has_key("bet_val_obj"):
                logger.info('Bet value %s does not exist for %s bet. Creating one.' % (bet_val_dict['name'], str(bet_obj)))
                bet_val_obj = BetValue.objects.create(name=bet_val_dict['name'], bet=bet_obj)
                bet_val_dict['bet_val_obj'] = bet_val_obj

    if data['tournament_data']['bets']:
        tourn_bet_obj = Bet.objects.exclude(tournament = None)
        if tourn_bet_obj:
            logger.debug('Tournament bet - %s found' % str(tourn_bet_obj))
            tourn_bet_obj = tourn_bet_obj[0]
        else:
            logger.info('No Tournament obj exists. Creating one.')
            categ, created = BetCategory.objects.get_or_create(name="Tournament Winner")
            if created:
                logger.info("New Bet Category %s created" % str(categ))
            tourn_bet_obj = Bet.objects.create(category=categ, match=None, tournament=Tournament.objects.all()[0])
        data['tournament_data']['bets'][0]['tourn_obj'] = tourn_bet_obj
        match_bet_values(data['tournament_data']['bets'][0]['values'], tourn_bet_obj)

    for matches_data in [data['live_data'], data['upcoming_data']]:
        for match_data in matches_data:
            logger.debug("Got match from stie - %s, %s" % (str(match_data['date'].date()), match_data['name']))
            match_data['match_obj'] = match_obj = Match.objects.get(match_date=match_data['date'].date(), name_lower=match_data['name'].lower())
            match_bet_objs = Bet.objects.filter(match=match_obj)
            logger.debug("Found %d bets for match - %s" % (len(match_bet_objs), str(match_obj)))
            for bet in match_data['bets']:
                for match_bet_obj in match_bet_objs:
                    if match_bet_obj.category.name == bet['name']:
                        bet['bet_obj'] = match_bet_obj
                        break
                if not bet.has_key('bet_obj'):
                    logger.info("Bet %s doesn't exists for match %s. Create one" % (bet['name'], str(match_obj)))
                    categ, created = BetCategory.objects.get_or_create(name=bet['name'])
                    if created:
                        logger.info("New Bet Category %s created" % str(categ))
                    match_bet_obj = Bet.objects.create(match=match_obj,category=categ)
                    bet['bet_obj'] = match_bet_obj
                match_bet_values(bet['values'], match_bet_obj)

def get_all_bet_data():
    data = cache.get('bet_data')
    if not data:
        data = _fetch_data_from_sites()
        _map_data_to_obj(data)
        cache.set('bet_data', data, settings.REFRESH_TIME)
    return data

def get_match_bet_data(match_id):
    if match_id is None:
        return
    data = get_all_bet_data()
    for match_bet_data in data['live_data'] + data['upcoming_data']:
        if match_bet_data['match_obj'].id == match_id:
            return match_bet_data
    return None

def get_tournament_bet_data():
    data = get_all_bet_data()
    return data['tournament_data']

def get_bet_value_data(bet_value_id):
    if bet_value_id is None:
        return

    data = get_all_bet_data()
    for bet_val_data in [i for match in (data['upcoming_data'] + data['live_data'] + [data['tournament_data']]) for bet in match['bets'] for i in bet['values']]:
        if bet_val_data['bet_val_obj'].id == bet_value_id:
            return bet_val_data
    return None


 #Задача 2. Напишите программу, которая найдёт произведение пар чисел списка. Парой считаем первый и последний элемент, второй и предпоследний и т.д.

#************************
def fillList(n,l,r):
    import random
    resultList = []
    for i in range(n):
        resultList.append(random.randint(l, r))

    return resultList

#************************
def listcomposition(lst):
    if len(lst) % 2 != 0:
        l = len(lst)//2 + 1
    else: l = len(lst)//2
    lstcomp = []
    for i in range(l):
        lstcomp.append(lst[i]*lst[len(lst)-i-1])
    return lstcomp

#************************
import os
os.system('cls')

print("Программа задает список из нескольких чисел и находит произведение пар чисел списка (первый и последний элемент, второй и предпоследний и т.д.)")
listN = int(input("Введите размерность списка: "))
listL = int(input("Введите начало диапазона чисел для заполнения списка: "))
listR = int(input("Введите окончание диапазона чисел для заполнения списка: "))

lst = fillList(listN, listL, listR)
lstcomp = listcomposition(lst)

print(f"Из списка {lst} путем умножения элементов получен: {lstcomp}")


import RPi.GPIO as GPIO
import time

buttonPin = 26

# Set buttonPin to INPUT mode with pull-up resistor
def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(buttonPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# If button pressed return 1, else return 0
def detect():
    return 1 if GPIO.input(buttonPin) == GPIO.LOW else 0

# Loops detect(). give one second buffer
def loop():
    while(True):
        print(detect())
        time.sleep(1)

# Program entrance
if __name__ == '__main__':
    print ('Program is starting...')
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # Press CTRL-C to end the program
        GPIO.cleanup()         # Release GPIO resources


""" Main Qt widget and file as well. """

import sys

from PySide6.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout
from PySide6.QtCore import QTimer

import globals
from main_gl_widget import MainGlWidget

# Important:
# You need to run the following command to generate the ui_form.py file
#     pyside6-uic form.ui -o ui_form.py, or
#     pyside2-uic form.ui -o ui_form.py
from ui_form import Ui_Widget

class Widget(QWidget):
    """ Program main Qt Widget. """

    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = Ui_Widget()
        self.ui.setupUi(self)

        self.setWindowTitle("Python based Conway's Game of Life")

        self.main_gl_widget = MainGlWidget(self)
        self.ui.horizontalLayout.insertWidget(0, self.main_gl_widget, 7)
        self.ui.horizontalLayout.setStretch(1, 4)

        self.__connect_signals()

        # Set refresh rate.
        timer = QTimer(self)
        timer.setInterval(1000 / globals.FPS)
        timer.timeout.connect(self.main_gl_widget.repaint)
        timer.start()

    def __connect_signals(self) -> None:
        self.ui.toggleButton.clicked.connect(self.__toggle_button_clicked)
        self.ui.rewindButton.clicked.connect(
            lambda: self.main_gl_widget.restart_game(globals.TEST_RLE)
        )

        self.ui.frequencySlider.valueChanged.connect(
            self.__freqency_slider_val_changed
        )

    def __toggle_button_clicked(self) -> None:
        idk = {"⏵": "⏸", "⏸": "⏵"}
        self.ui.toggleButton.setText(idk[self.ui.toggleButton.text()])
        self.main_gl_widget.toggle_game()

    def __freqency_slider_val_changed(self, freq: int) -> None:
        self.main_gl_widget.game.updater.set_frequency(freq)
        self.ui.frequencyLabel.setText(f"{freq}/s")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    widget = Widget()
    widget.show()
    sys.exit(app.exec())


from unittest.mock import patch

from django.urls import reverse
from rest_framework import status
from django.contrib import messages

from comment.conf import settings
from comment.models import Comment
from comment.tests.base import BaseCommentTest, BaseCommentFlagTest, BaseCommentViewTest
from comment.tests.test_utils import BaseAnonymousCommentTest, AnonymousUser, timezone, signing

class CommentViewTestCase(BaseCommentViewTest):
    def setUp(self):
        super().setUp()
        self.all_comments = Comment.objects.all().count()
        self.parent_comments = Comment.objects.all_parents().count()
        self.data = {
            'content': 'comment body',
            'app_name': 'post',
            'model_name': 'post',
            'parent_id': '',
            'model_id': self.post_1.id
        }

    def increase_count(self, parent=False):
        if parent:
            self.parent_comments += 1

        self.all_comments += 1

    @staticmethod
    def get_create_url():
        return reverse('comment:create')

    def comment_count_test(self):
        self.assertEqual(Comment.objects.all_parents().count(), self.parent_comments)
        self.assertEqual(Comment.objects.all().count(), self.all_comments)

    def test_create_parent_and_child_comment(self):
        self.assertEqual(self.all_comments, 0)
        self.assertEqual(self.parent_comments, 0)

        # parent comment
        response = self.client.post(self.get_create_url(), data=self.data)
        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, 'comment/comments/base.html')
        parent_comment = Comment.objects.get(object_id=self.post_1.id, parent=None)
        self.assertEqual(response.context.get('comment').id, parent_comment.id)
        self.assertTrue(response.context.get('comment').is_parent)

        self.increase_count(parent=True)
        self.comment_count_test()

        # child comment
        data = self.data.copy()
        data['parent_id'] = parent_comment.id
        response = self.client.post(self.get_create_url(), data=data)

        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, 'comment/comments/child_comment.html')
        child_comment = Comment.objects.get(object_id=self.post_1.id, parent=parent_comment)
        self.assertEqual(response.context.get('comment').id, child_comment.id)
        self.assertFalse(response.context.get('comment').is_parent)

        self.increase_count()
        self.comment_count_test()

    def test_create_comment_non_ajax_request(self):
        response = self.client_non_ajax.post(self.get_create_url(), data=self.data)
        self.assertEqual(response.status_code, 400)

    def test_create_anonymous_comment(self):
        self.client.logout()
        settings.COMMENT_ALLOW_ANONYMOUS = True
        data = self.data.copy()
        data['email'] = 'a@a.com'
        response = self.client.post(self.get_create_url(), data=data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertTemplateUsed(response, 'comment/comments/base.html')
        response_messages = response.context['messages']
        for r in response_messages:
            self.assertEqual(r.level, messages.INFO)
            self.assertEqual(r.message, (
                'We have have sent a verification link to your email. The comment will be '
                'displayed after it is verified.'
                )
            )
        # no change in comment count
        self.comment_count_test()

class TestEditComment(BaseCommentViewTest):
    @classmethod
    def setUpTestData(cls):
        super().setUpTestData()
        cls.comment = cls.create_comment(cls.content_object_1)
        cls.init_content = cls.comment.content

    def test_edit_comment(self):
        comment = self.create_comment(self.content_object_1)
        self.client.force_login(comment.user)
        self.assertEqual(Comment.objects.all().count(), 2)
        data = {
            'content': 'parent comment was edited',
            'app_name': 'post',
            'model_name': 'post',
            'model_id': self.post_1.id
        }
        get_url = self.get_url('comment:edit', comment.id, data)
        self.assertEqual(comment.content, 'comment 2')
        response = self.client.get(get_url, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed('comment/comments/update_comment.html')
        self.assertEqual(response.context['comment_form'].instance.id, comment.id)
        post_url = self.get_url('comment:edit', comment.id)
        response = self.client.post(post_url, data=data, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed('comment/comments/comment_content.html')
        comment.refresh_from_db()
        self.assertEqual(comment.content, data['content'])

        data['content'] = ''
        with self.assertRaises(ValueError) as error:
            self.client.post(
                self.get_url('comment:edit', comment.id), data=data, HTTP_X_REQUESTED_WITH='XMLHttpRequest'
            )
        self.assertIsInstance(error.exception, ValueError)

    def test_cannot_edit_comment_by_different_user(self):
        comment = self.comment
        self.client.force_login(self.user_2)
        data = {
            'content': 'parent comment was edited',
            'app_name': 'post',
            'model_name': 'post',
            'model_id': self.post_1.id
        }
        self.assertEqual(comment.user.username, self.user_1.username)
        response = self.client.get(self.get_url('comment:edit', comment.id), data=data)
        self.assertEqual(response.status_code, 403)
        self.assertEqual(response.reason_phrase, 'Forbidden')

        response = self.client.post(self.get_url('comment:edit', comment.id), data=data)
        self.assertEqual(response.status_code, 403)
        self.assertEqual(response.reason_phrase, 'Forbidden')

class TestDeleteComment(BaseCommentViewTest):

    def response_fails_test(self, response):
        self.assertEqual(response.status_code, 403)
        self.assertEqual(response.reason_phrase, 'Forbidden')

    def test_delete_comment(self):
        comment = self.create_comment(self.content_object_1)
        self.client.force_login(comment.user)
        init_count = Comment.objects.all().count()
        self.assertEqual(init_count, 1)
        get_url = self.get_url('comment:delete', comment.id, self.data)
        response = self.client.get(get_url, data=self.data)
        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, 'comment/comments/comment_modal.html')
        self.assertContains(response, 'html_form')

        response = self.client.post(self.get_url('comment:delete', comment.id), data=self.data)
        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, 'comment/comments/base.html')
        self.assertNotContains(response, 'html_form')
        self.assertRaises(Comment.DoesNotExist, Comment.objects.get, id=comment.id)
        self.assertEqual(Comment.objects.all().count(), init_count-1)

    def test_delete_comment_by_moderator(self):
        comment = self.create_comment(self.content_object_1)
        self.client.force_login(self.moderator)
        self.assertEqual(int(self.client.session['_auth_user_id']), self.moderator.id)
        self.assertTrue(self.moderator.has_perm('comment.delete_flagged_comment'))
        self.assertEqual(comment.user, self.user_1)
        init_count = Comment.objects.count()
        self.assertEqual(init_count, 1)
        # moderator cannot delete un-flagged comment
        response = self.client.post(self.get_url('comment:delete', comment.id), data=self.data)
        self.assertEqual(response.status_code, 403)

        # moderator can delete flagged comment
        settings.COMMENT_FLAGS_ALLOWED = 1
        self.create_flag_instance(self.user_1, comment)
        self.create_flag_instance(self.user_2, comment)
        response = self.client.post(self.get_url('comment:delete', comment.id), data=self.data)
        self.assertEqual(response.status_code, 200)
        self.assertRaises(Comment.DoesNotExist, Comment.objects.get, id=comment.id)

    def test_delete_comment_by_admin(self):
        comment = self.create_comment(self.content_object_1)
        self.client.force_login(self.admin)
        self.assertEqual(int(self.client.session['_auth_user_id']), self.admin.id)
        self.assertTrue(self.admin.groups.filter(name='comment_admin').exists())
        self.assertEqual(comment.user, self.user_1)
        init_count = Comment.objects.count()
        self.assertEqual(init_count, 1)

        # admin can delete any comment
        response = self.client.post(self.get_url('comment:delete', comment.id), data=self.data)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(Comment.objects.count(), init_count - 1)

    def test_cannot_delete_comment_by_different_user(self):
        comment = self.create_comment(self.content_object_1)
        self.client.force_login(self.user_2)
        self.assertEqual(comment.content, 'comment 1')
        self.assertEqual(comment.user.username, self.user_1.username)

        init_count = Comment.objects.all().count()
        self.assertEqual(init_count, 1)

        # test GET request
        response = self.client.get(self.get_url('comment:delete', comment.id), data=self.data)
        self.response_fails_test(response)

        # test POST request
        response = self.client.post(self.get_url('comment:delete', comment.id), data=self.data)
        self.response_fails_test(response)

class SetReactionViewTest(BaseCommentViewTest):
    def setUp(self):
        super().setUp()
        self.comment = self.create_comment(self.content_object_1)

    @staticmethod
    def get_reaction_url(obj_id, action):
        return reverse('comment:react', kwargs={
            'pk': obj_id,
            'reaction': action
        })

    def test_set_reaction_for_authenticated_users(self):
        """Test whether users can create/change reactions using view"""
        _url = self.get_reaction_url(self.comment.id, 'like')
        response = self.client.post(_url)
        data = {
            'status': 0,
            'likes': 1,
            'dislikes': 0,
            'msg': 'Your reaction has been updated successfully'
        }
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertDictEqual(response.json(), data)

    def test_set_reaction_for_old_comments(self):
        """Test backward compatibility for this update"""
        _url = self.get_reaction_url(self.comment.id, 'like')
        # delete the reaction object
        self.comment.reaction.delete()
        response = self.client.post(_url)
        data = {
            'status': 0,
            'likes': 1,
            'dislikes': 0,
            'msg': 'Your reaction has been updated successfully'
        }
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertDictEqual(response.json(), data)

    def test_set_reaction_for_unauthenticated_users(self):
        """Test whether unauthenticated users can create/change reactions using view"""
        _url = self.get_reaction_url(self.comment.id, 'dislike')
        self.client.logout()
        response = self.client.post(_url)
        self.assertEqual(response.status_code, status.HTTP_302_FOUND)
        self.assertEqual(response.url, '{}?next={}'.format(settings.LOGIN_URL, _url))

    def test_get_request(self):
        """Test whether GET requests are allowed or not"""
        _url = self.get_reaction_url(self.comment.id, 'like')
        response = self.client.get(_url)
        self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)

    def test_non_ajax_requests(self):
        """Test response if non AJAX requests are sent"""
        _url = self.get_reaction_url(self.comment.id, 'like')
        response = self.client_non_ajax.post(_url)
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

    def test_incorrect_comment_id(self):
        """Test response when an incorrect comment id is passed"""
        _url = self.get_reaction_url(102_876, 'like')
        response = self.client.post(_url)
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

    def test_incorrect_reaction(self):
        """Test response when incorrect reaction is passed"""
        _url = self.get_reaction_url(self.comment.id, 'likes')
        response = self.client.post(_url)
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

        # test incorrect type
        _url = self.get_reaction_url(self.comment.id, 1)
        response = self.client.post(_url)
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

class SetFlagViewTest(BaseCommentFlagTest):
    def setUp(self):
        super().setUp()
        self.flag_data.update({
            'info': ''
            })
        self.response_data = {
            'status': 1
        }

    def test_set_flag_for_flagging(self):
        _url = self.get_url('comment:flag', self.comment.id)
        self.flag_data['reason'] = 1
        response = self.client.post(_url, data=self.flag_data)
        response_data = {
            'status': 0,
            'flag': 1,
            'msg': 'Comment flagged'
        }
        self.assertEqual(response.status_code, 200)
        self.assertDictEqual(response.json(), response_data)

    @patch.object(settings, 'COMMENT_FLAGS_ALLOWED', 0)
    def test_set_flag_when_flagging_not_enabled(self):
        settings.COMMENT_FLAGS_ALLOWED = 0
        _url = self.get_url('comment:flag', self.comment.id)
        self.flag_data['reason'] = 1
        response = self.client.post(_url, data=self.flag_data)
        self.assertEqual(response.status_code, 403)

    def test_set_flag_for_flagging_old_comments(self):
        """Test backward compatibility for this update"""
        _url = self.get_url('comment:flag', self.comment.id)
        data = self.flag_data
        # delete the flag object
        self.comment.flag.delete()
        response = self.client.post(_url, data=data)
        response_data = {
            'status': 0,
            'flag': 1,
            'msg': 'Comment flagged'
        }
        self.assertEqual(response.status_code, 200)
        self.assertDictEqual(response.json(), response_data)

    def test_set_flag_for_unflagging(self):
        # un-flag => no reason is passed and the comment must be already flagged by the user
        _url = self.get_url('comment:flag', self.comment_2.id)
        data = {}
        response = self.client.post(_url, data=data)
        response_data = {
            'status': 0,
            'msg': 'Comment flag removed'
        }
        self.assertEqual(response.status_code, 200)
        self.assertDictEqual(response.json(), response_data)

    def test_set_flag_for_unauthenticated_user(self):
        """Test whether unauthenticated user can create/delete flag using view"""
        url = self.get_url('comment:flag', self.comment.id).replace('?', '')
        self.client.logout()
        response = self.client.post(url, data=self.flag_data)
        self.assertEqual(response.status_code, status.HTTP_302_FOUND)
        self.assertEqual(response.url, '{}?next={}'.format(settings.LOGIN_URL, url))

    def test_get_request(self):
        """Test whether GET requests are allowed or not"""
        url = self.get_url('comment:flag', self.comment.id)
        response = self.client.get(url, data=self.flag_data)
        self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)

    def test_non_ajax_requests(self):
        """Test response if non AJAX requests are sent"""
        url = self.get_url('comment:flag', self.comment.id)
        response = self.client_non_ajax.post(url, data=self.flag_data)
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

    def test_incorrect_comment_id(self):
        """Test response when an incorrect comment id is passed"""
        url = self.get_url('comment:flag', 102_876)
        response = self.client.post(url, data=self.flag_data)
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

    def test_incorrect_reason(self):
        """Test response when incorrect reason is passed"""
        url = self.get_url('comment:flag', self.comment.id)
        data = self.flag_data
        reason = -1
        data.update({'reason': reason})
        response = self.client.post(url, data=data)
        self.assertEqual(response.status_code, 200)

class ChangeFlagStateViewTest(BaseCommentFlagTest):
    @patch.object(settings, 'COMMENT_FLAGS_ALLOWED', 1)
    def setUp(self):
        super().setUp()
        self.data = {
            'state': self.comment.flag.REJECTED
        }
        self.create_flag_instance(self.user_1, self.comment, **self.flag_data)
        self.create_flag_instance(self.user_2, self.comment, **self.flag_data)

    def test_change_flag_state_for_unflagged_comment(self):
        self.comment.flag.toggle_flagged_state()
        self.assertFalse(self.comment.is_flagged)
        self.client.force_login(self.moderator)
        self.assertEqual(int(self.client.session['_auth_user_id']), self.moderator.id)
        response = self.client.post(self.get_url('comment:flag-change-state', self.comment.id), data=self.data)
        self.assertEqual(response.status_code, 400)

    def test_change_flag_state_by_not_permitted_user(self):
        self.assertTrue(self.comment.is_flagged)
        self.client.force_login(self.user_1)
        self.assertEqual(int(self.client.session['_auth_user_id']), self.user_1.id)
        response = self.client.post(self.get_url('comment:flag-change-state', self.comment.id), data=self.data)
        self.assertEqual(response.status_code, 403)

    def test_change_flag_state_with_wrong_state_value(self):
        self.assertTrue(self.comment.is_flagged)
        self.client.force_login(self.moderator)
        self.assertEqual(int(self.client.session['_auth_user_id']), self.moderator.id)
        self.assertEqual(self.comment.flag.state, self.comment.flag.FLAGGED)

        # valid state is REJECTED and RESOLVED
        self.data['state'] = self.comment.flag.UNFLAGGED
        response = self.client.post(self.get_url('comment:flag-change-state', self.comment.id), data=self.data)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.json()['state'], 0)
        self.assertEqual(self.comment.flag.state, self.comment.flag.FLAGGED)

    def test_change_flag_state_success(self):
        self.assertTrue(self.comment.is_flagged)
        self.client.force_login(self.moderator)
        self.assertEqual(int(self.client.session['_auth_user_id']), self.moderator.id)
        self.assertEqual(self.comment.flag.state, self.comment.flag.FLAGGED)

        # valid state is REJECTED and RESOLVED
        self.data['state'] = self.comment.flag.REJECTED
        response = self.client.post(self.get_url('comment:flag-change-state', self.comment.id), data=self.data)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.json()['state'], self.comment.flag.REJECTED)
        self.comment.flag.refresh_from_db()
        self.assertEqual(self.comment.flag.moderator, self.moderator)
        self.assertEqual(self.comment.flag.state, self.comment.flag.REJECTED)

class ConfirmCommentViewTest(BaseAnonymousCommentTest, BaseCommentTest):
    def setUp(self):
        super().setUp()
        # although this will work for authenticated users as well.
        self.client.logout()
        self.request.user = AnonymousUser()
        self.init_count = Comment.objects.all().count()
        self.template_1 = 'comment/anonymous/discarded.html'
        self.template_2 = 'comment/comments/messages.html'
        self.template_3 = 'comment/bootstrap.html'

    def get_url(self, key=None):
        if not key:
            key = self.key
        return reverse('comment:confirm-comment', args=[key])

    def template_used_test(self, response):
        self.assertTemplateUsed(response, self.template_1)
        self.assertTemplateUsed(response, self.template_2)
        self.assertTemplateUsed(response, self.template_3)

    def test_bad_signature(self):
        key = self.key + 'invalid'
        response = self.client.get(self.get_url(key))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(Comment.objects.all().count(), self.init_count)
        self.template_used_test(response)
        response_messages = response.context['messages']
        self.assertEqual(len(response_messages), 1)
        for r in response_messages:
            self.assertEqual(r.level, messages.ERROR)
            self.assertEqual(r.message, 'The link seems to be broken.')

    def test_comment_exists(self):
        comment_dict = self.comment_obj.to_dict().copy()
        comment = self.create_anonymous_comment(posted=timezone.now(), email='a@a.com')
        init_count = self.init_count + 1
        comment_dict.update({
            'posted': str(comment.posted),
            'email': comment.email
        })
        key = signing.dumps(comment_dict)

        response = self.client.get(self.get_url(key))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(Comment.objects.all().count(), init_count)
        self.template_used_test(response)
        response_messages = response.context['messages']
        self.assertEqual(len(response_messages), 1)
        for r in response_messages:
            self.assertEqual(r.level, messages.WARNING)
            self.assertEqual(r.message, 'The comment has already been verified.')

    def test_success(self):
        response = self.client.get(self.get_url())
        comment = Comment.objects.get(email=self.comment_obj.email, posted=self.time_posted)
        self.assertEqual(Comment.objects.all().count(), self.init_count + 1)
        self.assertEqual(response.status_code, status.HTTP_302_FOUND)
        self.assertEqual(response.url, comment.get_url(self.request))


from PIL import Image, ImageDraw, ImageFont, ImageColor, ImageEnhance
import requests
import io
import json
from rembg import remove, new_session
import uvicorn
from fastapi import FastAPI, Request
from fastapi.responses import FileResponse, Response
app = FastAPI()

def ReduceOpacity(im, opacity):
    """
    Returns an image with reduced opacity.
    Taken from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/362879
    """
    assert opacity >= 0 and opacity <= 1
    if im.mode != 'RGBA':
        im = im.convert('RGBA')
    else:
        im = im.copy()
    alpha = im.split()[3]
    alpha = ImageEnhance.Brightness(alpha).enhance(opacity)
    im.putalpha(alpha)
    return im

class Template:
    def __init__(self, template):
        path = f'templates/{template}.json'
        self.template = json.load(open(path))
        self.width = self.template['size']['width']
        self.height = self.template['size']['height']
    def calcXY(self, element):
        x = element['position']['x']
        y = element['position']['y']
        width = element['size']['width']
        height = element['size']['height']
        if x == 'center':
            x = (self.width - width) / 2
        if y == 'center':
            y = (self.height - height) / 2

        return x, y
    def calcXYText(self, element, content, font):
        x = element['position']['x']
        y = element['position']['y']
        image = Image.new(mode="RGB", size=(self.width, self.height))
        box = ImageDraw.Draw(image)
        _, _, w, d = box.textbbox((0, 0), content, font=font)
        if x == 'center':
            x = (self.width - w) / 2
        if y == 'center':
            y = (self.height - d) / 2
        return x, y, w, d

    def render(self, kwagrs) -> Image:
        background = None
        if self.template['name'] not in kwagrs:
            raise Exception(f"Missing {self.template['name']}")
        if self.template['type'] == 'image':
            background = Image.open(io.BytesIO(requests.get(kwagrs[self.template['name']]).content)).convert("RGBA")
            print("Hello")
            background = background.resize((self.template['size']['width'], self.template['size']['height']))
        if self.template['type'] == 'solid':
            background = Image.new(mode='RGBA', size=(self.template['size']['width'], self.template['size']['height']), color=ImageColor.getrgb(f"#{kwagrs[self.template['name']]}"))
        for element in self.template['elements']:
            if element['name'] not in kwagrs:
                raise Exception(f"Missing {element['name']}")
            # Render text
            element['opacity'] = element['opacity'] if 'opacity' in element else 1
            if element['type'] == 'text':
                img_text = Image.new("RGBA", background.size, (255,255,255,0))
                if f'{element["name"]}_color' in kwagrs:
                    element['font']['color'] = '#' + kwagrs[f'{element["name"]}_color']
                content: str = kwagrs[element['name']]
                font = ImageFont.truetype(font='fonts/' + element['font']['family'], size=element['font']['size'])
                draw = ImageDraw.Draw(img_text)
                x, y, w, d = self.calcXYText(element=element, content=content, font=font)
                if w > self.width:
                    contents = content.split(" ")
                    index : int = -1
                    while True:
                        left = " ".join(contents[0:index])
                        x, y, w, d = self.calcXYText(element=element, content=left, font=font)
                        if w > self.width:
                            index -= 1
                        else:
                            right = " ".join(contents[index:])
                            draw.text(xy=(x, y), text=left, font=font, fill=ImageColor.getrgb(element['font']['color']) + (int(element['opacity'] * 255),))
                            draw.text(xy=(x, y + d), text=right, font=font, fill=ImageColor.getrgb(element['font']['color']) + (int(element['opacity'] * 255),))
                            background = Image.alpha_composite(background, img_text)
                            break
                else:
                    draw.text(xy=(x, y), text=content, font=font, fill=ImageColor.getrgb(element['font']['color']) + (int(element['opacity'] * 255),))
                    background = Image.alpha_composite(background, img_text)
            # Render image
            if element['type'] == 'image':
                url = kwagrs[element['name']]
                image = Image.open(io.BytesIO(requests.get(url).content)).convert("RGBA")
                image = image.resize((element['size']['width'], element['size']['height']))
                x, y = self.calcXY(element=element)
                # new_image = Image.new("RGBA", image.size)
                # opacity = int(255 * element['opacity'])
                overlay_image = Image.new("RGBA", background.size)
                overlay_image.paste(image, (x, y))
                overlay_opacity = element['opacity']  # Adjust this value as needed for the desired overlay opacity

                # Create a copy of the overlay image with adjusted opacity
                overlay_with_opacity = Image.new("RGBA", overlay_image.size)
                for x in range(overlay_image.width):
                    for y in range(overlay_image.height):
                        r, g, b, a = overlay_image.getpixel((x, y))
                        overlay_with_opacity.putpixel((x, y), (r, g, b, int(a * overlay_opacity)))
                # temp_image = temp_image.resize(temp_image.size, Image.ANTIALIAS)
                # # Create a new alpha channel with the specified opacity
                # alpha = Image.new("L", image.size, opacity)
                # image.putalpha(int(element['opacity'] * 255))
                # image = ReduceOpacity(image, element['opacity'])
                # print(int(element['opacity'] * 255))

                # Combine the color channels of the original image with the new alpha channel
                # image = Image.alpha_composite(new_image, Image.merge("RGBA", image.split()[:-1] + (alpha,)))
                # background.paste(image, (x, y))
                background = Image.alpha_composite(background, overlay_with_opacity)
            # Render image with remove background
            if element['type'] == 'remove-background':
                url = kwagrs[element['name']]
                image = Image.open(io.BytesIO(requests.get(url).content)).convert("RGBA")
                image = image.resize((element['size']['width'], element['size']['height']))
                remove = RemoveBackground('u2net')
                remove.load_session()
                x, y = self.calcXY(element=element)
                image = remove.remove(image=image)
                overlay_image = Image.new("RGBA", background.size)
                overlay_image.paste(image, (x, y))
                overlay_opacity = element['opacity']  # Adjust this value as needed for the desired overlay opacity

                # Create a copy of the overlay image with adjusted opacity
                overlay_with_opacity = Image.new("RGBA", overlay_image.size)
                for x in range(overlay_image.width):
                    for y in range(overlay_image.height):
                        r, g, b, a = overlay_image.getpixel((x, y))
                        overlay_with_opacity.putpixel((x, y), (r, g, b, int(a * overlay_opacity)))
                background = Image.alpha_composite(background, overlay_with_opacity)
        return background

class RemoveBackground:
    def __init__(self, model: str) -> None:
        self.model = model
    def load_session(self) -> None:
        self.session = new_session(self.model)
    def remove(self, image: Image) -> Image:
        return remove(data=image, session=self.session, alpha_matting=True, post_process_mask=True, alpha_matting_foreground_threshold=270 ,alpha_matting_background_threshold=20, alpha_matting_erode_size=11)

"""
if __name__ == '__main__':
    test = Template('templates/template.json')
    title = 'Logo car'
    product = 'https://joytoyfigure.com/wp-content/uploads/2022/09/Warhammer-40K.jpg'
    logo = "https://cdn.joytoyfigure.com/wp-content/uploads/2023/01/joytoy-figure-New-logo.png"
    background = 'https://www.ledr.com/colours/white.jpg'
    image = test.render(background=background, title=title, logo=logo, product=product)
    image.save('a.png')
"""

@app.get('/image.webp')
def get(request: Request):
    try:
        params = request.query_params
        template = Template(params['template'])
        image = template.render(params)
        imageByte = io.BytesIO()
        image.save(imageByte, format='WebP', quality=85, lossless=False)
        headers = {"Content-Disposition": f'''inline; filename="{params['name'] if 'name' in params else "image"}.webp"'''}
        # image.save(imageByte, format='PNG')
        return Response(imageByte.getvalue(), headers=headers)
    except Exception as e:
        return Response(str(e))

if __name__ == '__main__':
    uvicorn.run("main:app", host='0.0.0.0', port=80, reload=True)

# def main(url: str, title_text: str | None = '') -> None:
#     background = Image.open(io.BytesIO(requests.get(url=url, stream=True).content))
#     title_size = 1
#     title_font = ImageFont.truetype(font='Montserrat-Black.ttf', size=title_size)
#     draw = ImageDraw.Draw(background)
#     while True:
#         _, _, w, _ = draw.textbbox((0, 0), text=title_text, font=title_font)
#         if w < 0.5 * background.width:
#             title_size += 1
#             title_font = ImageFont.truetype(font='Montserrat-Black.ttf', size=title_size)
#         else:
#             break
#     draw.text(xy=((background.width - w)/ 2 + 4, 1), text=title_text, font=title_font, fill=ImageColor.getrgb("#9E9E9E"))
#     draw.text(xy=((background.width - w)/ 2, 1), text=title_text, font=title_font, fill=ImageColor.getrgb("#8C0000"))
#     print(f"Text width: {w}")
#     print(f"Height: {background.height}")
#     print(f"Width: {background.width}")
#     background.save('test.png')
# if __name__ == '__main__':
    # main(url='https://img.freepik.com/premium-photo/abstract-rainbow-colorful-bright-feather-closeup-up-macro-view-background-plumage-texture-with-dew-drops_753134-644.jpg', title_text="aaaaaaaaaaaaa")


# 2016년 1월 1일은 금요일입니다. 2016년 a월 b일은 무슨 요일일까요? 두 수 a ,b를 입력받아 2016년 a월 b일이 무슨 요일인지 리턴하는 함수, solution을 완성하세요. 요일의 이름은 일요일부터 토요일까지 각각 SUN,MON,TUE,WED,THU,FRI,SAT

# 입니다. 예를 들어 a=5, b=24라면 5월 24일은 화요일이므로 문자열 "TUE"를 반환하세요.

# 제한 조건
# 2016년은 윤년입니다.
# 2016년 a월 b일은 실제로 있는 날입니다. (13월 26일이나 2월 45일같은 날짜는 주어지지 않습니다)

# jan = 31
# feb = 29
# march = 31
# apr = 30
# may = 31
# june = 30
# july = 31
# august = 31
# september = 30
# october = 31
# november = 30
# december = 31

# 방법 1
# def solution(a, b):
#     day = ['FRI', 'SAT', 'SUN', 'MON', 'TUE', 'WED', 'THU']
#     date = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
#     return day[(sum(date[:a-1]) + b) % 7  - 1]

# 다른 풀이 참고 방법2
# datetime 라이브러리 사용하기
# 과정1
    # print(datetime.datetime(2016, a, b))
# 과정2
    # print(datetime.datetime(2016, a, b).weekday())
import datetime

def solution(a, b):
    day = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN']
    return day[datetime.datetime(2016, a, b).weekday()]

a = 5
b = 24
solution(a, b)


def vaild(strs):
    length = len(strs)
    if strs == None or len(strs) == 0:
        return 1
    hstack = []
    sArr = list(strs)
    hstack.append(sArr.pop(0))
    while hstack and sArr:
        next_item = sArr.pop(0)
        if next_item in ["(", "[", "{"]:
            hstack.append(next_item)
        elif next_item == ")":
            top = hstack.pop()
            if top != "(":
                return 0
        elif next_item == "]":
            top = hstack.pop()
            if top != "[":
                return 0
        elif next_item == "}":
            top = hstack.pop()
            if top != "{":
                return 0
    if len(hstack) != 0:
        return 0
    return 1

s = input()
print(vaild(s))


import json
from typing import List, Dict, Any

def extract_json(string: str) -> List[Dict[str, Any]]:
    json_strings = []
    json_objects = []
    open_brackets = 0
    start_index = None

    for index, char in enumerate(string):
        if char == '{':
            open_brackets += 1
            if open_brackets == 1:
                start_index = index
        elif char == '}':
            open_brackets -= 1
            if open_brackets == 0:
                json_strings.append(string[start_index : index + 1])

    for json_str in json_strings:
        try:
            json_object = json.loads(json_str)
            json_objects.append(json_object)
        except json.JSONDecodeError as e:
            pass

    return json_objects

def loads_or_none(str:str):
    try:
        return json.loads(str)
    except:
        return None

# input_string = "博士：兔兔你好。{\"reply\": \"你好博士。\", \"mental\": \"\", \"activity\": \"\"}"

# extracted_json = extract_json(input_string)

# print(extracted_json)


#!/usr/bin/env python

"""The setup script."""

from setuptools import setup, find_packages

with open("README.rst") as readme_file:
    readme = readme_file.read()

with open("HISTORY.rst") as history_file:
    history = history_file.read()

with open("requirements.txt") as requirements_file:
    requirements = requirements_file.read().splitlines()

setup_requirements = [
    "pytest-runner",
]

test_requirements = [
    "pytest>=3",
]

setup(
    author="Harsh Parekh",
    author_email="harsh_parekh@outlook.com",
    python_requires=">=3.6",
    classifiers=[
        "Framework :: Flask",
        "Development Status :: 2 - Pre-Alpha",
        "Environment :: Web Environment",
        "Intended Audience :: Developers",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
        "Natural Language :: English",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3.6",
        "Programming Language :: Python :: 3.7",
        "Programming Language :: Python :: 3.8",
        "Topic :: Internet :: WWW/HTTP :: Dynamic Content",
        "Topic :: Software Development :: Libraries :: Python Modules",
    ],
    description="Rest API on Flask made a little too easy.",
    install_requires=requirements,
    license="MIT license",
    long_description=readme + "\n\n" + history,
    include_package_data=True,
    keywords="flask_easyapi",
    name="flask_easyapi",
    packages=find_packages(include=["flask_easyapi", "flask_easyapi.*"]),
    setup_requires=setup_requirements,
    test_suite="tests",
    tests_require=test_requirements,
    url="https://github.com/hXtreme/flask-easyapi",
    version="0.1.1",
    zip_safe=False,
)


import  tkinter as tk
from PIL import Image, ImageTk
from .constants import *
from utility.statistics import StatisticsKeys

class LoadStep:
    def __init__(self, gui):

        self.gui = gui
        self.loading_steps_frame = tk.Frame(self.gui.root, bg='#d9ddff')
        self.next_state_button = tk.Button(self.loading_steps_frame, text='Next', bg='grey', command=self.button_next)
        self.previous_state_button = tk.Button(self.loading_steps_frame, text='Previous', bg='grey', state=tk.DISABLED)
        self.loading_steps_title = tk.Label(self.loading_steps_frame, text="Load step", bg=TITLE_COLOR, justify="center", font=TITLE_FONT)

    # button utils
    def button_previous(self):

        self.gui.production_engine.previous()
        self.gui.print_current_state()
        self.place()

    def button_next(self):

        self.gui.production_engine.next()
        self.gui.print_current_state()
        self.place()

    def update_buttons(self):
        if self.gui.production_engine.current_index() <= 0:
            self.previous_state_button = tk.Button(self.loading_steps_frame, text="Previous", bg='grey', state=tk.DISABLED)
        else:
            self.previous_state_button = tk.Button(self.loading_steps_frame, text="Previous", bg='grey', command=self.button_previous)

        self.place()

    def place(self):

        self.loading_steps_frame.place(relx=1 - MAIN_GRAPH_OFFSET, rely=MAIN_GRAPH_OFFSET, relwidth=LOADING_STEPS_WIDTH, relheight=LOADING_STEPS_HEIGHT, anchor='ne')
        self.loading_steps_title.place(relwidth=1, relheight=0.4)
        self.next_state_button.place(relx = 0.5, rely=0.4, relwidth=0.5, relheight=0.6)
        self.previous_state_button.place(rely=0.4, relwidth=0.5, relheight=0.6)


"""Test the gambit.sigs.convert module."""

import pytest
import numpy as np

from gambit.sigs.convert import dense_to_sparse, sparse_to_dense, can_convert, \
	check_can_convert, convert_dense, convert_sparse
from gambit.kmers import KmerSpec
from gambit.test import random_seq

def test_dense_sparse_conversion():
	"""Test conversion between dense and sparse representations of k-mer coordinates."""

	for k in range(1, 10):

		kspec = KmerSpec(k, 'ATGAC')

		# Create dense signature with every 3rd k-mer
		vec = np.zeros(kspec.nkmers, dtype=bool)
		vec[np.arange(vec.size) % 3 == 0] = True

		# Convert to sparse
		sig = dense_to_sparse(vec)

		assert len(sig) == vec.sum()
		for index in sig:
			assert vec[index]

		# Check sorted
		assert np.all(np.diff(sig) > 0)

		# Check converting back
		assert np.array_equal(vec, sparse_to_dense(kspec, sig))

class TestKmerSpecConversion:
	"""Test converting signatures from one KmerSpec to another."""

	def test_can_convert(self):
		from_kspec = KmerSpec(11, 'ATGAC')

		compatible = [
			KmerSpec(11, 'ATGAC'),
			KmerSpec(8, 'ATGAC'),
			KmerSpec(10, 'ATGACA'),
			KmerSpec(8, 'ATGACA'),
		]

		for to_kspec in compatible:
			assert can_convert(from_kspec, to_kspec)
			check_can_convert(from_kspec, to_kspec)

		incompatible = [
			KmerSpec(11, 'CAGTA'),
			KmerSpec(12, 'ATGAC'),
			KmerSpec(11, 'ATGA'),
			KmerSpec(11, 'ATGACT'),
		]

		for to_kspec in incompatible:
			assert not can_convert(from_kspec, to_kspec)
			with pytest.raises(ValueError):
				check_can_convert(from_kspec, to_kspec)

	@pytest.fixture(scope='class')
	def seqs(self):
		np.random.seed(0)
		return [random_seq(100_000) for _ in range(100)]

	@pytest.mark.parametrize('to_kspec', [
		KmerSpec(10, 'ATGAC'),   # Reduce k
		KmerSpec(8, 'ATGAC'),    # Reduce k
		KmerSpec(9, 'ATGACGT'),  # Extend prefix
		KmerSpec(7, 'ATGACGT'),  # Extend prefix and reduce k further
	])
	def test_convert(self, seqs, to_kspec):
		from gambit.sigs.calc import calc_signature

		from_kspec = KmerSpec(11, 'ATGAC')

		for seq in seqs:
			from_sig = calc_signature(from_kspec, seq)
			from_vec = sparse_to_dense(from_kspec.k, from_sig)

			to_vec = convert_dense(from_kspec, to_kspec, from_vec)
			to_sig = convert_sparse(from_kspec, to_kspec, from_sig)

			found_sig = calc_signature(to_kspec, seq)

			assert np.array_equal(to_sig, found_sig)
			assert np.array_equal(to_vec, sparse_to_dense(to_kspec.k, found_sig))


import os
import glob
import re

primary=[
    r"path1",
    r"path2",
    r"path3",
    r"path4",
    r"path5"
]
secondary=[
    r"path6",
    r"path7"
]

pl=len(primary)
sl=len(secondary)

for q in range(pl):
    primary[q]+="\\"
    #print(primary[q])

for q in range(sl):
    secondary[q]+="\\"
    #print(secondary[q])

flag=0
xlsx=".xlsx"
xls=".xls"

def primary_search(pl,xlsx):
    for i in range(pl):
            os.chdir(primary[i])
            tempfilename=primary[i]+"**\\"+filename+xlsx
            l=glob.glob(tempfilename, recursive=True)
            if bool(l)==True:
                print(l)
            if bool(l)==False:
                print("該当なし")

def secondary_search(pl,xlsx):
    for i in range(pl):
            os.chdir(secondary[i])
            tempfilename=secondary[i]+"**\\"+filename+xlsx
            l=glob.glob(tempfilename, recursive=True)
            if bool(l)==True:
                print(l)
            if bool(l)==False:
                print("該当なし")

#def search(path,len,filetype):
#    for i in range(len):
#            os.chdir(path[i])
#            tempfilename=path[i]+"**\\"+filename+filetype
#            l=glob.glob(tempfilename, recursive=True)
#            if bool(l)==True:
#                print(l)
#            if bool(l)==False:
#                print("該当なし")
#   #ex)search(primary,pl,xls) search(secondary,sl,xlsx)

while flag==0:
    filename=input("file name?\n")
    print("優先パスを検索します")
    print("xlsxを検索")
    primary_search(pl,xlsx)
    print("xlsを検索")
    primary_search(pl,xls)
    print("\n")
    exitflag=int(input("さらに過去も検索:0,exit:1\n"))
    if exitflag==1:
        break
    else:
        print("xlsxを検索")
        secondary_search(sl,xlsx)
        print("xlsを検索")
        secondary_search(sl,xls)
        print("\n")
        flag=int(input("0:continue\n1:exit\n"))
input("end:enter")


import sys
sys.stdin = open("inputs/문자열비교.txt", "r")

def match(p, t):
    i = 0 # 전체 문자열 t의 인덱스
    j = 0 # 안에 속할 문자열 p의 인덱스
    while j < len(p) and i < len(t):
        if t[i] != p[j]: # 만약 일치에 실패한다면
            i = i-j # i는 j와 비교를 시작한 부분에서 한 칸 더 오른쪽으로 시작점을 옮김
            j = -1 # j는 처음부터 (인덱스 0부터) 비교 시작
        i = i+1
        j = j+1
    # 1 일치한다면 j가 len(p)까지 상승하여 (j의 끝까지 일치확인)
    # 2 일치하지 않는다면 결국 i가 len(t)까지 상승하여
    # while문이 종료될 것
    # 1의 경우
    if j == len(p):
        return 1
    # 2의 경우
    else:
        return 0

T = int(input())
for test_case in range(1, T+1):
    p = input()
    t = input()
    ans = match(p, t)
    print(f'#{test_case} {ans}')


'''
Author     : knight_byte
File       : A_Patrick_and_Shopping.py
Created on : 2021-04-19 14:15:35
'''

def main():
    d = sorted(list(map(int, input().split())))
    mi = min(2*(d[0]+d[1]), sum(d))
    print(mi)

if __name__ == '__main__':
    main()