import json
from django.forms import FloatField, IntegerField
from django.http import HttpRequest, JsonResponse
from django.shortcuts import render, redirect, get_object_or_404
from django.views.generic.base import View
from django.contrib.auth.mixins import LoginRequiredMixin
from django.db.models import F
from django.db.models import IntegerField
from django.db.models.functions import Cast
from datetime import datetime

from config.models import Product, CartProduct, Cart, Member
from product.views.product_views import doesCartExist

class CartView(LoginRequiredMixin, View):
    '''
    장바구니
    '''

    def get(self, request: HttpRequest, *args, **kwargs):
        context={}
        products=[]
        main_imgs=[]
        total_price=0

        if(doesCartExist is False):
            return render(request, 'cart.html',  context)

        cart=list(Cart.objects.filter(member__user_id=request.user.id).values_list('id', flat=True))[0]
        products_in_cart=list(CartProduct.objects.filter(cart=cart, deleteflag='0').order_by('-updated_at').values_list('product', flat=True))

        for p in products_in_cart:
            products.extend(CartProduct.objects.filter(product=p, cart=cart, deleteflag='0').order_by('-updated_at').values('product__main_img', 'product__name', \
                'product__price', 'amount', 'product__id', 'cart__id').annotate(total=Cast(F('amount') * F('product__price'), IntegerField())))
            main_imgs.append(Product.objects.get(id=p))

        for p in products:
            total_price=total_price+p.get('total')

        #context['products']=zip(products, main_imgs)
        context['main_imgs']=main_imgs
        context['products']=products
        context['total_price']=total_price
        context['memname'] = list(Member.objects.filter(user_id=request.user.id).values_list('mem_name', flat=True))[0]
        context['cart'] = CartProduct.objects.filter(cart__member__user=request.user, deleteflag='0').count()

        return render(request, 'cart.html',  context)

    def delete(self, request: HttpRequest, *args, **kwargs):
        context={}
        request.DELETE = json.loads(request.body)

        product_id = request.DELETE.get('product_id')
        cart_id = request.GET.get('cart_id')

        CartProduct.objects.filter(cart=cart_id, product=product_id).update(
            amount=0,
            deleteflag='1',
            deleted_at=datetime.now(),
        )
        context['success']=True

        return JsonResponse(context, content_type='application/json')

    def put(self, request: HttpRequest, *args, **kwargs):
        context={}
        request.PUT = json.loads(request.body)

        cart_id=list(Cart.objects.filter(member__user_id=request.user.id).values_list('id', flat=True))[0]
        product_id = request.PUT.get('product_id')
        amount = request.PUT.get('amount')

        CartProduct.objects.filter(cart=cart_id, product=product_id).update(
            amount=amount,
        )
        context['success']=True

        return JsonResponse(context, content_type='application/json')


import httpx
import json
import os
import hmac
import hashlib
import sys

from dotenv import load_dotenv

load_dotenv(".env")

###
# Let's define the question right here
###
CHATBOT_QUESTION = "What is Stargate? Can you give 5 key benefits?"
intercom_secret = os.getenv("INTERCOM_CLIENT_SECRET")

# Build the appropriate headers
def get_headers(body):
    """Helper to get necessary request headers for successful POST"""
    digest = hmac.new(
        intercom_secret.encode("utf-8"),
        msg=json.dumps(body).encode("utf-8"),
        digestmod=hashlib.sha1,
    ).hexdigest()

    return {"X-Hub-Signature": f"sha1={digest}"}

# Load the test request
user_data_file = "tests/test_request.json"
user_data = ""
with open(user_data_file, "r") as f:
    user_data = json.load(f)

def call_assistant_async(chatbot_question=CHATBOT_QUESTION):
    # Set the request appropriately
    user_data["data"]["item"]["conversation_parts"]["conversation_parts"][0][
        "body"
    ] = chatbot_question
    user_data["data"]["item"]["source"]["body"] = chatbot_question

    headers = get_headers(user_data)

    full_result = ""
    with httpx.stream(
        "POST",
        "http://127.0.0.1:5555/chat",
        json=user_data,
        headers=headers,
        timeout=600,
    ) as r:
        for chunk in r.iter_text():
            print(chunk, flush=True, end="")
            full_result += chunk

    return full_result

def call_assistant_sync(chatbot_question=CHATBOT_QUESTION):
    # Set the request appropriately
    user_data["data"]["item"]["conversation_parts"]["conversation_parts"][0][
        "body"
    ] = chatbot_question
    user_data["data"]["item"]["source"]["body"] = chatbot_question

    headers = get_headers(user_data)

    r = httpx.post("http://127.0.0.1:5555/chat", json=user_data, headers=headers)

    # Check if the request was successful
    if r.status_code == httpx.codes.created:
        return r.content.decode()
    else:
        return f"Request failed with status code {r.status_code}: {r.text}"

if __name__ == "__main__":
    call_assistant_async(chatbot_question=sys.argv[1])

    # Alternatively
    # example_result = call_assistant_sync()
    # print(example_result)


import logging
logger = logging.getLogger("ABG_main")
logger.setLevel(logging.INFO)
logHandler = logging.StreamHandler()
logHandler.setFormatter(logging.Formatter(logging.BASIC_FORMAT, None))
logger.addHandler(logHandler)

from frontend.ParseV import *
from frontend.ParseCSV import *
from transform.ModuleGraphToDataflowGraph import *
from transform.GridGraphToSlotGraph import *
from floorplan.AbgESolver import AbgESolver
from transform.DataflowGraphToLatencyGraph import *
from pipeline.LatRebSolver import LatRebSolver
from backend.LatencyGraphToBufferSpec import *
from backend.AbgVMapToTcl import *
from backend.DistributeLatencyToGrid import *

import numpy as np

from collections import defaultdict

import yaml

import os
def execAndEcho(cmd):
    logger.info(f"[os.system] {cmd}")
    os.system(cmd)

logger.info("[Op Phase] Generate build file system.")
output_dirs = [
    "build/",
    "build/csv/",
    "build/tcl/",
    "build/verilog/",
    "build/yaml/",
]
for dir in output_dirs:
    try:
        os.makedirs(dir)
    except FileExistsError:
        pass

logger.info("[Op Phase] Parse assets.")
path_hlsproj          = "assets/kernel3_u250"
path_prefloorplan_tcl = "assets/floorplan/U250.tcl"
path_prefloorplan_csv = "assets/floorplan/U250.csv"
logger.info(f"[Param] path_hlsproj={path_hlsproj}")
logger.info(f"[Param] path_prefloorplan_tcl={path_prefloorplan_tcl}")
logger.info(f"[Param] path_prefloorplan_csv={path_prefloorplan_csv}")
vhandle, mg = parseTopV(path_hlsproj)
gg = parseGridCSV(path_prefloorplan_csv)

logger.info("[Op Phase] Construct AbgE problem.")
dg = moduleGraphToDataflowGraph(mg)
sg = gridGraphToSlotGraph(gg)
abgESolver = AbgESolver(dg, sg, defaultdict(lambda:0.85), None)

logger.info("[Op Phase] Solve AbgE problem.")
PhiV, PhiE = abgESolver.solve()
vMap, eMap = abgESolver.resolveMap(PhiV, PhiE)

with open("build/yaml/AbgE_vMap.yaml", 'w') as f:
    yaml.dump({
        v_DG.name : v_SG.name
        for (v_DG, v_SG) in vMap.items()
    }, f)
with open("build/yaml/AbgE_eMap.yaml", 'w') as f:
    yaml.dump({
        (dg.V[e_DG.srcIdx].name, dg.V[e_DG.dstIdx].name) : (sg.V[e_SG.srcIdx].name, sg.V[e_SG.dstIdx].name)
        for (e_DG, e_SG) in eMap.items()
    }, f)

logger.info("[Op Phase] Construct LatReb problem.")
lg_raw = dataflowGraphToLatencyGraph(dg, sg, eMap)
latRebSolver = LatRebSolver(lg_raw)
logger.info("[Op Phase] Solve LatReb problem.")
S, B = latRebSolver.solve()
lg_bal = latRebSolver.resolveBal(S, B)

logger.info("[Op Phase] Store LatReb solution.")
with open("build/yaml/LatReb_vLat.yaml", 'w') as f:
    yaml.dump({
        v_LG.name : int(v_LG.lat)
        for v_LG in lg_bal.V
    }, f)
with open("build/yaml/LatReb_eLatBal.yaml", 'w') as f:
    yaml.dump({
        e_MG.name : {"lat": int(e_LG.lat), "bal": int(e_LG.bal)}
        for e_LG in lg_bal.E
        for e_MG in e_LG.components
    }, f)

logger.info("[Op Phase] Generate optimized top RTL.")
vhandle.toCustomizedNames()
top_module_name, rtl = vhandle.toRTL()

logger.info("[Op Phase] Store optimized top RTL.")
with open(f"build/verilog/{top_module_name}.v", 'w') as f:
    f.write(rtl)

logger.info("[Op Phase] Generate cross-die buffer specifications.")
buffer_specs = latencyGraphToBufferSpec(lg_bal)

logger.info("[Op Phase] Store cross-die buffer specifications.")
with open(f"build/csv/bufferspecs.csv", 'w') as f:
    f.write(buffer_specs)

logger.info("[Op Phase] Generate cross-die buffer RTLs.")
execAndEcho("cp build/csv/bufferspecs.csv chisel3/bvhlsfifo/hw/req.csv")
execAndEcho("make -C chisel3/bvhlsfifo/")

logger.info("[Op Phase] Store cross-die buffer RTLs.")
execAndEcho("cp chisel3/bvhlsfifo/builds/*.v build/verilog/")

logger.info("[Op Phase] Copy coarse pre-floorplan constraint.")
execAndEcho(f"cp {path_prefloorplan_tcl} build/tcl/prefloorplan.tcl")

logger.info("[Op Phase] Generate PE floorplan constraints.")
pe_constr = abgVMapToTcl("pfm_top_i/dynamic_region/.*/inst/", vMap)

logger.info("[Op Phase] Store PE floorplan constraints.")
with open("build/tcl/pe_constr.tcl", 'w') as f:
    f.write(pe_constr)

logger.info("[Op Phase] Generate cross-die buffer floorplan constraints.")
buf_constr = distributeLatencyToGridAsTcl("pfm_top_i/dynamic_region/.*/inst/", lg_bal, dg, gg, vMap)

logger.info("[Op Phase] Store cross-die buffer floorplan constraints.")
with open("build/tcl/buf_constr.tcl", 'w') as f:
    f.write(buf_constr)


from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from rest_framework_simplejwt.views import (
    TokenObtainPairView,
    TokenRefreshView,
    TokenVerifyView
)

from anime.views import AnimeViewSet
from auths.views import MyUserViewSet
from anime.views import AnimeSearchViewSet

router = DefaultRouter()
router.register(r'animes', AnimeViewSet, basename='anime')
router.register(r'users', MyUserViewSet, basename='user')
router.register(r'serch', AnimeSearchViewSet, basename='search')

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api-auth/', include('rest_framework.urls')),
    path('', include(router.urls))
]
urlpatterns += [
    path('api/token/verify/', TokenVerifyView.as_view(), name='token_verify'),
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]
urlpatterns += static(
    settings.STATIC_URL,
    document_root=settings.STATIC_ROOT
)
urlpatterns += static(
    settings.MEDIA_URL,
    document_root=settings.MEDIA_ROOT
)


import pyarrow as pa
import pyarrow.parquet as pq
from itemadapter import ItemAdapter
from datetime import datetime
import pytz
from google.cloud import storage
import os
import time
import pandas as pd

class NewsScraperPipeline:
    def process_item(self, item, spider):
        adapter = ItemAdapter(item)

        # convert published_on to daylight savings aware UTC time
        time_zone = pytz.timezone('US/Eastern')
        value = adapter.get("published_on")
        # Replace "ET" with the corresponding time zone offset
        value = value.replace('ET', '-0400')
        datetime_object = datetime.strptime(value, '%d %b, %Y, %H:%M %z').astimezone(time_zone)
        adapter["published_on"] = datetime_object

        # remove whitespace from texts
        text_fields = ["news_provided_by", "headline", "article"]
        for text_field in text_fields:
            value = adapter.get(text_field)
            adapter[text_field] = value.strip()

        return item

