from numpy import *
import re
import sys
import warnings
warnings.filterwarnings('ignore')

# Busca patrones en cada pagina que se le ingresa

def buscaPatron(txt, keyword, jumpMax):

        # El texto es transformado en array y se utilizan expresiones regulares
        # para establecer un patron.
    texto = array(list(txt))
    patron = re.compile(keyword)
    coincidencia = []
    toolbar_width = 50
    aux = len(texto) / toolbar_width
    cont = aux
    # setup toolbar
    print("\nBuscando : ", keyword)
    print("----------------------------------------------------------")
    sys.stdout.write("0 [%s] 100" % (" " * (toolbar_width)))
    sys.stdout.flush()
    # return to start of line, after '['
    sys.stdout.write("\b" * (toolbar_width + 1 + 4))

    for pagina, contenido in enumerate(texto):
        # print("****************Pagina ", pagina)

        if(pagina+1 >= cont):
            sys.stdout.write("#")
            sys.stdout.flush()
            cont += aux

        contenido = array(list(contenido))
        for jump in range(jumpMax):
            for i in range(jump + 1):
                # Se selecciona el texto con los saltos aplicados
                ContenidoConSalto = contenido[
                    arange(i, len(contenido), jump + 1)]
                ContenidoConSalto = "".join(ContenidoConSalto.tolist())

                # Devuelve un objeto iterador con los datos de la coincidencia
                # del patron.
                iterator = re.finditer(patron, ContenidoConSalto)
                for j in iterator:
                    # Si el iterador no esta vacio se guarda la coincidencia
                    if(j != None):
                        # print(ContenidoConSalto)
                        # print("yes")
                        # Se guardan los datos de la coincidencia en un
                        # diccionario para exportarlo.
                        coincidencia.append(
                            {'keyword': keyword, 'pagina': pagina + 1, 'salto': jump + 1,
                             'inicio': (jump + 1) * (j.start(0)) + i + 1, 'fin': (jump + 1) * (j.end(0)) - 1})

    if(toolbar_width>len(texto)):
    	for i in range(toolbar_width-len(texto)):
    		sys.stdout.write("#")
    		sys.stdout.flush()
    sys.stdout.write("\n")
    return coincidencia


from csv import DictReader, DictWriter
import sys

VEN_CODE = 'VenCode'
PART_NUMBER = 'PartNumber'
SKU = 'SKU'
QUANTITY = 'TotalQty'

FIELDNAMES = [VEN_CODE, PART_NUMBER, SKU, QUANTITY]

if len(sys.argv) > 2:
    filename_master = sys.argv[1]
    filename_supply = sys.argv[2]
else:
    filename_master = 'MasterInventory.csv'
    filename_supply = 'SupplyInventory.csv'

print("Master filename:", filename_master)
print("Supply filename:", filename_supply)

def create_master_cache():
    """Returns the master inventory as a dictionary."""

    cache = {}
    with open(filename_master, encoding="utf8") as csv_file:
        master = DictReader(csv_file)
        for part in master:
            code = part[VEN_CODE]
            num = part[PART_NUMBER]
            qty = part[QUANTITY]

            if cache.get(code):
                cache[code][num] = qty if qty else 0
            else:
                cache[code] = {num: qty if qty else 0}
    print(cache)
    return cache

def search_cache(cache, keys, level=0):
    """Search a an inventory cache."""

    if level >= len(keys):
        return False

    key = keys[level]
    val = cache.get(key)

    if level == len(keys)-1:
        return val if val != '' else 0
    if not val:
        return False
    return search_cache(val, keys, level+1)

def create_row(code, num, qty):
    """Helper function to create a row dictionary."""

    return {
        VEN_CODE: code,
        PART_NUMBER: num,
        SKU: f'{code}_{num}',
        QUANTITY: qty,
    }

def create_header(fieldnames):
    return dict((field, field) for field in fieldnames)

def write_to_master(cache):
    """Write row to 'newmaster.csv'"""

    with open("newmaster.csv", 'w', newline='', encoding="utf8") as out_file:
        writer = DictWriter(out_file, fieldnames=FIELDNAMES)

        # write header
        header = create_header(FIELDNAMES)
        writer.writerow(header)

        # write rows
        for code in cache:
            for num in cache[code]:
                qty = cache[code][num]
                row = create_row(code, num, qty)
                writer.writerow(row)

def update_master():
    """Create a new csv file called 'newmaster.csv' that will contain
    the rows from the master inventory file with quantities updated from
    the supply inventory."""

    try:
        # cache data in memory from the master inventory file
        master_cache = create_master_cache()

        with open(filename_supply, encoding="utf8") as csv_file:
            supply = DictReader(csv_file)

            # loop through each row in the supply inventory,
            # and update the qty in the master cache
            for part in supply:
                supply_code = part[VEN_CODE]
                supply_num = part[PART_NUMBER]
                supply_qty = part[QUANTITY]

                # search the master inventory cache
                # for the supply
                master_qty = search_cache(
                    master_cache,
                    [supply_code, supply_num]
                )

                if master_qty:
                    master_cache[supply_code][supply_num] = supply_qty

        # write the cache to the master csv file
        write_to_master(master_cache)

    except KeyError as e:
        print('There was an error', e)

if __name__ == "__main__":
    update_master()


from datetime import datetime as dt
from threading import Lock, Thread
from ..customtypes import PowermeterMonitorDict
from ..hardware import S0interface, ZeroW

def _calcPower(_time: dt) -> float:
    global currentTime
    delta_t_sec: float = (_time - currentTime).total_seconds()
    currentTime = _time
    return 3.6 / delta_t_sec

def _fillMonitorDict(_time: dt, monitor: PowermeterMonitorDict, lock: Lock) -> None:
    """calculates electric power and fills PowermeterMonitorDict"""

    # calculate power before filling monitor-dict
    power: float = _calcPower(_time)

    # if power is too big (rarely happens under heavy load -> "Sensorprellung")
    # limit: 3 Phasen à 63A à 240V == 45.36kW
    if power > 46:
        # Werte darüber sind unmöglich
        return

    with lock:
        # start filling
        monitor["datetime"].append(_time)
        monitor["power_kW"].append(power)

# initialize time to get clean intervals for calculating consumed electric power
currentTime: dt = dt.now()

def _powermeterFunc(device: ZeroW, monitor: PowermeterMonitorDict, lock: Lock) -> None:
    """
    Main loop waiting for S0-interface to receive a signal, and then storing its
    state in a globally shared python-Dictionary.
    """

    # initialisiere S0-Schnittstelle
    s0interface: S0interface = device.powermeter
    s0interface.wasteSignal()

    while True:
        s0interface.waitForSignal()
        _fillMonitorDict(dt.now(), monitor, lock)

def powermeterThread(device: ZeroW, monitor: PowermeterMonitorDict, lock: Lock) -> None:
    """starts the powermeter-Thread"""
    powermeterThread: Thread = Thread(
        target=_powermeterFunc,
        name="powermeterThread",
        args=([device, monitor, lock])
    )
    powermeterThread.start()


import sys

import websockets
import asyncio
import threading
import json

from Resources.ThreadedService import ThreadStatus
from Resources.ServiceType import ServiceType

import logging
_log = logging.getLogger("PingRelay")

class ControlServer(threading.Thread):
    def __init__(self, application, config):
        threading.Thread.__init__(self)
        self.running = False
        self.app = application
        if "web_server_port" in config:
            self.port = config["web_server_port"]
        else:
            self.port = 4000

    def run(self):
        self.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self.loop)
        try:
            self.sever_runner = websockets.serve(self.server, '0.0.0.0', self.port)
            self.loop.run_until_complete(self.sever_runner)
            self.running = True
        except Exception as err:
            _log.error("Error while starting server: {0}".format(err))
            return
        _log.info("Control server started")
        self.loop.run_forever()

    def stop(self):
        self.sever_runner.close()
        self.running = False

    async def server(self, websocket, path):
        while self.running and websocket.open:
            try:
                message_json = await websocket.recv()
            except Exception as err:
                _log.debug("A connection was closed: {0}".format(err))
                break
            try:
                message = json.loads(message_json)
            except Exception as err:
                self.send(websocket, {"Status": "Error", "error":"not in json format"})
            if "action" not in message:
                self.send(websocket, {"Status": "Error", "error":"action not specified"})
                pass
            action = message["action"].lower()
            if (action == "get status"):
                await self.action_get_status(websocket, message)
            elif (action == "disconnect"):
                await self.action_disconnect(websocket, message)
            elif (action == "reconnect"):
                await self.action_reconnect(websocket, message)
            else:
                self.send(websocket, {"Status": "Error", "error":"action not valid"})

    async def send(self, websocket, response):
        reaponse_json = json.dumps(response)
        try:
            await websocket.send(reaponse_json)
        except Exception as err:
            _log.debug("A connection was closed: {0}".format(err))

    async def action_get_status(self, websocket, message):
        listener_details = []
        for listener in self.app.listeners:
            listener_info = self.get_details(listener)
            listener_details.append(listener_info)

        emitter_details = []
        for emitter in self.app.emitters:
            emitter_info = self.get_details(emitter)
            emitter_details.append(emitter_info)

        listener_details.sort(key=lambda x: x['name'])
        emitter_details.sort(key=lambda x: x['name'])
        relay_details = {"messages" : self.app.messages}
        response = {"Status": "OK", "Response": "Status", "Listeners": listener_details, "Emitters": emitter_details, "Relay": relay_details}
        await self.send(websocket, response)

    async def action_disconnect(self, websocket, message):
        if "id" not in message:
            await self.send(websocket, {"Status": "Error", "error":"id not specified"})
            return
        connection_id = int(message["id"])
        connections = self.app.emitters + self.app.listeners
        match = next((x for x in connections if x.id == connection_id), None)
        if match is None:
            await self.send(websocket, {"Status": "Error", "error":"connection not found"})
            return
        match.stop()
        details = self.get_details(match)
        await self.send(websocket, {"Status": "OK", "Response": "Disconnect", "connection":details})

    async def action_reconnect(self, websocket, message):
        if "id" not in message:
            await self.send(websocket, {"Status": "Error", "error":"id not specified"})
            return
        connection_id = int(message["id"])
        connections = self.app.emitters + self.app.listeners
        match = next((x for x in connections if x.id == connection_id), None)
        if match is None:
            await self.send(websocket, {"Status": "Error", "error":"connection not found"})
            return
        if match.status() == ThreadStatus.Running:
            match.stop()
        self.app.reconnect_service(match)

        details = self.get_details(match)
        await self.send(websocket, {"Status": "OK", "Response": "Reconnect",  "connection":details})

    def get_details(self, connection):
        connection_info = {}
        connection_info["id"] = connection.id
        connection_info["name"] = connection.name
        connection_info["status"] = str(connection.status().value)
        connection_info["uptime"] = str(connection.uptime())
        connection_info["messages"] = connection.messages
        return connection_info


# Importa as bibliotecas requests e json
import requests
import json

# Inicia uma sessão com o servidor
session = requests.session()

# Cria um dicionário com a chave "palpite" inicializada com 0
dados = {"palpite": 0}

# Define o cabeçalho da solicitação com "content-type" como "application/json"
header = {"content-type": "application/json"}

# Realiza a primeira solicitação HTTP GET ao endpoint "http://127.0.0.1:1337/comecar_jogo"
r = session.get("http://127.0.0.1:1337/comecar_jogo")

