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

from django.db.models import Sum

from store.forms import AnularVentaForm
from store.functions import MiPaginador
from store.models import DetalleIngresoProducto
from store.values import ACCION_MODIFICAR
from store.ventas import *

@login_required(redirect_field_name='ret', login_url='/login')
def view(request):
    if request.method == 'POST':
        action = request.POST['action']
        if action == 'anular':
            venta = Venta.objects.get(pk=request.POST['id'])
            f = AnularVentaForm(request.POST)
            if f.is_valid():
                venta.valida = False
                venta.usuarioanula = request.user
                venta.motivoanulacion = f.cleaned_data['motivo']
                venta.save()

                salva_auditoria(request, venta, ACCION_MODIFICAR)

                # Actualizar Inventario
                for d in venta.detalles.all():
                    if InventarioReal.objects.filter(producto=d.producto).exists():
                        inventarioreal = InventarioReal.objects.filter(producto=d.producto)[0]
                        inventarioreal.cantidad = inventarioreal.cantidad + d.cantidad
                        ultimoingresoprod = None
                        if DetalleIngresoProducto.objects.filter(producto=d.producto).exists():
                            ultimoingresoprod = DetalleIngresoProducto.objects.filter(producto=d.producto).latest('id')
                        if ultimoingresoprod:
                            inventarioreal.valor = inventarioreal.valor + ultimoingresoprod.valor
                            inventarioreal.costo = inventarioreal.valor / inventarioreal.cantidad
                            inventarioreal.save()
                        else:
                            inventarioreal.valor = inventarioreal.valor + d.valor
                            inventarioreal.costo = inventarioreal.valor / inventarioreal.cantidad
                            inventarioreal.save()

                    else:
                        inventarioreal = InventarioReal(producto=d.producto,
                                                        cantidad=d.cantidad,
                                                        costo=d.pvp,
                                                        valor=d.valor)
                        inventarioreal.save()

                return HttpResponseRedirect('/cons_ventas')

            else:
                return HttpResponseRedirect('/cons_ventas?action=anular&id=' + str(venta.id))

    else:
        data = {'title': 'Consulta de Ventas'}
        addUserData(request, data)
        if 'action' in request.GET:
            action = request.GET['action']
            if action == 'detalle':
                data['venta'] = Venta.objects.get(pk=request.GET['idventa'])
                return render_to_response('cons_ventas/detalleventas.html', data)
            elif action == 'anular':
                data['venta'] = Venta.objects.get(pk=request.GET['id'])
                data['form'] = AnularVentaForm()
                return render_to_response('cons_ventas/anulaventa.html', data)
        else:
            search = None
            sesion = None

            if 'sesion' in request.GET:
                sesion = request.GET['sesion']
                data['sesionid'] = int(sesion) if sesion else ""
                data['sesion'] = SesionCaja.objects.get(pk=sesion) if sesion else ""
                data['totalventasesion'] = Venta.objects.filter(sesioncaja__id=sesion).aggregate(Sum('total'))['total__sum'] if sesion else ""
                data['cantidadventasesion'] = Venta.objects.filter(sesioncaja__id=sesion).count() if sesion else ""
                data['creditosesion'] = pagos_total_fecha_credito_sesion(data['sesion']) if sesion else ""
                data['valessesion'] = ""
                data['depositarsesion'] = data['totalventasesion'] - data['creditosesion'] - data['valessesion'] if sesion else ""
                data['promedioventasesion'] = Decimal(data['totalventasesion'] / data['cantidadventasesion']).quantize(Decimal(10) ** -2) if sesion else ""

            if 's' in request.GET:
                search = request.GET['s']

            if search:
                ventas = Venta.objects.filter(id__icontains=search)
            elif sesion:
                ventas = Venta.objects.filter(sesioncaja__id=sesion).order_by('-fecha', '-id', '-hora')
            else:
                ventas = Venta.objects.all()

            paging = MiPaginador(ventas, 25)
            p = 1
            try:
                if 'page' in request.GET:
                    p = int(request.GET['page'])
                page = paging.page(p)
            except:
                page = paging.page(1)

            data['paging'] = paging
            data['rangospaging'] = paging.rangos_paginado(p)
            data['page'] = page
            data['search'] = search if search else ""
            data['ventas'] = page.object_list
            data['sesionescaja'] = SesionCaja.objects.all().order_by('fecha')
            return render_to_response("cons_ventas/cons_ventas.html", data)


from SmartHomeObject import *

class Director:

   __builder = None

   def setBuilder(self, builder):
      self.__builder = builder

   def getSmartHomeObject(self):

      smartHomeObject = SmartHomeObject()

      stromverbrauch = self.__builder.getStromverbrauch()
      smartHomeObject.setStromverbrauch(stromverbrauch)

      sensorTyp = self.__builder.getSensorTyp()
      smartHomeObject.setSensorTyp(sensorTyp)

      steuergeraet = self.__builder.getSteuergeraet()
      smartHomeObject.setSteuergeraet(steuergeraet)

      produktID = self.__builder.getProduktID()
      smartHomeObject.setProduktID(produktID)
      return smartHomeObject


from __future__ import unicode_literals

# FIXME:
# use docinfo instead of meta for pg header

import re
from functools import partial

from six.moves import urllib

from lxml import etree
import lxml.html

import docutils.readers.standalone
from docutils import nodes, frontend
import docutils

from pkg_resources import resource_string # pylint: disable=E0611

from libgutenberg.GutenbergGlobals import NS
from libgutenberg.Logger import info, debug, warning, error
from libgutenberg.MediaTypes import mediatypes as mt

from ebookmaker import ParserFactory, parsers
from ebookmaker.parsers import HTMLParser, BROKEN

from ebookmaker.mydocutils import nodes as mynodes
from ebookmaker.mydocutils.writers import xhtml1, epub2, xetex

from ebookmaker.mydocutils.gutenberg import parsers as gutenberg_parsers
from ebookmaker.mydocutils.gutenberg.writers import nroff as gutenberg_nroff

mediatypes = (mt.rst, )

REB_EMACS_CHARSET = re.compile (rb'-\*-.*coding:\s*(\S+)',  re.I)

class Parser (HTMLParser.Parser):
    """ Parse a ReStructured Text

    and convert it to different xhtml flavours.

    """

    def __init__ (self, attribs = None):
        HTMLParser.Parser.__init__ (self, attribs)
        self.document1 = None

    def preprocess (self, charset):
        """ Insert pg header and footer. """

        return self.unicode_content ()

    def to_xhtml (self, html, base_url):
        html = html.replace (' ', ' ')
        html = html.replace ('—', '—')

        try:
            xhtml = etree.fromstring (
                html,
                lxml.html.XHTMLParser (),
                base_url = base_url)
        except etree.ParseError as what:
            error ("etree.fromstring says %s" % what)
            raise

        xhtml.make_links_absolute (base_url = base_url)

        return xhtml

    def rewrite_links (self, f):
        """ Rewrite all links using the function f. """

        doc = self.document1

        if 'coverpage' in doc.meta_block:
            coverpage = doc.meta_block['coverpage']
            coverpage[0] = f (coverpage[0])
        else:
            for field in doc.traverse (nodes.field):
                field_name, field_body = field.children
                if field_name.astext () == 'coverpage':
                    field_body[:] = nodes.paragraph ('', f (field_body.astext ()))
                    break

        for node in doc.traverse (nodes.reference):
            if 'uri' in node:
                node['uri'] = f (node['uri'])

        for node in doc.traverse (nodes.image):
            if 'uri' in node:
                node['uri'] = f (node['uri'])

        for node in doc.traverse (nodes.pending):
            # dropcap images
            if 'image' in node.details:
                node.details['image'] = f (node.details['image'])

    def iterlinks (self):
        """ Grab links and images in RST. """

        debug ("RSTParser iterlinks")

        doc = self.document1

        # return coverpage even in no_images build
        if 'coverpage' in doc.meta_block:
            coverpage = doc.meta_block['coverpage']
            yield coverpage[0], parsers.em.link (rel='icon')
        else:
            for field in doc.traverse (nodes.field):
                field_name, field_body = field.children
                if field_name.astext () == 'coverpage':
                    yield field_body.astext(), parsers.em.link (rel='icon')
                    break

        # need broken.png for no_images build
        # yield (BROKEN), parsers.em.img (rel = 'important')

        # anchor links
        for node in doc.traverse (nodes.reference):
            if 'uri' in node:
                yield node['uri'], parsers.em.a ()

        # images
        for node in doc.traverse (nodes.image):
            d = parsers.em.img ()
            # specify class important if you want to keep an image in a no_images build
            if 'important' in node.get ('classes', []):
                d.set('rel', 'important')
            if 'uri' in node:
                yield node['uri'], d

        # dropcap images
        for node in doc.traverse (nodes.pending):
            if 'image' in node.details:
                yield node.details['image'], parsers.em.img ()

    def get_settings (self, components, defaults):
        option_parser = frontend.OptionParser (
            components = components,
            defaults = defaults,
            read_config_files = 1)
        return option_parser.get_default_values ()

    def pre_parse (self):
        """ Parse a RST file as link list. """

        debug ("RSTParser: Pre-parsing %s" % self.attribs.url)

        default_style = self.get_resource (
            'mydocutils.parsers', 'default_style.rst')

        source = docutils.io.StringInput (default_style + self.unicode_content ())
        reader = docutils.readers.standalone.Reader ()
        parser = gutenberg_parsers.Parser ()

        overrides = {
            'get_resource': self.get_resource,
            'get_image_size': self.get_image_size_from_parser,
            'base_url': self.attribs.url,
            }

        doc = reader.read (
            source, parser, self.get_settings ((reader, parser), overrides))
        self.document1 = doc

        self.rewrite_links (partial (urllib.parse.urljoin, self.attribs.url))

        debug ("RSTParser: Done pre-parsing %s" % self.attribs.url)

    def _full_parse (self, writer, overrides):
        """ Full parse from scratch. """

        debug ("RSTParser: Full-parsing %s" % self.attribs.url)

        default_style = self.get_resource (
            'mydocutils.parsers', 'default_style.rst')

        source = docutils.io.StringInput (default_style + self.unicode_content (),
                                 self.attribs.url, 'unicode')
        reader = docutils.readers.standalone.Reader ()
        parser = gutenberg_parsers.Parser ()

        doc = reader.read (
            source, parser,
            self.get_settings ((reader, parser, writer), overrides))
        self.document1 = doc

        self.rewrite_links (partial (urllib.parse.urljoin, self.attribs.url))

        doc.transformer.populate_from_components ((source, reader, parser, writer))
        doc.transformer.apply_transforms ()
        debug ("RSTParser: Done full-parsing %s" % self.attribs.url)

        return doc

    def _full_parse_2 (self, writer, destination, overrides):
        """ Full parser from pickled doctree.

        Doesn't work yet. It turned out pickling a doctree is much
        harder than I thought. """

        debug ("Full-parsing %s" % self.attribs.url)

        source = docutils.io.StringInput (self.unicode_content ())
        reader = docutils.readers.standalone.Reader ()
        parser = gutenberg_parsers.Parser ()

        doc = reader.read (
            source, parser,
            self.get_settings ((reader, parser, writer), overrides))
        self.document1 = doc

        self.rewrite_links (partial (urllib.parse.urljoin, self.attribs.url))

        # make it picklable
        reporter = doc.reporter #  = None
        # doc.reporter = None
        transformer = doc.transformer
        doc.settings = None
        from docutils.parsers.rst.directives.html import MetaBody

        #for metanode in doc.traverse (MetaBody.meta):
        for pending in doc.traverse (nodes.pending):
            # pending.transform = None
            # docutils' meta nodes aren't picklable because the class is nested
            # in pending['nodes']
            if 'nodes' in pending.details:
                if isinstance (pending.details['nodes'][0], MetaBody.meta):
                    pending.details['nodes'][0].__class__ = mynodes.meta
        from six.moves import cPickle as pickle
        pickled = pickle.dumps (doc)

        doc = pickle.loads (pickled)

        #doc.transformer.populate_from_components (
        #    (source, reader, parser, writer))

        doc.transformer = transformer
        doc.reporter = reporter
        doc.settings = self.get_settings ((reader, parser, writer), overrides)

        doc.transformer.apply_transforms ()

        return writer.write (doc, destination)

    def rst2nroff (self, job, charset = 'utf-8'):
        """ Convert RST to nroff. """

        writer = gutenberg_nroff.Writer ()
        destination = docutils.io.StringOutput (encoding = 'unicode') # !

        overrides = {
            'doctitle_xform': 1,
            'sectsubtitle_xform': 1,
            'footnote_references': 'superscript',
            'compact_lists': 1,
            'compact_simple': 1,
            'page_numbers': 1,
            'no_images': True,
            'get_resource': self.get_resource,
            'format': job.type,
            'encoding': charset,
            'base_url': self.attribs.url,
            }

        doc = self._full_parse (writer, overrides)
        return writer.write (doc, destination)

    def rst2xetex (self, job):
        """ Convert RST to xetex. """

        writer = xetex.Writer ()
        destination = docutils.io.StringOutput (encoding = 'utf-8')

        overrides = {
            'doctitle_xform': 1,
            'sectsubtitle_xform': 1,
            'footnote_references': 'superscript',
            'compact_lists': 1,
            'compact_simple': 1,
            'page_numbers': 1,
            'format': job.type,
            'encoding': 'utf-8',
            'get_resource': self.get_resource,
            'get_image_size': self.get_image_size_from_parser,
            'base_url': self.attribs.url,
            }

        doc = self._full_parse (writer, overrides)
        return writer.write (doc, destination)

    def rst2htmlish (self, job, writer, more_overrides = {}):

        destination = docutils.io.StringOutput (encoding = 'unicode')

        overrides = {
            'stylesheet': None,
            'stylesheet_path': None,
            'xml_declaration': 0,
            'doctitle_xform': 1,
            'initial_header_level': 2,
            'sectsubtitle_xform': 1,
            'footnote_references': 'superscript',
            'page_numbers': 1,
            'format': job.type,
            'encoding': 'utf-8',
            'get_resource': self.get_resource,
            'get_image_size': self.get_image_size_from_parser,
            'base_url': self.attribs.url,
            }
        overrides.update (more_overrides)

        doc = self._full_parse (writer, overrides)
        return writer.fixup_xhtml (self.to_xhtml (writer.write (doc, destination), self.attribs.url))

    def rst2html (self, job):
        """ Convert RST input to HTML output. """
        return self.rst2htmlish (job, xhtml1.Writer ())

    def rst2epub2 (self, job):
        """ Convert RST input to HTML output with Epub2 tweaks. """
        return self.rst2htmlish (job, epub2.Writer (),
                                 { 'toc_backlinks': 'none' })

    def get_resource (self, package, resource):
        return resource_string ('ebookmaker.' + package, resource).decode ('utf-8')

    def get_image_size_from_parser (self, uri):
        # debug ("Getting image dimen for %s" % uri)
        parser = ParserFactory.ParserFactory.create (uri)
        parser.pre_parse ()
        if hasattr (parser, 'get_image_dimen'):
            return parser.get_image_dimen ()
        return None

    def get_charset_from_meta (self):
        """ Parse text for hints about charset. """
        # .. -*- coding: utf-8 -*-

        charset = None
        rst = self.bytes_content ()

        match = REB_EMACS_CHARSET.search (rst)
        if match:
            charset = match.group (1).decode ('ascii')
            debug ('Got charset %s from emacs comment' % charset)

        return charset

    def parse (self):
        """ Dummy. Use rst2* instead. """

        debug ("Done parsing %s" % self.attribs.url)