class GCSStoragePipeline:
    def __init__(self, bucket_name):
        self.bucket_name = bucket_name
        self.client = storage.Client()
        self.file_rows = []

    @classmethod
    def from_crawler(cls, crawler):
        bucket_name = crawler.settings.get('GCS_BUCKET_NAME')
        return cls(bucket_name)

    def open_spider(self, spider):
        pass

    def close_spider(self, spider):
        # Generate a unique file name for the session
        timestamp = time.strftime('%Y%m%d%H%M%S')
        file_name = f'latest_prnews/data_{timestamp}.parquet'

        # Save content to a local Parquet file
        local_file_name = f'{spider.name}_{timestamp}.parquet'
        df = pd.DataFrame(self.file_rows)

        # Add a dummy column to the DataFrame
        # This ensures that the resulting Parquet file will have at least
        # one non-root column, avoiding the ValueError when reading it.
        df["dummy_column"] = ""

        table = pa.Table.from_pandas(df)
        pq.write_table(table, local_file_name)

        # Upload the file to GCS
        bucket = self.client.get_bucket(self.bucket_name)
        blob = bucket.blob(file_name)
        blob.upload_from_filename(local_file_name)
        spider.logger.info(f'Saved {file_name} to GCS bucket {self.bucket_name}')

        # Delete the local file
        os.remove(local_file_name)

    def process_item(self, item, spider):
        self.file_rows.append(dict(item))
        return item


"""
Given two integers n and k, return all possible combinations of k numbers chosen from the range [1, n].

You may return the answer in any order.
"""

class Solution:
    def combine(self, n: int, k: int) -> list[list[int]]:
        combs = []

        def combinator(start, maximum, length, ret):
            nonlocal combs
            if length == 0:
                combs += [ret]
                return
            for i in range(start, maximum + 1):
                combinator(i + 1, maximum, length - 1, ret + [i])

        combinator(1, n, k, [])
        return combs


import argparse
import subprocess
import shlex
import seaborn as sns
import pandas as pd
import numpy as np
import concurrent.futures

from matplotlib import pyplot as plt
from matplotlib.patches import Patch
from functools import partial

parser = argparse.ArgumentParser()

parser.add_argument("bed_file_name", type=str, help='File path with query RNA coordinates (.bed format)')
parser.add_argument("all_cores", type=int, help="Total number of cores")
parser.add_argument("cores_per_thread", type=int, help="Number of cores per thread")

args = parser.parse_args()

def OrthoRNA(bed_with_rna_coord=args.bed_file_name, all_cores=args.all_cores, cores_per_thread=args.cores_per_thread):
    #ORTHO2ALIGN PARALLELIZATION
    ortho2align_multiprocess(bed_with_rna_coord, all_cores, cores_per_thread)

    #RESULT VISUSLIZATION
    org = ['gorilla', 'marmoset', 'pig', 'horse', 'dog', 'cat', 'mouse', 'chicken', 'platypus']
    #Reading files
    initial_df = pd.read_csv(bed_with_rna_coord, sep='\t', header=None)

    for i in org:
        org_df = []
        locals()['{}_annot'.format(i)] = pd.read_csv('./result/{}_result/annotation_files/bestSignificant.annotation.tsv'.format(i), sep='\t')
        org_df.append(locals()['{}_annot'.format(i)])

    for i in org:
        locals()['{}_bed'.format(i)] = pd.read_csv('./result/{}_result/bestSignificant.subject_orthologs.bed'.format(i), sep='\t', header=None)
        locals()['{}_bed'.format(i)] = locals()['{}_bed'.format(i)].iloc[:, [3,4]]
        locals()['{}_bed'.format(i)] = locals()['{}_bed'.format(i)].set_index(3)
        locals()['{}_bed'.format(i)].index.names = [None]
        locals()['{}_bed'.format(i)] = locals()['{}_bed'.format(i)].rename(columns={4: i})

    #Сonstructing a table of orthologues (0/1)
    df_binar_all = pd.DataFrame(np.nan, index=initial_df[3], columns=['human'])
    df_binar_all.index.names = [None]
    df_binar_all['human'] = 1
    for i in org:
        df_binar_all = add_organism(locals()['{}_annot'.format(i)], df_binar_all, i)
    df_binar_all.to_csv('./result/binary_table_of_orthologues.tab', sep="\t", index=True)

    #Adding an annotation for orthologues
    annot_df = add_organism_annotation(org_df, org, df_binar_all)
    annot_df['exist'] = annot_df.sum(axis=1)
    exist_annot_list = annot_df.pop('exist')

    #Drawing an illustration for df_binar_all
    palette = sns.color_palette("hls", len(org))
    pal = dict(zip(exist_annot_list.unique(), palette))
    row_colors = exist_annot_list.map(pal)
    handles = [Patch(facecolor=pal[name]) for name in pal]
    clustermap(df_binar_all, row_colors, handles, pal, "./result/binary_map.png")

    #Сonstructing a table of orthologues with aligment scores
    df_bed = pd.DataFrame('human', index=initial_df[3], columns=['human'])
    df_bed.index.names = [None]
    for i in org:
        df_bed = add_organism_score(locals()['{}_bed'.format(i)], df_bed)
    df_bed = df_bed.drop(columns=['human'])
    df_bed.to_csv('./result/score_table_of_orthologues.tab', sep="\t", index=True)

    #Normalisation (Query RNA length)
    rna_length = dict()
    for i in initial_df[3].tolist():
        rna_length[i] = int(initial_df[initial_df[3] == i][2]) - int(initial_df[initial_df[3] == i][1])
    df_bed = df_bed.div(rna_length, axis='index')
    df_bed.to_csv('./result/score_table_of_orthologues_normalized.tab', sep="\t", index=True)

    #Drawing an illustration df_bed
    clustermap(df_bed, row_colors, handles, pal, "./result/score_map.png")

    #Сonstructing a table with annotations of orthologues
    annot_merge = pd.DataFrame(columns=['Query'])
    annot_merge['Query']=initial_df[3]
    for i in org:
        df_tmp = locals()['{}_annot'.format(i)].iloc[:,[0,1]]
        df_tmp = df_tmp.rename(columns={"Orthologs": i})
        annot_merge = pd.merge(annot_merge, df_tmp, on='Query', how='outer')
    annot_merge.to_csv('./result/annotation_table_of_orthologues.tab', sep="\t", index=True)

def ortho2align_task(bed_with_rna_coord, org_name, cores_per_thread):
    with open("./ortho2align_stderr/ortho2align_stderr_{}.log".format(org_name), "w") as err:
            cmd = 'bash script.sh ' + bed_with_rna_coord + ' ' + org_name + ' ' + str(cores_per_thread)
            process = subprocess.Popen(
                shlex.split(cmd),
                stderr=err,
            )
            process.wait()
    return

def ortho2align_multiprocess(bed_with_rna_coord, all_cores, cores_per_thread):
    org = ['gorilla', 'marmoset', 'pig', 'horse', 'dog', 'cat', 'mouse', 'chicken', 'platypus']
    with concurrent.futures.ThreadPoolExecutor(all_cores) as executor:
        futures = [executor.submit(ortho2align_task, bed_with_rna_coord, i, cores_per_thread) for i in org]
        # wait for all download tasks to complete
        _ = concurrent.futures.wait(futures)

def add_organism(org_name_df, df, col_name):
    df[col_name] = 0
    df.loc[df.index.isin(org_name_df['Query']), col_name] = 1
    return df

def add_organism_annotation(org_df, org, df):
    df_tmp = pd.DataFrame(0, index=df.index, columns=list(df))
    i = 0
    for org_name_df in org_df:
        exist_annot = org_name_df[org_name_df['Orthologs'] != 'NotAnnotated']['Query'].tolist()
        df_tmp.loc[df_tmp.index.isin(exist_annot), org[i]] = 1
        i += 1
    return df_tmp

def clustermap(df, row_colors, handles, pal, fig_name, bool=True):
    sns.set(font_scale=1.5)
    mask = df.isin([0])
    clustermap = sns.clustermap(df.T, col_colors=row_colors, mask=mask.T, cmap="viridis")
    clustermap.cax.set_visible(bool)
    plt.setp(clustermap.ax_heatmap.get_yticklabels(), rotation=0)
    plt.legend(handles, pal, title='Число аннотированных ортологов', bbox_to_anchor=(1, 1), bbox_transform=plt.gcf().transFigure)
    plt.savefig(fig_name)

def add_organism_score(org_name_df, df):
    df1 = df.join(org_name_df).fillna(0)
    return df1

if __name__ == "__main__":
    OrthoRNA()


#!/usr/bin/env python

import os
import sys

import setuptools

# Utility function to read the README file
def readfile(filename):
    with open(filename) as f:
        return f.read()

# Utility function to read requirements.txt files
def readreq(filename):
    result = []
    with open(filename) as f:
        for line in f:
            line = line.strip()

            # Process requirement file references
            if line.startswith('-r '):
                subfilename = line.split(None, 1)[-1].split('#', 1)[0].strip()
                if subfilename:
                    result += readreq(subfilename)
                continue

            # Strip out "-e" prefixes
            if line.startswith('-e '):
                line = line.split(None, 1)[-1]

            # Detect URLs in the line
            idx = line.find('#egg=')
            if idx >= 0:
                line = line[idx + 5:]

            # Strip off any comments
            line = line.split('#', 1)[0].strip()

            # Save the requirement
            if line:
                result.append(line.split('#', 1)[0].strip())

    return result

# Invoke setup
setuptools.setup(
    name='state_analyzer',
    version='0.0.1',
    author='Kevin L. Mitchell',
    author_email='klmitch@mit.edu',
    url='https://github.com/klmitch/humboldt/tree/master/tools/state_analyzer',
    description='Humboldt State Analyzer',
    long_description=readfile('README.rst'),
    packages=setuptools.find_packages(exclude=['tests', 'tests.*']),
    install_requires=readreq('requirements.txt'),
    tests_require=readreq('test-requirements.txt'),
    entry_points={
        'console_scripts': [
            'humstate-canon = state_analyzer.main:canon.console',
            'humstate-dot = state_analyzer.main:dot.console',
        ],
    },
)


#!/usr/bin/env python3

# Pyqt5
from PyQt5.QtWidgets import QMainWindow, QStackedWidget, QWidget, QMessageBox
from PyQt5.QtGui import  QImage, QPalette, QBrush, QIcon,  QMovie, QPainter, QPixmap, QDesktopServices
from PyQt5.QtCore import QSize, QUrl

# System
import sys
import os

# Graphics
from graphics.rules_dialog import RulesDialog
from graphics.game_dialog import GameDialog
from graphics.multi_player_options import MultiPlayerOptions
from graphics.single_player_options import SinglePlayerOptions
from graphics.start_screen import StartScreen
from graphics.watch_options import WatchOptions
from graphics.load_game_options import LoadGameOptions

# Database
#from web.postgreSQL.psql_database import PsqlDatabase, PsqlDatabaseError

####################################################################################################

class MainWindow(QMainWindow):
    """ Class for the main window of the application. """

    # Link to home page of website
    """  http://0.0.0.0:8080/  """

####################################################################################################
    def __init__(self, *args, **kwargs):
        """ Initialize a main window for the minesweeper application. Contains buttons connected
            to load game options, singleplayer options, multiplayer options, and watch options.

            Inputs:     None
            Outputs:    None
        """
        # Initialize parent class
        super().__init__(*args, *kwargs)

        self.__database = None
        """
        # Create instance of database
        self.__database = PsqlDatabase()
        # Try to connect to the database
        try:
            # Connect to database
            self.__database.connectToDatabase()
        # Except a database error
        except PsqlDatabaseError as error:
            # String referencing README
            refString="\nRefer to README.txt section titled\n\"INSTALLING DOCKER AND INITIALIZING DATABASE\""
            # Critical error dialog
            criticalErrorDialog = QMessageBox.critical(self,'Database Error',str(error)+refString, QMessageBox.Ok)
            # Exit the application
            self.quit(1)
        """
        #-------------------------------------------------------------------------------------------
        # MENU BAR
        #-------------------------------------------------------------------------------------------
        # Add a menu bar
        menuBar = self.menuBar()
        # Make it sexy
        menuBar.setStyleSheet("background:rgba(100, 100, 125, 0.7);")

        # File menu
        fileMenu = menuBar.addMenu("File")
        # File/Load
        loadAction = fileMenu.addAction("Load")
        # Connect load to load dialog
        loadAction.triggered.connect(self.loadGameOptions)
        # File/Quit
        quitAction = fileMenu.addAction("Quit")
        # Connect quit to quit app
        quitAction.triggered.connect(lambda: self.quit(0))
        # Standard shortcut
        quitAction.setShortcut("CTRL+Q")

        # About menu
        helpMenu = menuBar.addMenu("Help")
        # Add about action
        aboutAction = helpMenu.addAction("About")
        #  link to open the website
        aboutAction.triggered.connect(self.openWeb)
        # Add Rules action
        rulesAction = helpMenu.addAction("Rules")
        # Connect rules to rules dialog
        rulesAction.triggered.connect(self.openRules)

        #-------------------------------------------------------------------------------------------
        # INITIALIZATION
        #-------------------------------------------------------------------------------------------
        # Start screen
        startScreen = StartScreen()
        # Set geometry
        self.setFixedSize(600, 338)

        # Create moving background
        self.movie = QMovie("graphics/images/movingMines.gif")
        # Connect changes in background to repaint
        self.movie.frameChanged.connect(self.repaint)
        # Start the movie
        self.movie.start()

        # Window title
        self.setWindowTitle("Minesweeper")
        # Central widget is the start screen
        self.setCentralWidget(startScreen)

        # Set a default player name
        self.playerName = ""

        # Connect multiplayer button to multiplayer options
        startScreen.singlePlayerPressed.connect(self.singlePlayerOptions)
        # Connect single player button to single player options
        startScreen.multiPlayerPressed.connect(self.multiPlayerOptions)
        # Connect Watch button to AI options
        startScreen.watchButtonPressed.connect(self.watchOptions)