# Verifica se a resposta contém "success" com o valor True
if r.json()["success"]:
    # Se sim, inicia um loop infinito
    while True:
        # Solicita ao usuário um palpite
        dados["palpite"] = input('Adivinhe o número > ')

        # Realiza uma solicitação HTTP POST ao endpoint "http://127.0.0.1:1337/adivinhar_numero"
        # com o corpo da mensagem contendo os dados codificados em JSON e o cabeçalho definido
        r = session.post("http://127.0.0.1:1337/adivinhar_numero", data=json.dumps(dados), headers=header)

        # Armazena a resposta em formato JSON na variável meu_json
        meu_json = r.json()

        # Imprime a resposta
        print(meu_json)

        # Verifica se a resposta contém "status" com o valor "vc acertou"
        if meu_json["status"] == "vc acertou":
            # Se sim, interrompe o loop e o jogo termina
            break
else:
    # Se a resposta da primeira solicitação não contém "success" com o valor True,
    # imprime a mensagem "Sem permissão para jogar" e o jogo não começa
    print('Sem permissão para jogar')


from flask import Flask, request, redirect, url_for, render_template, flash, session
from os import environ
import requests
from flask_sqlalchemy import SQLAlchemy
from rq import Queue
from rq.job import Job
from worker import conn
import json
import hmac
import hashlib
import base64

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:////tmp/test.db"
app.secret_key = "SECRET_MISSION_SOFTWARE_IS_THE_BEST"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)

q = Queue(connection=conn)

SHOPIFY_API_KEY = environ.get('SHOPIFY_API_KEY')
SHOPIFY_API_SECRET_KEY = environ.get('SHOPIFY_API_SECRET_KEY')
SCOPES = "write_orders,read_customers,read_products,write_products"

APP_SITE = "https://3d47e46c.ngrok.io"
ALL_WEBHOOKS = ["products/create", "products/update", "carts/create", "carts/update"]

class Shop(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), nullable=False)
    token = db.Column(db.String(64), unique=True, nullable=False)
    webhooks = db.relationship("Webhook", backref="shop", lazy="dynamic")

    def __repr__(self):
        return "<Shop %r>" % self.name