"""TEST NEW LESSON"""
def fib(num):
    """fibo docx"""
    mata = [[1, 1], [1, 0]]
    if num == 0:
        return 0
    power(mata, num - 1)
    return mata[0][0]

def multiply(mata, matb):
    """matrix multiply"""
    posx = (mata[0][0] * matb[0][0] + mata[0][1] * matb[1][0])
    posy = (mata[0][0] * matb[0][1] + mata[0][1] * matb[1][1])
    posz = (mata[1][0] * matb[0][0] + mata[1][1] * matb[1][0])
    posw = (mata[1][0] * matb[0][1] + mata[1][1] * matb[1][1])
    mata[0][0] = posx
    mata[0][1] = posy
    mata[1][0] = posz
    mata[1][1] = posw

def power(mata, num):
    """power"""
    if num == 0 or num == 1:
        return
    matb = [[1, 1], [1, 0]]
    power(mata, num // 2)
    multiply(mata, mata)
    if num % 2 != 0:
        multiply(mata, matb)

def main():
    """main docx"""
    num = int(input())
    print(fib(num))

main()


import json

import ephem
import pytest
from ephem import Observer

from app.helpers import DateTimeEncoder
from app.planets import Sun
from app.views import ObjectsPositionView

#
# def async_test(f):
#     def wrapper(*args, **kwargs):
#         coro = asyncio.coroutine(f)
#         future = coro(*args, **kwargs)
#         loop = asyncio.get_event_loop()
#         loop.run_until_complete(future)
#
#     return wrapper
#
#
# class TestMoon(TestCase):
#     def test_moon_day_calulcation(self):
#         dt = datetime.utcnow()
#         moon = ephem.Moon()
#
#         obs = ephem.Observer()
#         obs.lat = '52.26312730000001'
#         obs.lon = '104.3399244'
#
#         new_moon = ephem.previous_new_moon(dt)
#         next_new_moon = ephem.next_new_moon(dt)
#         next_full_moon = ephem.next_full_moon(dt).datetime() + timedelta(hours=8)
#         last_day = new_moon
#         for i in range(1, 32):
#             obs.date = last_day
#             day_end = obs.next_rising(moon, last_day, True)
#             print("day {} {} - {}".format(i, last_day.datetime() + timedelta(hours=8),
#                                           day_end.datetime() + timedelta(hours=8)))
#             if day_end > next_new_moon:
#                 break
#             last_day = day_end
#
#         moon.compute(obs)
# #         print(moon)
#
# @pytest.fixture
# def observer():
#     obs = ephem.Observer()
#     obs.lat = '52.26312730000001'
#     obs.lon = '104.3399244'
#     return obs
#
#
# async def test_compute_moon(test_client):
#     view = ObjectsPositionView(None)
#     await view.set_location('52.26312730000001', '104.3399244')
#
#
# async def test_computation(test_client):
#     view = ObjectsPositionView(None)
#     await view.set_location(52.26312730000001, 104.3399244)
#     await view.update_positions()

@pytest.fixture
def observer():
    obs = ephem.Observer()
    obs.lat = '52.26312730000001'
    obs.lon = '104.3399244'
    return obs

@pytest.fixture
def view():
    v = ObjectsPositionView(None)
    return v

async def test_profile_computation(view: ObjectsPositionView):
    for _ in range(10000):
        await view.update_positions()
        server_time = view.observer.date.datetime().utcnow().isoformat()
        msg = json.dumps({
            'planets': [planet.to_dict() for name, planet in view.planets.items()],
            'server_time': server_time
        }, cls=DateTimeEncoder)

def test_sun_day(observer):
    planet = Sun()
    planet.compute(observer)

def test_asc_coordinate(observer: Observer):
    asc = ephem.Equatorial(0, 0)
    asc.compute(observer)
    print (asc.az)


import cv2 as cv
import pytesseract
import PIL.Image
from matplotlib import pyplot as plt

"""
Python segmentation modes:
0 = Orientation and script detection (OSD) only.
1 = Automatic page segmentation with OSD.
2 = Automatic page segmentation, but no OSD, or OCR.
3 = Fully automatic page segmentation, but no OSD. (Default)
4 = Assume a single column of text of variable sizes.
5 = Assume a single uniform block of vertically aligned text.
6 = Assume a single uniform block of text.
7 = Treat the image as a single text line.
8 = Treat the image as a single word.
9 = Treat the image as a single word in a circle.
10 = Treat the image as a single character.
11 = Sparse text. Find as much text as possible in no particular order.
12 = Sparse text with OSD.
13 = Raw line. Treat the image as a single text line, bypassing hacks that are Tesseract-specific.

"""

"""
OCR Engine modes:
0 = Original Tesseract only.
1 = Neural nets LSTM only.
2 = Tesseract + LSTM.
3 = Default, based on what is available.
"""

myconfig = r'--oem 3 --psm 6'

wellPerformingConfigs = {
    1: r'--oem 3 --psm 11',
    2: r'--oem 3 --psm 3',
    3: r'--oem 3 --psm 1',
    4: r'--oem 3 --psm 12',
}

# text_cropped = pytesseract.image_to_string(PIL.Image.open('cropped.png'), config=myconfig)
# text_cropped_1 = pytesseract.image_to_string(PIL.Image.open('cropped2.png'), config=myconfig)
# text_uncropped = pytesseract.image_to_string(PIL.Image.open('uncropped.1920x1080.png'), config=myconfig)
# # print(text_cropped + "\n\n\n"+ text_cropped_1)
# print(text_uncropped)

# text1 = pytesseract.image_to_string(PIL.Image.open('1280x720.png'), config=myconfig)
# text2 = pytesseract.image_to_string(PIL.Image.open('1440x900.png'), config=myconfig)
# text3 = pytesseract.image_to_string(PIL.Image.open('1680x1050.png'), config=myconfig)

# print(text2)
cropped = "cropped.png"
cropped1 = "cropped1.png"
cropped2 = "cropped2.png"
uncropped1 = "uncropped.1920x1080.png"
uncropped2 = "1280x720.png"
uncropped3 = "1440x900.png"
uncropped4 = "1680x1050.png"

img = cv.imread(uncropped4)
# convert to grayscale
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# image binarization
_,tresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY|cv.THRESH_OTSU)
# height, width = img.shape
# print(width, height)

## draw boxes on individual characters
# boxes = pytesseract.image_to_boxes(img, config=myconfig)
# print(boxes)
# for box in boxes.splitlines():
#     box = box.split(' ')
#     x, y, w, h = int(box[1]), int(box[2]), int(box[3]), int(box[4])
#     cv.rectangle(img, (x, height-y), (w, height-h), (255, 0, 0), 1)
#     cv.putText(img, box[0], (x, height-y+25), cv.FONT_HERSHEY_COMPLEX, 1, (50, 50, 255), 2)

# draw boxes on words
data = pytesseract.image_to_data(tresh, config=myconfig, output_type=pytesseract.Output.DICT, lang='eng')
print(data['text'])
amountOfWords = len(data['text'])
for i in range(amountOfWords):
    if float(data['conf'][i]) > 30:
        x, y, w, h = int(data['left'][i]), int(data['top'][i]), int(data['width'][i]), int(data['height'][i])
        cv.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 1)
        cv.putText(img, data['text'][i], (x, y), cv.FONT_HERSHEY_COMPLEX, 1, (50, 50, 255), 2)

plt.imshow(tresh, cmap='gray')
plt.show()


import nltk
from nltk.corpus import brown

days = ['Monday', 'Tuesday', 'Wednesday', 'Thrusday', 'Friday', 'Saturday', 'Sunday']
categories = ['news', 'romance']

cfd = nltk.ConditionalFreqDist(
    (category, word)
    for category in categories
    for word in brown.words(categories=category)
)

tab = cfd.tabulate(conditions=categories, samples=days)
print(tab)

cfd.plot()


class Piece:
    def __init__(self, left = -1, right = -1, free = True):
        self.free = free
        self.left = left
        self.right = right

    def turn(self):
        temp = self.left
        self.left = self.right
        self.right = temp

    def __repr__(self):
        if self.free:
            return '[%s %s]' % (self.left, self.right)
        else:
            return '~%s %s~' % (self.left, self.right)

def can_use_piece(left, piece, right):
    if left.right == piece.left:
        if not right: return True
        if right.left == piece.right: return True
    return False

def can_use_turned_piece(left, piece, right):
    if left.right == piece.right:
        if not right: return True
        if right.left == piece.left: return True
    return False

def try_fill_board(left, pieces, right, placed_pieces, n):
    if placed_pieces == n-1:
        for piece in pieces:
            if piece.free:
                if can_use_piece(left, piece, right):
                    return True
                if can_use_turned_piece(left, piece, right):
                    piece.turn()
                    return True
        return False
    for piece in pieces:
        if piece.free:
            if can_use_piece(left, piece, None):
                piece.free = False
                if try_fill_board(piece, pieces, right, placed_pieces + 1, n):
                    return True
                piece.free = True
            elif can_use_turned_piece(left, piece, None):
                piece.free = False
                piece.turn()
                if try_fill_board(piece, pieces, right, placed_pieces + 1, n):
                    return True
                piece.free = True
    return False

if __name__ == '__main__':
    while True:
        n = int(input().strip())
        if n == 0:
            break
        m = int(input().strip())

        left_v = input().strip().split()
        left = Piece(int(left_v[0]), int(left_v[1]), False)

        right_v = input().strip().split()
        right = Piece(int(right_v[0]), int(right_v[1]), False)
        pieces = []
        for i in range(0, m):
            piece_v = input().strip().split()
            piece = Piece(int(piece_v[0]), int(piece_v[1]), True)
            pieces.append(piece)
        if try_fill_board(left, pieces, right, 0, n):
            print('YES')
        else:
            print('NO')


import unittest

from security.encryption.symmetric.aes import AdvancedEncryptionStandard
from security.encryption.symmetric.des import DataEncryptionStandard

class SymmetricTests(unittest.TestCase):
    def setUp(self):
        DataEncryptionStandard.set_key("unittest")
        AdvancedEncryptionStandard.set_key("unittestunittest")

    def test_des(self):
        word = "Test Message"
        hashed_word = DataEncryptionStandard.encrypt(word)
        self.assertNotEqual(word, hashed_word)
        self.assertEqual(word, DataEncryptionStandard.decrypt(hashed_word))

    def test_aes(self):
        word = "Test Message"
        hashed_word = AdvancedEncryptionStandard.encrypt(word)
        self.assertNotEqual(word, hashed_word)
        self.assertEqual(word, AdvancedEncryptionStandard.decrypt(hashed_word))