####################################################################################################

    def watchOptions(self):
        """ Displays the options for watching the AI playe minesweeper and stores the user's desired
            configuration

            Inputs:     None
            Outputs:    None
        """
        # Watch options dialog
        watchDialog = WatchOptions()
        # Execute the dialog box
        response = watchDialog.exec()
        # If dialog was accepted
        if response == watchDialog.Accepted:
            # Set configuration
            configuration = watchDialog.getConfiguration()
            # Create a game with the configuration
            self.createGame(configuration)

####################################################################################################

    def singlePlayerOptions(self):
        """ Displays the options for singleplayer minesweeper gameplay and stores the users desired
            configuration

            Inputs:     None
            Outputs:    None
        """
        # Single player option dialog
        singleDialog = SinglePlayerOptions(self.__database)
        # Execute the dialog and get a response
        response = singleDialog.exec()
        # If the dialog was accepted
        if response == singleDialog.Accepted:
            # Set the player name
            self.playerName = singleDialog.getName()
            # Set the configuration
            configuration = singleDialog.getConfiguration()
            # Create a game with the configuration
            self.createGame(configuration)

####################################################################################################

    def multiPlayerOptions(self):
        """ Displays the options for multiplayer minesweeper gameplay and stores the users desired
            configuration

            Inputs:     None
            Outputs:    None
        """
        # Multi player option dialog
        multiDialog = MultiPlayerOptions(self.__database)
        # Execute dialog and get a response
        response = multiDialog.exec()
        # If the dialog was accepted
        if response == multiDialog.Accepted:
            # Set the player name
            self.playerName = multiDialog.getName()
            # Set the configuration
            configuration = multiDialog.getConfiguration()
            # Create a game with the configuration
            self.createGame(configuration)

####################################################################################################

    def loadGameOptions(self):
        """ Displays the options for loading a previously save game. stores the configuration
            of the loaded game.

            Inputs:     None
            Outputs:    None
        """
        # Load game options dialog
        loadDialog = LoadGameOptions(self.__database)
        # Execute dialog box and get response
        response = loadDialog.exec()
        # If dialog was accepted
        if response == loadDialog.Accepted:
            # Set the player name
            self.playerName = loadDialog.getName()
            # Set the configuration
            configuration = loadDialog.getConfiguration()
            # Create a game with the configuration
            self.createGame(configuration)

####################################################################################################

    def createGame(self, configuration):
        """ Executes a game dialog based off the selected configuration

            Inputs:     configuration <list>
            Outputs:    None
        """
        # Create a game
        game = GameDialog(configuration, self.playerName, self.__database)
        # Execute the game
        game.exec()

####################################################################################################

    def openRules(self):
        rulesDialog = RulesDialog()
        rulesDialog.exec()

####################################################################################################

    def openWeb(self):
        """ Opens the application's web component

            Inputs:     None
            Outputs:    None
        """
        # Open the url for game website
        QDesktopServices.openUrl(QUrl("http://0.0.0.0:8080/"))

####################################################################################################

    def quit(self, returnCode):
        """ A shortcut function used to quit the application

            Inputs:     None
            Outputs:    None
        """
        exit(returnCode)

####################################################################################################

    def paintEvent(self, event):
        """ Method to allow for continuous background animation

            Inputs:     event <event>
            Outputs:    None
        """
        # Get current frame
        currentFrame = self.movie.currentPixmap()
        # Current frame rectangle
        frameRect = currentFrame.rect()
        # Current frame center
        frameRect.moveCenter(self.rect().center())
        # If frame has changed
        if frameRect.intersects(event.rect()):
            # Create a painter
            painter = QPainter(self)
            # Redraw background
            painter.drawPixmap(frameRect.left(), frameRect.top(), currentFrame)

####################################################################################################


import re
s1=str(input())
ri=s1.split("]")
num=[]
d=s1.count("]")-1
for i in range(d):
    num.append(ri[i].count("@")+1)
p = re.compile('.+?"(.+?)"')
s2 = p.findall(s1)
new=[]
a=0
accounts=[]
h=0
for v in range(len(s2)):
    new.append(s2[v])
    a=a+1
    if a==num[h]:
        h=h+1
        accounts.append(new)
        a=0
        new=[]
for k in range(len(accounts)):
    j=k+1
    while j<len(accounts):
        if len(set(accounts[k])&(set(accounts[j])))>=2:
            accounts[k]=list(set(accounts[k]).union(set(accounts[j])))
            del accounts[j]
            j=j-1
        else: j+=1
print(accounts)

s=input()
s=s[1:len(s)-1].split(",")
for i in range(len(s)):
    s[i]=int(s[i])
for i in s:
    if s.count(i)==1 :
        print(i)


import cv2
import numpy as np

# Load the camera matrix and distortion coefficients
# Calibrate camera
calib_data_path = "D:/3/P3/P3-e.DO-robot-arm/MultiMatrix.npz"
calib_data = np.load(calib_data_path)
print(calib_data.files)
camera_matrix = calib_data["camMatrix"]
distortion_coefficients = calib_data["distCoef"]

# Load the size of the Aruco markers in meters
marker_size = 0.04 # 5 cm

# Load the positions of the markers in the object's coordinate system
# These values should be known a priori
marker_positions = np.array([[0, 0, 0],
                             [marker_size, 0, 0],
                             [marker_size, marker_size, 0],
                             [0, marker_size, 0],
                             [0, 0, marker_size],
                             [marker_size, 0, marker_size],
                             [marker_size, marker_size, marker_size],
                             [0, marker_size, marker_size]])

# Load the image of the object with the Aruco markers
# Load Cap
cap = cv2.VideoCapture(1)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 400)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 400)
counter = 0

# Detect the Aruco markers in the image
marker_corners, marker_ids, _ = cv2.aruco.detectMarkers(cap, cv2.aruco.Dictionary_get(cv2.aruco.DICT_4X4_50))

# Estimate the pose of each marker
_, rvec, tvec, _ = cv2.aruco.estimatePoseSingleMarkers(marker_corners, marker_size, camera_matrix, distortion_coefficients)

# Convert the rotation vector to a rotation matrix
rotation_matrix, _ = cv2.Rodrigues(rvec)

# Convert the rotation matrix and translation vector to a 4x4 transformation matrix
transform_matrix = np.concatenate((rotation_matrix, tvec), axis=1)
transform_matrix = np.concatenate((transform_matrix, np.array([[0, 0, 0, 1]])), axis=0)

# Transform the marker positions from the object's coordinate system to the camera's coordinate system
marker_positions_camera = np.dot(transform_matrix, np.concatenate((marker_positions, np.ones((8, 1))), axis=1).T).T

# Compute the dimensions of the object in the camera's coordinate system
width = np.linalg.norm(marker_positions_camera[1] - marker_positions_camera[0])
length = np.linalg.norm(marker_positions_camera[2] - marker_positions_camera[1])
depth = np.linalg.norm(marker_positions_camera[4] - marker_positions_camera[0])

print('Width:', width)
print('Length:', length)
print('Depth:', depth)
cv2.imshow("cap", cap)


"""
621. Task Scheduler
# asynchronous processing
"""
## RC ##
## APPROACH : HASHMAP ##
## LOGIC : TAKE THE MAXIMUM FREQUENCY ELEMENT AND MAKE THOSE MANY NUMBER OF SLOTS ##
##  Slot size = (n+1) if n= 2 => slotsize = 3 Example: {A:5, B:1} => ABxAxxAxxAxxAxx => indices of A = 0,2 and middle there should be n elements, so slot size should be n+1

## Ex: {A:6,B:4,C:2} n = 2
## final o/p will be
## slot size / cycle size = 3
## Number of rows = number of A's (most freq element)
# [
#     [A, B,      C],
#     [A, B,      C],
#     [A, B,      idle],
#     [A, B,      idle],
#     [A, idle,   idle],
#     [A   -        - ],
# ]
#
# so from above total time intervals = (max_freq_element - 1) * (n + 1) + (all elements with max freq)
# ans   =     rows_except_last   * columns +        last_row

## but consider {A:5, B:1, C:1, D:1, E:1, F:1, G:1, H:1, I:1, J:1, K:1, L:1} n = 1
## total time intervals by above formula will be 4 * 2 + 1 = 9, which is less than number of elements, which is not possible. so we have to return max(ans, number of tasks)

## TIME COMPLEXITY : O(N) ##
## SPACE COMPLEXITY : O(1) ##

"""
A-3, B-3, C-3, D-3
ABCDABCDABCD with n = 2!
only need to calculate last BCD
"""

from collections import Counter
def leastInterval(self, tasks:[str], n: int) -> int:
    count = Counter(tasks)
    maxnum = max(count.values())
    if n ==0:
        return len(tasks)
    intervals = (n+1)*(maxnum-1)
    freq = list(count.values())
    addtional = 0
    for i in freq:
        if i == maxnum:
            addtional +=1
    ans = intervals + addtional
    return max(ans, len(tasks))


import telegram
from telegram.ext import (
    Updater,
    CommandHandler,
    CallbackQueryHandler,
    MessageHandler,
    ConversationHandler,
    Filters,
    PreCheckoutQueryHandler,
)
from django.conf import settings
from django.core.validators import URLValidator

from . import commands, callbacks, conversation, constants, messages, models

class Bot(object):

    command_handlers = {
        'start': commands.start,
        'stats': commands.stats,
        'broadcast': commands.broadcast,
        'feedback': commands.feedback,
        'admin': commands.admin
    }

    callback_query_handlers = {
        'main': callbacks.main,
        'help': callbacks.help,
        'donate': callbacks.donate,
        'stats': callbacks.stats,
        'set_lang': callbacks.set_lang,
        'lang': callbacks.lang,
        'disconnect_pocket': callbacks.disconnect_pocket,
    }

    conversation = {
        'entry_points': {
            'command_handlers': {
                'users': commands.users
            },
            'callback_query_handlers': {
                'feedback': conversation.feedback,
                'broadcast': conversation.broadcast,
                'md': conversation.direct_message,
                'confirm_md': conversation.send_direct_message,
                'cancel_md': conversation.cancel_direct_message,
            }
        },
        'states': {
            constants.INPUT_FEEDBACK: conversation.input_feedback,
            constants.INPUT_BROADCAST_MESSAGE: conversation.input_broadcast_message,
            constants.INPUT_DIRECT_MESSAGE: conversation.input_direct_message,
            constants.INPUT_USER_CRITERIA: conversation.input_user_criteria,
        }
    }

    def __init__(self):

        token = settings.TELEGRAM_TOKEN

        self.updater = Updater(token=token, use_context=True, workers=200)
        self.bot = telegram.Bot(token=token)

        # Notify admins
        for user in models.BotUser.objects.filter(is_admin=True):
            self.bot.send_message(chat_id=user.chat_id, text='ðŸ¤– Bot is running')

        dp = self.updater.dispatcher
        dp.add_error_handler(self.error_handler)

        # Init command handlers
        for key, value in self.command_handlers.items():
            dp.add_handler(CommandHandler(key, value))

        # Init callback query handlers
        for key, value in self.callback_query_handlers.items():
            dp.add_handler(CallbackQueryHandler(value, pattern=key))

        # Init conversation
        entry_points = []

        handlers = self.conversation['entry_points']['command_handlers']
        for key, value in handlers.items():
            entry_points.append(CommandHandler(key, value))

        handlers = self.conversation['entry_points']['callback_query_handlers']
        for key, value in handlers.items():
            entry_points.append(CallbackQueryHandler(value, pattern=key))

        states = {}
        handlers = self.conversation['states']
        for key, value in handlers.items():
            states[key] = [MessageHandler(Filters.text, value)]

        dp.add_handler(
            ConversationHandler(
                entry_points=entry_points,
                states=states,
                fallbacks=[]
            )
        )

        # Filter messages
        dp.add_handler(MessageHandler(Filters.regex(URLValidator.regex), messages.add_link))

    def error_handler(self, update, context):
        try:
            raise context.error
        except telegram.TelegramError as e:
            print(e.message)

    def start(self):
        self.updater.start_polling()
        print('[BOT] Running at https://t.me/{}'.format(self.bot.username))
        self.updater.idle()