class Webhook(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    webhook_id = db.Column(db.Integer, nullable=False)
    topic = db.Column(db.String(80), nullable=False)
    shop_id = db.Column(db.Integer, db.ForeignKey("shop.id"), nullable=False)

@app.route("/", methods=["GET"])
def start():
    return "hello world"

@app.route("/webhook/<category>/<action>", methods=["GET", "POST"])
def webhook(category, action):
    data = request.get_data()
    cur_hmac = request.headers.get("X-Shopify-Hmac-SHA256")

    signature = hmac.new(
        SHOPIFY_API_SECRET_KEY.encode("utf-8"), data, hashlib.sha256
    ).digest()
    if not hmac.compare_digest(base64.b64encode(signature), cur_hmac.encode("utf-8")):
        return "Sorry webhook"

    webhook_topic = "{}/{}".format(category, action)
    if request.method == "GET":
        return "???"
    else:
        job = q.enqueue_call(
            func=webhook_task, args=(webhook_topic, ), result_ttl=5000
        )
        print("Job added with id: {}".format(job.get_id()))
        return "Webhook called"

def add_webhook(shop, webhook_topic):
    webhooks = shop.webhooks.filter_by(topic=webhook_topic)
    if webhooks.count() == 0:
        webhook_url = "https://{}/admin/api/2019-04/webhooks.json".format(shop.name)
        headers = {
            "Content-Type": "application/json",
            "X-Shopify-Access-Token": shop.token,
        }
        data = {
            "webhook": {
                "topic": webhook_topic,
                "address": "{}/webhook/{}".format(APP_SITE, webhook_topic),
                "format": "json",
            }
        }
        r = requests.post(webhook_url, headers=headers, data=json.dumps(data))
        content = json.loads(r._content.decode("utf-8"))["webhook"]
        webhook = Webhook(
            webhook_id=content["id"], topic=content["topic"], shop_id=shop.id
        )
        db.session.add(webhook)
        db.session.commit()

def remove_webhook(shop, webhook_topic):
    webhooks = shop.webhooks.filter_by(topic=webhook_topic)
    if webhooks.count() == 1:
        webhook = webhooks[0]
        webhook_url = "https://{}/admin/api/2019-04/webhooks/{}.json".format(
            shop.name, webhook.webhook_id
        )
        headers = {"X-Shopify-Access-Token": shop.token}
        r = requests.delete(webhook_url, headers=headers)

        if r.status_code == 200:
            db.session.delete(webhook)
            db.session.commit()
        else:
            print(
                "ERROR: could not remove webhook with webhook_id:{} and topic:{}".format(
                    webhook.webhook_id, webhook.topic
                )
            )

def manage_webhooks(shop, enabled_webhooks):
    disabled_webhooks = []
    for webhook in ALL_WEBHOOKS:
        if webhook not in enabled_webhooks:
            disabled_webhooks.append(webhook)

    for webhook in enabled_webhooks:
        add_webhook(shop, webhook)
    for webhook in disabled_webhooks:
        remove_webhook(shop, webhook)

def delete_shop(shop):
    for webhook_topic in ALL_WEBHOOKS:
        remove_webhook(shop, webhook_topic)

    db.session.delete(shop)
    db.session.commit()

@app.route("/settings", methods=["GET", "POST", "DELETE"])
def settings():
    if "name" not in session:
        return "Sorry settings"

    name = session["name"]
    shop = Shop.query.filter_by(name=name).first()
    if request.method == "GET":
        webhook_checkboxes = []
        enabled_webhooks = list(map(lambda x: x.topic, shop.webhooks))
        for webhook in ALL_WEBHOOKS:
            if webhook in enabled_webhooks:
                webhook_checkboxes.append((webhook, True))
            else:
                webhook_checkboxes.append((webhook, False))
        return render_template("settings.html", webhook_checkboxes=webhook_checkboxes)
    elif request.method == "POST":
        enabled_webhooks = list(request.form)

        manage_webhooks(shop, enabled_webhooks)

        flash("Your changes have been saved.")
        return redirect(url_for("settings"))
    elif request.method == "DELETE":
        delete_shop(shop)
        return "Shop deleted"

def check_hmac(cur_hmac, querystring):
    hmac_start = querystring.find("hmac")
    hmac_end = querystring.find("&", hmac_start)
    message = querystring[0:hmac_start] + querystring[hmac_end + 1 :]

    signature = hmac.new(
        SHOPIFY_API_SECRET_KEY.encode("utf-8"), message.encode("utf-8"), hashlib.sha256
    ).hexdigest()

    return cur_hmac == signature

@app.route("/install", methods=["GET"])
def install():
    cur_hmac = request.args.get("hmac")
    name = str(request.args.get("shop"))
    querystring = request.environ["QUERY_STRING"]

    if not check_hmac(cur_hmac, querystring):
        return "Sorry install"

    shop = Shop.query.filter_by(name=name).first()
    if shop:
        # redirect to settings
        session["name"] = name
        return redirect(url_for("settings"))
    else:
        api_key = SHOPIFY_API_KEY
        redirect_uri = "{}/generateToken".format(APP_SITE)
        # TODO: better nonce
        state = "bhaskar" + name
        scopes = SCOPES
        url = "https://{}/admin/oauth/authorize?client_id={}&scope={}&redirect_uri={}&state={}".format(
            name, api_key, scopes, redirect_uri, state
        )
        return redirect(url)

@app.route("/generateToken", methods=["GET"])
def generateToken():
    nonce = request.args.get("state")
    code = request.args.get("code")
    name = str(request.args.get("shop"))

    if nonce != "bhaskar" + name:
        return "badskar"

    cur_hmac = request.args.get("hmac")
    querystring = request.environ["QUERY_STRING"]
    if not check_hmac(cur_hmac, querystring):
        return "Sorry generateToken"

    # TODO: check hostname

    client_id = SHOPIFY_API_KEY
    client_secret = SHOPIFY_API_SECRET_KEY
    url = "https://{}/admin/oauth/access_token".format(name)
    r = requests.post(
        url, data={"client_id": client_id, "client_secret": client_secret, "code": code}
    )
    content = json.loads(r._content.decode("utf-8"))
    token = content["access_token"]
    shop = Shop(name=name, token=token)
    db.session.add(shop)
    db.session.commit()
    return "Shopify app successfully connected"

def webhook_task(topic):
    print("Webhook recieved for " + topic)
    job = q.enqueue_call(
        func=slack_integration, args=(topic, ), result_ttl=5000
    )
    print("Job added with id: {}".format(job.get_id()))

def slack_integration(topic):
    url = environ.get('SLACK_URL')
    text = "Your shopify shop updated {}".format(topic)
    headers = {"Content-Type": "application/json"}
    data = {"text": text}
    r = requests.post(
        url, headers=headers, data=json.dumps(data)
    )
    print(r)


# File:         test_cc.py
# Purpose:      test the central controller backend
# Based on:     ../test_hybrid.py, ../test_uniform_sched.py

import openql as ql
import os
import unittest

from config import json_dir, output_dir
from typing import List, Tuple

config_fn = os.path.join(json_dir, 'test_cfg_cc.json')
platform_name = 's-17'
default_num_qubits = 17
default_num_cregs = 32
default_num_bregs = 32
all_qubits = range(0, default_num_qubits)

class TestCentralController(unittest.TestCase):
    @classmethod
    def setUp(cls):
        ql.initialize()
        ql.set_option('output_dir', output_dir)
        ql.set_option('scheduler', 'ALAP')
        ql.set_option('log_level', 'LOG_WARNING')

    # NB: based on PycQED::openql_helpers.py
    @staticmethod
    def _configure_compiler(
            platform: ql.Platform,
            cqasm_src_filename: str = "",
            extra_pass_options: List[Tuple[str, str]] = None
    ) -> ql.Compiler:
        # NB: for alternative ways to configure the compiler, see
        # https://openql.readthedocs.io/en/latest/gen/reference_configuration.html#compiler-configuration

        c = platform.get_compiler()

        # remove default pass list (this also removes support for most *global* options as defined in
        # https://openql.readthedocs.io/en/latest/gen/reference_options.html, except for 'log_level')
        # NB: this defeats automatic backend selection by OpenQL based on key "eqasm_compiler"
        c.clear_passes()

        # add the passes we need
        compiling_cqasm = cqasm_src_filename != ""
        if compiling_cqasm:
            # cQASM reader as very first step
            c.append_pass(
                'io.cqasm.Read',
                'reader',
                {
                    'cqasm_file': cqasm_src_filename
                }
            )

            # decomposer for legacy decompositions (those defined in the "gate_decomposition" section)
            # FIXME: comment incorrect, also decomposes new-style definitions
            # see https://openql.readthedocs.io/en/latest/gen/reference_passes.html#instruction-decomposer
            c.append_pass(
                'dec.Instructions',
                # NB: don't change the name 'legacy', see:
                # - https://openql.readthedocs.io/en/latest/gen/reference_passes.html#instruction-decomposer
                # - https://openql.readthedocs.io/en/latest/gen/reference_passes.html#predicate-key
                'legacy',
            )
        else:  # FIXME: experimental. Also decompose API input to allow use of new style decompositions
            c.append_pass(
                'dec.Instructions',
                # NB: don't change the name 'legacy', see:
                # - https://openql.readthedocs.io/en/latest/gen/reference_passes.html#instruction-decomposer
                # - https://openql.readthedocs.io/en/latest/gen/reference_passes.html#predicate-key
                'legacy',
            )

        # report the initial qasm
        c.append_pass(
            'io.cqasm.Report',
            'initial',
            {
                'output_suffix': '.cq',
                'with_timing': 'no'
            }
        )

        # schedule
        c.append_pass(
            'sch.ListSchedule',
            'scheduler',
            {
                'resource_constraints': 'yes'
            }
        )

        # report scheduled qasm
        c.append_pass(
            'io.cqasm.Report',
            'scheduled',
            {
                'output_suffix': '.cq',
            }
        )

        # generate code using CC backend
        # NB: OpenQL >= 0.10 no longer has a CC-light backend
        c.append_pass(
            'arch.cc.gen.VQ1Asm',
            'cc_backend'
        )

        # set compiler pass options
        # c.set_option('*.output_prefix', f'{OqlProgram.output_dir}/%N.%P')
        # if self._arch == 'CC':
        #     c.set_option('cc_backend.output_prefix', f'{OqlProgram.output_dir}/%N')
        c.set_option('scheduler.scheduler_target', 'alap')
        if compiling_cqasm:
            c.set_option('cc_backend.run_once', 'yes')  # if you want to loop, write a cqasm loop

        # finally, set user pass options
        if extra_pass_options is not None:
            for opt, val in extra_pass_options:
                c.set_option(opt, val)

        # log.debug("\n" + c.dump_strategy())
        return c

    def test_gate_decomposition_cz(self):
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s17_direct_iq_openql_0_10.json'))

        p = ql.Program('test_gate_decomposition_cz', platform, 17, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, 17, default_num_cregs, default_num_bregs)

        k.gate("cz", [8, 10])
        k.gate("cz", [10, 8])
        k.gate("cz", [8, 11])
        k.gate("cz", [11, 9])
        k.gate("cz", [11, 14])
        k.gate("cz", [14, 11])
        k.gate("cz", [10, 14])
        k.gate("cz", [14, 10])
        k.gate("cz", [9, 11])
        k.gate("cz", [11, 9])
        k.gate("cz", [9, 12])
        k.gate("cz", [12, 9])
        # k.gate("cz", [11, 15])
        # k.gate("cz", [15, 11])
        k.gate("cz", [12, 15])
        k.gate("cz", [15, 12])

        p.add_kernel(k)

        # compile, with new style gate decompositions
        c = self._configure_compiler(platform)
        c.compile(p)

    def test_native_instructions(self):
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s17_direct_iq_openql_0_10.json'))

        p = ql.Program('test_native_instructions', platform, 17, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, 17, default_num_cregs, default_num_bregs)

        k.gate("prepz", [0])
        k.gate("i", [0])
        k.gate("rx180", [0])
        k.gate("ry180", [0])
        k.gate("rx90", [0])
        k.gate("ry90", [0])
        k.gate("rxm90", [0])
        k.gate("rym90", [0])

        k.gate("measure", [0])

        p.add_kernel(k)
        p.compile()

    def test_special_instructions(self):
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s17_direct_iq_openql_0_10.json'))

        p = ql.Program('test_special_instructions', platform, 17, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, 17, default_num_cregs, default_num_bregs)

        k.gate("spec", [0])
        k.gate("rx12", [0])
        k.gate("square", [0])
        k.gate("rx45", [0])

        k.gate("rx2theta", [0])
        k.gate("rxm2theta", [0])
        k.gate("rx2thetaalpha", [0])
        k.gate("rphi180", [0])
        k.gate("rphi180beta", [0])
        k.gate("rx180beta", [0])
        k.gate("rphi180beta2", [0])
        k.gate("ry90beta", [0])
        k.gate("rym90alpha", [0])
        k.gate("ry90betapi", [0])
        k.gate("rphi180alpha", [0])
        k.gate("rx90alpha", [0])
        k.gate("rx180alpha2", [0])
        k.gate("rphim2theta", [0])

        p.add_kernel(k)
        p.compile()

    def test_gate_decompositions_alias(self):
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s17_direct_iq_openql_0_10.json'))

        p = ql.Program('test_gate_decompositions_alias', platform, 17, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, 17, default_num_cregs, default_num_bregs)

        k.gate("x", [0])
        k.gate("y", [0])
        k.gate("roty90", [0])
        k.gate("x180", [0])
        k.gate("y180", [0])
        k.gate("y90", [0])
        k.gate("x90", [0])
        k.gate("my90", [0])
        k.gate("mx90", [0])

        p.add_kernel(k)
        p.compile()

    # Quantum Error Correction cycle
    def test_qec(self):
        platform = ql.Platform(platform_name, config_fn)

        p = ql.Program('test_qec', platform, default_num_qubits, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, default_num_qubits, default_num_cregs, default_num_bregs)

        # pipelined QEC: [
        # see: R. Versluis et al., Phys. Rev. A 8, 034021 (2017)
        # - nw, ne, sw, se] -> [n, e, w, s] because we rotate grid
        # - H -> rym90, ry90, see Fig 2 of reference
        #
        # class SurfaceCode, qubits, tiles, width, getNeighbourN, getNeighbourE, getNeighbourW, getNeighbourS,
        # getX, getZ, getData

        # define qubit aliases:
        # FIXME: neighbours make no sense anymore
        x = 7
        x_n = x - 5
        x_e = x + 1
        x_s = x + 5
        x_w = x - 1

        z = 11
        z_n = z - 5
        z_e = z + 1
        z_s = z + 5
        z_w = z - 1

        # create classical registers
        # FIXME: deprecated by branch condex
        # if 0:
        #     rdx = ql.CReg(1)
        #     rdz = ql.CReg(2)

        # X stabilizers
        k.gate("rym90", [x])
        k.gate("rym90", [x_n])
        k.gate("rym90", [x_e])
        k.gate("rym90", [x_w])
        k.gate("rym90", [x_s])
        k.barrier([])

        k.gate("cz", [x, x_e])
        k.gate("cz", [x, x_n])
        k.gate("cz", [x, x_s])
        k.gate("cz", [x, x_w])
        k.barrier([])

        k.gate("ry90", [x])
        k.gate("ry90", [x_n])
        k.gate("ry90", [x_e])
        k.gate("ry90", [x_w])
        k.gate("ry90", [x_s])
        k.barrier([])

        # k.gate("measure", [x], rdX)
        k.gate('measure', [x], 0, 0.0, [0])
        k.barrier([])

        # Z stabilizers
        k.gate("rym90", [z])
        k.barrier([])

        k.gate("cz", [z, z_e])
        k.gate("cz", [z, z_s])
        k.gate("cz", [z, z_n])
        k.gate("cz", [z, z_w])
        k.barrier([])

        k.gate("ry90", [z])
        # k.gate("measure", [z], rdZ)
        k.gate('measure', [z], 0, 0.0, [1])

        p.add_kernel(k)
        p.compile()

    def test_angle(self):
        platform = ql.Platform(platform_name, config_fn)

        p = ql.Program('test_angle', platform, default_num_qubits, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, default_num_qubits, default_num_cregs, default_num_bregs)

        k.gate("rx180", [6], 0, 1.2345)     # NB: Python interface lacks classical parameter

        p.add_kernel(k)
        p.compile()

    def test_qi_example(self):
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s17_direct_iq_openql_0_10.json'))

        p = ql.Program('test_qi_example', platform, 17, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, 17, default_num_cregs, default_num_bregs)

        k.barrier([])
        for q in [0, 1, 2, 3, 4]:
            k.gate("prepz", [q])
        k.barrier([])

        k.gate("ry180", [0, 2])     # FIXME: "y" does not work, but gate decomposition should handle?
        # k.gate("cz", [0, 2])
        k.gate("cz", [8, 10])
        k.gate("y90", [2])
        k.barrier([])
        for q in [0, 1, 2, 3, 4]:
            k.gate("measure", [q])
        k.barrier([])

        p.add_kernel(k)

        # compile, with new style gate decompositions
        c = self._configure_compiler(platform)
        c.compile(p)

    # based on ../test_cqasm_reader.py::test_conditions
    # FIXME: uses old cqasm_reader
    def test_cqasm_conditions(self):
        cqasm_config_fn = os.path.join(json_dir, 'config_cc.json')
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s5_direct_iq.json'))
        number_qubits = platform.get_qubit_number()
        name = 'test_cqasm_conditions'
        program = ql.Program(name, platform, number_qubits)
        qasm_rdr = ql.cQasmReader(platform, program, cqasm_config_fn)
        qasm_str = """
            version 1.1

            var qa, qb: qubit
            var ca, cb: bool

            { measure_fb qa, ca | measure_fb qb, cb }
            # .barrier  # use subcircuit to force new kernel, and thus scheduling realm
            # barrier [qa,qb]
            # { barrier qa | barrier qb }
            barrier

            # # Old hack for feedback
            # { measure qa, ca | measure qb, cb }
            #
            # .wait_uhfqa # use subcircuit to force new kernel, and thus scheduling realm
            # { _wait_uhfqa qa | _wait_uhfqa qb }
            # .dist_dsm
            # { _dist_dsm qa, ca | _dist_dsm qb, cb }
            # .wait_dsm
            # { _wait_dsm qa | _wait_dsm qb }
            # .test
            #
            cond(true) x qa
            cond(false) y qa
            cond(ca) z qa
            cond(!true) x qa
            cond(!false) y qa
            cond(!ca) z qa
            cond(!!true) x qa
            cond(!!false) y qa
            cond(!!ca) z qa
            cond(ca && cb) x qa
            cond(ca && true) y qa
            cond(ca && false) z qa
            cond(true && cb) x qa
            cond(false && cb) y qa
            cond(ca || cb) z qa
            cond(ca || true) x qa
            cond(ca || false) y qa
            cond(true || cb) z qa
            cond(false || cb) x qa
            cond(ca ^^ cb) y qa
            cond(ca ^^ true) z qa
            cond(ca ^^ false) x qa
            cond(true ^^ cb) y qa
            cond(false ^^ cb) z qa
            cond(!(ca && cb)) x qa
            cond(!(ca && true)) y qa
            cond(!(ca && false)) z qa
            cond(!(true && cb)) x qa
            cond(!(false && cb)) y qa
            cond(!(ca || cb)) z qa
            cond(!(ca || true)) x qa
            cond(!(ca || false)) y qa
            cond(!(true || cb)) z qa
            cond(!(false || cb)) x qa
            cond(!(ca ^^ cb)) y qa
            cond(!(ca ^^ true)) z qa
            cond(!(ca ^^ false)) x qa
            cond(!(true ^^ cb)) y qa
            cond(!(false ^^ cb)) z qa
            """
        qasm_rdr.string2circuit(qasm_str)
        ql.set_option('log_level', 'LOG_INFO')
        program.compile()
        # self.assertTrue(file_compare(os.path.join(output_dir, name + '.qasm'),
        #                              os.path.join(qasm_golden_dir, name + '.qasm')))

    def test_cqasm_gate_decomposition(self):
        cqasm_config_fn = os.path.join(json_dir, 'config_cc.json')
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s5_direct_iq.json'))
        number_qubits = platform.get_qubit_number()
        name = 'test_cqasm_gate_decomposition'
        program = ql.Program(name, platform, number_qubits)
        qasm_rdr = ql.cQasmReader(platform, program, cqasm_config_fn)
        qasm_str = """
            version 1.1

            var qa, qb: qubit
            var ca, cb: bool

            { measure_fb qa, ca | measure_fb qb, cb }
            """
        qasm_rdr.string2circuit(qasm_str)
        ql.set_option('log_level', 'LOG_INFO')
        program.compile()

    # based on test_hybrid.py::test_do_while_nested_for()
    # FIXME: now fails with "in repeat-until loop body: expected creg reference, but got something else"
    @unittest.skip("fails on sf_cz_sw")
    # additionally, we don't support if_?_break anymore
    def test_nested_rus(self):
        num_qubits = 5
        q_idx = 0

        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s17_direct_iq_openql_0_10.json'))
        p = ql.Program('test_nested_rus', platform, num_qubits, default_num_cregs, default_num_bregs)

        outer_program = ql.Program('outer_program', platform, num_qubits, default_num_cregs, default_num_bregs)
        outer_kernel = ql.Kernel('outer_kernel', platform, num_qubits, default_num_cregs)
        outer_kernel.gate("measure_fb", [q_idx])
        outer_kernel.gate("if_1_break", [q_idx])  # FIXME: uses incorrect label
        outer_program.add_kernel(outer_kernel)

        inner_program = ql.Program('inner_program', platform, num_qubits, default_num_cregs, default_num_bregs)
        inner_kernel = ql.Kernel('inner_kernel', platform, num_qubits, default_num_cregs)
        inner_kernel.gate("measure_fb", [q_idx])
        inner_kernel.gate("if_0_break", [q_idx])
        inner_kernel.gate("rx180", [q_idx])
        inner_program.add_for(inner_kernel, 1000000)  # NB: loops *kernel*

        outer_program.add_program(inner_program)

        # NB: loops *program*, CC backend interprets all conditions as true
        foo = ql.CReg(0)
        p.add_do_while(outer_program, ql.Operation(foo, '==', foo))

        ql.set_option('log_level', 'LOG_INFO')  # override log level
        p.compile()

    # based on DCL test program
    @unittest.skip("fails on sf_cz_sw")
    # FIXME: additionally, we don't support if_?_break anymore
    def test_nested_rus_angle_0(self):
        num_qubits = 17

        ancilla1idx = 10
        ancilla2idx = 8
        data_idx = 11

        angle = 0
        echo_delay_inner_rus = 1
        echo_delay_inner_rus_data = 1
        echo_delay_outer_rus = 1

        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s17_direct_iq.json'))
        p = ql.Program('test_nested_rus_angle_0', platform, num_qubits, default_num_cregs, default_num_bregs)

        init_kernel = ql.Kernel('initKernel', platform, num_qubits, default_num_cregs)
        init_kernel.prepz(ancilla1idx)
        init_kernel.prepz(ancilla2idx)
        init_kernel.prepz(data_idx)
        init_kernel.gate('cw_{:02}'.format(int(angle) // 20 + 9), [data_idx])
        init_kernel.gate("wait", [], 0)
        p.add_kernel(init_kernel)

        outer_program = ql.Program('outerProgram', platform, num_qubits, default_num_cregs, default_num_bregs)
        rus_program_1 = ql.Program('rusProgram1', platform, num_qubits, default_num_cregs, default_num_bregs)
        rus_kernel_1 = ql.Kernel('rusKernel1', platform, num_qubits, default_num_cregs)
        rus_kernel_1.gate("rx2theta", [ancilla1idx])
        rus_kernel_1.gate("rYm90", [ancilla2idx])
        rus_kernel_1.gate("cz", [ancilla1idx, ancilla2idx])
        rus_kernel_1.gate("rXm2theta", [ancilla1idx])
        rus_kernel_1.gate("ry90beta", [ancilla2idx])
        rus_kernel_1.gate("wait", [ancilla1idx, ancilla2idx], 0)
        rus_kernel_1.gate("rphi180", [data_idx])
        rus_kernel_1.gate("measure_fb", [ancilla1idx])
        rus_kernel_1.gate("wait", [ancilla2idx], echo_delay_inner_rus)
        rus_kernel_1.gate("rphi180", [ancilla2idx])
        rus_kernel_1.gate("wait", [ancilla2idx], 1860-echo_delay_inner_rus)
        rus_kernel_1.gate("wait", [data_idx], echo_delay_inner_rus_data)
        rus_kernel_1.gate("wait", [ancilla1idx, ancilla2idx, data_idx], 0)
        rus_kernel_1.gate("if_0_break", [ancilla1idx])
        rus_kernel_1.gate("wait", [ancilla1idx, ancilla2idx, data_idx], 0)
        rus_kernel_1.gate("rx180", [ancilla1idx])
        rus_kernel_1.gate("rxm90", [ancilla2idx])
        rus_kernel_1.gate("rx180", [data_idx])
        rus_kernel_1.gate("wait", [ancilla1idx, ancilla2idx, data_idx], 0)
        rus_program_1.add_for(rus_kernel_1, 1000000)
        outer_program.add_program(rus_program_1)

        interm_program = ql.Program('intermProgram', platform, num_qubits, default_num_cregs, default_num_bregs)
        interm_kernel = ql.Kernel('intermKernel', platform, num_qubits, default_num_cregs)
        interm_kernel.gate("rx180", [ancilla2idx])
        interm_kernel.gate("rx180", [data_idx])
        interm_kernel.gate("rYm90", [data_idx])
        interm_kernel.gate("cz", [ancilla2idx, data_idx])
        interm_kernel.gate("rY90", [data_idx])
        interm_program.add_kernel(interm_kernel)
        outer_program.add_program(interm_program)

        rus_program_2 = ql.Program('rusProgram2', platform, num_qubits, default_num_cregs, default_num_bregs)
        rus_kernel_2 = ql.Kernel('rusKernel2', platform, num_qubits, default_num_cregs)
        rus_kernel_2.gate("rX2theta", [ancilla1idx])
        rus_kernel_2.gate("rYm90alpha", [ancilla2idx])
        rus_kernel_2.gate("cz", [ancilla1idx, ancilla2idx])
        rus_kernel_2.gate("rX2thetaalpha", [ancilla1idx])
        rus_kernel_2.gate("rY90betapi", [ancilla2idx])
        rus_kernel_2.gate("wait", [ancilla1idx, ancilla2idx], 0)
        rus_kernel_2.gate("rphi180beta", [data_idx])
        rus_kernel_2.gate("measure_fb", [ancilla1idx])
        rus_kernel_2.gate("wait", [ancilla2idx], echo_delay_inner_rus)
        rus_kernel_2.gate("rphi180alpha", [ancilla2idx])
        rus_kernel_2.gate("wait", [ancilla2idx], 1860-echo_delay_inner_rus)
        rus_kernel_2.gate("wait", [data_idx], echo_delay_inner_rus_data)
        rus_kernel_2.gate("wait", [ancilla1idx, ancilla2idx, data_idx], 0)
        rus_kernel_2.gate("if_0_break", [ancilla1idx])
        rus_kernel_2.gate("wait", [ancilla1idx, ancilla2idx, data_idx], 0)
        rus_kernel_2.gate("rx180", [ancilla1idx])
        rus_kernel_2.gate("rx90alpha", [ancilla2idx])
        rus_kernel_2.gate("rx180beta", [data_idx])
        rus_kernel_2.gate("wait", [ancilla1idx, ancilla2idx, data_idx], 0)
        rus_program_2.add_for(rus_kernel_2, 1000000)
        outer_program.add_program(rus_program_2)

        end_kernel = ql.Kernel('outerKernel', platform, num_qubits, default_num_cregs)
        end_kernel.gate("wait", [ancilla2idx, data_idx], 0)
        end_kernel.gate("rx180alpha2", [ancilla2idx])
        end_kernel.gate("measure_fb", [ancilla2idx])
        end_kernel.gate("wait", [data_idx], echo_delay_outer_rus)
        end_kernel.gate("rphi180beta2", [data_idx])
        end_kernel.gate("wait", [data_idx], 1880-echo_delay_outer_rus)
        end_kernel.gate("wait", [ancilla2idx, data_idx], 0)
        end_kernel.gate("if_0_break", [ancilla2idx])
        outer_program.add_kernel(end_kernel)

        foo = ql.CReg(0)
        p.add_do_while(outer_program, ql.Operation(foo, '==', foo))

        measure_kernel = ql.Kernel('measureKernel', platform, num_qubits, default_num_cregs)
        measure_kernel.gate("measure_fb", [data_idx])
        p.add_kernel(measure_kernel)

        ql.set_option('log_level', 'LOG_INFO')  # override log level
        p.compile()

    def test_rc_sched_measure(self):
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s5_direct_iq.json'))

        p = ql.Program('test_rc_sched_measure', platform, 5, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, 5, default_num_cregs, default_num_bregs)

        for q in [0, 1, 2, 3, 4]:
            k.gate("measure", [q])
        k.gate('x', [0])
        for q in [0, 1, 2, 3, 4]:
            k.gate("measure", [q])
        k.gate('x', [1])

        p.add_kernel(k)
        p.compile()

    # FIXME: solve for real
    @unittest.skip("fails: 'Inconsistency detected in bundle contents: time travel not yet possible in this version'")
    def test_rc_sched_measure_asap(self):
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s5_direct_iq.json'))

        p = ql.Program('test_rc_sched_measure_asap', platform, 5, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, 5, default_num_cregs, default_num_bregs)

        k.gate('x', [2])
        for q in [0, 1, 2, 3, 4]:
            k.gate("measure", [q])
        k.gate('x', [0])
        for q in [0, 1, 2, 3, 4]:
            k.gate("measure", [q])
        k.gate('x', [1])

        p.add_kernel(k)
        ql.set_option('scheduler', 'ASAP')
        p.compile()

    def test_rc_sched_measure_barrier(self):
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s5_direct_iq.json'))

        p = ql.Program('test_rc_sched_measure_barrier', platform, 5, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, 5, default_num_cregs, default_num_bregs)

        for q in [0, 1, 2, 3, 4]:
            k.gate("measure", [q])
        k.barrier([])
        k.gate('x', [0])
        k.barrier([])
        for q in [0, 1, 2, 3, 4]:
            k.gate("measure", [q])
        k.barrier([])
        k.gate('x', [1])

        p.add_kernel(k)
        p.compile()

    # FIXME: solve for real
    @unittest.skip("fails with new IR")
    def test_rc_sched_cz(self):
        num_qubits = 17

        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s17_direct_iq.json'))

        p = ql.Program('test_rc_sched_cz', platform, num_qubits, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, num_qubits, default_num_cregs, default_num_bregs)

        # NB: requires resource to manage fluxing
        k.gate("cz", [10, 14])  # no associated park
        k.gate("cz", [9, 11])   # parks 12
        k.gate('x', [10])
        p.add_kernel(k)

        ql.set_option('log_level', 'LOG_DEBUG')  # override log level
        p.compile()

    def test_rc_sched_prepz(self):
        num_qubits = 17

        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s17_direct_iq.json'))

        p = ql.Program('test_rc_sched_prepz', platform, num_qubits, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, num_qubits, default_num_cregs, default_num_bregs)

        k.gate('x', [2])
        k.gate('prepz', [1, 2])
        k.gate('x', [1])
        p.add_kernel(k)

        ql.set_option('log_level', 'LOG_DEBUG')  # override log level
        p.compile()

    # FIXME: add:
    # - qec_pipelined
    # - long program (RB)

if __name__ == '__main__':
    unittest.main()


# Implementation of classic arcade game Pong

import simplegui
import random

# initialize globals - pos and vel encode vertical info for paddles
# canvas size (playfield)
WIDTH = 600
HEIGHT = 400

# ball size
BALL_RADIUS = 20

# paddle dimensions
PAD_WIDTH = 8
PAD_HEIGHT = 80
HALF_PAD_WIDTH = PAD_WIDTH / 2
HALF_PAD_HEIGHT = PAD_HEIGHT / 2

BALL_MAX_X_SPEED = 240
BALL_MIN_X_SPEED = 120
BALL_MAX_Y_SPEED = 180
BALL_MIN_Y_SPEED = 60

# scale factor for ball speed per second to ball speed per frame
FRAMES_PER_SEC = 60

# default paddle speed: cover top-to-bottom move in the time ball moves between mid-line and gutter
PADDLE_SPEED = BALL_MAX_X_SPEED * (HEIGHT - PAD_HEIGHT) / (WIDTH / 2 - PAD_WIDTH - BALL_RADIUS)

# ball directions
LEFT = False
RIGHT = True

# ball position and velocity
ball_pos = [WIDTH / 2, HEIGHT / 2]
ball_vel = [-5, -1]

# left paddle position and velocity
paddleL_pos = [0, HEIGHT / 2]
paddleL_vel = [0, 0]

# right paddle position and velocity
paddleR_pos = [WIDTH - PAD_WIDTH - 1, HEIGHT / 2]
paddleR_vel = [0, 0]

# left player score
scoreL = 0

# right player score
scoreR = 0

# fancy add-on features
game_over = False
score_timer = 0

# first to WIN_SCORE wins
WIN_SCORE = 9

# digit dimenstion
DW = WIDTH / 16
DH = HEIGHT / 10

# left score position
LX = WIDTH / 4 - DW / 2
LY = HEIGHT / 5

# right score position
RX = 3 * WIDTH / 4 - DW / 2
RY = HEIGHT / 5

# digit polylines
L0 = ((LX, LY - DH), (LX, LY + DH), (LX + DW, LY + DH), (LX + DW, LY - DH), (LX, LY - DH))
R0 = ((RX, RY - DH), (RX, RY + DH), (RX + DW, RY + DH), (RX + DW, RY - DH), (RX, RY - DH))
L1 = ((LX, LY - DH), (LX, LY + DH))
R1 = ((RX, RY - DH), (RX, RY + DH))
L2 = ((LX, LY - DH), (LX + DW, LY - DH), (LX + DW, LY), (LX, LY), (LX, LY + DH), (LX + DW, LY + DH))
R2 = ((RX, RY - DH), (RX + DW, RY - DH), (RX + DW, RY), (RX, RY), (RX, RY + DH), (RX + DW, RY + DH))
L3 = ((LX, LY - DH), (LX + DW, LY - DH), (LX + DW, LY), (LX, LY), (LX + DW, LY), (LX + DW, LY + DH), (LX, LY + DH))
R3 = ((RX, RY - DH), (RX + DW, RY - DH), (RX + DW, RY), (RX, RY), (RX + DW, RY), (RX + DW, RY + DH), (RX, RY + DH))
L4 = ((LX, LY - DH), (LX, LY), (LX + DW, LY), (LX + DW, LY - DH), (LX + DW, LY + DH))
R4 = ((RX, RY - DH), (RX, RY), (RX + DW, RY), (RX + DW, RY - DH), (RX + DW, RY + DH))
L5 = ((LX + DW, LY - DH), (LX, LY - DH), (LX, LY), (LX + DW, LY), (LX + DW, LY + DH), (LX, LY + DH))
R5 = ((RX + DW, RY - DH), (RX, RY - DH), (RX, RY), (RX + DW, RY), (RX + DW, RY + DH), (RX, RY + DH))
L6 = ((LX + DW, LY - DH), (LX, LY - DH), (LX, LY + DH), (LX + DW, LY + DH), (LX + DW, LY), (LX, LY))
R6 = ((RX + DW, RY - DH), (RX, RY - DH), (RX, RY + DH), (RX + DW, RY + DH), (RX + DW, RY), (RX, RY))
L7 = ((LX, LY - DH), (LX + DW, LY - DH), (LX + DW, LY + DH))
R7 = ((RX, RY - DH), (RX + DW, RY - DH), (RX + DW, RY + DH))
L8 = ((LX, LY), (LX, LY + DH), (LX + DW, LY + DH), (LX + DW, LY - DH), (LX, LY - DH), (LX, LY), (LX + DW, LY))
R8 = ((RX, RY), (RX, RY + DH), (RX + DW, RY + DH), (RX + DW, RY - DH), (RX, RY - DH), (RX, RY), (RX + DW, LY))
L9 = ((LX, LY + DH), (LX + DW, LY + DH), (LX + DW, LY - DH), (LX, LY - DH), (LX, LY), (LX + DW, LY))
R9 = ((RX, RY + DH), (RX + DW, RY + DH), (RX + DW, RY - DH), (RX, RY - DH), (RX, RY), (RX + DW, RY))

# List of digit polylines for each side
LEFT_DIGITS = (L0, L1, L2, L3, L4, L5, L6, L7, L8, L9)
RIGHT_DIGITS = (R0, R1, R2, R3, R4, R5, R6, R7, R8, R9)

#================================================================================
# bounce ball off paddle
def reverse_ball_x_speed():
    dx_per_frame = ball_vel[0] / FRAMES_PER_SEC

# move the ball back
    ball_pos[0] = ball_pos[0] - dx_per_frame

# reverse the velocity
    ball_vel[0] = -ball_vel[0]

# increase the velocity by 10%
    ball_vel[0] = (ball_vel[0] * 110) / 100
    dx_per_frame = ball_vel[0] / FRAMES_PER_SEC

# move the ball in the new direction
    ball_pos[0] = ball_pos[0] + dx_per_frame

#================================================================================
# move ball in x direction
def move_ball_horizontal():
# scale horizontal velocity for 60fps update rate
    dx_per_frame = ball_vel[0] / FRAMES_PER_SEC

# update ball horizontal position with scaled horizontal velocity
    ball_pos[0] = ball_pos[0] + dx_per_frame

#================================================================================
def check_ball_horizontal_hits():
    global scoreL, scoreR

# If ball edge moves off the left-side of the playfield,
    if (ball_pos[0] - BALL_RADIUS) <= PAD_WIDTH:

# if there is a paddle in the way, reverse x speed, else score
        if ball_collides_with_paddle(paddleL_pos) == True:
            reverse_ball_x_speed()

        else:
            scoreR = scoreR + 1

# start a new game to right player
            spawn_ball(RIGHT)

# if the ball edge moves off the right-side of the playfield
    if (ball_pos[0] + BALL_RADIUS) >= (WIDTH - PAD_WIDTH - 1):

# if there is a paddle in the way, reverse x speed, else score
        if ball_collides_with_paddle(paddleR_pos) == True:
            reverse_ball_x_speed()
        else:
            scoreL = scoreL + 1

# start a new game to left player
            spawn_ball(LEFT)

#================================================================================
# move the ball in the y direction
def move_ball_vertical():
# scale vertical velocity for 60fps update rate
    dy_per_frame = ball_vel[1] / FRAMES_PER_SEC

# update the vertical position with the scaled vertical velocity
    ball_pos[1] = ball_pos[1] + dy_per_frame

# If ball edge moves off the playfield,
    if (ball_pos[1] < BALL_RADIUS) or (ball_pos[1] > (HEIGHT - BALL_RADIUS)):

# move it back
        ball_pos[1] = ball_pos[1] - dy_per_frame

# reverse the velocity
        ball_vel[1] = -ball_vel[1]
        dy_per_frame = ball_vel[1] / FRAMES_PER_SEC

# move in the new direction instead
        ball_pos[1] = ball_pos[1] + dy_per_frame

#================================================================================
# adjust paddle y position by paddle speed in y direction
def move_paddle_position(paddle_pos, paddle_vel):
# move paddle centre
    paddle_pos[1] = paddle_pos[1] + paddle_vel[1]

# if moving off screen, reverse
    if paddle_pos[1] < HALF_PAD_HEIGHT:
        paddle_pos[1] = paddle_pos[1] - paddle_vel[1]

    if paddle_pos[1] > (HEIGHT - HALF_PAD_HEIGHT):
        paddle_pos[1] = paddle_pos[1] - paddle_vel[1]

    return paddle_pos

#================================================================================
def ball_collides_with_paddle(paddle_pos):
# if ball centre is lower than paddle centre
    if ball_pos[1] >= paddle_pos[1]:
        dy = ball_pos[1] - paddle_pos[1]

    else:
        dy = paddle_pos[1] - ball_pos[1]

# if ball centre is no more than half pad height away from paddle centre, it is collision
    if dy <= HALF_PAD_HEIGHT:
        collision = True

    else:
        collision = False

    return collision

#================================================================================
def stop_game():
    global game_over

    ball_vel[0] = 0
    ball_vel[1] = 0
    ball_pos[0] = WIDTH / 2
    ball_pos[1] = HEIGHT / 2

    game_over = True

#================================================================================
# initialize ball_pos and ball_vel for new bal in middle of table
# if direction is RIGHT, the ball's velocity is upper right, else upper left
def spawn_ball(direction):
    global ball_pos, ball_vel # these are vectors stored as lists

# pick a random position on midline from center half of playfield width
    ball_y = random.randrange(HEIGHT / 4, HEIGHT * 3 / 4)

# set start position on midline horizontally
    ball_pos = [WIDTH / 2, ball_y]

# set the horizontal speedvector in the range 120-240 pixels/second to start with
    x_per_sec = random.randrange(BALL_MIN_X_SPEED, BALL_MAX_X_SPEED + 1)
    if direction == LEFT:
        x_per_sec = -x_per_sec

# set the vertical speedvector in the range 60-180 pixels/second to start with
    y_per_sec = random.randrange(BALL_MIN_Y_SPEED, BALL_MAX_Y_SPEED + 1)

# y_per_sec negative value to start upward
    ball_vel = [x_per_sec, -y_per_sec]

#================================================================================
# define event handlers
def new_game():
    global paddleL_pos, paddleR_pos, paddleL_vel, paddleR_vel  # these are numbers
    global scoreL, scoreR  # these are ints
    global game_over

    paddleL_pos = [0, HEIGHT / 2]
    paddleL_vel = [0, 0]
    paddleR_pos = [WIDTH - PAD_WIDTH - 1, HEIGHT / 2]
    paddleR_vel = [0, 0]

    scoreL = 0
    scoreR = 0

    game_over = False

# pick a random direction for the first spawm (rest spawn towards winner)
    if random.randrange(0, 10) < 5:
        spawn_ball(LEFT)
    else:
        spawn_ball(RIGHT)

#================================================================================
def draw(canvas):
    global score_timer
    global paddleL_pos, paddleR_pos

# draw mid line and gutters
    canvas.draw_line([WIDTH / 2, 0],[WIDTH / 2, HEIGHT], 1, "Silver")
    canvas.draw_line([PAD_WIDTH, 0],[PAD_WIDTH, HEIGHT], 1, "Silver")
    canvas.draw_line([WIDTH - PAD_WIDTH - 1, 0],[WIDTH - PAD_WIDTH - 1, HEIGHT], 1, "Silver")

# update ball
    move_ball_vertical()
    move_ball_horizontal()

# draw ball
    canvas.draw_circle(ball_pos, BALL_RADIUS, 1, "White", "White")

# in game, update paddle's vertical position, keep paddle on the screen
    if game_over == False:
        paddleL_pos = move_paddle_position(paddleL_pos, paddleL_vel)
        paddleR_pos = move_paddle_position(paddleR_pos, paddleR_vel)

# draw paddles
    top = paddleL_pos[1] - HALF_PAD_HEIGHT
    bot = paddleL_pos[1] + HALF_PAD_HEIGHT
    left = 1
    right = PAD_WIDTH
    canvas.draw_polygon(([left, top],[right, top],[right, bot], [left, bot], [left, top]), 1, "White", "White")

    top = paddleR_pos[1] - HALF_PAD_HEIGHT
    bot = paddleR_pos[1] + HALF_PAD_HEIGHT
    left = WIDTH - PAD_WIDTH - 1
    right = WIDTH - 1
    canvas.draw_polygon(([left, top],[right, top],[right, bot], [left, bot], [left, top]), 1, "White", "White")

# determine whether paddle and ball collide
    check_ball_horizontal_hits()

# draw scores
# at winning score
    if scoreL == WIN_SCORE:

# make paddle bounce up and down, while flashing winning score. because it looks cool !
        if score_timer < 60:
# in first second counts, calculate Y position going from bottom to top
            paddleY = (60 - score_timer) * (HEIGHT - 1 - PAD_HEIGHT) / 60
        else:
# in second second counts, calculate Y position going from top to bottom
            paddleY = (score_timer - 60) * (HEIGHT - 1 - PAD_HEIGHT) / 60
# flash winning score by showing it every other second
            canvas.draw_polyline(LEFT_DIGITS[scoreL], HALF_PAD_WIDTH, "white")

# put paddle at bouncy position for next draw
        paddleL_pos = [WIDTH - PAD_WIDTH - 1, HALF_PAD_HEIGHT + paddleY]
# and stop playing (until game reset)
        stop_game()

    else:
# not a winning score, just draw the digit
        canvas.draw_polyline(LEFT_DIGITS[scoreL], HALF_PAD_WIDTH, "white")

# if at a winning score ...
    if scoreR == WIN_SCORE:

        if score_timer < 60:
# in first second counts, calculate Y position going from bottom to top
            paddleY = (60 - score_timer) * (HEIGHT - 1 - PAD_HEIGHT) / 60
        else:
# in second second counts, calculate Y position going from top to bottom
            paddleY = (score_timer - 60) * (HEIGHT - 1 - PAD_HEIGHT) / 60
# flash winning score by showing it every other second
            canvas.draw_polyline(RIGHT_DIGITS[scoreR], HALF_PAD_WIDTH, "white")

# put paddle at bouncy position for next draw
        paddleR_pos = [WIDTH - PAD_WIDTH - 1, HALF_PAD_HEIGHT + paddleY]
# and stop playing (until game reset)
        stop_game()

    else:
# not a winning score, just draw the digit
        canvas.draw_polyline(RIGHT_DIGITS[scoreR], HALF_PAD_WIDTH, "white")

# if score_timer is running, update, else reset
    if score_timer > 0:
        score_timer = score_timer - 1
    else:
        score_timer = 120

#================================================================================
def keydown(key):
    if key == simplegui.KEY_MAP["w"]:
        paddleL_vel[1] = -PADDLE_SPEED / 60
    if key == simplegui.KEY_MAP["s"]:
        paddleL_vel[1] = PADDLE_SPEED / 60
    if key == simplegui.KEY_MAP["up"]:
        paddleR_vel[1] = -PADDLE_SPEED / 60
    if key == simplegui.KEY_MAP["down"]:
        paddleR_vel[1] = PADDLE_SPEED / 60

#================================================================================
def keyup(key):
    if key == simplegui.KEY_MAP["w"]:
        paddleL_vel[1] = 0
    if key == simplegui.KEY_MAP["s"]:
        paddleL_vel[1] = 0
    if key == simplegui.KEY_MAP["up"]:
        paddleR_vel[1] = 0
    if key == simplegui.KEY_MAP["down"]:
        paddleR_vel[1] = 0

#================================================================================
# create frame
frame = simplegui.create_frame("Pong", WIDTH, HEIGHT)
frame.set_draw_handler(draw)
frame.set_keydown_handler(keydown)
frame.set_keyup_handler(keyup)
frame.add_button("Reset Game", new_game, 125)

# start frame
new_game()
frame.start()


# -*- coding: utf-8 -*-"""
"""
This module administrates lamp clustering and feature extraction.
"""

import argparse, argcomplete
import sys

from .lamplight import image_info
from .lamplight import get_index_cond, make_clusters_dict, overlapping_clusters, simplify
from .topographical import check_topograph
from .register import commit_register_image_file
from .utility import get_resource

from . import model as mod

def _get_lamps(src_image, radius, size):
    points_dict  = get_index_cond(src_image)
    cluster_dict = make_clusters_dict(points_dict, radius, size)
    for i, raw_lamp in enumerate(overlapping_clusters(cluster_dict)):
        #print("creating lamp : {}".format(i), file=sys.stderr)
        yield simplify(raw_lamp)

@mod.db_session
def make_cluster(radius, size, topograph):
    topograph = mod.re_get(topograph)
    clst = mod.Cluster.get(radius=radius, size=size, topograph=topograph)
    if not clst:
        clst = mod.Cluster(radius=radius, size=size, topograph=topograph)
    return clst

@mod.check_tables(mod.Cluster, 'lamps')
def check_cluster(topograph, radius, size):
    clst = make_cluster(radius, size, topograph)
    _, _, src_image = image_info(get_resource(topograph.dst_image.label))
    for simple_lamp in _get_lamps(src_image, radius, size):
        r, g, b = simple_lamp[0], simple_lamp[1], simple_lamp[2]
        x, y    = simple_lamp['medoid']
        min_x, min_y, max_x, max_y = simple_lamp['min_x'], simple_lamp['min_y'], simple_lamp['max_x'], simple_lamp['max_y']
        lamp    = make_lamp(clst, x, y, r, g, b, min_x, min_y, max_x, max_y)
    return {'radius' : radius, 'size' : size, 'topograph' : topograph}

@mod.db_session
def make_lamp(cluster, medoid_x, medoid_y, red, green, blue, min_x, min_y, max_x, max_y):
    cluster = mod.re_get(cluster)
    lamp = mod.Lamp(
        cluster=cluster,
        medoid_x=medoid_x, medoid_y=medoid_y,
        red=red, green=green, blue=blue,
        min_x=min_x, max_x=max_x, min_y=min_y, max_y=max_y
    )
    return lamp

def interface(filename, step, radius, size):
    src_image = commit_register_image_file(filename)
    topograph = check_topograph(src_image, step)
    for lamp in check_cluster(topograph, radius, size):
        print(lamp.feature_vector)

def cli_interface(arguments):
    """
    by convention it is helpful to have a wrapper_cli method that interfaces
    from commandline to function space.
    """
    filename = arguments.image_filename
    radius   = arguments.radius
    size     = arguments.size
    step     = arguments.step
    interface(filename, step, radius, size)

#####################################
##         PARSERS
#####################################
def generate_parser(parser):
    parser.add_argument('image_filename', type=str,
        help="Image Filename to be clustered")
    parser.add_argument('--radius', type=int, default=30,
        help="Cluster acceptance radius")
    parser.add_argument('--size', type=int, default=20,
        help="Cluster minimum size")
    parser.add_argument('--step', type=int, default=10)
    parser.set_defaults(func=cli_interface)
    return parser


class Tree:
    """
    Class to print nested dictionary
    as a tree (similar to unix command).
    """

    def __init__(self):
        self.keyCount = 0
        self.listCount = 0
        self.outstr = ''

    def register(self, dc):
        """
        Method to keep track of the number of (subkeys)
        and number of lists in the structure.
        :param dc: dictionary or list
        :type dc: dictionary or list
        :return:
        """
        if isinstance(dc, dict):
            self.keyCount += 1
        elif isinstance(dc, list):
            self.listCount += 1

    def summary(self) -> str:
        """
        Print dictionary summary.
        :return: print summary of data
        """
        return str(self.keyCount) + " keys, " + str(self.listCount) + " lists"

    def walk(self, dc, prefix=""):
        """
        Method to walk through the
        data structure and build
        tree representation as a string
        which is stored in outstr.
        :param dc: data structure to print
        :param prefix: initial prefix
        :return: updates self.outstr
        """
        # finance data
        # is either dict or list of dicts
        # to print the structure we only
        # need the keys of one of the elements
        # in case data is a list
        if isinstance(dc, list):
            if isinstance(dc[0], dict):
                dc = dc[0]

        for i in range(len(dc)):
            k = list(dc.keys())[i]
            v = dc[k]
            self.register(v)

            if i == len(dc) - 1:
                self.outstr += f'{prefix}└─── {k} ({type(v)})\n'
                if isinstance(v, dict):
                    self.walk(v, prefix + "    ")
                elif isinstance(v, list):
                    self.walk(v, prefix + "    ")
            else:
                self.outstr += f'{prefix}├─── {k} ({type(v)})\n'
                if isinstance(v, dict):
                    self.walk(v, prefix + "|   ")
                elif isinstance(v, list):
                    if isinstance(v[0], dict):
                        self.walk(v[0], prefix + "|   ")


import math
import os
import re

import docx
from docxcompose.composer import Composer

from src.logic.pathes import main_path, out_path

from .paragraph_replace_text import paragraph_replace_text

ALL_DOCUMENTS = {
    "BaseEquipment": os.path.join(main_path, "templates", "template_equipment.docx"),
}

def find_and_replace(document: docx.Document, parameters: dict) -> docx.Document:
    for table in document.tables:
        tmpStyle = table.style
        for rows in table.rows:
            for cell in rows.cells:
                for paragraph in cell.paragraphs:
                    for search, r in parameters.items():
                        paragraph_replace_text(paragraph, re.compile(search), r)
        table.style = tmpStyle
    return document

def compose_single_equipment(parameters: dict):
    doc = docx.Document(ALL_DOCUMENTS["BaseEquipment"])
    find_and_replace(doc, parameters)

    checkRow = ["test_date", "remark", "testVision", "testFunction", "tester"]
    parameterChecks: dict = {}
    if len(parameters["checks"]) <= 9:
        find_and_replace(doc, {"pagenumber": "1"})
        for iterChecks in range(1, 10):
            for check, iter in zip(checkRow, range(5)):
                try:
                    parameterChecks[check + str(iterChecks)] = parameters["checks"][iterChecks - 1][iter]
                except IndexError:
                    parameterChecks[check + str(iterChecks)] = ""
        find_and_replace(doc, parameterChecks)
        composed_master = Composer(doc)
    else:
        find_and_replace(doc, {"pagenumber": str(1)})
        for iterChecks in range(1, 10):
            for check, iter in zip(checkRow, range(5)):
                try:
                    parameterChecks[check + str(iterChecks)] = parameters[
                        "checks"
                    ][0 * 9 + (iterChecks - 1)][iter]

                except IndexError:
                    parameterChecks[check + str(iterChecks)] = ""
        find_and_replace(doc, parameterChecks)
        composed_master = Composer(doc)

        for iterPages in range(2, math.ceil(len(parameters["checks"]) / 9) + 1):
            doc = docx.Document(ALL_DOCUMENTS["BaseEquipment"])
            find_and_replace(doc, parameters)
            find_and_replace(doc, {"pagenumber": str(iterPages)})
            parameterChecks: dict = {}
            for iterChecks in range(1, 10):
                for check, iter in zip(checkRow, range(5)):
                    try:
                        parameterChecks[check + str(iterChecks)] = parameters["checks"][
                            ((iterPages - 1) * 9) + (iterChecks - 1)
                        ][iter]
                    except IndexError:
                        parameterChecks[check + str(iterChecks)] = ""
            find_and_replace(doc, parameterChecks)
            composed_master.append(doc)

    composed_master.save(out_path)
    return composed_master

def compose_multiple_equipment(parametersList: list):
    first = True
    master = None
    for parameters in parametersList:
        if first:
            master = compose_single_equipment(parameters)
            first = False
        else:
            master.append(compose_single_equipment(parameters).doc)
    master.save(out_path)


from typing import List

def minimumOperations(nums: List[int]) -> int:
    cont = 0

    while sum(nums) != 0:
        print(nums)
        min_number = min(elem for elem in nums if elem != 0)
        nums = list(map(lambda x: x - min_number if x != 0 else 0, nums))

        cont += 1

    return cont

if __name__ == "__main__":
    print(minimumOperations([0]))


from os import getenv
from dotenv import load_dotenv, find_dotenv

if not find_dotenv():
    exit('Переменные окружения не загружены т.к отсутствует файл .env')
else:
    load_dotenv()

API_HOST = "hotels4.p.rapidapi.com"
BOT_TOKEN = getenv('BOT_TOKEN')
RAPID_API_KEY = getenv('RAPID_API_KEY')
DEFAULT_COMMANDS = (
    ('start', "Запустить бота"),
    ('help', "Вывести справку"),
    ("lowprice", "Поиск отелей с меньшей ценой"),
    ("highprice", "Поиск отелей с более высокой ценой"),
    ("bestdeal", "Бест деал по отелям"),
    ("history", "Вывод комманд и отелей которые были найдены"),
    ("cancel", "Отмена команды.")
)


# day25

def find_loop_size(n):
    val  = 1
    loop = 0
    while val != n:
        val *= 7
        val %= 20201227
        loop += 1

    return loop

def transform_value(subj_num, loop_size):
    val = 1
    for i in range(loop_size):
        val *= subj_num
        val %= 20201227

    return val

door_pub_key = 11562782
card_pub_key = 18108497

# get loop sizes for each
door_loop_size = find_loop_size(door_pub_key)
card_loop_size = find_loop_size(card_pub_key)

# get encryption key
encr_key = transform_value(door_pub_key, card_loop_size)

print(encr_key)


#Ler 3 valores (A, B e C) representando as medidas dos lados de um triângulo e escrever se formam
#ou não um triângulo. OBS: para formar um triângulo, o valor de cada lado deve ser menor que a soma
#dos outros 2 lados.

A = int(input('Digite o valor do lado A do triângulo: '))
B = int(input('Digite o valor do lado B do triângulo: '))
C = int(input('Digite o valor do lado C do triângulo: '))

if A < B + C and B < A + C and C < B + A:
    print('Os lados formam um triângulo')
else:
    print('Os lados não formam um triângulo')


import os

from tensorflow.dtensor.python import config as d_config
from tensorflow.dtensor.python import mesh_util
from tensorflow.python.distribute import distribute_lib
from tensorflow.python.distribute import multi_worker_util
from tensorflow.python.distribute.cluster_resolver import tfconfig_cluster_resolver
from tensorflow.python.distribute.experimental import dtensor_strategy_extended
from tensorflow.python.distribute.experimental import dtensor_util

class MultiWorkerMirroredStrategy(distribute_lib.Strategy):
  """A distribution strategy for synchronous training on multiple workers.

  This strategy implements synchronous distributed training across multiple
  workers, each with potentially multiple GPUs. Similar to
  `tf.distribute.MirroredStrategy`, it replicates all variables and computations
  to each local device. The difference is that it uses a distributed collective
  implementation (e.g. all-reduce), so that multiple workers can work together.
  """

  def __init__(self, cluster_resolver=None, communication_options=None, *,
               mesh=None):
    """Creates the strategy.

    Args:
      cluster_resolver: optional
        `tf.distribute.cluster_resolver.ClusterResolver`. In case neither `mesh`
        nor `cluster_resolver` are provided,
        `tf.distribute.cluster_resolver.TFConfigClusterResolver` is used.
      communication_options: currently ignore.
      mesh: optional Dtensor global mesh for the computation. Note that either
        `mesh` or the `cluster_resolver` should be provided. and not both.
    """
    self._validate_init_args(mesh, cluster_resolver)
    if not mesh:
      if not cluster_resolver:
        # Use the TFConfigClusterResolver as default
        cluster_resolver = tfconfig_cluster_resolver.TFConfigClusterResolver()
      dtensor_env_var = _parse_dtensor_env_var_from_cluster_resolver(
          cluster_resolver)
      _config_dtensor_env_var(dtensor_env_var)
      mesh = _build_distributed_mesh(dtensor_util.DEFAULT_BATCH_MESH_DIM_NAME)
    extended = dtensor_strategy_extended.DTensorStrategyExtended(
        container_strategy=self, mesh=mesh)
    super().__init__(extended)
    self._mesh = mesh
    self._cluster_resolver = cluster_resolver

  @classmethod
  def _validate_init_args(cls, mesh, cluster_resolver):
    if mesh and cluster_resolver:
      raise ValueError('Mesh and cluster_resolver can not be provided at the '
                       f'same time. Received mesh = {mesh}, cluster_resolver = '
                       f'{cluster_resolver}')
    if mesh and len(mesh.shape()) != 1:
      raise ValueError('The mesh for MultiWorkerMirroredStrategy must be 1D, '
                       f'received: {len(mesh.shape())}D')

  def reduce(self, reduce_op, value, axis):
    return dtensor_util.dtensor_reduce(self, reduce_op, value, axis)

  @property
  def mesh(self):
    """Returns the mesh used by the strategy."""
    return self._mesh

def _parse_dtensor_env_var_from_cluster_resolver(cluster_resolver):
  """Parse the env vars for Dtensor based on the cluster resolver.

  In the multi-client setting, each of the DTensor jobs need to aware of each
  other, and the interface to setup those values are via the envvars. The
  value used by dtensor are different from the existing
  `MultiWorkerMirroredStrategy`. This function will parse the value from
  cluster resolver, and populate the corresponding value for DTensor jobs in the
  `os.environ`.

  Args:
    cluster_resolver: A `tf.distribute.cluster_resolver.ClusterResolver`
      instance.

  Returns:
    A dict of {Str:Str} which contains all the env vars needed by DTensor jobs.
    The value is for verification purpose.

  Raises:
    The value parsed from existing cluster spec is not valid.
  """
  result = {}

  # Retrieve the number of host, cluster config from the resolver.
  cluster_spec = multi_worker_util.normalize_cluster_spec(
      cluster_resolver.cluster_spec())
  # Export all the necessary envvars for dtensor
  # Get all the jobs from the cluster spec. Note that the in the normal
  # setting, it could be multiple worker devices without chief, and the
  # worker 0 will be the chief, or an explicit chief with multiple worker job.
  dtensor_jobs = []
  if 'chief' in cluster_spec.jobs:
    dtensor_jobs.extend(cluster_spec.job_tasks('chief'))
  if 'worker' in cluster_spec.jobs:
    dtensor_jobs.extend(cluster_spec.job_tasks('worker'))

  if None in dtensor_jobs:
    raise ValueError('Unexpected dtensor job address from cluster spec: '
                     f'{cluster_spec}')
  result['DTENSOR_JOBS'] = ','.join(dtensor_jobs)
  result['DTENSOR_NUM_CLIENTS'] = str(len(dtensor_jobs))

  if cluster_resolver.task_type == 'chief':
    dtensor_client_id = 0
  elif cluster_resolver.task_type == 'worker':
    dtensor_client_id = cluster_resolver.task_id
    if 'chief' in cluster_spec.jobs:
      dtensor_client_id += 1
  result['DTENSOR_CLIENT_ID'] = str(dtensor_client_id)
  result['DTENSOR_JOB_NAME'] = 'worker'

  return result

def _config_dtensor_env_var(dtensor_env_vars):
  for k, v in dtensor_env_vars.items():
    os.environ[k] = v

def _build_distributed_mesh(batch_dim_name):
  device_type = d_config.preferred_device_type()
  local_devices = d_config.local_devices(device_type)
  number_clients = d_config.num_clients()
  dtensor_util.initialize_accelerator_system_once(device_type)
  # This assumes each client has same number of devices.
  mesh_dims = [(batch_dim_name, len(local_devices) * number_clients)]
  return mesh_util.create_distributed_mesh(
      mesh_dims, device_type=device_type)


from pathlib import Path
import pandas as pd
from prefect import flow, task
from prefect_gcp.cloud_storage import GcsBucket
from prefect_gcp import GcpCredentials

@task(retries=3)
def extract_from_gcs(color: str, year: int, month: int) -> Path:
    """Download trip data from GCS"""
    gcs_path = f"data/{color}/{color}_tripdata_{year}-{month:02}.parquet"
    gcs_block = GcsBucket.load("dezoomcamp")
    gcs_block.get_directory(from_path=gcs_path, local_path=f"./")
    return Path(f"{gcs_path}")

@task()
def read(path: Path) -> pd.DataFrame:
    """read the data into pandas"""
    df = pd.read_parquet(path)
    return df

@task()
def write_bq(df: pd.DataFrame) -> int:
    """Write DataFrame to BiqQuery"""

    gcp_credentials_block = GcpCredentials.load("dezoomcamp-gcp-creds")

    df.to_gbq(
        destination_table="trips_data_all.rides",
        project_id="smart-grin-376216",
        credentials=gcp_credentials_block.get_credentials_from_service_account(),
        chunksize=500_000,
        if_exists="append",
    )
    return len(df)

@flow()
def el_gcs_to_bq(year: int, month: int, color: str) -> None:
    """Main ETL flow to load data into Big Query"""

    path = extract_from_gcs(color, year, month)
    df = read(path)
    row_count = write_bq(df)
    return row_count

@flow(log_prints=True)
def el_parent_gcs_to_bq(
    months: list[int] = [1, 2], year: int = 2021, color: str = "yellow"
):
    """Main EL flow to load data into Big Query"""
    total_rows = 0

    for month in months:
        rows = el_gcs_to_bq(year, month, color)
        total_rows += rows

    print(total_rows)

if __name__ == "__main__":
    el_parent_gcs_to_bq(months=[2, 3], year=2019, color="yellow")


"""
[ref]: https://github.com/dsgiitr/d2l-pytorch/blob/master/d2l/data/fashion_mnist.py

* Download Fashion-MNIST dataset
* Get labels
* Show the dataset
"""
import sys
sys.path.insert(0, '..')
import os
import os.path as osp
import logging

import coloredlogs
import torchvision
from torchvision import transforms
from torch.utils.data import DataLoader

from ..utils.figure import test, plt

coloredlogs.install(level="INFO", fmt="%(asctime)s %(filename)s %(levelname)s %(message)s")

def load_data_fashion_mnist(batch_size=1, resize=None, root=osp.join(osp.dirname(__file__), 'datasets','fashion_mnist')):
    """
    DownLoad the Fashion-MNIST dataset and then load into memory.
    """
    root = os.path.expanduser(root)  # convert to absolute path
    logging.info("the ROOT path of Fashion-MNIST: {}".format(root))

    transformer = []

    if resize:
        transformer += [transforms.Resize(resize)]
    transformer += [transforms.ToTensor()]
    transformer = transforms.Compose(transformer)

    mnist_train = torchvision.datasets.FashionMNIST(root=root, train=True, transform=transformer, download=True)
    mnist_test = torchvision.datasets.FashionMNIST(root=root, train=False, transform=transformer, download=True)

    num_workers = 0 if sys.platform.startswith('win32') else 4

    train_iter = DataLoader(mnist_train, batch_size, shuffle=True, num_workers=num_workers)
    test_iter = DataLoader(mnist_test, batch_size, shuffle=False, num_workers=num_workers)

    return train_iter, test_iter

def get_fashion_mnist_labels(labels):
    """
    Get text labels for Fashion-MNIST.
    """
    text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',
                   'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']

    return [text_labels[int(i)] for i in labels]

def show_fashion_mnist(images,labels):
    """
    Plot Fashion-MNIST images with labels.
    """

    _, figs = plt.subplots(1, len(images), figsize=(12, 12))

    for f, img, lbl in zip(figs, images, labels):
        f.imshow(img.reshape((28, 28)).numpy())
        f.set_title(lbl)
        f.axes.get_xaxis().set_visible(False)
        f.axes.get_yaxis().set_visible(False)

    plt.show()


# -*- coding: utf-8 -*-
"""
Created on Fri Sep 07 17:48:41 2018

@author: ScanningLabAnalysis
"""

# -*- coding: utf-8 -*-
"""
Created on Thu Jun 07 15:46:51 2018

@author: rustyn
"""

import tifffile
import os
import numpy as np
#import skimage.filters as filt

def genBkgdImg(bkgdImage):

    with tifffile.TiffFile(bkgdImage) as tif:
        bkgd = tif.asarray().astype('float')
        # Convert to float for division and scale
        bkgd = (bkgd - np.amin(bkgd))/(np.amax(bkgd) - np.amin(bkgd))

    return bkgd

def stackToOPTPlanes(inputFile, outputFolder, doBackground = False, bkgdDict = {}, includeDownsample = False):

    with tifffile.TiffFile(inputFile) as tif:
        for k in range(len(tif.pages)):
            saveName = 'imgRot_' + format(int(k), '04d') + '.tif'

            img = tif.pages[k].asarray()

            if doBackground:

                if str.find(inputFile, 'fluor'):
                    bkgd = bkgdDict['fluor']
                else:
                    bkgd = bkgdDict['trans']

                startType = img.dtype
                # Assuming always an integer datatype
                maxForType = np.iinfo(startType).max

                # Frame flattening

                subImg = img - bkgd.T
                img = (maxForType*((subImg - np.amin(subImg))/(np.amax(subImg) - np.amin(subImg)))).astype(startType)

            imgToSave = img[:, range(0, img.shape[1], 4)]
            imgToSave = imgToSave[range(0, img.shape[0], 4), :]

            if not os.path.isdir(os.path.split(outputFolder)[0]):
                os.mkdir(os.path.split(outputFolder)[0])

            if not os.path.isdir(outputFolder):
                os.mkdir(outputFolder)

            if not os.path.isdir(os.path.join(outputFolder, 'native')):
                os.mkdir(os.path.join(outputFolder, 'native'))

            if not os.path.isdir(os.path.join(outputFolder, 'native', 'recon')):
                os.mkdir(os.path.join(outputFolder, 'native', 'recon'))

            tifffile.imsave(os.path.join(outputFolder, 'native', saveName), img.T)

            if includeDownsample:
                if not os.path.isdir(os.path.join(outputFolder, 'downsample')):
                    os.mkdir(os.path.join(outputFolder, 'downsample'))

                if not os.path.isdir(os.path.join(outputFolder, 'downsample', 'recon')):
                    os.mkdir(os.path.join(outputFolder, 'downsample', 'recon'))

                tifffile.imsave(os.path.join(outputFolder, 'downsample', saveName), imgToSave.T)

    return True

def copyDummyReconFile(dummyReconLogFile, outputFolder):

    if not dummyReconLogFile in os.listdir(os.path.join(outputFolder, 'native')):
        os.system('copy ' + dummyReconLogFile + ' ' +  os.path.join(outputFolder, 'native', 'imgRot_.log'))

    return True

def genBkgdFigDict(bkgdFileDict):

    bkgdDict = {'trans': genBackgroundFig(bkgdFileDict['trans'], 3),
                'fluor': genBackgroundFig(bkgdFileDict['fluor'], 3)}

    return bkgdDict

def genBackgroundFig(backgroundImage, blurSigma):

    bkgd = tifffile.TiffFile(backgroundImage).asarray().astype(float)

    subImg = filt.gaussian(bkgd.T, sigma = 8)

    return subImg

def parseInputFolder(inputFolder):

    wk = os.walk(inputFolder)
    dirList = next(wk)[1]

    fileList = []

    for k in range(len(dirList)):

        num = str.split(dirList[k], '.')[0]

        if num[0:5].isdigit():

            detailList = []
            detailList.append(dirList[k])

            # String is numbers only in first 6 characters
            # Taken as mouse ID number and assumed to be valid

            detailList.append(num[0:6]) # Add mouse ID to folder constructor list

            if num.endswith('fluor'):
                # is fluorescent channel

                detailList.append('fluor')

            else:
                # is transmission channel

                detailList.append('trans')

            detailList.append('MMStack_Pos-1.ome.tif')  # Append default filename to list

        else:
            continue

        fileList.append(detailList)

    return fileList

def main():

    inputFolder = r'F:\dyiOPT\20191014'
    outputFolder = r'D:\Data\diyOPT\20191014'

    alignmentOnly = False

    dummyReconLogFile = r'C:\Users\ScanningLabAnalysis\Documents\Python\diyOPT\imgRot_.log'

    doBackgroundSub = False
    bkgdImages = {'trans': r'G:\diyOPT\20181113\bfFlat\MMStack_Pos0.ome.tif',
                  'fluor': r'G:\diyOPT\20181113\fluorflat\MMStack_Pos0.ome.tif'}

    if doBackgroundSub:
        bkgdDict = genBkgdFigDict(bkgdImages)
    else:
        bkgdDict = {}

    fileList = parseInputFolder(inputFolder)

    for f in fileList:

        inputFile = os.path.join(inputFolder, f[0], f[-1])
        outPath = os.path.join(outputFolder, f[1], f[2])

        if os.path.isfile(inputFile):

            out1 = stackToOPTPlanes(inputFile, outPath, doBackground = doBackgroundSub, bkgdDict = bkgdDict)

            if out1 and not alignmentOnly:

                out2 = copyDummyReconFile(dummyReconLogFile, outPath)

                if out2:

                    print('Successfully deplaned ' + inputFile)

            else:
                print("Exited stack deleaving for input " + inputFile)

        else:
            print('Path ' + os.path.join(inputFolder, f[0]) + ' does not contain valid stack file.')

if __name__ == "__main__":
    main()


import numpy as np
from gym.envs.mujoco import mujoco_env
from gym import utils

DEFAULT_CAMERA_CONFIG = {}

class SwimmerEnv(mujoco_env.MujocoEnv, utils.EzPickle):
    def __init__(self,
                 xml_file='swimmer.xml',
                 forward_reward_weight=1.0,
                 ctrl_cost_weight=1e-4,
                 reset_noise_scale=0.1,
                 exclude_current_positions_from_observation=True):
        utils.EzPickle.__init__(**locals())

        self._forward_reward_weight = forward_reward_weight
        self._ctrl_cost_weight = ctrl_cost_weight

        self._reset_noise_scale = reset_noise_scale

        self._exclude_current_positions_from_observation = (
            exclude_current_positions_from_observation)

        mujoco_env.MujocoEnv.__init__(self, xml_file, 4)

    def control_cost(self, action):
        control_cost = self._ctrl_cost_weight * np.sum(np.square(action))
        return control_cost

    def step(self, action):
        xy_position_before = self.sim.data.qpos[0:2].copy()
        self.do_simulation(action, self.frame_skip)
        xy_position_after = self.sim.data.qpos[0:2].copy()

        xy_velocity = (xy_position_after - xy_position_before) / self.dt
        x_velocity, y_velocity = xy_velocity

        forward_reward = self._forward_reward_weight * x_velocity

        ctrl_cost = self.control_cost(action)

        observation = self._get_obs()
        reward = forward_reward - ctrl_cost
        done = False
        info = {
            'reward_fwd': forward_reward,
            'reward_ctrl': -ctrl_cost,

            'x_position': xy_position_after[0],
            'y_position': xy_position_after[1],
            'distance_from_origin': np.linalg.norm(xy_position_after, ord=2),

            'x_velocity': x_velocity,
            'y_velocity': y_velocity,
            'forward_reward': forward_reward,
        }

        return observation, reward, done, info

    def _get_obs(self):
        position = self.sim.data.qpos.flat.copy()
        velocity = self.sim.data.qvel.flat.copy()

        if self._exclude_current_positions_from_observation:
            position = position[2:]

        observation = np.concatenate([position, velocity]).ravel()
        return observation

    def reset_model(self):
        noise_low = -self._reset_noise_scale
        noise_high = self._reset_noise_scale

        qpos = self.init_qpos + self.np_random.uniform(
            low=noise_low, high=noise_high, size=self.model.nq)
        qvel = self.init_qvel + self.np_random.uniform(
            low=noise_low, high=noise_high, size=self.model.nv)

        self.set_state(qpos, qvel)

        observation = self._get_obs()
        return observation

    def viewer_setup(self):
        for key, value in DEFAULT_CAMERA_CONFIG.items():
            if isinstance(value, np.ndarray):
                getattr(self.viewer.cam, key)[:] = value
            else:
                setattr(self.viewer.cam, key, value)


from itertools import combinations
import copy

def dfs(x, y):
    # 바이러스 걸린 구역일 때만 상하좌우 보기
    for i in range(4):
        nx = x + dx[i]
        ny = y + dy[i]
        # 범위 넘어가면 넘어감
        if nx < 0 or ny < 0 or nx >= n or ny >= m:
            continue
        # 벽 말고 빈공간일때만 전파
        if temp_graph[nx][ny] == 0:
            temp_graph[nx][ny] = 2
            dfs(nx, ny)
    return

n, m = map(int, input().split())
graph = []

wall = 0
list_empty = []
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
for i in range(n):
    graph.append(list(map(int, input().split())))

for i in range(n):
    for j in range(m):
        if graph[i][j] == 0:
            list_empty.append((i, j))

# 빈 공간에 벽을 세울 수 있는 경우의 수 전부
list_wall_combi = list(combinations(list_empty, 3))
safe = 0

for i in list_wall_combi:
    # deepcopy 안쓰면 graph의 값이 계속 바뀐다
    temp_graph = copy.deepcopy(graph)
    for j in i:
        # 벽 세움
        temp_graph[j[0]][j[1]] = 1
    for j in range(n):
        for k in range(m):
            if temp_graph[j][k] == 2:
                # 바이러스 있는 위치에서 dfs 돌림
                dfs(j, k)
    tmp_safe = 0
    for i in temp_graph:
        for j in i:
            if j == 0:
                tmp_safe += 1
    if safe < tmp_safe:
        safe = tmp_safe
print(safe)

# from collections import deque
# import copy
#
# N, M = map(int, input().split())
# lab = [list(map(int, input().split())) for _ in range(N)]
#
# dy = [-1, 1, 0, 0]
# dx = [0, 0, 1, -1]
#
# safezone = 0
#
# def spread_virus():
#     global safezone
#     lab_ = copy.deepcopy(lab)
#
#     queue = deque()
#     for i in range(N):
#         for j in range(M):
#             if lab_[i][j] == 2:
#                 queue.append((i, j))
#
#     while queue:
#         y, x = queue.popleft()
#         for i in range(4):
#             ny, nx = y+dy[i], x+dx[i]
#             if 0 <= ny < N and 0 <= nx < M:
#                 if lab_[ny][nx] == 0:
#                     lab_[ny][nx] = 2
#                     queue.append((ny, nx))
#
#     safezone = max(safezone, sum(l.count(0) for l in lab_))
#
#
# def build_wall(wall):
#     if wall == 3:
#         spread_virus()
#         return
#
#     for i in range(N):
#         for j in range(M):
#             if lab[i][j] == 0:
#                 lab[i][j] = 1
#                 build_wall(wall+1)
#                 lab[i][j] = 0
#
# build_wall(0)
# print(safezone)