import math
import numpy as np
from scipy import signal

# RPI4
from scipy.fftpack import fftshift
# PC
# from scipy.fft import fftshift

# fft parameter
N_FFT_point = 128
SamplingFreq = 650
fft_window = signal.windows.hamming(128)

def stft_crop(I_raw_data, Q_raw_data):
    # make complex input with I-data, Q-data and remove DC component
    complex_raw_data = []
    for i in range(0, 1920):
        complex_raw_data.append(
            complex(I_raw_data[i], Q_raw_data[i]))
    complex_raw_data_DC = complex_raw_data - np.mean(complex_raw_data)

    # stft
    f, t, Zxx = signal.stft(x=complex_raw_data_DC, fs=SamplingFreq, window=fft_window,
                            nperseg=N_FFT_point, nfft=N_FFT_point, noverlap=N_FFT_point//2, boundary=None)

    # fftshift
    Zxx = fftshift(abs(Zxx), axes=0)

    # crop image into 36x28 from 128x29
    Zxx = Zxx[46:82, 1:29]

    power_sum = 0

    # make fft result into integer from float
    for i in range(36):
        for j in range(28):
            Zxx[i][j] = math.ceil(abs(Zxx[i][j]))
            power_sum += Zxx[i][j] * Zxx[i][j]

    return Zxx, power_sum


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Comandi per gli admin
"""

import textfiles

ADMIN = "Database/Admin.txt"
admins = []

def admin():
    comandi = "*COMANDI ADMIN:*\n\n"
    comandi += "*/addadmin* Seguito da @username, aggiunge l'username alla lista degli admin.\n"
    comandi += "*/admin* Mostra i comandi utilizzabili esclusivamente dagli admin.\n"
    comandi += "*/getadmins* Mostra una lista con tutti gli admin.\n"
    comandi += "*/getchatids* Restituisce tutti gli ID delle chat in cui è stato utilizzato "
    comandi += "il Bot con relativo nome della chat.\n"
    comandi += "*/getdatabaseinfo* Mostra le informazioni su tutti i Database del Bot.\n"
    comandi += "*/getpropic* _Seguito dallo user ID_, restituisce tutte le immagini del profilo "
    comandi += "della persona corrispondente a quell'ID.\n"
    comandi += "*/reload* Riavvia i Database ricaricando gli ID dai file.\n"
    comandi += "*/sendall* _Seguito da un messaggio_, invia il messaggio a tutti gli utenti che hanno usato il Bot.\n"
    comandi += "*/sendmessage* _Seguito da [ID chat] e da un messaggio_, "
    comandi += "invia il messaggio alla chat con l'ID inserito.\n"
    comandi += "\n*SPECIALI*\n"
    comandi += "*/aggiungititolo* seguito da [ID azione] e dal nome dell'azione, "
    comandi += "aggiunge una nuova azione alla lista delle azioni seguite.\n"
    return comandi

def add_admin(messaggio):
    testo = messaggio.text
    rimuovi = "/addadmin @"
    if testo.startswith(rimuovi):
        adm = testo.replace(rimuovi, "")
        textfiles.append(adm + "\n", ADMIN)
        admins.extend([adm])
        return "L'admin @" + adm + " è stato aggiunto."
    else:
        return "ERRORE: formulazione della richiesta"

def get_admins():
    testo = ""
    for a in admins:
        testo += "@" + a + "\n"
    return testo

def get_admins_command():
    testo = "*ADMINS:*\n\n"
    testo += get_admins()
    return testo

def is_admin(user):
    return user in admins

def realod_admin():
    if textfiles.exists(ADMIN):
        lista = textfiles.readLines(ADMIN)
        del admins[:]
        for s in lista:
            admins.extend([s])
    else:
        textfiles.write("", ADMIN)

def is_digit(n):
    try:
        float(n)
        return True
    except ValueError:
        return False


from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import selenium.webdriver.support.ui as ui
from selenium.webdriver.chrome.options import Options
import time

#Getting Chrome Driver and setting profile settings
options1 = Options()
options1.add_argument(r"--user-data-dir=C:\Users\Ayoub\AppData\Local\Google\Chrome\User Data 1")
options1.add_argument(r'--profile-directory=Profile 1')
browser = webdriver.Chrome("C:\Program Files (x86)\chromedriver.exe",options=options1)

#Load page
browser.get("https://google.com/search?q=python")

#Wait to find element in page
first_result = ui.WebDriverWait(browser, 15).until(lambda browser: browser.find_element_by_class_name('eKjLze'))
first_link = first_result.find_element_by_tag_name('a')

# Save the window opener (current window, do not mistaken with tab... not the same)
main_window = browser.current_window_handle

# Open the link in a new tab by sending key strokes on the element
# Use: Keys.CONTROL + Keys.SHIFT + Keys.RETURN to open tab on top of the stack
first_link.send_keys(Keys.CONTROL + Keys.RETURN)

# Switch tab to the new tab, which we will assume is the next one on the right
browser.find_element_by_tag_name('body').send_keys(Keys.CONTROL + Keys.TAB)
time.sleep(2)

# Put focus on current window which will be the window opener
browser.switch_to.window(main_window)
time.sleep(2)

# Switch window handles
browser.switch_to.window(browser.window_handles[1])

# Do stuff with buttons
#browser.find_element_by_tag_name('body').send_keys(Keys.CONTROL + 'w')


from .import views
from django.conf.urls import url,include
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
app_name='dpyApp'

urlpatterns = [
    url(r'^$', views.home),
    url(r'^home/$', views.home),
    url(r'^login/$', views.login),
    url(r'^signup/$', views.signup),
    url(r'^ajax/validate_username/$', views.validate_username, name='validate_username'),
    url(r'^ajax/insert_user/$', views.insert_user, name='insert_user'),
    url(r'^update_user/$', views.update_user, name='update_user'),
    url(r'^validate_login/', views.validate_login, name='validate_login'),
    url(r'^logout/', views.logout, name='logout'),
]

urlpatterns += staticfiles_urlpatterns()


from typing import List

def average(values: List[float]) -> float:
    """values 내 수들의 평균을 반환한다. values 내 어떤 항목은 None일 수 있는데,
    None 값은 평균을 계산할 때 제외한다.

    >>> average([20, 30])
    25.0
    >>> average([None, 20, 30])
    25.0
    """

    count = 0 # 지금까지 본 값들의 개수
    total = 0 # 지금까지 본 값들의 합
    for value in values:
        if value is not None:
            total += value

        count += 1

    return total / count

if __name__ == '__main__':
    import doctest
    doctest.testmod()


from tensorflow.python.framework import dtypes
from tensorflow.python.framework import ops
from tensorflow.python.ops import array_ops
from tensorflow.python.ops import array_ops_stack
from tensorflow.python.ops import cond
from tensorflow.python.ops import gen_linalg_ops
from tensorflow.python.ops import linalg_ops
from tensorflow.python.ops import math_ops
from tensorflow.python.ops.linalg import linalg_impl as _linalg

@ops.RegisterGradient("MatrixInverse")
def _MatrixInverseGrad(op: ops.Operation, grad):
  """Gradient for MatrixInverse."""
  ainv = op.outputs[0]
  op_adjoint = op.get_attr("adjoint")
  return -math_ops.matmul(  # pylint: disable=invalid-unary-operand-type
      ainv,
      math_ops.matmul(grad, ainv, adjoint_a=op_adjoint,
                      adjoint_b=not op_adjoint),
      adjoint_a=not op_adjoint)

@ops.RegisterGradient("Einsum")
def _EinsumGrad(op: ops.Operation, grad):
  """Gradient for Einsum."""
  ellipsis = "..."

  def _GetAxisFromLabel(subscripts, label):
    """Returns the axis (possibly negative) corresponding to a label.

    Returns the axis index of the axis label if it is before an ellipsis (or if
    the ellipsis is not present), and the negative index if it occurs after the
    ellipsis. E.g. index of `b` in `ab...cd`, is `1`, but that of `c` is `-2`.

    For multiple occurrences, returns the leftmost one. If not found, returns
    None.

    Args:
      subscripts: A string denoting the einsum subscript (e.g. `ab...cd`)
      label: The single character axis label.
    """
    splits = subscripts.split(ellipsis)
    index = splits[0].find(label)
    if index != -1:
      return index
    if len(splits) < 2:
      return None
    index = splits[1].find(label)
    if index != -1:
      return index - len(splits[1])
    return None

  def _GetBcastSubshape(subscripts):
    """Returns a tuple denoting the slice mapping to ellipsis.

    For a given subscript, returns a tuple (start, end) denoting the start
    axis index and the (negative) end axis index respectively. For any input
    Tensor `x` described by the subscript, `x[start:end]` would be the slice
    represented by the ellipsis. E.g. For `ab...cd` returns `[1, -2]`.

    If ellipsis is not present in `subscripts`, returns `(0, 0)`.

    Args:
      subscripts: A string denoting the einsum subscript.
    """
    start = subscripts.find(ellipsis)
    if start == -1:
      return 0, 0
    remaining = len(subscripts) - (start + len(ellipsis))
    end = -remaining if remaining > 0 else None
    return start, end

  def _GetReducedSubscripts(reduced_label_set, input_shape, subscripts):
    """Returns reduced subscripts and their corresponding dimensions and axes.

    Given a set of axis labels, returns their concatenated subscript, their
    corresponding dimensions from input_shape, and their corresponding axes.
    Note that the concatenated subscript `reduced_subs` may have axis labels
    from `reduced_label_set` in any order. For example, for the reduced label
    set `{b, d}`, subscripts `aabbcd` and input shape `[2,2,5,5,3,4]`, returns
    subscripts `bd`, dimensions `[5,4]` and axes `[2,5]`.

    Args:
      reduced_label_set: Set of axis labels which appear in `subscripts`.
      input_shape: A `Tensor` representing the shape of the einsum operand
        corresponding to `subscripts`.
      subscripts: A string denoting the einsum subscript.

    Returns:
      reduced_subs: Subscripts formed by a concatenation of labels in
        `reduced_label_set`.
      reduced_dims: Dimensions from `input_shape` corresponding to each label
        in `reduced_subs`.
      reduced_axes: Axes described by `subscripts` corresponding to each label
        in `reduced_subs`. If there are multiple occurrences in `subscripts`,
        we consider only the leftmost one.

    """
    # Concatenate the sequence of reduced axis labels.
    reduced_subs = "".join(list(reduced_label_set))
    # Get the axis (may be positive, negative or zero) for each of the reduced
    # labels. If the same label appears multiple times, get the left-most axis.
    reduced_axes = [_GetAxisFromLabel(subscripts, s) for s in reduced_subs]
    # Get the corresponding dimensions for each reduced axis.
    reduced_dims = array_ops_stack.stack(
        [input_shape[ax] for ax in reduced_axes])
    return reduced_subs, reduced_dims, reduced_axes

  def _GetGradReduced(output_grad, output_subs, input_subs, input_shape,
                      reduced_label_set):
    """Returns the gradient wrt input for a unary einsum with reductions.

    Args:
      output_grad: The gradient wrt the output of a unary einsum operation.
      output_subs: The output subscript. (E.g. `ac` for equation `abc->ac`).
      input_subs: The input subscript. (E.g. `abc` for equation `abc->ac`).
      input_shape: A `Tensor` representing the shape of the input operand.
      reduced_label_set: The set of axis labels appearing in `input_subs` but
        not in `output_subs`.
    """
    # Let's say the einsum operation was "aabbcd->ca", where axis labels 'b' and
    # 'd' are reduced with input_shape [2,2,5,5,3,4]. Then obtain the reduced
    # subscripts "bd", corresponding dimensions [5,4] and axes [2,5].
    reduced_subs, reduced_dims, reduced_axes = _GetReducedSubscripts(
        reduced_label_set, input_shape, input_subs)
    # Whether either the input or the output subscripts have a repeated label.
    # This is true for "aabbcd->ca" or "abd->cca" but false for "abcd->ca".
    has_repeated_labels = (
        len(set(input_subs)) + len(set(output_subs)) <
        len(input_subs) + len(output_subs))
    # Compute the input subscripts without the reduced axis labels, e.g. "aac"
    # for the equation "aabbcd->ca".
    input_subs_without_reduced_labels = "".join(
        [s for s in input_subs if s not in reduced_label_set])

    # The gradient wrt the input for the equation "abc->ac" (or, equivalently
    # reduce_sum(..., axis=1)) is just the gradient of the output tiled N times
    # along axis 1, where label 'b' represents a dimension of size N.
    #
    # If we're not dealing with repeated labels, and the non-reduced labels
    # doesn't need to be transposed, then just tiling is enough and there is no
    # need to call another einsum. For example, tiling is sufficient for
    # "abcd->ac". But for equations like "aabbcd->ac" (generalized traces) or
    # "abc->ca" (transpose), we'd need another einsum operation after tiling.
    if (not has_repeated_labels and
        input_subs_without_reduced_labels == output_subs):
      # Obtain the shape of the output, as if keepdims=True on reduce sum. E.g.
      # for the equation "abcd->ac" with input shape [2,5,3,4], we get the
      # reduced shape [2,1,3,1].
      reduced_shape = math_ops.reduced_shape(
          input_shape, ops.convert_to_tensor(reduced_axes))
      # Reshaping the gradient (wrt "ac") to [2,1,3,1] and broadcasting it to
      # the shape [2,5,3,4] results in the gradient wrt "abcd".
      return array_ops.broadcast_to(
          array_ops.reshape(output_grad, reduced_shape), input_shape)

    # If we *do* have traces or transpose operations, then prepend the extra
    # reduced dimensions to the front. E.g. Given the equation "aabbcd->ca" we'd
    # first obtain the VJP for "bdca->ca", and then the VJP for "aabbcd->bdca".
    #
    # Obtain the input shape with reduced dimensions prepended, viz. [5,4,3,2].
    # This is the shape of the intermediate "bdca".
    grad_shape_with_reduced_labels = array_ops.concat(
        [reduced_dims, array_ops.shape(output_grad)], axis=0)
    # Obtain the output shape of the reduction-only equation "bdca->ca" as if
    # keepdims=True; viz. [1,1,3,2]. Since we prepended the reduced labels, we
    # just have to prepend that many 1s to the output shape.
    reduced_shape = (
        array_ops.concat([
            array_ops.ones(len(reduced_label_set), dtype=dtypes.int32),
            array_ops.shape(output_grad)
        ],
                         axis=0))
    # Compute the VJP for the intermediate (viz. "bdca->ca") for which
    # broadcasting is sufficient.
    broadcasted_grad = array_ops.broadcast_to(
        array_ops.reshape(output_grad, reduced_shape),
        grad_shape_with_reduced_labels)
    # Compute the VJP for the final step (viz. "aabbcd->bdca"). We can use
    # einsum with the input and output subscripts reversed (viz. "bdca->aabbcd")
    # since the output axis labels now appear in the input subscripts.
    return gen_linalg_ops.einsum([broadcasted_grad],
                                 "{}->{}".format(reduced_subs + output_subs,
                                                 input_subs))

  def _GetGradWrt(output_grad, other_operand, input_shape, input_subs,
                  other_subs, output_subs):
    """Returns the gradient wrt an input operand for a binary einsum.

    This function does not handle (un)broadcasting. This must be done separately
    on the returned gradient.

    Args:
      output_grad: The gradient wrt the output of a binary einsum operation.
      other_operand: The complementary `Tensor` operand i.e. which is not the
        input operand.
      input_shape: A `Tensor` representing the shape of input operand.
      input_subs: The subscripts of the input operand.
      other_subs: The subscripts of the complementary operand.
      output_subs: The output subscripts.
    """
    # Claim: For the einsum operation z = einsum("{eq_x},{eq_y}->{eq_z}", x, y),
    #   where the equation involves only Tensor contractions, generalized traces
    #   and transposes, the input gradients are given by the vector-jacobian
    #   products (VJPs):
    #
    #     grad_wrt_x = einsum("{eq_y},{eq_z}->{eq_x}", y, grad_wrt_z)
    #     grad_wrt_y = einsum("{eq_x},{eq_z}->{eq_y}", x, grad_wrt_z}
    #
    #   where grad_wrt_x and grad_wrt_y are the gradients with respect to inputs
    #   x and y and grad_wrt_z is the given gradient with respect to output z.
    #
    # Proof: For unary einsum equations involving only transpose ("ij->ji") and
    #   traces ("ii->i"), the linear mapping's Jacobian at input x is given
    #   by the function itself. We can verify that the linear map given by the
    #   VJP are einsums with the equations "ji->ij" and "i->ii" respectively,
    #   where the latter represents 'un-tracing', or filling the diagonal with
    #   the input axis and non-diagonal entries are zeros.
    #        Furthermore, recall that matrix multiplication, which is
    #   represented by the equation "ab,bc->ac", has its VJPs given by the
    #   einsum equations "ac,bc->ab" and "ab,ac->bc" (see, for example
    #   https://math.stackexchange.com/a/2755680). Combined with transposes and
    #   traces we can rewrite Tensor contractions as regular matrix
    #   multiplication. Since each of these operations have their VJPs described
    #   by einsums of the required pattern, the result follows.
    #
    # Accordingly, einsum operations except for those with reductions, e.g.
    # "abc,cd->ad" have their VJPs defined by:
    #   "{output_subs},{other_subs}->{input_subs}".
    #
    # But if there is a reduction, this would lead to the equation "ad,cd->abc"
    # which is invalid because the reduced axis label 'b' is present in the
    # output but not in any of the inputs. Therefore, we compute the VJP in two
    # steps: first we obtain VJP for "ac,cd->ad" and then we compute the VJP of
    # "abc->ac" or, equivalently, reduce_sum(..., axis=1).
    #
    # Compute the set of input axis labels which doesn't appear in either the
    # output subscripts or the other operand's subscript. E.g. the set {'b'} for
    # the equation "abc,cd->ad".
    reduced_label_set = set(input_subs).difference(
        set(output_subs + other_subs + "."))
    # Obtain the input subscripts with the reduced axis labels removed. E.g.
    # "ac" in the above example.
    left_subs = "".join(s for s in input_subs if s not in reduced_label_set)

    # Compute the gradient wrt the input, without accounting for the operation
    # "abc->ac". So, now we have the VJP of the operation "ac,cd->ad".
    grad_reduced = gen_linalg_ops.einsum([output_grad, other_operand],
                                         "{},{}->{}".format(
                                             output_subs, other_subs,
                                             left_subs))
    # If the reduced_label_set is empty, then we already have the gradient
    # wrt the input.
    if not reduced_label_set:
      return grad_reduced
    # Otherwise, we currently have the gradient wrt the output of the reduction
    # operation "abc->ac". Invoke the subroutine for the gradient for unary
    # einsum with reductions.
    return _GetGradReduced(grad_reduced, left_subs, input_subs, input_shape,
                           reduced_label_set)

  equation = op.get_attr("equation")
  if isinstance(equation, bytes):
    equation = equation.decode()
  input_subs, output_subs = equation.split("->")

  if len(op.inputs) == 1:
    # For the unary einsum z = einsum("{eq_x}->{eq_z}", x), the gradient wrt the
    # input (VJP) is given by the reversed equation:
    #   grad_wrt_x = einsum("{eq_z}->{eq_x}", grad_wrt_z)
    # (See the justification in _GetGradWrt). This is valid unless there are
    # reduced axis labels; i.e. axis labels appearing in the input but not in
    # the output subscripts.
    input_shape = array_ops.shape(op.inputs[0])
    # Find the axis labels which appear only in the input.
    reduced_label_set = set(input_subs).difference(set(output_subs + ellipsis))
    if not reduced_label_set:
      # Return the einsum given by the reversed equation, since we don't have
      # reduced axes.
      return gen_linalg_ops.einsum([grad],
                                   "{}->{}".format(output_subs, input_subs))
    # We do have reduced axes, so we invoke the subroutine for reduced unary
    # einsums.
    return _GetGradReduced(grad, output_subs, input_subs, input_shape,
                           reduced_label_set)

  x_subs, y_subs = input_subs.split(",")
  # Add ellipsis for broadcasted dimensions if any operand does not have it.
  # This is because the equation "...ij,jk->ik" may be valid if the 0th input's
  # batch shape is empty, but the VJP equation "jk,ik->...ij" is not valid
  # because only the output subscripts contain ellipsis.
  if ellipsis in output_subs:
    if ellipsis not in x_subs:
      x_subs += ellipsis
    if ellipsis not in y_subs:
      y_subs += ellipsis

  # Obtain the gradients wrt the inputs x and y, without taking into account
  # the unbroadcasting.
  x, y = op.inputs[0], op.inputs[1]
  if grad.dtype.is_complex:
    x = math_ops.conj(x)
    y = math_ops.conj(y)

  x_shape = array_ops.shape(x)
  y_shape = array_ops.shape(y)
  grad_x = _GetGradWrt(grad, y, x_shape, x_subs, y_subs, output_subs)
  grad_y = _GetGradWrt(grad, x, y_shape, y_subs, x_subs, output_subs)

  if ellipsis not in output_subs:
    # If no ellipsis in the output; then no need to unbroadcast.
    return grad_x, grad_y

  # Below we handle the case that broadcasting between x and y was necessary,
  # with x and y having possibly different batch shapes.

  # Obtain the range of axes which map to ellipsis. E.g. for subscripts 'ab...c'
  # and shape of rank 10; the range [3:-1] denotes the broadcasted axes.
  bx_start, bx_end = _GetBcastSubshape(x_subs)
  by_start, by_end = _GetBcastSubshape(y_subs)
  # If the static batch shapes are equal, we don't need to unbroadcast.
  x_shape_static = x.get_shape()
  y_shape_static = y.get_shape()
  if (x_shape_static.is_fully_defined() and
      y_shape_static.is_fully_defined() and
      x_shape_static[bx_start:bx_end] == y_shape_static[by_start:by_end]):
    return grad_x, grad_y

  # Sum the gradient across the broadcasted axes.
  rx, ry = array_ops.broadcast_gradient_args(x_shape[bx_start:bx_end],
                                             y_shape[by_start:by_end])
  grad_x = array_ops.reshape(
      math_ops.reduce_sum(grad_x, bx_start + rx), x_shape)
  grad_y = array_ops.reshape(
      math_ops.reduce_sum(grad_y, by_start + ry), y_shape)
  return grad_x, grad_y

@ops.RegisterGradient("MatrixDeterminant")
def _MatrixDeterminantGrad(op: ops.Operation, grad):
  """Gradient for MatrixDeterminant."""
  a = op.inputs[0]
  c = op.outputs[0]
  a_adj_inv = linalg_ops.matrix_inverse(a, adjoint=True)
  multipliers = array_ops.reshape(grad * c,
                                  array_ops.concat([array_ops.shape(c), [1, 1]],
                                                   0))
  return multipliers * a_adj_inv

@ops.RegisterGradient("MatrixSquareRoot")
def _MatrixSquareRootGrad(op: ops.Operation, grad):
  """Gradient for MatrixSquareRoot."""

  # Let A be an m x m square matrix (or batch of matrices)
  # Let R = sqrtm(A)
  # By definition, A = RR
  # Take the differential: dA = d(RR) = RdR + dRR
  # Solve the resulting Sylvester equation for dR

  # Used to find Kronecker products within the Sylvester equation
  def _KroneckerProduct(b1, b2):
    """Computes the Kronecker product of two batches of square matrices."""
    b1_shape = array_ops.shape(b1)
    b2_shape = array_ops.shape(b2)
    b1_order = b1_shape[-1]
    b2_order = b2_shape[-1]

    shape_slice_size = [math_ops.subtract(array_ops.size(b1_shape), 2)]
    shape_slice = array_ops.slice(b1_shape, [0],
                                  shape_slice_size)  # Same for both batches
    b1_reshape_shape = array_ops.concat(
        [shape_slice, [b1_order], [1], [b1_order], [1]], 0)
    b2_reshape_shape = array_ops.concat(
        [shape_slice, [1], [b2_order], [1], [b2_order]], 0)

    b1_reshape = array_ops.reshape(b1, b1_reshape_shape)
    b2_reshape = array_ops.reshape(b2, b2_reshape_shape)

    order_prod = b1_order * b2_order
    kprod_shape = array_ops.concat([shape_slice, [order_prod], [order_prod]], 0)
    return array_ops.reshape(b1_reshape * b2_reshape, kprod_shape)

  sqrtm = op.outputs[0]  # R
  shape = array_ops.shape(sqrtm)
  order = shape[-1]  # m
  matrix_count = math_ops.reduce_prod(shape[0:-2])

  # Get batch of m x m identity matrices
  eye = linalg_ops.eye(order, dtype=sqrtm.dtype)  # m x m identity matrix
  eye_flat = array_ops.reshape(eye, [-1])
  eye_tiled = array_ops.tile(eye_flat, [matrix_count])
  eye_batch = array_ops.reshape(eye_tiled, shape)

  # The transpose of R is taken in the k1 term instead of k2 in
  # order to prevent redundant transposition of R (i.e. (R')' = R)
  sqrtm_transpose = array_ops.matrix_transpose(sqrtm)
  k1 = _KroneckerProduct(eye_batch, sqrtm_transpose)
  k2 = _KroneckerProduct(sqrtm, eye_batch)
  ksum = math_ops.add(k1, k2)

  # Vectorize dA
  shape_slice_size = [math_ops.subtract(array_ops.size(shape), 2)]
  shape_slice = array_ops.slice(shape, [0], shape_slice_size)
  shape_vec_da = array_ops.concat([shape_slice, [order * order], [1]], 0)
  vec_da = array_ops.reshape(array_ops.matrix_transpose(grad), shape_vec_da)

  # Solve for vec(dR)
  vec_dsqrtm = linalg_ops.matrix_solve(ksum, vec_da)

  # Solve for dR by inverse vectorizing vec(dR)
  dsqrtm_transpose = array_ops.reshape(vec_dsqrtm, shape)
  return array_ops.matrix_transpose(dsqrtm_transpose)

@ops.RegisterGradient("LogMatrixDeterminant")
def _LogMatrixDeterminantGrad(op: ops.Operation, _, grad_b):
  """Gradient for LogMatrixDeterminant."""
  a = op.inputs[0]
  c = op.outputs[1]
  a_adj_inv = linalg_ops.matrix_inverse(a, adjoint=True)
  multipliers = array_ops.reshape(
      grad_b, array_ops.concat([array_ops.shape(c), [1, 1]], 0))
  return multipliers * a_adj_inv

@ops.RegisterGradient("Cholesky")
def _CholeskyGrad(op: ops.Operation, grad):
  """Gradient for Cholesky."""

  # Gradient is l^{-H} @ ((l^{H} @ grad) * (tril(ones)-1/2*eye)) @ l^{-1}
  l = op.outputs[0]
  num_rows = array_ops.shape(l)[-1]
  batch_shape = array_ops.shape(l)[:-2]
  l_inverse = linalg_ops.matrix_triangular_solve(l,
                                                 linalg_ops.eye(
                                                     num_rows,
                                                     batch_shape=batch_shape,
                                                     dtype=l.dtype))

  middle = math_ops.matmul(l, grad, adjoint_a=True)
  middle = array_ops.matrix_set_diag(middle,
                                     0.5 * array_ops.matrix_diag_part(middle))
  middle = array_ops.matrix_band_part(middle, -1, 0)

  grad_a = math_ops.matmul(
      math_ops.matmul(l_inverse, middle, adjoint_a=True), l_inverse)

  grad_a += _linalg.adjoint(grad_a)
  return grad_a * 0.5

@ops.RegisterGradient("Qr")
def _QrGrad(op: ops.Operation, dq, dr):
  """Gradient for Qr."""

  # The methodology is explained in detail in https://arxiv.org/abs/2009.10071
  # QR and LQ Decomposition Matrix Backpropagation Algorithms for
  # Square, Wide, and Deep, Real and Complex, Matrices and Their Software
  # Implementation
  q, r = op.outputs
  if (r.shape.ndims is None or r.shape.as_list()[-2] is None or
      r.shape.as_list()[-1] is None):
    raise NotImplementedError("QrGrad not implemented with dynamic shapes. "
                              f"Received r.shape: {r.shape}")
  if (r.shape.dims[-2].value > r.shape.dims[-1].value and
      q.shape.dims[-2].value == q.shape.dims[-1].value):
    raise NotImplementedError("QrGrad not implemented when nrows > ncols "
                              "and full_matrices is true. Received r.shape="
                              f"{r.shape} with nrows={r.shape.dims[-2]}"
                              f"and ncols={r.shape.dims[-1]}.")

  def _TriangularSolve(x, r):
    """Equiv to matmul(x, adjoint(matrix_inverse(r))) if r is upper-tri."""
    return _linalg.adjoint(
        linalg_ops.matrix_triangular_solve(
            r, _linalg.adjoint(x), lower=False, adjoint=False))

  def _QrGradSquareAndDeepMatrices(q, r, dq, dr):
    """Gradient for matrix orders num_rows >= num_cols
    and full_matrices is false.
    """
    qdq = math_ops.matmul(q, dq, adjoint_a=True)
    qdq_ = qdq - _linalg.adjoint(qdq)
    rdr = math_ops.matmul(r, dr, adjoint_b=True)
    rdr_ = rdr - _linalg.adjoint(rdr)
    tril = array_ops.matrix_band_part(qdq_ + rdr_, -1, 0)

    grad_a = math_ops.matmul(q, dr + _TriangularSolve(tril, r))
    grad_b = _TriangularSolve(dq - math_ops.matmul(q, qdq), r)
    ret = grad_a + grad_b

    if q.dtype.is_complex:
      # need to add a correction to the gradient formula for complex case
      m = rdr - _linalg.adjoint(qdq)
      eyem = _linalg.set_diag(array_ops.zeros_like(m), _linalg.diag_part(m))
      correction = eyem - math_ops.cast(math_ops.real(eyem), q.dtype)
      ret = ret + _TriangularSolve(
          math_ops.matmul(q, _linalg.adjoint(correction)), r)

    return ret

  num_rows, num_cols = q.shape.dims[-2].value, r.shape.dims[-1]

  if num_rows >= num_cols:
    return _QrGradSquareAndDeepMatrices(q, r, dq, dr)

  # Partition a = [x, y], r = [u, v] and reduce to the square case
  a = op.inputs[0]
  y = a[..., :, num_rows:]
  u = r[..., :, :num_rows]
  dv = dr[..., :, num_rows:]
  du = dr[..., :, :num_rows]
  dy = math_ops.matmul(q, dv)
  dx = _QrGradSquareAndDeepMatrices(q, u,
                                    dq + math_ops.matmul(y, dv, adjoint_b=True),
                                    du)
  return array_ops.concat([dx, dy], axis=-1)

@ops.RegisterGradient("MatrixSolve")
def _MatrixSolveGrad(op: ops.Operation, grad):
  """Gradient for MatrixSolve."""
  a = op.inputs[0]
  adjoint_a = op.get_attr("adjoint")
  c = op.outputs[0]
  grad_b = linalg_ops.matrix_solve(a, grad, adjoint=not adjoint_a)
  if adjoint_a:
    grad_a = -math_ops.matmul(c, grad_b, adjoint_b=True)  # pylint: disable=invalid-unary-operand-type
  else:
    grad_a = -math_ops.matmul(grad_b, c, adjoint_b=True)  # pylint: disable=invalid-unary-operand-type
  return (grad_a, grad_b)

@ops.RegisterGradient("MatrixSolveLs")
def _MatrixSolveLsGrad(op: ops.Operation, grad):
  """Gradients for MatrixSolveLs."""

  # TODO(rmlarsen): The implementation could be more efficient:
  #   a) Output the Cholesky factorization from forward op instead of
  #      recomputing it here.
  #   b) Implement a symmetric rank-k update op instead of computing
  #      x*z + transpose(x*z). This pattern occurs other places in TensorFlow.
  # pylint: disable=g-doc-args
  def _Overdetermined(op: ops.Operation, grad):
    """Gradients for the overdetermined case of MatrixSolveLs.

    This is the backprop for the solution to the normal equations of the first
    kind:
       X = F(A, B) = (A^T * A + lambda * I)^{-1} * A^T * B
    which solve the least squares problem
       min ||A * X - B||_F^2 + lambda ||X||_F^2.
    """
    a = op.inputs[0]
    b = op.inputs[1]
    x = op.outputs[0]
    l2_regularizer = math_ops.cast(op.inputs[2], a.dtype.base_dtype)
    # pylint: disable=protected-access
    chol = linalg_ops._RegularizedGramianCholesky(
        a, l2_regularizer=l2_regularizer, first_kind=True)
    # pylint: enable=protected-access
    # Temporary z = (A^T * A + lambda * I)^{-1} * grad.
    z = linalg_ops.cholesky_solve(chol, grad)
    xzt = math_ops.matmul(x, z, adjoint_b=True)
    zx_sym = xzt + array_ops.matrix_transpose(xzt)
    grad_a = -math_ops.matmul(a, zx_sym) + math_ops.matmul(b, z, adjoint_b=True)  # pylint: disable=invalid-unary-operand-type
    grad_b = math_ops.matmul(a, z)
    return (grad_a, grad_b, None)

  # pylint: disable=g-doc-args
  def _Underdetermined(op: ops.Operation, grad):
    """Gradients for the underdetermined case of MatrixSolveLs.

    This is the backprop for the solution to the normal equations of the second
    kind:
      X = F(A, B) = A * (A*A^T + lambda*I)^{-1} * B
    that (for lambda=0) solve the least squares problem
      min ||X||_F subject to A*X = B.
    """
    a = op.inputs[0]
    b = op.inputs[1]
    l2_regularizer = math_ops.cast(op.inputs[2], a.dtype.base_dtype)
    # pylint: disable=protected-access
    chol = linalg_ops._RegularizedGramianCholesky(
        a, l2_regularizer=l2_regularizer, first_kind=False)
    # pylint: enable=protected-access
    grad_b = linalg_ops.cholesky_solve(chol, math_ops.matmul(a, grad))
    # Temporary tmp = (A * A^T + lambda * I)^{-1} * B.
    tmp = linalg_ops.cholesky_solve(chol, b)
    a1 = math_ops.matmul(tmp, a, adjoint_a=True)
    a1 = -math_ops.matmul(grad_b, a1)  # pylint: disable=invalid-unary-operand-type
    a2 = grad - math_ops.matmul(a, grad_b, adjoint_a=True)
    a2 = math_ops.matmul(tmp, a2, adjoint_b=True)
    grad_a = a1 + a2
    return (grad_a, grad_b, None)

  fast = op.get_attr("fast")
  if fast is False:
    raise ValueError("Gradient not defined for fast=False")
  matrix_shape = op.inputs[0].get_shape()[-2:]
  if matrix_shape.is_fully_defined():
    if matrix_shape[-2] >= matrix_shape[-1]:
      return _Overdetermined(op, grad)
    else:
      return _Underdetermined(op, grad)
  else:
    # We have to defer determining the shape to runtime and use
    # conditional execution of the appropriate graph.
    matrix_shape = array_ops.shape(op.inputs[0])[-2:]
    return cond.cond(matrix_shape[-2] >= matrix_shape[-1],
                     lambda: _Overdetermined(op, grad),
                     lambda: _Underdetermined(op, grad))

@ops.RegisterGradient("BandedTriangularSolve")
def _BandedTriangularSolveGrad(op: ops.Operation, grad):
  """Gradient for BandedTriangularSolve."""
  a = op.inputs[0]
  b = op.inputs[1]
  num_bands = array_ops.shape(a)[-2]
  adjoint_a = op.get_attr("adjoint")
  lower_a = op.get_attr("lower")
  c = op.outputs[0]
  grad_b = linalg_ops.banded_triangular_solve(
      a, grad, lower=lower_a, adjoint=not adjoint_a)
  if adjoint_a:
    grad_a = -math_ops.matmul(c, grad_b, adjoint_b=True)  # pylint: disable=invalid-unary-operand-type
  else:
    grad_a = -math_ops.matmul(grad_b, c, adjoint_b=True)  # pylint: disable=invalid-unary-operand-type
  if lower_a:
    grad_a = array_ops.matrix_diag_part(
        grad_a, k=(-(num_bands - 1), 0), align="LEFT_RIGHT")
  else:
    grad_a = array_ops.matrix_diag_part(
        grad_a, k=(0, num_bands - 1), align="LEFT_RIGHT")
  # If the static batch shapes are equal, we don't need to unbroadcast.
  if (a.shape.is_fully_defined() and b.shape.is_fully_defined() and
      a.shape[:-2] == b.shape[:-2]):
    return grad_a, grad_b
  a_shape = array_ops.shape(a)
  b_shape = array_ops.shape(b)
  ra, rb = array_ops.broadcast_gradient_args(a_shape[:-2], b_shape[:-2])
  grad_a = array_ops.reshape(math_ops.reduce_sum(grad_a, axis=ra), a_shape)
  grad_b = array_ops.reshape(math_ops.reduce_sum(grad_b, axis=rb), b_shape)
  return grad_a, grad_b

@ops.RegisterGradient("MatrixTriangularSolve")
def _MatrixTriangularSolveGrad(op: ops.Operation, grad):
  """Gradient for MatrixTriangularSolve."""
  a = op.inputs[0]
  b = op.inputs[1]
  adjoint_a = op.get_attr("adjoint")
  lower_a = op.get_attr("lower")
  c = op.outputs[0]
  grad_b = linalg_ops.matrix_triangular_solve(
      a, grad, lower=lower_a, adjoint=not adjoint_a)
  if adjoint_a:
    grad_a = -math_ops.matmul(c, grad_b, adjoint_b=True)  # pylint: disable=invalid-unary-operand-type
  else:
    grad_a = -math_ops.matmul(grad_b, c, adjoint_b=True)  # pylint: disable=invalid-unary-operand-type
  if lower_a:
    grad_a = array_ops.matrix_band_part(grad_a, -1, 0)
  else:
    grad_a = array_ops.matrix_band_part(grad_a, 0, -1)
  # If the static batch shapes are equal, we don't need to unbroadcast.
  if (a.shape.is_fully_defined() and b.shape.is_fully_defined() and
      a.shape[:-2] == b.shape[:-2]):
    return grad_a, grad_b
  a_shape = array_ops.shape(a)
  b_shape = array_ops.shape(b)
  ra, rb = array_ops.broadcast_gradient_args(a_shape[:-2], b_shape[:-2])
  grad_a = array_ops.reshape(math_ops.reduce_sum(grad_a, axis=ra), a_shape)
  grad_b = array_ops.reshape(math_ops.reduce_sum(grad_b, axis=rb), b_shape)
  return grad_a, grad_b

# To avoid nan in cases with degenerate eigenvalues or
# degenerate/zero singular values in calculations of
# f and s_inv_mat, we introduce a Lorentz broadening.
def _SafeReciprocal(x, epsilon=1e-20):
  return x * math_ops.reciprocal(x * x + epsilon)

# pylint: disable=g-doc-args
@ops.RegisterGradient("Eig")
def _EigGrad(op: ops.Operation, grad_e, grad_v):
  """Gradient for Eig.

  Based on eq. 4.77 from paper by
  Christoph Boeddeker et al.
  https://arxiv.org/abs/1701.00392
  See also
  "Computation of eigenvalue and eigenvector derivatives
  for a general complex-valued eigensystem" by Nico van der Aa.
  As for now only distinct eigenvalue case is considered.
  """
  e = op.outputs[0]
  compute_v = op.get_attr("compute_v")
  # a = op.inputs[0], which satisfies
  # a[...,:,:] * v[...,:,i] = e[...,i] * v[...,i]
  with ops.control_dependencies([grad_e, grad_v]):
    if compute_v:
      v = op.outputs[1]
      vt = _linalg.adjoint(v)
      # Construct the matrix f(i,j) = (i != j ? 1 / (e_i - e_j) : 0).
      # Notice that because of the term involving f, the gradient becomes
      # infinite (or NaN in practice) when eigenvalues are not unique.
      # Mathematically this should not be surprising, since for (k-fold)
      # degenerate eigenvalues, the corresponding eigenvectors are only defined
      # up to arbitrary rotation in a (k-dimensional) subspace.
      f = array_ops.matrix_set_diag(
          _SafeReciprocal(
              array_ops.expand_dims(e, -2) - array_ops.expand_dims(e, -1)),
          array_ops.zeros_like(e))
      f = math_ops.conj(f)
      vgv = math_ops.matmul(vt, grad_v)
      mid = array_ops.matrix_diag(grad_e)
      diag_grad_part = array_ops.matrix_diag(
          array_ops.matrix_diag_part(
              math_ops.cast(math_ops.real(vgv), vgv.dtype)))
      mid += f * (vgv - math_ops.matmul(math_ops.matmul(vt, v), diag_grad_part))
      # vt is formally invertible as long as the original matrix is
      # diagonalizable. However, in practice, vt may
      # be ill-conditioned when matrix original matrix is close to
      # non-diagonalizable one
      grad_a = linalg_ops.matrix_solve(vt, math_ops.matmul(mid, vt))
    else:
      _, v = linalg_ops.eig(op.inputs[0])
      vt = _linalg.adjoint(v)
      # vt is formally invertible as long as the original matrix is
      # diagonalizable. However, in practice, vt may
      # be ill-conditioned when matrix original matrix is close to
      # non-diagonalizable one
      grad_a = linalg_ops.matrix_solve(
          vt, math_ops.matmul(array_ops.matrix_diag(grad_e), vt))
    return math_ops.cast(grad_a, op.inputs[0].dtype)

@ops.RegisterGradient("SelfAdjointEigV2")
def _SelfAdjointEigV2Grad(op: ops.Operation, grad_e, grad_v):
  """Gradient for SelfAdjointEigV2."""
  e = op.outputs[0]
  compute_v = op.get_attr("compute_v")
  # a = op.inputs[0], which satisfies
  # a[...,:,:] * v[...,:,i] = e[...,i] * v[...,i]
  with ops.control_dependencies([grad_e, grad_v]):
    if compute_v:
      v = op.outputs[1]
      # Construct the matrix f(i,j) = (i != j ? 1 / (e_i - e_j) : 0).
      # Notice that because of the term involving f, the gradient becomes
      # infinite (or NaN in practice) when eigenvalues are not unique.
      # Mathematically this should not be surprising, since for (k-fold)
      # degenerate eigenvalues, the corresponding eigenvectors are only defined
      # up to arbitrary rotation in a (k-dimensional) subspace.
      f = array_ops.matrix_set_diag(
          _SafeReciprocal(
              array_ops.expand_dims(e, -2) - array_ops.expand_dims(e, -1)),
          array_ops.zeros_like(e))
      grad_a = math_ops.matmul(
          v,
          math_ops.matmul(
              array_ops.matrix_diag(grad_e) +
              f * math_ops.matmul(v, grad_v, adjoint_a=True),
              v,
              adjoint_b=True))
    else:
      _, v = linalg_ops.self_adjoint_eig(op.inputs[0])
      grad_a = math_ops.matmul(v,
                               math_ops.matmul(
                                   array_ops.matrix_diag(grad_e),
                                   v,
                                   adjoint_b=True))
    # The forward op only depends on the lower triangular part of a, so here we
    # symmetrize and take the lower triangle
    grad_a = array_ops.matrix_band_part(grad_a + _linalg.adjoint(grad_a), -1, 0)
    grad_a = array_ops.matrix_set_diag(grad_a,
                                       0.5 * array_ops.matrix_diag_part(grad_a))
    return grad_a

@ops.RegisterGradient("Svd")
def _SvdGrad(op: ops.Operation, grad_s, grad_u, grad_v):
  """Gradient for the singular value decomposition."""

  # The derivation for the compute_uv=False case, and most of
  # the derivation for the full_matrices=True case, are in
  # Giles' paper (see reference at top of file).  A derivation for
  # the full_matrices=False case is available at
  # https://j-towns.github.io/papers/svd-derivative.pdf
  # The derivation for complex valued SVD can be found in
  # https://re-ra.xyz/misc/complexsvd.pdf or
  # https://giggleliu.github.io/2019/04/02/einsumbp.html
  a = op.inputs[0]
  a_shape = a.get_shape().with_rank_at_least(2)
  grad_s = math_ops.cast(grad_s, a.dtype)
  grad_s_mat = array_ops.matrix_diag(grad_s)

  if not op.get_attr("compute_uv"):
    s, u, v = linalg_ops.svd(a, compute_uv=True)
    grad_a = math_ops.matmul(u, math_ops.matmul(grad_s_mat, v, adjoint_b=True))
    grad_a.set_shape(a_shape)
    return grad_a

  full_matrices = op.get_attr("full_matrices")

  grad_u_shape = grad_u.get_shape().with_rank_at_least(2)
  grad_v_shape = grad_v.get_shape().with_rank_at_least(2)
  m = a_shape.dims[-2].merge_with(grad_u_shape[-2])
  n = a_shape.dims[-1].merge_with(grad_v_shape[-2])
  batch_shape = a_shape[:-2].merge_with(grad_u_shape[:-2]).merge_with(
      grad_v_shape[:-2])
  a_shape = batch_shape.concatenate([m, n])

  m = a_shape.dims[-2].value
  n = a_shape.dims[-1].value
  # TODO(rmlarsen): Make this work with placeholders.
  if m is None or n is None:
    raise NotImplementedError(
        "SVD gradient has not been implemented for input with unknown "
        "inner matrix shape.")

  s = op.outputs[0]
  u = op.outputs[1]
  v = op.outputs[2]
  s = math_ops.cast(s, a.dtype)

  use_adjoint = False
  if m > n:
    # Compute the gradient for A^H = V * S^T * U^H, and (implicitly) take the
    # Hermitian transpose of the gradient at the end.
    use_adjoint = True
    m, n = n, m
    u, v = v, u
    grad_u, grad_v = grad_v, grad_u

  with ops.control_dependencies([grad_s, grad_u, grad_v]):
    if full_matrices and abs(m - n) > 1:
      raise NotImplementedError(
          "svd gradient is not implemented for abs(m - n) > 1 "
          f"when full_matrices is True. Received: m={m} and n={n} from "
          f"op input={a} with shape={a_shape}.")
    s_mat = array_ops.matrix_diag(s)
    s2 = math_ops.square(s)

    # NOTICE: Because of the term involving f, the gradient becomes
    # infinite (or NaN in practice) when singular values are not unique.
    # Mathematically this should not be surprising, since for (k-fold)
    # degenerate singular values, the corresponding singular vectors are
    # only defined up a (k-dimensional) subspace. In practice, this can
    # lead to numerical instability when singular values are close but not
    # exactly equal.

    s_shape = array_ops.shape(s)
    f = array_ops.matrix_set_diag(
        _SafeReciprocal(
            array_ops.expand_dims(s2, -2) - array_ops.expand_dims(s2, -1)),
        array_ops.zeros_like(s))
    s_inv_mat = array_ops.matrix_diag(_SafeReciprocal(s))

    v1 = v[..., :, :m]
    grad_v1 = grad_v[..., :, :m]

    u_gu = math_ops.matmul(u, grad_u, adjoint_a=True)
    v_gv = math_ops.matmul(v1, grad_v1, adjoint_a=True)

    f_u = f * u_gu
    f_v = f * v_gv

    term1_nouv = (
        grad_s_mat + math_ops.matmul(f_u + _linalg.adjoint(f_u), s_mat) +
        math_ops.matmul(s_mat, f_v + _linalg.adjoint(f_v)))

    term1 = math_ops.matmul(u, math_ops.matmul(term1_nouv, v1, adjoint_b=True))

    if m == n:
      grad_a_before_transpose = term1
    else:
      gv1t = array_ops.matrix_transpose(grad_v1, conjugate=True)
      gv1t_v1 = math_ops.matmul(gv1t, v1)
      term2_nous = gv1t - math_ops.matmul(gv1t_v1, v1, adjoint_b=True)

      if full_matrices:
        v2 = v[..., :, m:n]
        grad_v2 = grad_v[..., :, m:n]

        v1t_gv2 = math_ops.matmul(v1, grad_v2, adjoint_a=True)
        term2_nous -= math_ops.matmul(v1t_gv2, v2, adjoint_b=True)

      u_s_inv = math_ops.matmul(u, s_inv_mat)
      term2 = math_ops.matmul(u_s_inv, term2_nous)

      grad_a_before_transpose = term1 + term2

    if a.dtype.is_complex:
      eye = _linalg.eye(s_shape[-1], batch_shape=s_shape[:-1], dtype=a.dtype)
      l = eye * v_gv
      term3_nouv = math_ops.matmul(s_inv_mat, _linalg.adjoint(l) - l)
      term3 = 1 / 2. * math_ops.matmul(
          u, math_ops.matmul(term3_nouv, v1, adjoint_b=True))

      grad_a_before_transpose += term3

    if use_adjoint:
      grad_a = array_ops.matrix_transpose(
          grad_a_before_transpose, conjugate=True)
    else:
      grad_a = grad_a_before_transpose

    grad_a.set_shape(a_shape)
    return grad_a

def _LeftShift(x):
  """Shifts next-to-last dimension to the left, adding zero on the right."""
  rank = array_ops.rank(x)
  zeros = array_ops.zeros((rank - 2, 2), dtype=dtypes.int32)
  pad = array_ops.concat([zeros, array_ops.constant([[0, 1], [0, 0]])], axis=0)
  return array_ops.pad(x[..., 1:, :], pad)

def _RightShift(x):
  """Shifts next-to-last dimension to the right, adding zero on the left."""
  rank = array_ops.rank(x)
  zeros = array_ops.zeros((rank - 2, 2), dtype=dtypes.int32)
  pad = array_ops.concat([zeros, array_ops.constant([[1, 0], [0, 0]])], axis=0)
  return array_ops.pad(x[..., :-1, :], pad)

@ops.RegisterGradient("TridiagonalMatMul")
def _TridiagonalMatMulGrad(op: ops.Operation, grad):
  """Gradient for TridiagonalMatMul."""
  superdiag_conj = array_ops.matrix_transpose(op.inputs[0], conjugate=True)
  maindiag_conj = array_ops.matrix_transpose(op.inputs[1], conjugate=True)
  subdiag_conj = array_ops.matrix_transpose(op.inputs[2], conjugate=True)
  rhs_conj = math_ops.conj(op.inputs[3])

  superdiag_grad = math_ops.reduce_sum(_LeftShift(rhs_conj) * grad, axis=-1)
  maindiag_grad = math_ops.reduce_sum(rhs_conj * grad, axis=-1)
  subdiag_grad = math_ops.reduce_sum(_RightShift(rhs_conj) * grad, axis=-1)
  rhs_grad = _RightShift(superdiag_conj * grad) + \
      maindiag_conj * grad + _LeftShift(subdiag_conj * grad)

  superdiag_grad = array_ops.expand_dims(superdiag_grad, -2)
  maindiag_grad = array_ops.expand_dims(maindiag_grad, -2)
  subdiag_grad = array_ops.expand_dims(subdiag_grad, -2)

  return superdiag_grad, maindiag_grad, subdiag_grad, rhs_grad

@ops.RegisterGradient("TridiagonalSolve")
def _TridiagonalSolveGrad(op: ops.Operation, grad):
  """Gradient for TridiagonalSolveGrad."""
  diags = op.inputs[0]
  x = op.outputs[0]
  partial_pivoting = op.get_attr("partial_pivoting")
  perturb_singular = op.get_attr("perturb_singular")

  # Transposing the matrix within tridiagonal_solve kernel by interchanging
  # superdiagonal and subdiagonal wouldn't work on GPU due to mismatch with
  # paddings required by cusparse*gtsv routines.
  # So constructing the transposed matrix in Python.
  diags_transposed = _TransposeTridiagonalMatrix(diags)

  grad_rhs = linalg_ops.tridiagonal_solve(
      diags_transposed,
      grad,
      partial_pivoting=partial_pivoting,
      perturb_singular=perturb_singular)
  grad_diags = -_MatmulExtractingThreeDiagonals(grad_rhs, x)  # pylint: disable=invalid-unary-operand-type
  return grad_diags, grad_rhs

def _TransposeTridiagonalMatrix(diags):
  """Transposes a tridiagonal matrix.

  Args:
    diags: the diagonals of the input matrix in the compact form (see
      linalg_ops.tridiagonal_solve).

  Returns:
    Diagonals of the transposed matrix in the compact form.
  """

  diag = diags[..., 1, :]

  if diags.shape.is_fully_defined():
    # For fully defined tensor we can concat with a tensor of zeros, which is
    # faster than using array_ops.pad().
    zeros = array_ops.zeros(list(diags.shape[:-2]) + [1], dtype=diags.dtype)
    superdiag = array_ops.concat((diags[..., 2, 1:], zeros), axis=-1)
    subdiag = array_ops.concat((zeros, diags[..., 0, :-1]), axis=-1)
  else:
    rank = array_ops.rank(diags)
    zeros = array_ops.zeros((rank - 2, 2), dtype=dtypes.int32)
    superdiag_pad = array_ops.concat((zeros, array_ops.constant([[0, 1]])),
                                     axis=0)
    superdiag = array_ops.pad(diags[..., 2, 1:], superdiag_pad)
    subdiag_pad = array_ops.concat((zeros, array_ops.constant([[1, 0]])),
                                   axis=0)
    subdiag = array_ops.pad(diags[..., 0, :-1], subdiag_pad)
  return array_ops_stack.stack([superdiag, diag, subdiag], axis=-2)

def _MatmulExtractingThreeDiagonals(x, y_tr):
  """Multiplies matrices and extracts three diagonals from the product.

  With sizes M x K and K x M, this function takes O(MK) time and O(M) space,
  while using math_ops.matmul, and then extracting the diagonals would take
  O(M^2 K) time and O(M^2) space.

  Args:
    x: first matrix
    y_tr: second matrix transposed

  Returns:
    Diagonals of the product in compact format (see
    linalg_ops.tridiagonal_solve)

  """
  diag = math_ops.reduce_sum(x * y_tr, axis=-1)

  if y_tr.shape.is_fully_defined():
    zeros = array_ops.zeros(
        list(x.shape[:-2]) + [1, x.shape[-1]], dtype=x.dtype)
    superdiag = math_ops.reduce_sum(
        x * array_ops.concat((y_tr[..., 1:, :], zeros), axis=-2), axis=-1)
    subdiag = math_ops.reduce_sum(
        x * array_ops.concat((zeros, y_tr[..., :-1, :]), axis=-2), axis=-1)
  else:
    rank = array_ops.rank(y_tr)
    zeros = array_ops.zeros((rank - 2, 2), dtype=dtypes.int32)
    superdiag_pad = array_ops.concat(
        (zeros, array_ops.constant([[0, 1], [0, 0]])), axis=0)
    superdiag = math_ops.reduce_sum(
        x * array_ops.pad(y_tr[..., 1:, :], superdiag_pad), axis=-1)
    subdiag_pad = array_ops.concat(
        (zeros, array_ops.constant([[1, 0], [0, 0]])), axis=0)
    subdiag = math_ops.reduce_sum(
        x * array_ops.pad(y_tr[..., :-1, :], subdiag_pad), axis=-1)
  return array_ops_stack.stack([superdiag, diag, subdiag], axis=-2)


import tensorflow as tf
from configuration import TXT_DIR, BATCH_SIZE

class TFDataset(object):
    def __init__(self):
        self.txt_dir = TXT_DIR

    @staticmethod
    def get_length_of_dataset(dataset):
        count = 0
        for _ in dataset:
            count += 1
        return count

    def generate_datatset(self):
        dataset = tf.data.TextLineDataset(filenames=self.txt_dir)
        length_of_dataset = self.get_length_of_dataset(dataset)
        train_dataset = dataset.batch(batch_size=BATCH_SIZE)
        return train_dataset, length_of_dataset


from django.db import models
from django.conf import settings
from ckeditor_uploader.fields import RichTextUploadingField

class GameTitleModel(models.Model):
    """ゲームタイトル名保存モデル"""

    name = models.CharField(verbose_name='ゲームタイトル名', max_length=50, unique=True)

    def __str__(self):
        return self.name

class TagModel(models.Model):
    """タグ名保存モデル"""

    name = models.CharField(verbose_name='タグ名', max_length=50, blank=True)

    def __str__(self):
        return self.name

class PostModel(models.Model):
    """記事投稿モデル"""

    title = models.CharField(
        verbose_name='タイトル', max_length=150
    )
    writer = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.PROTECT, verbose_name='投稿者', related_name='post_writer_set'
    )
    game = models.ForeignKey(
        GameTitleModel, on_delete=models.PROTECT, verbose_name='ゲームタイトル'
    )
    tags = models.ManyToManyField(
        TagModel, verbose_name='タグ', blank=True
    )
    content = RichTextUploadingField(
        verbose_name='本文', blank=True
    )
    likes = models.ManyToManyField(
        settings.AUTH_USER_MODEL, verbose_name='いいね', blank=True, related_name='post_likes_set'
    )
    bookmarks = models.ManyToManyField(
        settings.AUTH_USER_MODEL, verbose_name='ブックマーク', blank=True, related_name='post_bookmarks_set'
    )
    page_view = models.IntegerField(
        verbose_name='累計PV数', default=0
    )
    is_public = models.IntegerField(
        verbose_name='公開設定', choices=((0, '非公開'), (1, '公開'),), default=0
    )
    created_at = models.DateTimeField(
        verbose_name='作成日', auto_now_add=True
    )
    updated_at = models.DateTimeField(
        verbose_name='最終更新日', auto_now=True
    )

    def __str__(self):
        return 'タイトル{}:投稿者{}'.format(self.title[:20], self.writer)

class CommentModel(models.Model):
    """記事に対するコメント投稿モデル"""

    writer = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name='コメントしたユーザー',
        related_name='comment_writer_set'
    )
    text = models.TextField(
        verbose_name='本文', max_length=1500
    )
    target = models.ForeignKey(
        PostModel, on_delete=models.CASCADE, verbose_name='対象記事'
    )
    likes = models.ManyToManyField(
        settings.AUTH_USER_MODEL, verbose_name='いいね', blank=True, related_name='comment_likes_set'
    )
    created_at = models.DateTimeField(
        verbose_name='作成日', auto_now_add=True
    )

    def __str__(self):
        return '{}さんの{}へのコメント'.format(self.writer, self.target)

class DailyTrendModel(models.Model):
    """24時間の人気記事モデル"""

    daily_post = models.OneToOneField(
        PostModel, on_delete=models.CASCADE
    )
    daily_pv = models.IntegerField(
        verbose_name='24時間PV数', default=0
    )
    path = models.URLField(
        verbose_name='URL', blank=True
    )

    def __str__(self):
        return '{}/{}views'.format(self.daily_post, self.daily_pv)

class WeeklyTrendModel(models.Model):
    """7日間の人気記事モデル"""

    weekly_post = models.OneToOneField(
        PostModel, on_delete=models.CASCADE
    )
    weekly_pv = models.IntegerField(
        verbose_name='7日間PV数', default=0
    )
    path = models.URLField(
        verbose_name='URL', blank=True
    )

    def __str__(self):
        return '{}/{}views'.format(self.weekly_post, self.weekly_pv)

class MonthlyTrendModel(models.Model):
    """30日間の人気記事モデル"""

    monthly_post = models.OneToOneField(
        PostModel, on_delete=models.CASCADE
    )
    monthly_pv = models.IntegerField(
        verbose_name='30日間PV数', default=0
    )
    path = models.URLField(
        verbose_name='URL', blank=True
    )

    def __str__(self):
        return '{}/{}views'.format(self.monthly_post, self.monthly_pv)


t = int(input())
result = []

for _ in range(t):
    k = int(input())
    n = int(input())

    people = [i for i in range(1, n+1)]

    for _ in range(k):
        for i in range(1, n):
            people[i] += people[i-1]
    result.append(people[-1])

for i in result:
    print(i)


import unittest

from EpidemicComMeN import *

class InfectTestCase(unittest.TestCase):
    def setUp(self):
        self.birth_rate = 0.1
        self.infection_rate = 3
        self.recovery_rate = 1/3.0
        self.death_rate = 0.1
        self.death_by_infection_rate = 0.001

        self.dynamics = SIRSinglePatchDynamics(self.birth_rate, self.infection_rate, self.recovery_rate,
                                               self.death_rate, self.death_by_infection_rate)

    def test_run(self):
        seeding = {0:{SUSCEPTIBLE: 10000-10, INFECTIOUS: 10}}
        self.dynamics.run(10, seeding, 1)


import os

BUILTIN_HEADERS_DIR = os.path.join(os.path.dirname(__file__), "include")

# Stubs for MacOSX.sdk/usr/include
DARWIN_HEADERS_DIR = os.path.join(os.path.dirname(__file__), "darwin-include")

# Types declared by pycparser fake headers that we should ignore
IGNORE_DECLARATIONS = {
    "size_t",
    "__builtin_va_list",
    "__gnuc_va_list",
    "__int8_t",
    "__uint8_t",
    "__int16_t",
    "__uint16_t",
    "__int_least16_t",
    "__uint_least16_t",
    "__int32_t",
    "__uint32_t",
    "__int64_t",
    "__uint64_t",
    "__int_least32_t",
    "__uint_least32_t",
    "__s8",
    "__u8",
    "__s16",
    "__u16",
    "__s32",
    "__u32",
    "__s64",
    "__u64",
    "_LOCK_T",
    "_LOCK_RECURSIVE_T",
    "_off_t",
    "__dev_t",
    "__uid_t",
    "__gid_t",
    "_off64_t",
    "_fpos_t",
    "_ssize_t",
    "wint_t",
    "_mbstate_t",
    "_flock_t",
    "_iconv_t",
    "__ULong",
    "__FILE",
    "ptrdiff_t",
    "wchar_t",
    "__off_t",
    "__pid_t",
    "__loff_t",
    "u_char",
    "u_short",
    "u_int",
    "u_long",
    "ushort",
    "uint",
    "clock_t",
    "time_t",
    "daddr_t",
    "caddr_t",
    "ino_t",
    "off_t",
    "dev_t",
    "uid_t",
    "gid_t",
    "pid_t",
    "key_t",
    "ssize_t",
    "mode_t",
    "nlink_t",
    "fd_mask",
    "_types_fd_set",
    "clockid_t",
    "timer_t",
    "useconds_t",
    "suseconds_t",
    "FILE",
    "fpos_t",
    "cookie_read_function_t",
    "cookie_write_function_t",
    "cookie_seek_function_t",
    "cookie_close_function_t",
    "cookie_io_functions_t",
    "div_t",
    "ldiv_t",
    "lldiv_t",
    "sigset_t",
    "__sigset_t",
    "_sig_func_ptr",
    "sig_atomic_t",
    "__tzrule_type",
    "__tzinfo_type",
    "mbstate_t",
    "sem_t",
    "pthread_t",
    "pthread_attr_t",
    "pthread_mutex_t",
    "pthread_mutexattr_t",
    "pthread_cond_t",
    "pthread_condattr_t",
    "pthread_key_t",
    "pthread_once_t",
    "pthread_rwlock_t",
    "pthread_rwlockattr_t",
    "pthread_spinlock_t",
    "pthread_barrier_t",
    "pthread_barrierattr_t",
    "jmp_buf",
    "rlim_t",
    "sa_family_t",
    "sigjmp_buf",
    "stack_t",
    "siginfo_t",
    "z_stream",
    "int8_t",
    "uint8_t",
    "int16_t",
    "uint16_t",
    "int32_t",
    "uint32_t",
    "int64_t",
    "uint64_t",
    "int_least8_t",
    "uint_least8_t",
    "int_least16_t",
    "uint_least16_t",
    "int_least32_t",
    "uint_least32_t",
    "int_least64_t",
    "uint_least64_t",
    "int_fast8_t",
    "uint_fast8_t",
    "int_fast16_t",
    "uint_fast16_t",
    "int_fast32_t",
    "uint_fast32_t",
    "int_fast64_t",
    "uint_fast64_t",
    "intptr_t",
    "uintptr_t",
    "intmax_t",
    "uintmax_t",
    "bool",
    "va_list",
    "char16_t",
    "char32_t",
    "MirEGLNativeWindowType",
    "MirEGLNativeDisplayType",
    "xcb_window_t",
    "xcb_visualid_t",
    "atomic_bool",
    "atomic_char",
    "atomic_schar",
    "atomic_uchar",
    "atomic_short",
    "atomic_ushort",
    "atomic_int",
    "atomic_uint",
    "atomic_long",
    "atomic_ulong",
    "atomic_ullong",
    "atomic_char16_t",
    "atomic_char32_t",
    "atomic_wchar_t",
    "atomic_int_least8_t",
    "atomic_uint_least8_t",
    "atomic_int_least16_t",
    "atomic_uint_least16_t",
    "atomic_int_least32_t",
    "atomic_uint_least32_t",
    "atomic_int_least64_t",
    "atomic_uint_least64_t",
    "atomic_int_fast8_t",
    "atomic_uint_fast8_t",
    "atomic_int_fast16_t",
    "atomic_uint_fast16_t",
    "atomic_int_fast32_t",
    "atomic_uint_fast32_t",
    "atomic_int_fast64_t",
    "atomic_uint_fast64_t",
    "atomic_intptr_t",
    "atomic_uintptr_t",
    "atomic_size_t",
    "atomic_ptrdiff_t",
    "atomic_intmax_t",
    "atomic_uintmax_t",
    "atomic_flag",
    "memory_order",
}

STDINT_DECLARATIONS = {
    "int8_t",
    "uint8_t",
    "int16_t",
    "uint16_t",
    "int32_t",
    "uint32_t",
    "int64_t",
    "uint64_t",
    "int_least8_t",
    "uint_least8_t",
    "int_least16_t",
    "uint_least16_t",
    "int_least32_t",
    "uint_least32_t",
    "int_least64_t",
    "uint_least64_t",
    "int_fast8_t",
    "uint_fast8_t",
    "int_fast16_t",
    "uint_fast16_t",
    "int_fast32_t",
    "uint_fast32_t",
    "int_fast64_t",
    "uint_fast64_t",
    "intptr_t",
    "uintptr_t",
    "intmax_t",
    "uintmax_t",
}


import sys
input = sys.stdin.readline

arr = []
for _ in range(9):
    temp = list(map(int,input().split(' ')))
    arr.append(temp)

max_V=0
max_x,max_y=0,0
for i in range(9):
    if max_V < max(arr[i]):
        max_V = max(arr[i])
        max_y=i

for j in range(9):
    if arr[max_y][j] == max_V:
        max_x = j

print(max_V)
print(max_y+1,max_x+1)


####################################
# SVÅRARE UPPGIFTER - 5 o 6
####################################

# Grafuppgifter

# Tenta

# Tenta 2015_2

t = {'a': (('b', 4), ('c', 7), ('d', 3)),
     'b': (('e', 2), ('f', 9)),
     'c': (('g', 5), ),
     'd': (('h', 4), ('i', 3)),
     'e': (),
     'f': (),
     'g': (('j', 2), ('k', 1), ('l', 8)),
     'h': (),
     'i': (('m', 6), ),
     'j': (),
     'k': (),
     'l': (),
     'm': ()}

def get_node(tup):
    return tup[0]

def get_dist(tup):
    return tup[1]

def distance(tree, start, end): # funkar inte alls bra, bara för a-b och a-e
    def walk(dist, start, end):
        print("1. dist =", dist)
        if start == end:
            print("THE END.", "start = end =", start)
            return 0
        else:
            print("start =", start)
            for tup in tree[start]:
                print("3.", "tree[start] =", tree[start])
                print("4.", "tup =", tup)
                dist += get_dist(tup)
                print("5. dist =", dist)
                print("gonna calculate new_dist")
                new_dist = walk(0, get_node(tup), end)
                print("new_dist =", new_dist)
                if new_dist:
                    dist += new_dist
                    print("6. dist =", dist)
                if dist:
                    return dist
                return -1
    return walk(0, start, end)

def distance_2(tree, start, end):
    def walk(node, dist):
        print("1. dist =", dist)
        if node == end:
            print("THE END.", "start = end =", start)
            return dist
        else:
            for tup in tree[node]:
                print("2.", "tree[node] =", tree[node])
                res = walk(get_node(tup), get_dist(tup) + dist)
                print("3.", "res =", res)
                return res
    return walk(start, 0)

def distance_3(tree, start, end):
    def walk(node, dist):
        if node == end:
            return dist
        else:
            children = tree[node]
            if not children:
                return -1
            else:
                for pair in children:
                    res = walk(pair[0], dist + pair[1])
                    if res > 0:
                        return res
                    return -1
    return walk(start, 0)

# Tenta 2014_1
children = {'Linus': ('Eva', 'Per'),
 'Linnea': ('Per', ),
 'Eva': ('Emilia', 'Emil'),
 'Per': ('Stina', ),
 'Stina': ('Lillan', )}

def descendants(start, tree): # funkar typ, resultat är ej rak lista
    res = []
    #print("1.", "start", start)
    if start not in tree:
        return []
    else:
        for person in tree[start]:
            #print("2.", "tree[start] =", tree[start])
            #print("3.", "person =", person)
            if person not in res:
                res.append(person)
                #print("4. appending", person)
                #print("provisory res =", res)
            new_person = descendants(person, tree)
            #print("5.", "new_person =", new_person)
            if new_person not in res and new_person:
                res.append(new_person)
                #print("6. appending", new_person)
    return res

def new_descendants(start, tree):
    def get_descendants(res = []):
        if start not in tree:
            return []
        else:
            for person in tree[start]:
                if person not in res:
                    res.append(person)
                new_person = new_descendants(person, tree)
                if new_person not in res and new_person:
                    res.append(new_person)
        return res
    def get_straight(seq):
        if not seq:
            return []
        elif isinstance(seq[0], list):
            return get_straight(seq[0]) + get_straight(seq[1:])
        else:
            return [seq[0]] + get_straight(seq[1:])
    return get_straight(get_descendants())

# Tenta 2013 (given a person, find it's ancestor)

svensson = ['Erik', ['Olle', ['Eva', 'Karin', 'Anna'],
                               ['Lars', 'Maria'],
                               ['Pär', 'Sofia']],
                      'Lisa',
                      ['Stina', ['Gunnar', 'Lasse'],
                                'Lennart']]

def ancestors(person, tree):
    if isinstance(tree, str): #HUR SKULLE tree ENS BLI EN STRÄNG?
        if person == tree:
            return [person]
        else:
            return []
    elif person == tree[0]:
        return [person]
    else:
        for child_tree in tree[1:]:
            result = ancestors(person, child_tree)
            if result:#i.e. om personen vi letade efter hittades (person == tree)
                return [tree[0]] + result
            else:
                return []

# Exempeltenta (has loop)

example_graph = {'a': ('b', 'd'),
              'b': ('c'),
              'c': ('d'),
              'd': ('b', 'e'),
              'e': ('f'),
              'f': ()}

def has_loop(start, graph):
    def loop_check(node, visited):
        if node in visited:
            return True
        else:
            return check_children(graph[node], [node] + visited)
    def check_children(children, visited):
        if not children:
            return False
        else:
            res = loop_check(children[0], visited)
            if res: # DÚVIDA: HUR SKULLE 'res' INTE FINNAS? res = True/False
                return res
            else:
                return check_children(children[1:], visited)

    return loop_check(start, [])

# Testing some graph exercises

graph = {'A': ['B', 'C'],
             'B': ['C', 'D'],
             'C': ['D'],
             'D': ['C'],
             'E': ['F'],
             'F': ['C']}

def find_path(start, end, tree, path = []):
    path = path + [start]
    #print("1)", "path =", path)
    if (start or end) not in tree:
        return []
    elif start == end:
        #print("The End.", "start = end =", start)
        return path
    else:
        for children in tree[start]:
            #print("2)", "children =", children)
            if children not in path:
                new_path = find_path(children, end, tree, path)
                if new_path:
                    #print("3)", "new_path =", new_path)
                    return new_path
        return None

def find_all_paths(start, end, tree, path = []):
    path = path + [start]
    #print("1)", "path =", path)
    if start == end:
        #print("1", "start = end =", start)
        return path
    else:
        path_list = []
        for children in tree[start]:
            #print("2)", "children =", children)
            if children not in path:
                new_path = find_all_paths(children, end, tree, path)
                if new_path:
                    #print("3)", "new_path =", new_path)
                    path_list.append(new_path)
                else:
                    return None
        return path_list

def find_shortest_path(start, end, tree, path = []):
    path = path + [start]
    if start == end:
        return path
    else:
        shortest = []
        for child in tree[start]:
            if child not in path:
                if child not in path:
                    new_path = find_shortest_path(child, end, tree, path)
                    if new_path:
                        if not shortest or len(new_path) < len(shortest):
                            shortest = new_path
        return shortest


from __future__ import division, print_function

import sys, os, platform, os.path
import glob, shutil
import subprocess
import distutils.sysconfig
import fnmatch

def remove(patterns):
    matches = set()
    for root, dirs, files in os.walk("."):
        for pattern in patterns:
            for filename in fnmatch.filter(files, pattern):
                matches.add(os.path.join(root, filename))

    for filename in matches:
        try: os.remove(filename)
        except: pass

if len(sys.argv) == 1: sys.exit()

if sys.argv[1] == "build":
    if len(sys.argv) > 2 and sys.argv[2] == "dist":
        if platform.system() == "Windows":
            import build_win
            sys.argv = sys.argv[:2]
            build_win.build()
        else:
            print(platform.system() + " not supported.")
    else:
        includes = distutils.sysconfig.get_python_inc()

        if platform.system() == "Linux":
            subprocess.call("gcc -fPIC -O3 -c -o mask_extension/bitmask.o mask_extension/bitmask.c", shell=True)
            subprocess.call("gcc -I%s -fPIC -O3 -c -o mask_extension/_mask.o mask_extension/_mask.c" % includes, shell=True)
            subprocess.call("gcc -shared -o mask_extension/_mask.so mask_extension/bitmask.o mask_extension/_mask.o", shell=True)
        else:
            libs = os.path.join(os.path.join(includes, ".."), "libs")
            subprocess.call("gcc -O3 -c -o mask_extension/bitmask.o mask_extension/bitmask.c", shell=True)
            subprocess.call("gcc -I%s -O3 -c -o mask_extension/_mask.o mask_extension/_mask.c" % includes, shell=True)
            subprocess.call("gcc -shared -o mask_extension/_mask.pyd mask_extension/bitmask.o mask_extension/_mask.o -L%s -lpython27" % libs, shell=True)

elif sys.argv[1] == "clean":
    patterns = [
        "*~",
        "*.pyc",
        "*.pyo",
        "*.o",
        "game_profile",
        "profile.txt"
    ]
    remove(patterns)
    try: shutil.rmtree("dist")
    except: pass
elif sys.argv[1] == "testclient":
    import client_main
#    client_main.profileGG2()
    client_main.GG2main(skipmenu=True)
elif sys.argv[1] == "menuclient":
    import client_main
#    client_main.profileGG2()
    client_main.GG2main(skipmenu=False)
elif sys.argv[1] == "testserver":
    import server.main
    server.main.GG2main()
elif sys.argv[1] == "test":
    subprocess.Popen([sys.executable, 'make.py', 'testclient'])
    subprocess.Popen([sys.executable, 'make.py', 'testserver']).wait()


from PIL import Image, ImageFilter, ImageStat, ImageEnhance
import face_recognition, argparse
from os import path
from math import sqrt

def check_file_exist(path):
    try:
        with open(path, 'rb') as image_file:
            image = face_recognition.load_image_file(image_file)
            return image
    except OSError:
        pass

def brightness(image):
    # image = Image.open("./img/Brightness/camera.jpg")
    Exist = check_file_exist(image) # Image exist
    # Convert the image te RGB if it is a .gif for example
    image = Image.fromarray(Exist)
    imag = image.convert ('RGB')
    # coordinates of the pixel
    X,Y = 0,0
    # Get RGB
    pixelRGB = imag.getpixel((X,Y))
    R,G,B = pixelRGB
    brightness = sum([R,G,B])/3 # 0 is dark (black) and 255 is bright (white)
    print(brightness)
    return brightness

def brightness_detection(image):
    Brightness = brightness(image)
    threshold = 125.0
    if Brightness < threshold:
        print("{}: {:.2f}".format('Too dark brightness', Brightness)) # lay so thap phan
        return False
    else:
        print("{}: {:.2f}".format('Brightness is right', Brightness)) # lay so thap phan
        return True

def result_brightness(image):
    if brightness_detection(image) == True:
        return True
    else:
        return False

parser = argparse.ArgumentParser(
        description='Detects faces in the given image.')

parser.add_argument(
    "image",
    help='the image you\'d like to detect faces in.')

parser.add_argument(
    'mode', help='Set to call function need to do')

args = parser.parse_args()

if args.mode == 'brightness':
    result_brightness(args.image)

# RUNN python test.py ./img/Brightness/camera.jpg brightness