from PyQt5 import QtCore, QtWidgets

from .. import icons

class SquareButton(QtWidgets.QToolButton):
    """A button whose width is fixed to its height, so that it always remains square, while adjusting its side length
    to match its layout."""

    def __init__(self, parent=None, icon=None, tooltip=''):
        """Initialise the widget with parameters passed to constructor."""
        super().__init__(parent)
        self.setToolTip(tooltip)
        if icon:
            self.setIcon(icon)
            self.setIconSize(QtCore.QSize(16, 16))

        self.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum))
        self.setPopupMode(QtWidgets.QToolButton.InstantPopup)
        self.setStyleSheet('QToolButton::menu-indicator { width: 0; image: none }')  # hide dropdown arrow indicator

    def resizeEvent(self, event):
        """Handle a resize event so that the widget stays square."""
        self.setFixedWidth(self.height())

class UniverseMapButton(SquareButton):
    """A square push button displaying the "universe map" symbol."""

    def __init__(self, parent=None):
        """Initialise a SquareButton with some default values."""
        super().__init__(parent, icon=icons.universe, tooltip='Open universe map')


import unittest

from binary_tree import BinaryTree

class TestBunaryTreeMethods(unittest.TestCase):

    def test_balanced(self):
        root = BinaryTree(3)
        root.left = BinaryTree(9)
        root.right = BinaryTree(20)

        self.assertTrue(root.is_tree_balanced())

    def test_balanced_left(self):
        root = BinaryTree(3)
        root.left = BinaryTree(9)
        root.right = BinaryTree(20)
        root.left.right = BinaryTree(19)

        self.assertTrue(root.is_tree_balanced())

    def test_balanced_right(self):
        root = BinaryTree(3)
        root.left = BinaryTree(9)
        root.right = BinaryTree(20)
        root.right.right = BinaryTree(19)

        self.assertTrue(root.is_tree_balanced())

    def test_not_balanced_left(self):
        root = BinaryTree(1)
        root.left = BinaryTree(2)
        root.right = BinaryTree(3)
        root.left.left = BinaryTree(4)
        root.left.right = BinaryTree(5)
        root.left.right.left = BinaryTree(6)

        self.assertFalse(root.is_tree_balanced())

    def test_not_balanced_right(self):
        root = BinaryTree(1)
        root.right = BinaryTree(2)
        root.left = BinaryTree(3)
        root.right.left = BinaryTree(4)
        root.right.right = BinaryTree(5)
        root.right.right.left = BinaryTree(6)

        self.assertFalse(root.is_tree_balanced())

    def test_get_height(self):
        root = BinaryTree(3)
        root.left = BinaryTree(9)
        root.right = BinaryTree(20)
        root.right.right = BinaryTree(19)

        self.assertEqual(root.get_height(), 3)

    def test_get_balance(self):
        root = BinaryTree(3)
        root.left = BinaryTree(9)
        root.right = BinaryTree(20)
        root.right.right = BinaryTree(19)

        self.assertEqual(root.get_balance(), 1)

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


def caculate_2(temp):
    temp.reverse()
    index=0
    for i in range(len(temp)):
        index = index + temp[i]*(2**i)
    return index

def caculate_3(temp):
    temp.reverse()
    index=0
    for i in range(len(temp)):
        index = index + temp[i]*(3**i)
    return index

sec = input()
third = input()
a1 = list(sec)
b1 = list(third)
a = [int(i) for i in a1]
b = [int(i) for i in b1]
k = [0,1,2]
answera = list()
answerb = list()
answer = list()
for i in range(len(a)):
    temp = a.copy()
    temp[i] = 1-temp[i]
    caculate_2(temp)
for i in range(len(b)):
    temp = b.copy()
    k1 = k.copy()
    k1.pop(temp[i])
    for j in range(2):
        temp[i] = k1[j]
        caculate_3(temp)
for i in range(len(answera)):
    temp = answera[i]
    for j in range(len(answerb)):
        if temp==answerb[i]:
            answer.append(temp)
print(answer[0])


import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import time

from lib import dict

matplotlib.rcParams['font.family'] = 'FangSong'

def compare_with_yesterday(y1, y2):
    if y1 >= y2:
        return '+' + str(y1 - y2)
    else:
        return '-' + str(y1 - y2)

if __name__ == '__main__':
    current_stat = dict.PPP

    # 以第一行、第一列为DataFrame的行列信息
    data = pd.read_csv('./export.csv', header=0, index_col=0)
    x = data.index
    # print(x)

    plt.title('Twitter Followers Statistics for Poppin\'Party Members')
    for i in range(0, 5):
        plt.plot(x, data[current_stat[i]['name']], color=current_stat[i]['color'], label=current_stat[i]['id'])
    plt.xticks(x, x, rotation=30)
    plt.legend()
    plt.show()

    print('Poppin\'Party声优Twitter关注者数统计')
    # 哪里NMD有时间啊害搁着百京时间
    print('百京时间' + data.index[len(data) - 1] + '记录')
    for i in range(0, 5):
        print(current_stat[i]['name'] + ': ' + str(
            data[current_stat[i]['name']][len(data) - 1]) + ' (' + compare_with_yesterday(
            data[current_stat[i]['name']][len(data) - 1], data[current_stat[i]['name']][len(data) - 2]) + ')')
    print('*无需授权，随意转载')
    print('*技术支持：申必壬')
    plt.savefig('./temp.png')


from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from django.core.context_processors import csrf
from forms import *
from models import *
import datetime
from SOControl.models import SO

dic = {

       }

def createOS(request):
    if request.method == 'POST':
        form = OSForm(request.POST)

        if form.is_valid():
            form.save()
            return HttpResponseRedirect('/list/so')

    else:
        form = OSForm()

    dic.update({
                'form' : form,
            })

    dic.update(csrf(request))

    return render_to_response('SOControl/createForm.html', dic)

def listOS(request):
    os_list = SO.objects.all()
    dic.update({
                'os_list' : os_list
                })

    return render_to_response('SOControl/list.html', dic)

def editSO(request, soid):
    try:
        so = SO.objects.get(id=soid)
    except:
        return HttpResponseRedirect('/list/so/')
    if request.method == 'POST':
        form = OSForm(request.POST, instance=so)

        if form.is_valid():
            form.save()

            return HttpResponseRedirect('/list/so')
    else:
        form = OSForm(instance=so)

    dic.update({
                'form' : form,
                'soid' : soid,
            })

    dic.update(csrf(request))

    return render_to_response('SOControl/editForm.html', dic)


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

import os
import morningstar_ci_libs as nci

build_dir = "build"

packages_to_install = \
[
"qt5-default",
"qt5-qmake",
"qtbase5-dev-tools",
"qttools5-dev-tools",
"build-essential",
"libboost-dev",
"libboost-system-dev",
"libboost-filesystem-dev",
"libboost-program-options-dev",
"libboost-thread-dev",
"libboost-regex-dev",
"libssl-dev",
"libdb++-dev",
"libminiupnpc-dev",
"libqrencode-dev",
"libcurl4-openssl-dev"
]

nci.install_packages_debian(packages_to_install)

nci.mkdir_p(build_dir)
os.chdir(build_dir)
nci.call_with_err_code('qmake "USE_UPNP=1" "USE_QRCODE=0" "RELEASE=1" "MORNINGSTAR_CONFIG += Tests" ../morningstar-wallet.pro')
nci.call_with_err_code("make -j3")

# run tests
nci.call_with_err_code("./wallet/test/morningstar-tests")

print("")
print("")
print("Building finished successfully.")
print("")


class Solution(object):
    def shortestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        """
        Find the max length of palindom start from 0, and add the reverse part in the previous

        The smartest way to solve this problem is combine kmp and reverse
        reverse the string and combine them, we only need to check the last pre of the combine string
        then we minus the largest pre and comnie them
        EX:
        aacecaaa#aaacecaa
        we only care about the last letter of the in the pre array
        """
        if not s:
            return ""

        #initial build the string
        revs=s[::-1]
        new_str=s+'#'+revs
        #mark the next array in KMP
        next=[0]*(len(new_str)+1)
        j=0
        for i in xrange(1,len(new_str)):
            #if not equal,we check back the first equal string
            while j>0 and new_str[i]!=new_str[j]: j=next[j]
            if new_str[i]==new_str[j]:j+=1
            next[i+1]=j
        return revs[:len(s)-next[-1]]+s


import sys
sys.path.append('..')

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'

from tensorflow.keras.layers import Conv2D, BatchNormalization, PReLU, UpSampling2D, Add
import numpy as np
import tensorflow as tf
import odl
import odl.contrib.tensorflow
import matplotlib.pyplot as plt

sess = tf.Session()

# ---------------------------
# Specify parameters
epochs = 51
batch_size = 4
n_training_samples = 1709
n_validation_samples = 458
n_batches = n_training_samples//batch_size
n_batches_val = n_validation_samples//batch_size

initial_lr = 1e-3

size = 512
n_theta = 32
upsampling_factor = 23
n_s = 768

# ---------------------------
# Set up tomography operator

space = odl.uniform_discr([-128, -128], [128, 128], [size, size], dtype='float32', weighting=1.0)
angle_partition = odl.uniform_partition(0, np.pi, n_theta)
angle_partition_up = odl.uniform_partition(0, np.pi, n_theta*upsampling_factor)
detector_partition = odl.uniform_partition(-360, 360, n_s)
geometry = odl.tomo.Parallel2dGeometry(angle_partition, detector_partition)
geometry_up = odl.tomo.Parallel2dGeometry(angle_partition_up, detector_partition)

operator = odl.tomo.RayTransform(space, geometry)
pseudoinverse = odl.tomo.fbp_op(operator)

Radon = odl.tomo.RayTransform(space, geometry_up)
FBP = odl.tomo.fbp_op(Radon)

operator /= odl.operator.power_method_opnorm(operator)
Radon /= odl.operator.power_method_opnorm(Radon)

# Create tensorflow layer from odl operator
odl_op_layer = odl.contrib.tensorflow.as_tensorflow_layer(operator, 'RayTransform')
odl_op_layer_pseudo = odl.contrib.tensorflow.as_tensorflow_layer(pseudoinverse, 'RayTransformPseudo')

radon_layer = odl.contrib.tensorflow.as_tensorflow_layer(Radon, 'Radon')
fbp_layer = odl.contrib.tensorflow.as_tensorflow_layer(FBP, 'FBP')

# ---------------------------
# Set up denoising network
inp_shape = operator.range.shape + (1, )

inp = tf.placeholder(tf.float32, shape=(None,) + inp_shape, name='input_denoising')

out = Conv2D(64, (3, 3), padding='same')(inp)
out = BatchNormalization()(out)
out = PReLU()(out)

out = Conv2D(64, (3, 3), padding='same')(out)
out = BatchNormalization()(out)
out = PReLU()(out)

out = Conv2D(64, (3, 3), padding='same')(out)
out = BatchNormalization()(out)
out = PReLU()(out)

out = Conv2D(64, (3, 3), padding='same')(out)
out = BatchNormalization()(out)
out = PReLU()(out)

out = Conv2D(1, (3, 3), padding='same')(out)
out = PReLU()(out)

out = Add()([out, inp])

# Make output operator consistent
out = odl_op_layer_pseudo(out)
out = Conv2D(64, (10, 10), padding='same')(out)
out = BatchNormalization()(out)
out = PReLU()(out)
out = Conv2D(1, (1, 1), padding='same')(out)
out = odl_op_layer(out)
out = tf.identity(out, name='output_denoising')

# ---------------------------
# Define upsampling network
inp = tf.placeholder(tf.float32, shape=(None, ) + inp_shape, name='input_upsample')
out = UpSampling2D(size=(upsampling_factor, 1), interpolation='bilinear')(inp)

out = Conv2D(32, (3, 3), padding='same')(out)
out = BatchNormalization()(out)
out = PReLU()(out)

out = Conv2D(32, (3, 3), padding='same')(out)
out = BatchNormalization()(out)
out = PReLU()(out)

out = Conv2D(32, (3, 3), padding='same')(out)
out = BatchNormalization()(out)
out = PReLU()(out)

out = Conv2D(32, (3, 3), padding='same')(out)
out = BatchNormalization()(out)
out = PReLU()(out)

out = Conv2D(1, (3, 3), padding='same')(out)
out = PReLU()(out)

# Make output operator consistent
out = fbp_layer(out)
out = Conv2D(64, (10, 10), padding='same')(out)
out = BatchNormalization()(out)
out = PReLU()(out)
out = Conv2D(1, (1, 1), padding='same')(out)
out = radon_layer(out)
out = tf.identity(out, name='output_upsample')

y_true = tf.placeholder(shape=(None,) + (n_theta*upsampling_factor, n_s, 1), dtype=tf.float32)

# ---------------------------
# Set up loss function for training
loss = tf.reduce_sum(tf.squared_difference(out, y_true))

learning_rate = tf.placeholder(dtype=tf.float32)
opt = tf.train.AdamOptimizer(learning_rate=learning_rate, name='adam_upsample')

train_op = opt.minimize(loss)

# ----------------------------
# Restore denoising model
sess.run(tf.global_variables_initializer())

# Restore graph from trained model
restore_path = "models/"
if 1:
    new_saver = tf.train.import_meta_graph(restore_path + 'denoising_network-0.meta')
    new_saver.restore(sess, tf.train.latest_checkpoint(restore_path))

graph = tf.get_default_graph()

inp_denois = tf.get_default_graph().get_tensor_by_name("input_denoising:0")
out_denois = tf.get_default_graph().get_tensor_by_name("output_denoising:0")

# ---------------------------
# Set up various functions

def plot_validation(y_in, y_pred, y_true, epoch=10):
    n_images = y_in.shape[0]
    for i in range(n_images):
        fig, axs = plt.subplots(nrows=2, ncols=2)
        im = axs[0, 0].imshow(y_true[i, ..., 0], cmap='bone')
        axs[0, 0].axis('off')
        axs[0, 0].set_title('True')
        fig.colorbar(im, ax=axs[0, 0])

        im = axs[0, 1].imshow(y_in[i, ..., 0], cmap='bone')
        axs[0, 1].set_aspect(n_s / n_theta)
        axs[0, 1].axis('off')
        axs[0, 1].set_title('Input')
        fig.colorbar(im, ax=axs[0, 1])

        im = axs[1, 0].imshow(y_pred[i, ..., 0], cmap='bone')
        axs[1, 0].axis('off')
        axs[1, 0].set_title('Prediction')
        fig.colorbar(im, ax=axs[1, 0])

        im = axs[1, 1].imshow(np.abs(y_true[i, ..., 0] - y_pred[i, ..., 0]), cmap='bone')
        axs[1, 1].axis('off')
        axs[1, 1].set_title('Difference')
        fig.colorbar(im, ax=axs[1, 1])

        fig.savefig('images/UpsampleValidationImage_Epoch' + str(epoch) + '_' + str(i) + '.pdf', format='pdf')
        fig.clf()

        plt.subplot(221)
        plt.imshow(FBP(y_true[i, ..., 0]), cmap='bone')
        plt.axis('off')
        plt.title('True')

        plt.subplot(222)
        plt.imshow(pseudoinverse(y_in[i, ..., 0]), cmap='bone')
        plt.axis('off')
        plt.title('Input')

        plt.subplot(223)
        plt.imshow(FBP(y_pred[i, ..., 0]), cmap='bone')
        plt.axis('off')
        plt.title('Prediction')

        plt.subplot(224)
        plt.imshow(FBP(y_true[i, ..., 0] - y_pred[i, ..., 0]), cmap='bone')
        plt.axis('off')
        plt.title('Difference')
        plt.colorbar()

        fig.savefig('images/UpsampleReconImage_Epoch' + str(epoch) + '_' + str(i) + '.pdf', format='pdf')
        fig.clf()
    pass

def cosine_decay(epoch, total, initial=1e-3):
    return initial/2.*(1 + np.cos(np.pi*epoch/total))

nmse = tf.reduce_mean(tf.reduce_sum(tf.square(y_true - out), axis=[1, 2, 3])/tf.reduce_sum(y_true**2, axis=[1, 2, 3]))

# ---------------------------
data_path = "../data/mayoclinic/data/full3mm/"
sigma = 0.2

def data_generator_upsample(batch_size=32, mode='train', rescale=1000.):
    p = data_path + mode
    files = np.random.choice(os.listdir(p), size=batch_size, replace=False)
    X = [np.load(p + '/' + file) for file in files]

    # Get high resolution sinograms
    y_t = [Radon(x / rescale) for x in X]
    y_t = np.stack(y_t)[..., None]

    # Get low resolution sinograms
    y_n = [operator(x / rescale) for x in X]
    y_n = [y + np.random.normal(0, 1, y.shape) * sigma for y in y_n]
    y_n = np.stack(y_n)[..., None]

    return y_n, y_t

# ---------------------------
save_path = "models/upsampling_network"
n_save = 10
n_val = 1

print("Initialization successful. Starting training...", flush=True)
hist = {'loss': [], 'nmse': [], 'loss_val': [], 'nmse_val': []}

for i in range(epochs):
    ERR = []
    NMSE = []

    print("### Epoch %d/%d ###" % (i + 1, epochs))
    for j in range(n_batches):
        print("Progress %f" % ((j+1)/n_batches), end='\r', flush=True)
        y_input, y_output = data_generator_upsample(batch_size=batch_size, mode='train')
        y_denois = sess.run(out_denois, feed_dict={inp_denois: y_input})

        fd = {inp: y_denois,
              y_true: y_output,
              learning_rate: cosine_decay(i, epochs)}

        c, nm, _ = sess.run([loss, nmse, train_op], feed_dict=fd)
        NMSE.append(nm)
        ERR.append(c)

    print("   Training: Loss %f NMSE %f" % (np.mean(ERR), np.mean(NMSE)), end='\r', flush=True)
    hist['loss'].append(np.mean(ERR))
    hist['nmse'].append(np.mean(NMSE))

    # Validate model performance
    if i % n_val == 0:
        ERR_VAL = []
        NMSE_VAL = []
        for j in range(n_batches_val):
            y_input, y_output = data_generator_upsample(batch_size=batch_size, mode='val')
            y_denois = sess.run(out_denois, feed_dict={inp_denois: y_input})

            fd = {inp: y_denois,
                  y_true: y_output}

            c, nm = sess.run([loss, nmse], feed_dict=fd)
            ERR_VAL.append(c)
            NMSE_VAL.append(nm)
        print(" ")
        print("   Validation: Loss %f Validation NMSE %f" % (np.mean(ERR_VAL), np.mean(NMSE_VAL)))
        print(" ", flush=True)
        hist['loss_val'].append(np.mean(ERR_VAL))
        hist['nmse_val'].append(np.mean(NMSE_VAL))

    if (i % 10) == 0:
        y_input, y_output = data_generator_upsample(batch_size=batch_size, mode='val')
        y_denois = sess.run(out_denois, feed_dict={inp_denois: y_input})

        fd = {inp: y_denois,
              y_true: y_output}

        y_pred = sess.run(out, feed_dict=fd)
        plot_validation(y_input, y_pred, y_output, epoch=i)

    # Save model every
    if (i % n_save) == 0:
        new_saver.save(sess, save_path, global_step=i)

plt.semilogy(hist['loss'])
plt.semilogy(hist['loss_val'])
plt.savefig('images/upsample_loss.pdf', format='pdf')


# Import dependencies
import bs4                    as bs
import pandas                 as pd

# Set Multiplier
multiplier = dict({ 'Debit' : -1,
                    'Credit':  1  })

def extract_transactions(xml_file: type(bs.BeautifulSoup(features="lxml"))) -> pd.DataFrame():
    """
        Extract Transactions Table from SAF-T XML file and export as Pandas DataFrame
        - Create calculated column from Credit/Debit field and Amount field

        Inputs
        --------------------
            xml_file ( Beautiful Soup XML object ):    SAF-T file loaded as XML object

        Outputs
        --------------------
            dataset_transactions ( Pandas Dataframe ): Table of Transactions
    """
    # Initialise variables - Create temporary dictionary and list
    temp_list = list()
    temp_dict = dict()

    # For each Transaction in Transactions:
    #   For each Line in Transaction:
    #      Extract Fields:
    #          - Account ID
    #          - Transaction Amount
    #          - Transaction Flag

    for transaction in xml_file.find('n1:generalledgerentries').find('n1:journal').find_all('n1:transaction'):
        for general_ledger_line_entry in transaction.find_all('n1:line'):
            temp_dict = dict({'Account ID' : general_ledger_line_entry.find('n1:accountid').get_text(strip=True)})

            # Determine if the Transaction Amount is a Debit or a Credit
            # Add Transaction Amount and Transaction Flag (Debit/ Credit) to temp_dict
            if general_ledger_line_entry.find('n1:debitamount') is None:
                temp_dict['Transaction Amount'] = general_ledger_line_entry.find('n1:creditamount').find('n1:amount').get_text(strip=True)
                temp_dict['Transaction Flag'] = 'Credit'

            else:
                temp_dict['Transaction Amount'] = general_ledger_line_entry.find('n1:debitamount').find('n1:amount').get_text(strip=True)
                temp_dict['Transaction Flag'] = 'Debit'

            # Add current row (temp_dict) to accumulated table (temp_list)
            temp_list.append(temp_dict)

    # Convert temp_list to Pandas DataFrame
    # Convert Amount columns from Strings to Floats
    # Combine Balance Amounts and Flags into Calculated Column
    dataset_transactions = pd.DataFrame(temp_list)
    dataset_transactions['Transaction Amount'] = dataset_transactions['Transaction Amount'].astype('float')
    dataset_transactions['Transaction Amount, +/-'] = dataset_transactions[['Transaction Amount','Transaction Flag']].apply(lambda x: x['Transaction Amount'] * multiplier[x['Transaction Flag']], axis = 1)

    return dataset_transactions.sort_values(by=['Account ID', 'Transaction Flag'])

def extract_accounts(xml_file: type(bs.BeautifulSoup(features="lxml"))) -> pd.DataFrame():
    """
        Extract Accounts Table from SAF-T XML file and export as Pandas DataFrame
        - Combine Debit and Credit Balances into single Balance field
        - Create calculated column from Debit/Credit field and Balance field

        Inputs
        --------------------
            xml_file ( Beautiful Soup XML object ): SAF-T file loaded as XML object

        Outputs
        --------------------
            dataset_accounts  ( Pandas Dataframe ): Table of Transactions

    """
    # Initialise variables - Create temporary dictionary and list
    temp_list = list()
    temp_dict = dict()

    #For each Account in Accounts:
    #   Extract Fields:
    #       - Account ID
    #       - Account Description
    #       - Standard ID
    #       - Account Type
    #       - Account Creation Date
    #       - Opening Balance Amount
    #       - Opening Balance Flag
    #       - Closing Balance Amount
    #       - Closing Balance Flag

    for account in xml_file.find('n1:generalledgeraccounts').find_all('n1:account'):
        temp_dict = dict({'Account ID'           : account.find('n1:accountid').get_text(strip=True),
                          'Description'          : account.find('n1:accountdescription').get_text(strip=True),
                          'Standard ID'          : account.find('n1:standardaccountid').get_text(strip=True),
                          'Account Type'         : account.find('n1:accounttype').get_text(strip=True),
                          'Account Creation Date': account.find('n1:accountcreationdate').get_text(strip=True)
                         })

        # Determine if the Account Balance is a Debit or a Credit
        # Add Balance Amount and Balance Flag (Debit/ Credit) to temp_dict
        # Opening Balance
        if account.find('n1:openingdebitbalance') is None:
           temp_dict['Opening Balance Amount'] = account.find('n1:openingcreditbalance').get_text(strip=True)
           temp_dict['Opening Balance Flag'] = 'Credit'
        else:
           temp_dict['Opening Balance Amount'] = account.find('n1:openingdebitbalance').get_text(strip=True)
           temp_dict['Opening Balance Flag'] = 'Debit'

        # Closing Balance
        if account.find('n1:closingdebitbalance') is None:
           temp_dict['Closing Balance Amount'] = account.find('n1:closingcreditbalance').get_text(strip=True)
           temp_dict['Closing Balance Flag'] = 'Credit'
        else:
           temp_dict['Closing Balance Amount'] = account.find('n1:closingdebitbalance').get_text(strip=True)
           temp_dict['Closing Balance Flag'] = 'Debit'

        # Add current row (temp_dict) to accumulated table (temp_list)
        temp_list.append(temp_dict)

    # Convert temp_list to Pandas DataFrame
    # Convert Amount columns from Strings to Floats
    # Combine Balance Amounts and Flags into Calculated Column
    dataset_accounts = pd.DataFrame(temp_list)
    dataset_accounts['Opening Balance Amount']      = dataset_accounts['Opening Balance Amount'].astype('float')
    dataset_accounts['Opening Balance Amount, +/-'] = dataset_accounts[['Opening Balance Amount','Opening Balance Flag']].apply(lambda x: x['Opening Balance Amount'] * multiplier[x['Opening Balance Flag']], axis = 1)
    dataset_accounts['Closing Balance Amount']      = dataset_accounts['Closing Balance Amount'].astype('float')
    dataset_accounts['Closing Balance Amount, +/-'] = dataset_accounts[['Closing Balance Amount','Closing Balance Flag']].apply(lambda x: x['Closing Balance Amount'] * multiplier[x['Closing Balance Flag']], axis = 1)

    return dataset_accounts.sort_values(by=['Account ID'])


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
        ('projects', '0005_auto_20151001_0101'),
    ]

    operations = [
        migrations.AddField(
            model_name='project',
            name='screenshot',
            field=models.ImageField(default='test', upload_to=b'screenshots'),
            preserve_default=False,
        ),
    ]


from pip._vendor import requests

class YaUploader:
    def __init__(self, token):
        self.token = token

    def get_headers(self):
        return {'Content-Type': 'application/json', 'Authorization': 'OAuth {}'.format(self.token)}

    def upload(self, file_path):
        url = 'https://cloud-api.yandex.net/v1/disk/resources/upload'
        params = {'path': file_path, 'overwrite': 'True'}
        headers = self.get_headers()
        link_dickt = requests.get(url, headers = headers, params = params).json()
        href = link_dickt.get('href', '')
        post_ = requests.put(href, data = open(file_path, 'rb'))
        return print(post_.status_code)

if __name__ == '__main__':
    path_to_file = 'Text.txt'
    token = ''
    uploader = YaUploader(token)
    result = uploader.upload(path_to_file)


import time
import sys
import numpy as np

from ..tools import stats

from cirtorch.utils.whiten import whitenlearn, whitenapply, pcawhitenlearn

def whiten(params, data):
    """Apply pre-computed whitening"""
    dimensions = params.pop("dimensions", None) or None
    assert not params, params.keys()
    whitening, names, values = data
    assert len(names) == len(values)
    resources = stats.ResourceUsage()

    time0 = time.time()
    whitened = whitenapply(values.T, whitening['m'], whitening['P'], dimensions)
    timing = time.time() - time0
    metadata = {"timings": {"whitening_apply": round(timing, 2)},
                "resource_usage": resources.take_current_stats().get_resources()}

    return metadata, names, whitened.T

def learn_lw_whitening(params, data):
    """Learn Lw whitening"""
    assert not params
    names, values, queries, positives = data
    assert len(names) == len(values)
    assert len(queries) == len(positives)

    # Handle data
    values = values.astype(np.float64).T
    name_index = {x: i for i, x in enumerate(names)}
    qidxs = np.array([name_index[x] for x in queries])
    pidxs = np.array([name_index[x] for x in positives])

    resources = stats.ResourceUsage()

    # Learn the whitening on a shuffled subset of the data if the matrix is not positive definite
    time0 = time.time()
    max_trials = 100
    max_excluded = 0.95
    trial = 0
    while True:
        try:
            if trial == 0:
                qwhit, pwhit = qidxs, pidxs
            else:
                idxs = np.random.permutation(len(qidxs))[:int(len(qidxs) * (1 - trial/max_trials*max_excluded))]
                print("Using subset of queries (%s/%s) trial %s" % (len(idxs), len(qidxs), trial), file=sys.stderr)
                qwhit, pwhit = qidxs[idxs], pidxs[idxs]

            whit_m, whit_p = whitenlearn(values, qwhit, pwhit)
            break
        except np.linalg.linalg.LinAlgError as e:
            if str(e) != "Matrix is not positive definite" or trial >= max_trials-1:
                raise
            trial += 1
    timing = time.time() - time0

    metadata = {"stats": {"failed_times": trial,
                          "vectors_used": round(len(qwhit) / float(len(qidxs)), 2),
                          "vectors_total": len(qidxs)},
                "timings": {"whitening_learn": round(timing, 2)},
                "resource_usage": resources.take_current_stats().get_resources()}
    return metadata, {'m': whit_m, 'P': whit_p}

def learn_pca_whitening(params, data):
    """Learn PCA whiteining"""
    shrink = params.pop("shrink", None) or None
    assert not params
    values, = data

    values = values.astype(np.float64).T

    resources = stats.ResourceUsage()
    time0 = time.time()
    whit_m, whit_P = pcawhitenlearn(values, shrink)
    timing = time.time() - time0

    metadata = {"timings": {"whitening_learn": round(timing, 2)},
                "resource_usage": resources.take_current_stats().get_resources()}
    return metadata, {'m': whit_m, 'P': whit_P}

def paste_pca_normalize(params, data):
    """Concatenate vectors horizontally and optionally apply pca dimension reduction"""
    dimensions = params.pop("dimensions") or None
    assert not params
    assert len(set(len(x) for x in data)) == 1

    if data[0].shape == (0,):
        return {}, data[0]

    value = np.concatenate(data, axis=1)

    if dimensions:
        resources = stats.ResourceUsage()
        time0 = time.time()

        value -= np.mean(value)
        eigval, eigvec = np.linalg.eig(value.T.dot(value))
        vecs = eigvec[:,np.argsort(eigval)[-dimensions:]]
        value = value.dot(vecs.dot(vecs.T))

        timing = time.time() - time0
        metadata = {"timings": {"pca_compute": round(timing, 2)},
                    "resource_usage": resources.take_current_stats().get_resources()}
    else:
        metadata = {}

    value = value / np.expand_dims(np.linalg.norm(value, axis=1), axis=1)

    return metadata, value


class Solution:
    def fib(self, n: int) -> int:
        if n == 0:
            return 0
        elif n == 1:
            return 1
        else:
            return (self.fib(n-1) + self.fib(n-2)) % 1000000007

    def fib_bp(self, n: int) -> int:
        a, b = 0,1
        for i in range(0, n):       # n-1次
            a, b = b, a+b
        return a % 1000000007

if __name__ == "__main__":
    sol = Solution()
    print(sol.fib_bp(100))


import torch.nn as nn

# -------------------
# Model - Multi layer Perceptron
# -------------------
class MLP(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(MLP, self).__init__()
        self.layers = nn.Sequential(
            nn.Linear(input_size, hidden_size),
            nn.ReLU(),
            nn.Linear(hidden_size, output_size),
        )

    def forward(self, x):
        # Flatten the input images from [28,28] to [784]
        x = x.view(x.size(0), -1)
        return self.layers(x)


# https://codecombat.com/play/level/second-gem
# One gem is safe, others are bombs.
# But you know the answer: always take the second.

while True:
    items = hero.findItems()
    # If there are gems:
    if (len(items) > 1):
        # Collect the second from "items".
        hero.moveXY(items[1].pos.x, items[1].pos.y)
    # Else:
    else:
        # Move to the center mark.
        hero.moveXY(40, 34)


from pymongo import MongoClient
from pymongo.errors import ConnectionFailure

class MindfulMongo:
    def __init__(self, host, port, db_name):
        self.connect_to_database(host, port)
        self.database = self.client[db_name]
        self.database.users.create_index("discord_id", unique = True)

    def connect_to_database(self, host, port):
        try:
            self.client = MongoClient(host, port)
        except ConnectionFailure as e:
            print("Could not connect to MongoDB: %s" % str(e))

    def save_user(self, user_data):
        result = self.__users().update_one(
            {"discord_id": user_data["discord_id"]},
            { '$set': user_data },
            upsert = True
        )

        return result.raw_result['updatedExisting']

    def retrieve_user(self, discord_id):
        user = self.__users().find_one({
            "discord_id": discord_id
        })

        return user

    def __users(self):
        return self.database['users']


#
# SCons build script for building OpenCL applications using OclWrapper
#
# (c) 2011-now Wim Vanderbauwhede <wim.vanderbauwhede@mail.be>
#

"""
`plat` or `sdk` (AMD|NVIDIA|Intel|Xilinx) is used to identify where the libraries and header files for the platform are to be found.
`dev` (CPU, GPU, ACC) sets a macro "DEV_$dev" in the build system
`platidx` and `devidx` allow to provide the actual indices. This does not override dev, and currently there are no checks
`gpu` is the devidx for a GPU platform
`cpu` is the devidx for a CPU platform
`acc` is the devidx for an ACC platform

If the platidx is not known, we can try and guess it from the $plat value. We should report if that failed.
The logic is
- If it is NVIDIA, it is a GPU
- If it is Intel, it is either a GPU or a CPU (forget MIC or FPGA), so look at $dev
- If it is AMD, it is either a GPU or a CPU, so look at $dev
- If it is Xilinx, it must be an FPGA
"""

import os
import re
# import commands # OBSOLETE
import subprocess
import sys
import os.path
from SCons.Variables import Variables
from SCons.Environment import Environment
opts=''

def getOpt(optname,desc,default):

    global opts
    opts.Add(optname,desc,default)
    optionl = list(filter (lambda x: x.key==optname,opts.options))
    if optionl:
        option=optionl[0]
        if optname in opts.args and opts.args[optname]!=option.default:
            return opts.args[option.key]
        else:
            return option.default
    else:
        print( "No such option: "+optname )

def initOcl(*envt):
    if envt==():
        env=Environment()
    else:
        env=envt[0]

    global opts,dev,plat,sdk, devidx,platidx,multi,kernel,kopts,kernel_opts,useF,useFC,useDyn, mcModel, OPENCL_DIR, useOclWrapper, sel

    OPENCL_DIR=os.environ['OPENCL_DIR']

    envsh = open(OPENCL_DIR+'/OpenCLIntegration/ocl_env.sh', "r")
    envs =envsh.read()
    help = """
    Options:
     lib=0|1 [1] build an OclWrapper library
    *dyn=0|1 [0] build a dynamic Library             OclBuilder.useDyn
    *mcm=s|m|l [s] mcmodel flag for gcc/gfortran
    *plat=AMD|NVIDIA|Intel|Altera|Xilinx|MIC [NVIDIA]
    *dev=CPU|GPU|ACC|FPGA [GPU] device
    *devidx=device index as reported by `clinfo -l`, will be guessed from plat/dev
    *platidx=platform index as reported by `clinfo -l`, will be guessed from plat/dev
     cpu=-1|0|1 [-1, means automatic selection]
     gpu=-1|0|1 [-1, means automatic selection]
     acc=-1|0|1 [-1, means automatic selection]
     O=[gcc -O flag] [3]
     F=0|1 [0] use the functional (non-OO) interface OclBuilder.useF
     V=1.1|1.2|2.x [1.2] OpenCL C++ API version
     info=0|1                                        (DEVINFO, PLATINFO)
    *oclwrapper=0|1 [1] use the OclWrapper API       OclBuilder.useOclWrapper

    The following flags can be used to define macros in your code, they are passed on to the OpenCL kernel as well.
     kernel=<number> [1]                             KERNEL
     sel=<number> [1] generic selection flag         SELECT
     w=<number> [1024] width, e.g. for matrix        WIDTH
     wx,wy,wz=<number> [128,128,64] x/y/z dimensions WX,WY,WZ
     nth=<number> [1] number of threads per core     NTH
     nunits=<number> [1] number of compute units         NUNITS
     ngroups=<number> [0] number of workgroups         NGROUPS
     order=<number> [1] loop order                     LOOP_ORDER
     ref=0|1|2 [1]     reference 2=ref only          REF
     v=0|1 [1]         verbose                       VERBOSE
     warn=0|1 [1]      warnings                      WARNINGS
     mode=0|1|2   COPY|COPY+ALLOC|USE
     dbg=0|1 [0]                                     OCLDBG
     nruns= [1]                                      NRUNS
     multi=0|1 [0]   Support multiple devices in threads, for use with Fortran/GMCF     OCL_MULTIPLE_DEVICES
    *kopts=<string> kernel options, can only be a single alphanumeric string
                    if you need complex options, put them in the Scons script
                    For example, to add a path for kernel includes:
                    OclBuilder.kopts='-I/abs/path/to/includes'

    D=[comma-sep list of host-only macros, without values]

    The options marked with * can be set as OclBuilder.OPTION=VALUE in the SCons script
    The macros controlled by the other options are listed on the right
    The directory for the OclWrapper can be accessed via OclBuilder.OPENCL_DIR

    The environment variables listed in "$OPENCL_DIR/ocl_env.sh" must be set.

    """
    # + "\n"+ envs

   # by default, use the OclWrapper.
    if not 'useOclWrapper' in globals():
        useOclWrapper = True

    # if commands.getoutput("uname") == "Darwin":
    if subprocess.check_output(['uname',''], shell=True).strip()  == "Darwin":
        OSX=1
        OSFLAG='-DOSX'
    else:
        OSX=0
        OSFLAG='-D__LINUX__'

    opts=Variables()
    CWD= os.environ['PWD']
    args=sys.argv[1:]
    for arg in args:
        if re.match("(\w+)=(\w+)",arg):
            (k,v)=arg.split('=')
            opts.args[k]=v

    oclwrapper = getOpt('oclwrapper','OclWrapper','1')
    if oclwrapper != '1':
        useOclWrapper = False

    devidx=getOpt('devidx','Device Index','-1')
    platidx=getOpt('platidx','Platform Index','-1')

    dev=getOpt('dev','Device','GPU')
    plat=getOpt('plat','Platform','NVIDIA')
    sdk=getOpt('sdk','Platform SDK','NVIDIA')
#    print( "PLAT:"+plat)
    if OSX==1:
        plat='Apple'
        sdk='Apple'
    if plat=='AMD' or sdk=='AMD':
        AMD_SDK_PATH=os.environ['AMDAPPSDKROOT']
    elif plat=='Intel' or sdk=='Intel':
        INTEL_SDK_PATH=os.environ['INTELOCLSDKROOT']
    elif plat=='MIC':
        INTEL_SDK_PATH=os.environ['INTELOCLSDKROOT']
        dev='ACC'
    elif plat=='Altera':
        ALTERA_SDK_PATH=os.environ['ALTERAOCLSDKROOT']
        dev='ACC'
    else:
        if plat != 'Apple':
            NVIDIA_SDK_PATH=os.environ['NVSDKCUDA_ROOT']
            if os.environ['OPENCL_GPU']!='NVIDIA':
#                print 'No NVIDIA platform, defaulting to AMD CPU'
                if os.environ['OPENCL_CPU']=='AMD':
                    AMD_SDK_PATH=os.environ['AMDAPPSDKROOT']
                    plat='AMD'
                    dev='CPU'
                elif os.environ['OPENCL_ACC']=='Intel':
                    INTEL_SDK_PATH=os.environ['INTELOCLSDKROOT']
                    plat='MIC'
                    dev='ACC'
                elif os.environ['OPENCL_ACC']=='Altera':
                    ALTERA_SDK_PATH=os.environ['ALTERAOCLSDKROOT']
                    plat='Altera'
                    dev='FPGA'
                elif os.environ['OPENCL_ACC']=='Xilinx':
                    XILINX_SDK_PATH=os.environ['SDACCELROOT']
                    plat='Xilinx'
                    dev='FPGA'
                elif os.environ['OPENCL_CPU']=='Intel':
                    INTEL_SDK_PATH=os.environ['INTELOCLSDKROOT']
                    plat='Intel'
                    dev='CPU'
                else:
                    print( 'No OpenCL-capable GPU found' )
                    exit
#        else:
#            print 'NVIDIA'
    env['KERNEL_OPTS']=[]
    cpu=getOpt('cpu','CPU','-1')
    gpu=getOpt('gpu','GPU','-1')
    acc=getOpt('acc','ACC','-1')

    platidx_devidx_status=getPlatDevIdxFromPlatDec(plat,dev)
    status=platidx_devidx_status[2]
    if status==0:
        # if platidx/devidx had been set explicitly, we don't overwrite them
        if platidx!=-1:
            platidx=platidx_devidx_status[0]
        if devidx!=-1:
            devidx=platidx_devidx_status[1]
    elif status==1:
        print("No valid platform for "+plat+"/"+dev)
        exit(1)
    elif status==2:
        print("No valid device for "+plat+"/"+dev)
        exit(1)
    else:
        print("No clinfo progam, continuing with default values platidx="+str(platidx)+"/devidx="+str(devidx))
    # print(platidx,devidx)
    devidxflag='-DDEVIDX=-1'
    platidxflag='-DPLATIDX=-1'
    if cpu!='-1':
        devidxflag='-DDEVIDX='+cpu
        dev='CPU'
    if gpu!='-1':
        devidxflag='-DDEVIDX='+gpu
        dev='GPU'
    if acc!='-1':
        devidxflag='-DDEVIDX='+acc
        dev='ACC'
    if devidx!=-1:
        devidxflag='-DDEVIDX='+str(devidx)
    if platidx!=-1:
        platidxflag='-DPLATIDX='+str(platidx)

    kernel=getOpt('kernel','KERNEL','1')
    sel=getOpt('sel','SELECT','1')
    nth=getOpt('nth','#threads','1')
    nunits=getOpt('nunits','#compute units','1')
    ngroups=getOpt('ngroups','#workgroups','0')
    loop_order=getOpt('order','loop order','1')

    multi=getOpt('multi','Support multiple devices (Fortran)','0')
    multimacro='-DOCL_MULTIPLE_DEVICES=1'
    if multi=='0':
        multimacro=''

    if not 'kopts' in globals():
        kopts=getOpt('kopts','OpenCL kernel compilation options. Can only be a single alphanumeric string.','-cl-fast-relaxed-math')
    nruns=getOpt('nruns','Number of runs','1')
    width=getOpt('w','Width','1024')
    wx=getOpt('wx','X-width','128')
    wy=getOpt('wy','Y-width','128')
    wz=getOpt('wz','Z-width','64')
    env.Append(KERNEL_OPTS=['-DKERNEL='+kernel])
    env.Append(KERNEL_OPTS=['-DSELECT='+sel])
    env.Append(KERNEL_OPTS=['-DNTH='+nth])
    env.Append(KERNEL_OPTS=['-DNUNITS='+nunits])
    env.Append(KERNEL_OPTS=['-DWIDTH='+width])
    env.Append(KERNEL_OPTS=['-DWX='+wx])
    env.Append(KERNEL_OPTS=['-DWY='+wy])
    env.Append(KERNEL_OPTS=['-DWZ='+wz])
    env.Append(KERNEL_OPTS=['-DLOOP_ORDER='+loop_order])
    env.Append(KERNEL_OPTS=[multimacro])
    ref=getOpt('ref','Reference','1')
    refflag='-DREF'

    verbose=getOpt('v','Verbose','0')
    vflag='-DVERBOSE'
    if verbose=='0':
        vflag=''

    warnings=getOpt('warn','Warnings','1')
    wflag='-Wall'
    if ('PGCXX' in os.environ and os.environ['CXX'] == os.environ['PGCXX']):
       wflag = ''
    if warnings=='0':
        vflag=''

    version=getOpt('V','Version','1.2')
    verflag=''
    ver2flag=''
    tgtver=''
    hpptgtver=''
    if version[0:2]=='2.':
        # TODO: derive this from the version!
        numver=int(100*float(version))
        tgtver='-DCL_TARGET_OPENCL_VERSION='+str(numver)
        hppnumver=numver
        # A HACK!
        if hppnumver>210:
            hppnumver=210
        hpptgtver = '-DCL_HPP_TARGET_OPENCL_VERSION='+str(hppnumver) #210
    if version=='1.2' or version[0:2]=='2.':
        verflag='-DOCLV2'
    if version[0:2]=='2.':
        ver2flag='-DOCLV22'
    dbg=getOpt('dbg','Debug','0')
    dbgflag='-g'
    dbgmacro='-DOCLDBG=1'
    if dbg=='0':
        dbgmacro=''
        dbgflag=''

    useF=getOpt('F','Functional',0)
    useFC='0'
    if 'useF' in env:
        if env['useF']==1:
            useF='1'
    if 'useFC' in env:
        if env['useFC']==1:
            useFC='1'
    useDyn=getOpt('dyn','Dynamic Library',0)
    if 'useDyn' in env:
        if env['useDyn']==1:
            useDyn='1'

    mcModel=getOpt('mcm','GCC Code Model Flag','s')

    optim=getOpt('O','Optimisation','2')
    optflag='-O'+optim
    mode=getOpt('mode','Mode','1')
    memreadflag='-DMRMODE='+mode
    devinfo=getOpt('info','DeviceInfo','0')
    devinfoflag=''
    platinfoflag=''
    if devinfo=='1':
        devinfoflag='-DDEVINFO'
        platinfoflag='-DPLATINFO'

    defs=getOpt('D','Defines',None)
    defflags=[]
    if defs!=None:
        deflist=defs.split(',')
        defflags=map (lambda s: '-D'+s, deflist)

    DEVFLAGS=['-DDEV_'+dev,devidxflag,platidxflag]+env['KERNEL_OPTS']+['-DNRUNS='+nruns,'-DNGROUPS='+ngroups,'-DREF='+ref,vflag,verflag, ver2flag, tgtver, hpptgtver, memreadflag,devinfoflag,platinfoflag,multimacro]+defflags
    if plat=='Altera':
        DEVFLAGS+=['-DFPGA']
    if dev=='CPU':
        dbg_dev=dbgmacro+' '
    else:
        dbg_dev=''
    kernel_opts='\\"'+kopts+' -DEXT_DEFS '+dbg_dev+(' '.join(env['KERNEL_OPTS']))+'\\"'
    KERNEL_OPTS=['-DKERNEL_OPTS='+kernel_opts+'']
    # if commands.getoutput("uname") == "Darwin":
    if subprocess.check_output(['uname',''], shell=True).strip()  == "Darwin":
        DEVFLAGS+=['-DOSX']
    if useOclWrapper:
        oclsources= list(map (lambda s: OPENCL_DIR+'/OpenCLIntegration/'+s, ['Timing.cc','DeviceInfo.cc','PlatformInfo.cc','OclWrapper.cc']))
        env['OCLSOURCES']=oclsources
    if plat=='Altera':
        oclsources+=[OPENCL_DIR+'/OpenCLIntegration/libstdcxx-compatibility.cpp']
    if OSX==1 and 'ROOTSYS' in os.environ:
        print( 'Setting CXX to g++-4.2 for CERN ROOT on OS X' )
        env['CXX'] = ['g++-4.2'] # FIXME: because any higher g++ results in ERROR: malloc: *** error for object 0x7fff7064c500: pointer being freed was not allocated
    elif 'CXX_COMPILER' in os.environ:
        env['CXX'] = [ os.environ['CXX_COMPILER'] ]
    elif 'CXX' in os.environ:
        env['CXX'] = [ os.environ['CXX'] ]
    if ('GCXX' in  os.environ and  os.environ['CXX'] ==  os.environ['GCXX'] and int(os.environ['GCXX_VERSION'])<480):
        print('OLD GCXX: '+os.environ['GCXX_VERSION'])
        env.Append(CXXFLAGS = ['-std=c++0x','-m64','-fPIC','-DOLD_CXX',wflag,dbgflag,dbgmacro,optflag]+DEVFLAGS+KERNEL_OPTS)
    else:
        env.Append(CXXFLAGS = ['-std=c++11',wflag,dbgflag,dbgmacro,optflag]+DEVFLAGS+KERNEL_OPTS)
    env.Append(CFLAGS = [wflag,dbgflag,optflag]+DEVFLAGS+KERNEL_OPTS)
    env['MACROS'] = DEVFLAGS
    #env.Append(CXXFLAGS = ['-mcmodel=large']

    env.Help(help)
    env.Append(CPPPATH=[OPENCL_DIR+'/OpenCLIntegration'])
    if OSX==1:
        env.Append(FRAMEWORKS=['OpenCL'])
    else:
        if plat !='Altera':
            env.Append(LIBS=['OpenCL'])
        if plat=='AMD':
            env.Append(CPPPATH=[AMD_SDK_PATH+'/include/', AMD_SDK_PATH+'/include/CL','/usr/include/CL'])
            env.Append(LIBPATH=[AMD_SDK_PATH+'/lib/x86_64'])
        elif plat=='Intel':
            env.Append(CPPPATH=[INTEL_SDK_PATH+'/include/',INTEL_SDK_PATH+'/include/CL'])
            env.Append(LIBPATH=[INTEL_SDK_PATH+'/lib64'])
        elif plat=='MIC':
            env.Append(CPPPATH=[INTEL_SDK_PATH+'/include/'])
            env.Append(LIBPATH=[INTEL_SDK_PATH+'/lib64'])
        elif plat=='Altera':
            env.Append(CPPPATH=map(lambda s: ALTERA_SDK_PATH+s, ['/host/include/','/common/inc','/board/nalla_pcie/include' ]))
            env.Append(LIBPATH=[ALTERA_SDK_PATH+'/host/linux64/lib',ALTERA_SDK_PATH+'/board/nalla_pcie/linux64/lib']) #,ALTERA_SDK_PATH+'/'+os.environ['AOCL_BOARD_PACKAGE_ROOT']+'/linux64/lib'])
            env.Append(LIBS=['alteracl', 'dl', 'acl_emulator_kernel_rt', 'alterahalmmd', 'nalla_pcie_mmd', 'elf', 'rt', 'stdc++'])
            env.Append(CXXFLAGS = ['-fPIC'])
        elif plat=='Xilinx':
#DSA := xilinx:adm-pcie-7v3:1ddr:1.0
#XOCC := $(XILINX_SDACCEL)/bin/xocc
            XILINX_OPENCL = XILINX_SDK_PATH
            OPENCL_INC = XILINX_OPENCL+'/runtime/include/1_2'
            OPENCL_LIB = XILINX_OPENCL+'/runtime/lib/x86_64'
#CLFLAGS := -g --xdevice $(DSA)
#export XCL_PLATFORM=xilinx_adm-pcie-7v3_1ddr_1_0
            env.Append(CPPPATH=map(lambda s: XILINX_SDK_PATH+s, ['/runtime/include/1_2']))
            env.Append(LIBPATH=[XILINX_SDK_PATH+'/runtime/lib/x86_64'])
            #env.Append(LIBS=['xilinxcl', 'dl', 'acl_emulator_kernel_rt', 'xilinxhalmmd', 'FIXMEnalla_pcie_mmd', 'elf', 'rt', 'stdc++'])
            #env.Append(CXXFLAGS = ['-fPIC'])
        else: # means NVIDIA
            env.Append(CPPPATH=[NVIDIA_SDK_PATH+'/include',NVIDIA_SDK_PATH+'/OpenCL/common/inc' ,NVIDIA_SDK_PATH+'/OpenCL/common/inc/CL'])

    if useF=='1':
        if 'FORTRAN_COMPILER' in os.environ:
            env['FORTRAN']=os.environ['FORTRAN_COMPILER']
            env['F95']=os.environ['FORTRAN_COMPILER']
        if 'FC' in os.environ:
            env['FORTRAN']=os.environ['FC']
            env['F95']=os.environ['FC']
        if ('GFORTRAN' in os.environ and env['FORTRAN'] == os.environ['GFORTRAN']) :
            env['FORTRANFLAGS']=env['CFLAGS']
            if OSX==1:
                env['LINKFLAGS']=['-Wl,-stack_size,0x40000000'] # Give OS X 1G stack
            env.Append(FORTRANFLAGS=['-Wno-aliasing','-Wno-unused','-Wno-unused-dummy-argument','-cpp','-m64','-ffree-form','-ffree-line-length-0','-fconvert=big-endian'])
            #env.Append(FORTRANFLAGS=['-mcmodel=large'])
#env['F95FLAGS']=['-Wno-aliasing','-Wno-unused','-Wno-unused-dummy-argument','-cpp','-m64','-mcmodel=medium','-ffree-form','-ffree-line-length-0','-fconvert=big-endian']
            env['F95FLAGS']=['-Wno-aliasing','-Wno-unused','-Wno-unused-dummy-argument','-cpp','-m64','-ffree-form','-ffree-line-length-0','-fconvert=big-endian']
            env.Append(F95FLAGS=env['CFLAGS'])
        else :
            env['CFLAGS'].pop(0)
            env['CFLAGS'].pop(0)
            env['CFLAGS'].pop(0)
            env['FORTRANFLAGS']=env['CFLAGS']
            if ('PGFORTRAN' in os.environ and env['FORTRAN'] == os.environ['PGFORTRAN']) :
                env.Append(FORTRANFLAGS=['-cpp','-m64','-fast','-Mfree','-Mipa=fast'])
                env['F95FLAGS']=env['FORTRANFLAGS']
            else:
                print('Unknown compiler, no options specified.')
        if useOclWrapper:
            if useDyn=='1':
                flib = env.SharedLibrary('OclWrapperF', [oclsources,OPENCL_DIR+'/OpenCLIntegration/OclWrapperF.cc'])
            else:
                flib = env.Library('OclWrapperF', [oclsources,OPENCL_DIR+'/OpenCLIntegration/OclWrapperF.cc'])
            fflib = env.Object('oclWrapper.o',OPENCL_DIR+'/OpenCLIntegration/oclWrapper.f95')
    if useOclWrapper:
        if useFC=='1':
            if useDyn=='1':
                flib = env.SharedLibrary('OclWrapperF', [oclsources,OPENCL_DIR+'/OpenCLIntegration/OclWrapperF.cc'])
            else:
                flib = env.Library('OclWrapperF', [oclsources,OPENCL_DIR+'/OpenCLIntegration/OclWrapperF.cc'])
        if useDyn=='1':
            lib = env.Library('OclWrapper',oclsources)
        else:
            lib = env.Library('OclWrapper',oclsources)
        env.Append(LIBPATH=['.',OPENCL_DIR+'/OpenCLIntegration/'])
    else:
        env.Append(LIBPATH=['.'])
# WRONG: -lOpenCL -lstdc++ -lOclWrapperF -lOclWrapper
# SHOULD BE: -lOclWrapperF -lOclWrapper -lOpenCL -lstdc++
    if useOclWrapper:
        if useF=='1':
            env.Append(LIBS=['stdc++'])
            env.Install(OPENCL_DIR+'/OpenCLIntegration/lib', flib)
            env.Alias('installf',OPENCL_DIR+'/OpenCLIntegration/lib', flib)
            env.Prepend(LIBS=['OclWrapper'])
            env.Prepend(LIBS=['OclWrapperF'])
        elif useFC=='1':
            # env.Append(LIBS=['stdc++'])
            env.Install(OPENCL_DIR+'/OpenCLIntegration/lib', flib)
            env.Alias('installf',OPENCL_DIR+'/OpenCLIntegration/lib', flib)
            env.Prepend(LIBS=['OclWrapper'])
            env.Prepend(LIBS=['OclWrapperF'])
        else:
            env.Prepend(LIBS=['OclWrapper'])
        env.Install(OPENCL_DIR+'/OpenCLIntegration/lib', lib)
        env.Alias('install',OPENCL_DIR+'/OpenCLIntegration/lib', lib)
    return env

def build(appname,sources):
    global opts, OPENCL_DIR
    env = initOcl()
    env.Program(appname+'_'+dev+'_'+plat+'_'+kernel,sources)

def buildF(env,appname,sources):
    global opts, OPENCL_DIR
#    VariantDir('.',OPENCL_DIR+'/OpenCLIntegration/')
    if useF=='1':
        env.Program(appname+'_'+dev+'_'+plat+'_'+kernel,sources+['oclWrapper.o'])
    else:
        env.Program(appname+'_'+dev+'_'+plat+'_'+kernel,sources)

def getPlatDevIdxFromPlatDec(plat,dev):
    res =  subprocess.check_output( ['perl', OPENCL_DIR+'/OpenCLIntegration/get-plat-dev-idx-from-clinfo.pl',plat,dev])
    dec_res = res.decode()
    res_array = list(map(int, dec_res.split(',')))
    # print(plat,dev,res_array)
    # [platidx,devidx, status]
    # status:
    # 0: success
    # 1: invalid platidx
    # 2: invalid devidx
    return res_array


# -*- coding: utf-8 -*-

import os
import string
import re

def slugify(value):
    """Converts to lowercase, removes non-alpha chars
    and converts spaces to hyphens"""
    value = re.sub('[^\w\s-]', '', value).strip().lower()
    return re.sub('[-\s]+', '-', value)

def validate_ISBN10(isbn):
    """
    Validate ISBN10 code. Returns the ISBN or False if is not valid.
    """
    isbn = isbn.replace("-", "").replace(" ", "")

    if len(isbn) == 10 and not [x for x in isbn if x not in (
            string.digits + "X")]:

        total = 0
        for i in range(9):
            total += int(isbn[i]) * (10 - i)
        z = (11 - (total % 11)) % 11
        if (z == 10 and isbn[-1] == 'X') or ("%d" % z == isbn[-1]):
            return isbn
        else:
            return False

def validate_ISBN13(isbn):
    """
    Validate ISBN13 code. Returns the ISBN or False if is not valid.
    """
    # El chequeo para ISBN de 13 digitos sale de:
    # ref:
    # http://en.wikipedia.org/wiki/International_Standard_Book_Number#ISBN-13

    isbn = isbn.replace("-", "").replace(" ", "")

    if len(isbn) == 13 and not [x for x in isbn if x not in string.digits]:
        i = 1
        total = 0
        for n in isbn[:-1]:
            total = total + i * int(n)
            if i == 1:
                i = 3
            else:
                i = 1
        check = 10 - (total % 10)
        if check == int(isbn[-1]):
            return isbn
        else:
            return False

def validate_ISBN(isbn):
    """
    Validate ISBN13 or ISBN10 code. Returns the ISBN or False if any is valid.
    """
    return validate_ISBN10(isbn) or validate_ISBN13(isbn)

SCRIPTPATH = os.path.abspath(os.path.dirname(__file__))
BASEPATH = os.path.expanduser(os.path.join('~', '.aranduka'))
BOOKPATH = os.path.join(BASEPATH, 'ebooks')
COVERPATH = os.path.join(BASEPATH, 'covers')
PLUGINPATH = [os.path.join(BASEPATH, 'plugins'),
              os.path.join(SCRIPTPATH, 'plugins')]

for P in [SCRIPTPATH, BASEPATH, BOOKPATH, COVERPATH] + PLUGINPATH:
    if not os.path.isdir(P):
        os.makedirs(P)

VALID_EXTENSIONS = ['epub', 'fb2', 'mobi', 'pdf', 'txt',
                    'lit', 'html', 'htm', 'cbz', 'cbr', 'cb7']


import torch.nn as nn
import config
from models.base_model import TrashBaseClass

class TrashBaseline(TrashBaseClass):
    def __init__(self, *args, **kwargs):
        super().__init__()
        self.net = nn.Sequential(
            nn.Flatten(),
            nn.Linear(config.IMAGE_SIZE * config.IMAGE_SIZE *
                      config.INPUT_CHANNELS, 64),
            nn.ReLU(),
            nn.Linear(64, 64),
            nn.ReLU(),
            nn.Linear(64, 64),
            nn.ReLU(),
            nn.Linear(64, config.NUM_CLASSES)
        )

    def forward(self, x):
        return self.net(x)


from collections import defaultdict, deque
from itertools import cycle
from math import atan2, pi

from .registry import register
from .utils import Vector, normalize_angle

@register(day=10)
def solve(file, verbose):
    asteroids = set()

    for y, line in enumerate(file):
        for x, char in enumerate(line.strip()):
            if char == '#':
                asteroids.add(Vector(x, y))

    observed = defaultdict(set)
    byangle = defaultdict(lambda: defaultdict(deque))

    for station in asteroids:
        for asteroid in asteroids:
            if station == asteroid:
                continue

            rel = asteroid - station

            # rotate angle by 90° because the laser starts pointing up.
            angle = normalize_angle(atan2(rel.y, rel.x) + pi / 2, center=pi)
            observed[station].add(angle)
            byangle[station][angle].append(asteroid)

    best = max(observed.items(), key=lambda x: len(x[1]))
    print('Part 1:', len(best[1]))

    station = best[0]

    blasted = []

    for angle in cycle(sorted(byangle[station])):
        try:
            target = byangle[station][angle].popleft()
        except IndexError:
            continue

        blasted.append(target)

        if len(blasted) == 200:
            found = blasted[-1]
            print('Part 2:', found.x * 100 + found.y)
            break