import numpy as np
from algorithms import metrics
from collections import defaultdict
from scipy.stats import mannwhitneyu

def evaluate(models, models_q=None):
    """
    Evaluates the models based on some evaluation metrics. This includes the model after q recommendation queries and
    also the models after all recommendation queries are processed.
    :param models: List of models
    :param models_q: List of models after each recommendation query
    :return: dict() where the key is the evaluation metric and the value is the average value over all users; and without
    the average
    """
    results, results_samples = _evaluate(models)
    if models_q is not None:
        results_q, results_q_samples = _evaluate_q(models_q)
        return {**results, **results_q}, {**results_samples, **results_q_samples}
    else:
        return {**results, **results_samples}

def _evaluate_q(models):
    """
    Evaluates the models after q recommendation queries
    :param models: List of models
    :return: dict() where the key is the evaluation metric and the value is the average value over all users; and without
    the average
    """
    results = defaultdict(list)
    results_samples = defaultdict(list)
    for k_idx, m in enumerate(models):
        avg, sample = metrics.avg_neighborhood_size_q(m, n_queries=100)
        results["avg_neighborhood_size_q"].append(avg)
        results_samples["avg_neighborhood_size_q"].append(sample)
        avg, sample = metrics.avg_rating_overlap_q(m, n_queries=100)
        results["avg_rating_overlap_q"].append(avg)
        results_samples["avg_rating_overlap_q"].append(sample)
    return results, results_samples

def _evaluate(models, users=None):
    """
    Evaluates the models after all recommendation queries
    :param models: List of models
    :return: dict() where the key is the evaluation metric and the value is the average value over all users; and without
    the average
    """
    results = defaultdict(list)
    results_samples = defaultdict(list)
    for k_idx, m in enumerate(models):
        avg, sample = metrics.mean_absolute_error(m, users=users)
        results["mean_absolute_error"].append(avg)
        results_samples["mean_absolute_error"].append(sample)
        avg, sample = metrics.avg_privacy_risk_dp(m, users=users)
        results["avg_privacy_risk_dp"].append(avg)
        results_samples["avg_privacy_risk_dp"].append(sample)
        avg, sample = metrics.avg_privacy_risk(m, users=users)
        results["avg_privacy_risk"].append(avg)
        results_samples["avg_privacy_risk"].append(sample)
        avg, sample = metrics.ndcg(m, users=users)
        results["avg_ndcg"].append(avg)
        results_samples["avg_ndcg"].append(sample)

        frac_vulnerables = metrics.fraction_vulnerables(m, users=users)
        results["fraction_vulnerables"].append(frac_vulnerables)
        if 1 - frac_vulnerables > 0:
            below_threshold_pr = (m.privacy_risk[m.privacy_risk < m.threshold])

        else:
            # if there are no secures
            below_threshold_pr = [0]
        results["avg_privacy_risk_dp_secures"].append(np.mean(below_threshold_pr))
        results_samples["avg_privacy_risk_dp_secures"].append(below_threshold_pr)

        results["recommendation_frequency"].append(metrics.recommendation_frequency(m, n=10, users=users))

    return results, results_samples

def significance_tests(results1, results2):
    """
    Performs significance tests between results1 and results2
    :param results1: user-wise values for the evaluation metrics
    :param results2: user-wise values for the evaluation metrics
    :return: dictionary of results of the significance tests
    """
    significance = dict()

    mae_significance = dict()
    mae_significance["<"] = _significance_test(results1["mean_absolute_error"], results2["mean_absolute_error"], h0="<")
    mae_significance[">"] = _significance_test(results1["mean_absolute_error"], results2["mean_absolute_error"], h0=">")
    mae_significance["=="] = _significance_test(results1["mean_absolute_error"], results2["mean_absolute_error"], h0="==")
    significance["mean_absolute_error"] = mae_significance

    pr_significance = dict()
    pr_significance["<"] = _significance_test(results1["avg_privacy_risk_dp"], results2["avg_privacy_risk_dp"], h0="<")
    pr_significance[">"] = _significance_test(results1["avg_privacy_risk_dp"], results2["avg_privacy_risk_dp"], h0=">")
    pr_significance["=="] = _significance_test(results1["avg_privacy_risk_dp"], results2["avg_privacy_risk_dp"], h0="==")
    significance["privacy_risk_dp"] = pr_significance

    pr_secure_significance = dict()
    pr_secure_significance["<"] = _significance_test(results1["avg_privacy_risk_dp_secures"], results2["avg_privacy_risk_dp_secures"], h0="<")
    pr_secure_significance[">"] = _significance_test(results1["avg_privacy_risk_dp_secures"], results2["avg_privacy_risk_dp_secures"], h0=">")
    pr_secure_significance["=="] = _significance_test(results1["avg_privacy_risk_dp_secures"], results2["avg_privacy_risk_dp_secures"], h0="==")
    significance["privacy_risk_dp_secures"] = pr_secure_significance

    neighborhood_size_significance = dict()
    neighborhood_size_significance["<"] = _significance_test_q(results1["avg_neighborhood_size_q"], results2["avg_neighborhood_size_q"], h0="<")
    neighborhood_size_significance[">"] = _significance_test_q(results1["avg_neighborhood_size_q"], results2["avg_neighborhood_size_q"], h0=">")
    neighborhood_size_significance["=="] = _significance_test_q(results1["avg_neighborhood_size_q"], results2["avg_neighborhood_size_q"], h0="==")
    significance["avg_neighborhood_size_q"] = neighborhood_size_significance

    rating_overlap_significance = dict()
    rating_overlap_significance["<"] = _significance_test_q(results1["avg_rating_overlap_q"], results2["avg_rating_overlap_q"], h0="<")
    rating_overlap_significance[">"] = _significance_test_q(results1["avg_rating_overlap_q"], results2["avg_rating_overlap_q"], h0=">")
    rating_overlap_significance["=="] = _significance_test_q(results1["avg_rating_overlap_q"], results2["avg_rating_overlap_q"], h0="==")
    significance["avg_rating_overlap_q"] = rating_overlap_significance

    return significance

def _mann_whitney_u_test(x, y, alternative="less"):
    """
    performs the mann whitney u test
    :param x: first sample
    :param y: second sample
    :param alternative: alternative hypothesis
    :return: U score, p value and effect size r
    """
    u, p = mannwhitneyu(x, y, alternative=alternative)
    nx = len(x)
    ny = len(y)
    mu_u = (nx * ny) / 2
    sigma_u = np.sqrt(nx * ny * (nx + ny + 1) / 12)
    z = (u - mu_u) / sigma_u
    n = len(x) + len(y)
    r = z / np.sqrt(n)

    return u, p, r

def _significance_test_q(x, y, h0="<"):
    """
    preforms significance tests after q recommendation queries
    :param x: first sample
    :param y: second sample
    :param h0: null hypothesis
    :return: list of results (for every q one result dict)
    """
    n_ks = len(x)
    results = []
    for k_idx in range(n_ks):
        n_queries = len(x[k_idx])
        results_k = []
        for q in range(n_queries):
            n_samples = len(x[k_idx][q])
            if np.array_equal(x[k_idx][q], y[k_idx][q]):
                results_k.append({"p": np.inf, "sample_size": n_samples, "r": np.nan, "U": np.nan})
            elif h0 == "<":
                u, p, r = _mann_whitney_u_test(x[k_idx][q], y[k_idx][q], alternative="greater")
                results_k.append({"p": p, "sample_size": n_samples, "r": r, "U": u})
            elif h0 == ">":
                u, p, r = _mann_whitney_u_test(x[k_idx][q], y[k_idx][q], alternative="less")
                results_k.append({"p": p, "sample_size": n_samples, "r": r, "U": u})
            elif h0 == "==":
                u, p, r = _mann_whitney_u_test(x[k_idx][q], y[k_idx][q], alternative="two-sided")
                results_k.append({"p": p, "sample_size": n_samples, "r": r, "U": u})
            else:
                print("Unknown h0!")
        results.append(results_k)

    return results

def _significance_test(x, y, h0="<"):
    """
    preforms significance tests after all recommendation queries
    :param x: first sample
    :param y: second sample
    :param h0: null hypothesis
    :return: list of results (for every q one result dict)
    """
    n_ks = len(x)
    n_samples = len(x[0])

    #n_ks, n_samples = np.array(x).shape
    results = []
    for k_idx in range(n_ks):
        if np.array_equal(x[k_idx], y[k_idx]):
            print("x equal y")
            results.append({"p": np.inf, "sample_size": n_samples, "r": np.nan, "U": np.nan})
        elif h0 == "<":
            u, p, r = _mann_whitney_u_test(x[k_idx], y[k_idx], alternative="greater")
            results.append({"p": p, "sample_size": n_samples, "r": r, "U": u})
        elif h0 == ">":
            u, p, r = _mann_whitney_u_test(x[k_idx], y[k_idx], alternative="less")
            results.append({"p": p, "sample_size": n_samples, "r": r, "U": u})
        elif h0 == "==":
            u, p, r = _mann_whitney_u_test(x[k_idx], y[k_idx], alternative="two-sided")
            results.append({"p": p, "sample_size": n_samples, "r": r, "U": u})
        else:
            print("Unknown h0!")

    return results


class Solution:
    def numJewelsInStones(self, jewels: str, stones: str) -> int:
        num = 0
        checked = []
        for char in jewels:
            for character in stones:
                if char == character and char not in checked:
                    num += 1
            checked.append(char)
        return num


# -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import
from .. import enginefactory as ef
from .. import expr as e

def test_EngineFactory():
    reload(ef)
    ef.EngineFactory.set_engineclass(ef.PyEngine)
    col = [e.Column(i) for i in range(10)]
    q = (col[1]=="hoge") & (col[2]=="fuga") & (col[4]=="poyo") | (col[2]=="hogera") & (col[5]=="piyo")
    eng = ef.compile_query(q)
    colids = {colname: cid for cid, colname in enumerate((1,2,4,5))}
    assert eng
    print(q)
    print(eng.format())
    state = 0
    col = colids[1]
    op = eng.exprs
    # 最初は =hoge
    a = eng.expr_table[state][col]
    assert ('=', 'hoge') == op[ a ]

    # 成功したら次は =fuga or =hogera
    state = eng.success_table[state][col]
    col = colids[2]
    a = eng.expr_table[state][col]
    assert ('=', 'fuga') == op[ a ] or ('=', 'hogera') == op[ a ]

    if op[a] == ('=', 'fuga'):
        state0 = eng.success_table[state][col]
        state1 = eng.fail_table[state][col]
        assert ('=', 'hogera') == op[ eng.expr_table[state0][col] ]
        assert ('=', 'hogera') == op[ eng.expr_table[state1][col] ]
    elif op[a] == ('=', 'hogera'):
        state0 = eng.success_table[state][col]
        state1 = eng.fail_table[state][col]
        assert ('=', 'fuga') == op[ eng.expr_table[state0][col] ]
        assert ('=', 'fuga') == op[ eng.expr_table[state1][col] ]

    # =fugaに成功したら =hogeraの次は=poyo
    # さらに成功したら終了
    state = eng.success_table[state0][col]
    col = colids[4]
    assert ('=', 'poyo') == op[ eng.expr_table[state][col] ]
    assert eng.success == eng.success_table[state][col]

def test_Engine():
    reload(ef)
    ef.EngineFactory.set_engineclass(ef.PyEngine)
    col = [e.Column(i) for i in range(10)]
    q = (col[1]=="hoge") & (col[2]=="fuga") & (col[4]=="poyo") | (col[2]=="hogera") & (col[5]=="piyo")
    eng = ef.compile_query(q)
    assert eng
    print(q)
    print(eng.format())
    colids = {colname: cid for cid, colname in enumerate((1,2,4,5))}
    for colid, c in enumerate(['aa', 'hoge', 'fuga', 'bbb', 'poyo', 'fa']):
        if colid in colids:
            print(colids[colid], c)
            eng.transition(colids[colid], c)

        if eng.is_success: break

    assert eng.is_success
    eng.reset()
    for colid, c in enumerate(['aa', 'hoge', 'hogera', 'bbb', 'poyo', 'piyo']):
        if colid in colids:
            eng.transition(colids[colid], c)

        if eng.is_success: break

    assert eng.is_success

    eng.reset()
    for colid, c in enumerate(['aa', 'hoge', 'hogera', 'bbb', 'poyo', 'uuu']):
        if colid in colids:
            eng.transition(colids[colid], c)

        if eng.is_success: break
        if eng.is_fail: break

    assert eng.is_fail

def test_EngineFactory2():
    reload(ef)
    ef.EngineFactory.set_engineclass(ef.PyEngine)
    col = [e.Column(i) for i in range(10)]
    q = (col[0]=="a")
    eng = ef.compile_query(q)
    assert eng
    print(eng.format())

def test_EngineFactory3():
    reload(ef)
    ef.EngineFactory.set_engineclass(ef.PyEngine)
    col = [e.Column(i) for i in range(10)]
    q = (col[2] >= "hoge") & (col[0]=='a') & (col[2]<='hoge')
    eng = ef.compile_query(q)
    assert eng
    print(eng.format())
    assert eng.success_table[0][0]!=1

def test_EngineFactory4():
    cols = [e.Column(i) for i in range(10)]
    q = (cols[1]=='hoge') | (cols[2]=='fuga') & (cols[4]=='poyo') | (cols[2]=='hogera') & (cols[5]=='piyo')
    ef.EngineFactory.set_engineclass(ef.PyEngine)
    eng = ef.compile_query(q)
    assert eng
    print(q)
    print(eng.format())

def test_EngineFactory5():
    cols = [e.Column(i) for i in range(10)]
    q = (cols[0] >= '2014-10-03 12:00:00') & (cols[0] < '2014-10-03 12:02:00') & (cols[1]=='hoge')
    ef.EngineFactory.set_engineclass(ef.PyEngine)
    eng = ef.compile_query(q)
    print(q)
    print(eng.format())
    data = [
        ["2014-10-03 12:00:11", "hoge"],
        ["2014-10-03 12:01:11", "hoge"],
        ["2014-10-03 12:01:11", "fuga"],
        ["2014-10-03 12:10:11", "hoge"],
        ]
    cnt = 0
    for row in data:
        eng.reset()
        for colid, val in enumerate(row):
            eng.transition(colid, val)

        if eng.is_success:
            cnt += 1

    assert 2 == cnt


from django.contrib.auth import login, logout
from django.contrib.auth.models import User
from django.core.mail import send_mail
from django.http import HttpResponse
from django.shortcuts import render, redirect
from django.urls import reverse_lazy, reverse
from django.conf import settings

from django.views import View
from django.views.generic import ListView, DetailView, DeleteView, UpdateView, CreateView

from Tours_app.forms import LoginForm, SignUpForm, EmailForm
from Tours_app.models import Tour, Review, Category, Reservation

class HomePageView(View):
    def get(self, request):
        return render(request, 'base.html')

class AboutPageView(View):
    def get(self, request):
        return render(request, 'about.html')

class TourListView(ListView):
    def get(self, request):
        tours = Tour.objects.all()
        types = Category.objects.all()
        return render(request, 'tourlist.html', {'objects':tours , 'types': types})

class CategoryListView(View):
    def get(self, request, pk):
        category = Category.objects.get(pk=pk)
        return render(request, 'categories.html', {'category': category})

class AddTourView(CreateView):
    model = Tour
    fields = ['name', 'days', 'start_date', 'end_date', 'category', 'price']
    template_name = 'touraddform.html'

    def get_success_url(self):
        tour = self.object
        url = reverse('tourlist')
        return url

class UpdateTourView(UpdateView):
    model = Tour
    fields = ['name', 'days', 'start_date', 'end_date', 'category', 'price']
    template_name = 'tourupdate.html'

    def get_success_url(self):
        tour = self.object
        tour.save()
        url = reverse('tourlist')
        return url

class DeleteTourView(DeleteView):
    model = Tour
    template_name = 'tourdelete.html'
    success_url = reverse_lazy('tourlist')

class LoginView(View):
    def get(self, request):
        form = LoginForm()
        return render(request, 'loginform.html', {'form': form})

    def post(self, request):
        loginForm = LoginForm(request.POST)
        if loginForm.is_valid():
            login(request, loginForm.user)
            return redirect("/")
        return render(request, 'loginform.html', {'form': loginForm})

class LogoutView(View):
    def get(self, request):
        logout(request)
        return redirect('/')

class SignUp(View):
    def get(self, request):
        form = SignUpForm()
        return render(request, 'signupform.html', {'form': form})

    def post(self, request):
        form = SignUpForm(request.POST)
        if form.is_valid():
            del form.cleaned_data['re_password']
            User.objects.create_user(**form.cleaned_data)
            return redirect('/')
        return render(request, 'signupform.html', {'form': form})

class AddReviewView(CreateView):
    model = Review
    fields = '__all__'
    template_name = 'reviewform.html'

    def get_success_url(self):
        review = self.object
        url = reverse('review')
        return url

class ReviewView(ListView):
    def get(self, request):
        reviews = Review.objects.all()
        return render(request, 'reviewlist.html', {'reviews': reviews})

class TourDetails(DetailView):
    model = Tour
    fields = '__all__'
    template_name = 'tourdetails.html'

    def get_success_url(self):
        tour = self.object
        url = reverse('tourdetails', args=(tour.id))
        return url

class ContactView(View):
    def get(self, request):
        form = EmailForm()
        return render(request, 'contact.html', {'form': form})

    def post(self, request):
        form = EmailForm(request.POST)
        if form.is_valid():
            cd = form.cleaned_data
            subject = "Kontakt z adventuretours"
            imie = cd['imie']
            tekst = cd['tekst']
            send_mail(subject, imie, settings.DEFAULT_FROM_EMAIL, [cd['odbiorca']])
            messageSent = True
        else:
            form = EmailForm()
        return render(request, 'contact.html', {
            'form': form,
            'messageSent': messageSent,

        })

class ReservationView(CreateView):
    model = Reservation
    fields = '__all__'
    template_name = 'reservationform.html'

    def get_success_url(self):
        url = reverse('reservation')
        return url

class ReservationList(View):
    def get(self, request):
        tour = Tour.objects.all()
        reservation = Reservation.objects.all()
        return render(request, 'reservationlist.html', {'reservation': reservation, 'tour': tour})


import copy
import re
import string
from pprint import pprint

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from tqdm import tqdm

# %%

elevation = np.array([list(line) for line in pd.read_csv('input', header=None)[0].values])

start_pos = tuple([i.item() for i in np.where(elevation == 'S')])
end_pos = tuple([i.item() for i in np.where(elevation == 'E')])
elevation[start_pos] = 'a'
elevation[end_pos] = 'z'

vfunc = np.vectorize(string.ascii_lowercase.index)
elevation = vfunc(elevation)

# %%

# add ring of zeros
elev_mat = np.full((elevation.shape[0] + 2, elevation.shape[1] + 2), -1, dtype=float)
elev_mat[1:-1, 1:-1] = elevation
start_pos = tuple([i + 1 for i in start_pos])
end_pos = tuple([i + 1 for i in end_pos])

# %%

import heapq
import sys

class Graph:

    def __init__(self):
        self.vertices = {}

    def add_vertex(self, name, edges):
        self.vertices[name] = edges

    def shortest_path(self, start, finish):
        distances = {}  # Distance from start to node
        previous = {}  # Previous node in optimal path from source
        nodes = []  # Priority queue of all nodes in Graph

        for vertex in self.vertices:
            if vertex == start:  # Set root node as distance of 0
                distances[vertex] = 0
                heapq.heappush(nodes, [0, vertex])
            else:
                distances[vertex] = sys.maxsize
                heapq.heappush(nodes, [sys.maxsize, vertex])
            previous[vertex] = None

        while nodes:
            smallest = heapq.heappop(nodes)[1]  # Vertex in nodes with smallest distance in distances
            if smallest == finish:  # If the closest node is our target we're done so print the path
                path = []
                while previous[smallest]:  # Traverse through nodes til we reach the root which is 0
                    path.append(smallest)
                    smallest = previous[smallest]
                return path
            if distances[smallest] == sys.maxsize:  # All remaining vertices are inaccessible from source
                # print('inaccessible')
                break

            for neighbor in self.vertices[smallest]:  # Look at all the nodes that this vertex is attached to
                alt = distances[smallest] + self.vertices[smallest][neighbor]  # Alternative path distance
                if alt < distances[neighbor]:  # If there is a new shortest path update our priority queue (relax)
                    distances[neighbor] = alt
                    previous[neighbor] = smallest
                    for n in nodes:
                        if n[1] == neighbor:
                            n[0] = alt
                            break
                    heapq.heapify(nodes)
        return distances

    def __str__(self):
        return str(self.vertices)

# %%

for scenic in [False, True]:  # True for part 2
    g = Graph()  # create graph
    for i in range(1, elev_mat.shape[0] - 1):
        for j in range(1, elev_mat.shape[1] - 1):
            neighbors = [(i + 1, j), (i, j + 1), (i - 1, j), (i, j - 1)]
            neighbor_dict = {neig: 1 for neig in neighbors if ((elev_mat[neig] - elev_mat[i, j]) <= 1) and (elev_mat[neig] != -1)}
            if ((i, j) == start_pos) and scenic:
                neighbor_dict.update({(ii, jj): 0 for ii, jj in zip(*np.where(elev_mat == 0))})
            g.add_vertex((i, j),  neighbor_dict)

            # g.add_vertex((i, j),  {neig: 1 for neig in neighbors if ((elev_mat[neig] - elev_mat[i, j]) <= 1) and (elev_mat[neig] != -1)})

    shortest = g.shortest_path(start_pos, end_pos)

    if scenic:
        # minus one because of old start tile
        print(f'shortest path length: {len(shortest) - 1}')
    else:
        print(f'shortest path length: {len(shortest)}')

    elev_mat_img = elev_mat.copy()
    plt.figure(figsize=(14, 14))
    plt.plot(np.array(shortest).T[1], np.array(shortest).T[0], color='orange', lw=1)
    plt.plot(start_pos[1], start_pos[0], marker='x', color='red', ms='5')
    plt.plot(end_pos[1], end_pos[0], marker='x', color='red', ms=6)
    plt.imshow(elev_mat_img, origin='upper')
    plt.show()

# %%


import requests
import json

def get_apikey(file):
    with open(file, "rt") as f:
        api_key = f.read()
    return api_key

def check_beer(file_token, url):
    param = {
        "apiKey": get_apikey(file_token),
        "in": "circle:21.01595,105.82301;r=2000",
        "q": 'beer+bia+bar',
        "limit": 50,
    }
    r = requests.get(url, params=param)
    result = {"type": "FeatureCollection",
              "features": []
              }
    nearbeer = r.json()
    for i in nearbeer["items"]:
        lat = i["position"]["lat"]
        lng = i["position"]["lng"]
        data = {
            "type": "Feature",
            "geometry": {"type": "Point", "coordinates": [lng, lat]},
            "properties": {"Address": i["address"]["label"],
                           "name": i["title"]},
        }
        result["features"].append(data)
    with open("pymi_beer.geojson", "wt", encoding="utf-8") as f:
        json.dump(result, f, ensure_ascii=False, indent=4)
    return result

def main():
    file = "token.text"
    url = "https://discover.search.hereapi.com/v1/discover"
    for i in check_beer(file, url)["features"]:
        print(i)
    print('link to my map :'
          'https://github.com/longhoang1912/ex9/blob/map/pymi_beer.geojson')

if __name__ == "__main__":
    main()


def abbreviation(s1, s2):
    n, m = len(s1), len(s2)
    dp = [[False] * (m+1) for _ in range(n+1)]

    # Initialize the DP table
    dp[0][0] = True
    for i in range(n):
        if s1[i].isupper():
            break
        else:
            dp[i+1][0] = True

    # Fill in the DP table
    for i in range(n):
        for j in range(m):
            if s1[i].upper() == s2[j]:
                dp[i+1][j+1] = dp[i+1][j+1] or dp[i][j]
            if s1[i].islower():
                dp[i+1][j+1] = dp[i+1][j+1] or dp[i][j+1]

    return 'YES' if dp[n][m] else 'NO'

print(abbreviation('AbCDE', 'ABDE'))


# CompOFA – Compound Once-For-All Networks for Faster Multi-Platform Deployment
# Under blind review at ICLR 2021: https://openreview.net/forum?id=IgIk8RRT-Z
#
# Implementation based on:
# Once for All: Train One Network and Specialize it for Efficient Deployment
# Han Cai, Chuang Gan, Tianzhe Wang, Zhekai Zhang, Song Han
# International Conference on Learning Representations (ICLR), 2020.

import argparse
import numpy as np
import os
import random

import horovod.torch as hvd
import torch

from ofa.elastic_nn.modules.dynamic_op import DynamicSeparableConv2d
from ofa.elastic_nn.networks import OFAMobileNetV3
from ofa.imagenet_codebase.run_manager import DistributedImageNetRunConfig
from ofa.imagenet_codebase.run_manager.distributed_run_manager import DistributedRunManager
from ofa.imagenet_codebase.data_providers.base_provider import MyRandomResizedCrop
from ofa.utils import download_url
from ofa.elastic_nn.training.progressive_shrinking import load_models

parser = argparse.ArgumentParser()
parser.add_argument('--task', type=str, default='depth', choices=[
    'kernel', 'depth', 'expand', 'compound', 'teacher',
])
parser.add_argument('--phase', type=int, default=1, choices=[1, 2])
parser.add_argument('--name', type=str, default='default')
parser.add_argument('--resume', action='store_true')
parser.add_argument('--fixed_kernel', action='store_true')
parser.add_argument('--heuristic', type=str, default='none', choices=['simple', 'none'])

args = parser.parse_args()
args.teacher_path = download_url('https://file.lzhu.me/projects/OnceForAll/ofa_checkpoints/ofa_D4_E6_K7',
                                 model_dir='./downloads')

args.manual_seed = 0

args.lr_schedule_type = 'cosine'

args.base_batch_size = 256
args.valid_size = None

args.opt_type = 'sgd'
args.momentum = 0.9
args.no_nesterov = False
args.weight_decay = 3e-5
args.label_smoothing = 0.1
args.no_decay_keys = 'bn#bias'
args.fp16_allreduce = False

args.model_init = 'he_fout'
args.validation_frequency = 1
args.print_frequency = 10

args.n_worker = 8
args.resize_scale = 0.08
args.distort_color = 'tf'
args.image_size = '128,160,192,224'
args.continuous_size = True
args.not_sync_distributed_image_size = False

args.bn_momentum = 0.1
args.bn_eps = 1e-5
args.dropout = 0.1
args.base_stage_width = 'proxyless'

args.width_mult_list = '1.0'
args.dy_conv_scaling_mode = -1
args.independent_distributed_sampling = False

args.kd_ratio = 1.0
args.kd_type = 'ce'

if args.task == 'kernel':
    args.path = f'runs/{args.name}/teacher2kernel'
    args.dynamic_batch_size = 1
    args.n_epochs = 120
    args.base_lr = 2.6 * args.base_batch_size/2048
    args.warmup_epochs = 5
    args.warmup_lr = -1
    args.ks_list = '3,5,7'
    args.expand_list = '6'
    args.depth_list = '4'
elif args.task == 'depth':
    args.path = f'runs/{args.name}/base2depth/phase{args.phase}'
    args.dynamic_batch_size = 2
    if args.phase == 1:
        args.n_epochs = 25
        args.base_lr = 0.08 * args.base_batch_size/2048
        args.warmup_epochs = 0
        args.warmup_lr = -1
        args.expand_list = '6'
        args.depth_list = '3,4'
        args.ks_list = '3,5,7'
    else:
        args.n_epochs = 120
        args.base_lr = 0.24*args.base_batch_size/2048
        args.warmup_epochs = 5
        args.warmup_lr = -1
        args.expand_list = '6'
        args.depth_list = '2,3,4'
        args.ks_list = '3,5,7'
elif args.task == 'expand':
    args.path = f'runs/{args.name}/depth2depth_width/phase{args.phase}'
    args.dynamic_batch_size = 4
    if args.phase == 1:
        args.n_epochs = 25
        args.base_lr = 0.08 * args.base_batch_size/2048
        args.warmup_epochs = 0
        args.warmup_lr = -1
        args.expand_list = '4,6'
        args.depth_list = '2,3,4'
        args.ks_list = '3,5,7'
    else:
        args.n_epochs = 120
        args.base_lr = 0.24*args.base_batch_size/2048
        args.warmup_epochs = 5
        args.warmup_lr = -1
        args.expand_list = '3,4,6'
        args.depth_list = '2,3,4'
        args.ks_list = '3,5,7'
elif args.task == 'teacher':
    args.path = f'runs/teacher/{args.name}'
    args.dynamic_batch_size = 1
    args.n_epochs = 180
    args.base_lr = 2.6 * args.base_batch_size / 2048
    args.warmup_epochs = 0
    args.warmup_lr = -1
    args.kd_ratio = 0.0
    args.expand_list = '3,4,6'
    args.depth_list = '2,3,4'
    args.ks_list = '3,5,7'
elif args.task == 'compound':
    assert(args.heuristic=='simple')
    args.path = f'runs/{args.name}/compound/phase{args.phase}'
    args.dynamic_batch_size = 4
    if args.phase == 1:
        args.n_epochs = 25
        args.base_lr = 0.08*args.base_batch_size/2048
        args.warmup_epochs = 0
        args.warmup_lr = -1
        args.expand_list = '3,4,6'
        args.depth_list = '2,3,4'
        args.ks_list = '3,5,7'
    else:
        args.n_epochs = 120
        args.base_lr = 0.24*args.base_batch_size/2048
        args.warmup_epochs = 5
        args.warmup_lr = -1
        args.expand_list = '3,4,6'
        args.depth_list = '2,3,4'
        args.ks_list = '3,5,7'
else:
    raise NotImplementedError

if __name__ == '__main__':
    os.makedirs(args.path, exist_ok=True)

    # Initialize Horovod
    hvd.init()
    # Pin GPU to be used to process local rank (one GPU per process)
    torch.cuda.set_device(hvd.local_rank())

    num_gpus = hvd.size()

    torch.manual_seed(args.manual_seed)
    torch.cuda.manual_seed_all(args.manual_seed)
    np.random.seed(args.manual_seed)
    random.seed(args.manual_seed)

    # image size
    args.image_size = [int(img_size) for img_size in args.image_size.split(',')]
    if len(args.image_size) == 1:
        args.image_size = args.image_size[0]
    MyRandomResizedCrop.CONTINUOUS = args.continuous_size
    MyRandomResizedCrop.SYNC_DISTRIBUTED = not args.not_sync_distributed_image_size

    # build run config from args
    args.lr_schedule_param = None
    args.opt_param = {
        'momentum': args.momentum,
        'nesterov': not args.no_nesterov,
    }
    args.init_lr = args.base_lr * num_gpus  # linearly rescale the learning rate
    if args.warmup_lr < 0:
        args.warmup_lr = args.base_lr
    args.train_batch_size = args.base_batch_size
    args.test_batch_size = args.base_batch_size * 2
    run_config = DistributedImageNetRunConfig(**args.__dict__, num_replicas=num_gpus, rank=hvd.rank())

    # print run config information
    if hvd.rank() == 0:
        print('Run config:')
        for k, v in run_config.config.items():
            print('\t%s: %s' % (k, v))

    if args.dy_conv_scaling_mode == -1:
        args.dy_conv_scaling_mode = None
    DynamicSeparableConv2d.KERNEL_TRANSFORM_MODE = args.dy_conv_scaling_mode

    # build net from args
    args.width_mult_list = [float(width_mult) for width_mult in args.width_mult_list.split(',')]
    args.ks_list = [int(ks) for ks in args.ks_list.split(',')]
    args.expand_list = [int(e) for e in args.expand_list.split(',')]
    args.depth_list = [int(d) for d in args.depth_list.split(',')]

    net = OFAMobileNetV3(
        n_classes=run_config.data_provider.n_classes, bn_param=(args.bn_momentum, args.bn_eps),
        dropout_rate=args.dropout, base_stage_width=args.base_stage_width, width_mult_list=args.width_mult_list,
        ks_list=args.ks_list, expand_ratio_list=args.expand_list, depth_list=args.depth_list,
        compound=(args.heuristic!='none'), fixed_kernel=args.fixed_kernel,
    )
    # teacher model
    if args.kd_ratio > 0:
        args.teacher_model = OFAMobileNetV3(
            n_classes=run_config.data_provider.n_classes, bn_param=(args.bn_momentum, args.bn_eps),
            dropout_rate=0, width_mult_list=1.0, ks_list=7, expand_ratio_list=6, depth_list=4,
        )
        args.teacher_model.cuda()

    """ Distributed RunManager """
    # Horovod: (optional) compression algorithm.
    compression = hvd.Compression.fp16 if args.fp16_allreduce else hvd.Compression.none
    distributed_run_manager = DistributedRunManager(
        args.path, net, run_config, compression, backward_steps=args.dynamic_batch_size, is_root=(hvd.rank() == 0)
    )

    if args.resume:
        distributed_run_manager.load_model()

    distributed_run_manager.save_config()
    # hvd broadcast
    distributed_run_manager.broadcast()

    # load teacher net weights
    if args.kd_ratio > 0:
        load_models(distributed_run_manager, args.teacher_model, model_path=args.teacher_path)

    # training
    from ofa.elastic_nn.training.progressive_shrinking import validate, train

    validate_func_dict = {'image_size_list': {224},
                          'width_mult_list': sorted({0, len(args.width_mult_list) - 1}),
                          'ks_list': None if args.fixed_kernel else sorted({min(args.ks_list), max(args.ks_list)}),
                          'expand_ratio_list': sorted({min(args.expand_list), max(args.expand_list)}),
                          'depth_list': sorted({min(net.depth_list), max(net.depth_list)})}

    if args.task == 'teacher':
        net.set_constraint([4], 'depth')
        net.set_constraint([6], 'expand_ratio')
        net.set_constraint([7], 'kernel_size')
        net.set_active_subnet(d=4, e=6, ks=7)
        train(distributed_run_manager, args,
                        lambda _run_manager, epoch, is_test: validate(_run_manager, epoch, is_test, **validate_func_dict))
    elif args.task == 'kernel':
        validate_func_dict['ks_list'] = sorted(args.ks_list)
        if distributed_run_manager.start_epoch == 0:
            # model_path = download_url('https://hanlab.mit.edu/files/OnceForAll/ofa_checkpoints/ofa_D4_E6_K7',
            #                           model_dir='.torch/ofa_checkpoints/%d' % hvd.rank())
            model_path = args.teacher_path
            load_models(distributed_run_manager, distributed_run_manager.net, model_path=model_path)
            distributed_run_manager.write_log('%.3f\t%.3f\t%.3f\t%s' %
                                              validate(distributed_run_manager, **validate_func_dict), 'valid')
        train(distributed_run_manager, args,
              lambda _run_manager, epoch, is_test: validate(_run_manager, epoch, is_test, **validate_func_dict))
    elif args.task == 'depth':
        from ofa.elastic_nn.training.progressive_shrinking import supporting_elastic_depth
        supporting_elastic_depth(train, distributed_run_manager, args, validate_func_dict)
    elif args.task == 'expand':
        from ofa.elastic_nn.training.progressive_shrinking import supporting_elastic_expand
        supporting_elastic_expand(train, distributed_run_manager, args, validate_func_dict)
    elif args.task == 'compound':
        from ofa.elastic_nn.training.progressive_shrinking import supporting_compound
        supporting_compound(train, distributed_run_manager, args, validate_func_dict)
    else:
        raise NotImplementedError


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

from scipy import stats

import numpy as np
import warnings

from ...compat import check_is_fitted
from .base import BaseEndogTransformer

__all__ = ['BoxCoxEndogTransformer']

class BoxCoxEndogTransformer(BaseEndogTransformer):
    r"""Apply the Box-Cox transformation to an endogenous array

    The Box-Cox transformation is applied to non-normal data to coerce it more
    towards a normal distribution. It's specified as::

        (((y + lam2) ** lam1) - 1) / lam1, if lmbda != 0, else
        log(y + lam2)

    Parameters
    ----------
    lmbda : float or None, optional (default=None)
        The lambda value for the Box-Cox transformation, if known. If not
        specified, it will be estimated via MLE.

    lmbda2 : float, optional (default=0.)
        The value to add to ``y`` to make it non-negative. If, after adding
        ``lmbda2``, there are still negative values, a ValueError will be
        raised.

    neg_action : str, optional (default="raise")
        How to respond if any values in ``y <= 0`` after adding ``lmbda2``.
        One of ('raise', 'warn', 'ignore'). If anything other than 'raise',
        values <= 0 will be truncated to the value of ``floor``.

    floor : float, optional (default=1e-16)
        A positive value that truncate values to if there are values in ``y``
        that are zero or negative and ``neg_action`` is not 'raise'. Note that
        if values are truncated, invertibility will not be preserved, and the
        transformed array may not be perfectly inverse-transformed.
    """
    def __init__(self, lmbda=None, lmbda2=0, neg_action="raise", floor=1e-16):

        self.lmbda = lmbda
        self.lmbda2 = lmbda2
        self.neg_action = neg_action
        self.floor = floor

    def fit(self, y, X=None):
        """Fit the transformer

        Learns the value of ``lmbda``, if not specified in the constructor.
        If defined in the constructor, is not re-learned.

        Parameters
        ----------
        y : array-like or None, shape=(n_samples,)
            The endogenous (time-series) array.

        X : array-like or None, shape=(n_samples, n_features), optional
            The exogenous array of additional covariates. Not used for
            endogenous transformers. Default is None, and non-None values will
            serve as pass-through arrays.
        """
        lam1 = self.lmbda
        lam2 = self.lmbda2

        if lam2 < 0:
            raise ValueError("lmbda2 must be a non-negative scalar value")

        if lam1 is None:
            y, _ = self._check_y_X(y, X)
            _, lam1 = stats.boxcox(y + lam2, lmbda=None, alpha=None)

        self.lam1_ = lam1
        self.lam2_ = lam2
        return self

    def transform(self, y, X=None, **kwargs):
        """Transform the new array

        Apply the Box-Cox transformation to the array after learning the
        lambda parameter.

        Parameters
        ----------
        y : array-like or None, shape=(n_samples,)
            The endogenous (time-series) array.

        X : array-like or None, shape=(n_samples, n_features), optional
            The exogenous array of additional covariates. Not used for
            endogenous transformers. Default is None, and non-None values will
            serve as pass-through arrays.

        Returns
        -------
        y_transform : array-like or None
            The Box-Cox transformed y array

        X : array-like or None
            The X array
        """
        check_is_fitted(self, "lam1_")

        lam1 = self.lam1_
        lam2 = self.lam2_

        y, exog = self._check_y_X(y, X)
        y += lam2

        neg_mask = y <= 0.
        if neg_mask.any():
            action = self.neg_action
            msg = "Negative or zero values present in y"
            if action == "raise":
                raise ValueError(msg)
            elif action == "warn":
                warnings.warn(msg, UserWarning)
            y[neg_mask] = self.floor

        if lam1 == 0:
            return np.log(y), exog
        return (y ** lam1 - 1) / lam1, exog

    def inverse_transform(self, y, X=None):
        """Inverse transform a transformed array

        Inverse the Box-Cox transformation on the transformed array. Note that
        if truncation happened in the ``transform`` method, invertibility will
        not be preserved, and the transformed array may not be perfectly
        inverse-transformed.

        Parameters
        ----------
        y : array-like or None, shape=(n_samples,)
            The transformed endogenous (time-series) array.

        X : array-like or None, shape=(n_samples, n_features), optional
            The exogenous array of additional covariates. Not used for
            endogenous transformers. Default is None, and non-None values will
            serve as pass-through arrays.

        Returns
        -------
        y : array-like or None
            The inverse-transformed y array

        X : array-like or None
            The inverse-transformed X array
        """
        check_is_fitted(self, "lam1_")

        lam1 = self.lam1_
        lam2 = self.lam2_

        y, exog = self._check_y_X(y, X)
        if lam1 == 0:
            return np.exp(y) - lam2, exog

        numer = y * lam1  # remove denominator
        numer += 1.  # add 1 back to it
        de_exp = numer ** (1. / lam1)  # de-exponentiate
        return de_exp - lam2, exog


# ian.heywood@physics.ox.ac.uk

import sys
import pickle
import time
import shutil

def stamp():
    return str(time.time()).replace('.','')

project_info = pickle.load(open('project_info.p','rb'))
ref_ant = project_info['ref_ant']
targets = project_info['target_list']

myuvrange = '>150m'

myms = sys.argv[3]

for target in targets:
    if target[2] == myms:
        target_name = target[0]

clearstat()
clearstat()

code = target_name[-3:]

gptab = 'cal_'+myms+'_'+target_name+'_'+stamp()+'.GP0'
gatab = 'cal_'+myms+'_'+target_name+'_'+stamp()+'.GA0'

gaincal(vis=myms,
    field='0',
    uvrange=myuvrange,
    caltable=gptab,
    refant = str(ref_ant),
    solint='192s',
    solnorm=False,
    combine='',
    minsnr=3,
    calmode='p',
    parang=False,
    gaintable=[],
    gainfield=[],
    interp=[],
    append=False)

gaincal(vis=myms,
    field='0',
    uvrange=myuvrange,
    caltable=gatab,
    refant = str(ref_ant),
    solint='inf',
    solnorm=False,
    combine='',
    minsnr=3,
    calmode='ap',
    parang=False,
    gaintable=[gptab],
    gainfield=[''],
    interp=[''],
    append=False)

applycal(vis=myms,
    gaintable=[gptab,gatab],
    field='0',
    calwt=False,
    parang=False,
    applymode='calonly',
    gainfield=['',''],
    interp = ['nearest','linear'])

# statwt(vis=myms,
#     field='0')

clearstat()
clearstat()


import numpy as np
import itertools
import names
import sys
from matplotlib import pyplot as plt

number_of_cities=int(sys.argv[1])
n_o_b=30
cities=[]

class City:
    def __init__(self,x,y,name):
        self.name=name
        self.x=x
        self.y=y

for i in range(number_of_cities):
    x=np.random.random()*100
    y=np.random.random()*100
    city=City(x,y,names.get_first_name())
    cities.append(city)

def fact(n):
    res=1
    for i in range(2,n+1):
        res*=i
    return res

def swap(array,i,j):
    temp=array[i]
    array[i]=array[j]
    array[j]=temp
    return array

def reverse_from(index,array):
    temp_array=[]
    for i in range(index,len(array)):
        temp_array.append(array.pop())
    for el in temp_array:
        array.append(el)
    return array

def trad_to_array(index_list,array):
    res=[]
    for i in index_list:
        res.append(array[i])
    return res

def get_largeY(array,index):
    ret_index=-1
    ret=0
    for i in range(len(array)):
        if array[index]<array[i]:
            ret=i
            if ret > ret_index:
                ret_index=ret
    return ret_index

def get_largeX(array):
    ret_index=-1
    for i in range(len(array)-1):
        if array[i]<array[i+1] and i > ret_index:
            ret_index=i
    if ret_index==-1:
        return None
    else:
        return ret_index

def each_possibility(array):
    load=0
    shuff_arrays=[]
    shuff_arrays.append(array)
    indexlist=list(range(len(array)))
    undred=fact(number_of_cities)
    print('Construction a list of each possibility')
    while True:
        load+=1
        percent=load/undred
        print(int(percent*n_o_b)*'*'+(n_o_b-int(percent*n_o_b))*'-'+'  '+str(round(percent*100,3))+'%', end="\r")
        X=get_largeX(indexlist)
        if X==None:
            return shuff_arrays
        Y=get_largeY(indexlist,X)
        indexlist=swap(indexlist,X,Y)
        indexlist=reverse_from(X+1,indexlist)
        temp_array=trad_to_array(indexlist,array)
        shuff_arrays.append(temp_array)

def dist_between(city1,city2):
    x_tmp=abs(city1.x-city2.x)
    y_tmp=abs(city1.y-city2.y)
    return np.sqrt(pow(x_tmp,2)+pow(y_tmp,2))

def search_for_the_best_path(cities):
    best_dist=float('inf')
    best_shuffl= []
    e_pos=each_possibility(cities)
    undred=len(e_pos)
    count=0
    print('Searching for the best path')
    print(' ')
    for shuff_cities in e_pos:
        percent=round(count/undred*n_o_b)
        print('Searching : '+percent*'*'+(n_o_b-percent)*'-', end="\r")
        count+=1
        tot_dist=0
        for i in range(len(shuff_cities)-1):
            tot_dist+=dist_between(shuff_cities[i],shuff_cities[i+1])
        if tot_dist < best_dist:
            best_shuffl=shuff_cities
            best_dist=tot_dist
    print('Completed!                                              ')
    return best_dist,best_shuffl

def print_result(dist,cities):
    traj=''
    print('')
    print('Best dist is around '+str(int(round(dist)))+'km')
    for city in cities:
        traj+=city.name+'-->'
    print(traj[:-3])

data=search_for_the_best_path(cities)

fig=plt.figure()
ax = plt.axes(xlim=(0, 200), ylim=(0, 100))
plt.xticks([]), plt.yticks([])

line, = ax.plot([], [], marker="o",lw=2,color="green")

x=[]
y=[]
for city in data[1]:
    x.append(city.x)
    y.append(city.y)
line.set_data(x, y)
plt.show()


import setuptools

with open("README.md", "r") as fh:
    long_description = fh.read()

setuptools.setup(
    name="jpegdupes",
    version="2.1.0",
    author="Jesús Jiménez",
    author_email="jesjimenez@gmail.com",
    description="Image duplicate finder that ignores JPEG metadata",
    long_description=long_description,
    long_description_content_type="text/markdown",
    keywords="image duplicate finder metadata jpeg",
    url="https://github.com/jesjimher/imgdupes",
    packages=setuptools.find_packages(),
    python_requires=">=3",
    install_requires=[
        "texttable",
        "jpegtran-cffi>0.5",
        "Pillow",
    ],
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
        "Operating System :: OS Independent",
    ],
    #    scripts=['jpegdupes/jpegdupes.py']
    entry_points={"console_scripts": ["jpegdupes=jpegdupes.jpegdupes:main"]},
)


from CdColour import *

class CdCalibrate():

    def __init__(self):
        self.__multiplier = None
        self.__shapeDetected = 0
        self.__allArcLength = []
        self.__squareArc = None

    def getColourBoundary(self, counter, colourStr):
        self.__multiplier = int(counter/5)
        boundary = self.increaseRange(self.__multiplier)
        col_boundary = CdColour(boundary,(255,0,0),colourStr)
        return col_boundary

    def docalibrate(self, shapeController, allShapes, counter, colourStr, col_boundary, shape):

        RunCode = True

        shapeFound = shapeController.shapeDetected(allShapes)

        # shapeFound = shapeController.detectShape(allShapes[0], shape)
        if (shapeFound == True):
            if allShapes[0].getShape() == shape:
                self.__shapeDetected += 1
                print('shape detected = ' + str(self.__shapeDetected))
                self.__allArcLength.append(allShapes[0].getArcLen())
                if (self.__shapeDetected > 5):
                    totalArcLength = 0
                    for i in self.__allArcLength:
                        totalArcLength += i
                    averageArcLength = totalArcLength / len(self.__allArcLength)
                    print('average arc length = ' + str(averageArcLength))
                    print('Max = ' + str(averageArcLength * 1.1))
                    print('Min = ' + str(averageArcLength * 0.9))
                    arcLengthValid = True
                    for i in self.__allArcLength:
                        print(i)
                        if ((averageArcLength * 0.9) < i < (averageArcLength * 1.1)):
                            print('pass')
                        else:
                            arcLengthValid = False
                            print('fail')
                    if (arcLengthValid):
                        self.__squareArc = averageArcLength
                        print('wawa = ' + str(self.__squareArc))
                        if (counter > 4):
                            boundary = self.increaseRange(1.5 + self.__multiplier)
                            col_boundary = CdColour(boundary, (255, 0, 0), colourStr)
                        tempColRange = col_boundary.getHsv()
                        print('weba = ' + str(tempColRange))
                        RunCode = False
                    else:
                        self.__shapeDetected = 0
                        self.__allArcLength = []
            else:
                self.__shapeDetected = 0
                self.__allArcLength = []
        else:
            self.__shapeDetected = 0
            self.__allArcLength = []

        return  RunCode, col_boundary

        # Need to find a counter / shape

    def getSquareArc(self):
        return  self.__squareArc

    def increaseRange(self, multiplier):
        Hmin = (99 * (0.95 ** multiplier))
        Hmax =  (123 * (1.05 ** multiplier))
        Vmin =  (121 * (0.95 ** multiplier))
        if (Hmin < 0):
            Hmin = 0
        if (Hmax > 180):
            Hmax = 180
        if (Vmin < 0):
            Vmin = 0
        boundary = [[Hmin, Hmax], [Vmin, 255], [0, 255]]
        return boundary


def load_data(file):
    output = []
    data = open(file, 'r')
    for line in data:
        output.append(line.strip())

    data.close()
    return output

class Screen:
    def __init__(self, height, width):
        self.height = height
        self.width = width
        self.grid = [["." for i in range(width)] for j in range(height)]

    def print_screen(self):
        for y in range(0, self.height):
            for x in range(0, self.width):
                print(self.grid[y][x], end="")
            print("")
        print("")

    def count_lit_pixels(self):
        counter = 0
        for y in range(0, self.height):
            for x in range(0, self.width):
                if self.grid[y][x] == "#":
                    counter += 1
        return counter

    def add_rectangle(self, rect_x, rect_y):
        for y in range(0, rect_y):
            for x in range(0, rect_x):
                self.grid[y][x] = "#"

    def rotate_x(self, col, shift):
        mod_shift = shift % self.height
        col_buffer = ["." for j in range(self.height)]
        # build buffer
        for y in range(0, self.height):
            col_buffer[(y + mod_shift) % self.height] = self.grid[y][col]

        # write buffer
        for y in range(0, self.height):
            self.grid[y][col] = col_buffer[y]

    def rotate_y(self, row, shift):
        mod_shift = shift % self.width
        row_buffer = ["." for j in range(self.width)]
        # build buffer
        for x in range(0, self.width):
            row_buffer[(x + mod_shift) % self.width] = self.grid[row][x]

        # write buffer
        for x in range(0, self.width):
            self.grid[row][x] = row_buffer[x]

if __name__ == "__main__":
    instructions = load_data("data_8")
    print(instructions)

    grid_height = 6
    grid_width = 50

    screen = Screen(grid_height, grid_width)

    for command in instructions:
        parsed = command.split(" ")
        if parsed[0] == "rect":
            split_coord = parsed[1].split("x")
            screen.add_rectangle(int(split_coord[0]), int(split_coord[1]))
        else:
            if parsed[1] == "row":
                screen.rotate_y(int(parsed[2].strip("y=")), int(parsed[4]))
            else:
                screen.rotate_x(int(parsed[2].strip("x=")), int(parsed[4]))

    screen.print_screen()
    print(f"Lit pixels = {screen.count_lit_pixels()}")


import numpy as np
import matplotlib.pyplot as plt
import sys

def demo_fass(feature, sample):
    X_tilda = np.load('X_tilda_feature{}.npy'.format(feature))
    T_tilda = np.load('T_tilda_feature{}.npy'.format(feature))
    prob = np.load('prob_feature{}.npy'.format(feature))
    t_max = np.max(T_tilda[sample])

    fig, axs = plt.subplots(2, 1)
    axs[0].plot(X_tilda[sample], T_tilda[sample], color='navy')
    # axs[0].set_xlabel('X feature: {} sample: {}'.format(feature, sample))
    axs[0].set_ylabel('t')
    # axs[0].hlines(t_true_sum, X_tilda[1, 0], X_tilda[1, -1], linestyles='--')
    axs[1].plot(X_tilda[sample], prob[sample], color='navy')
    axs[1].set_xlabel('X feature: {} sample: {}'.format(feature, sample))
    axs[1].set_ylabel('pdf')

    plt.ion()
    plt.show()
    plt.waitforbuttonpress()

    t_arr = np.linspace(0, t_max, 50)
    to_delete = []
    prob_list = []
    for t_iteration in t_arr:
        plt.pause(0.5)
        for td in to_delete:
            td.remove()
        to_delete = []
        to_delete.append(axs[0].hlines(t_iteration, X_tilda[1, 0], X_tilda[1, -1]))
        fill_index = T_tilda[sample] <= t_iteration
        x_fill = X_tilda[sample][fill_index]
        y_fill = T_tilda[sample][fill_index]
        prob_fill = prob[sample][fill_index]
        to_delete.append(axs[0].fill_between(x_fill, y_fill, color='navy', alpha=0.5))
        to_delete.append(axs[1].fill_between(x_fill, prob_fill, color='navy', alpha=0.5))
    plt.waitforbuttonpress()

if __name__ == '__main__':
    feature, sample = 0, 1
    demo_fass(feature, sample)


import os
import subprocess

import cfscrape
from bs4 import BeautifulSoup

requests = cfscrape.create_scraper()
escolha = 0

def option(numero=0):
    global escolha
    escolha = int(numero)

while True:
    busca = input("Nome do filme: ")
    busca = busca.split()
    termos_da_busca = []

    for item in range(len(busca) - 1):
        termos_da_busca.append(busca[item] + "+")

    concatenando = "".join(termos_da_busca)
    # busca[len(busca)-1] Retorna a último palavra capturada pelo input
    url = concatenando + busca[len(busca) - 1]
    url_final = "https://www.baixarfilmetorrent.net/?s=" + url

    print()
    print("Carregando lista de filmes...")
    print()

    req = requests.get(url_final)
    soup = BeautifulSoup(req.text, "html.parser")
    listagem_da_pesquisa = soup.find_all("div", {"class": "item"})

    titulos = []
    links = []

    for filme in listagem_da_pesquisa:
        titulos.append(str(filme).split('"')[5])
        links.append(str(filme).split('"')[3])

    for titulo in range(0, len(titulos)):
        print([titulo + 1], titulos[titulo])

    print()
    select_number = int(input("Selecione um número: "))
    lin = links[select_number - 1]

    link = requests.get(lin)
    soup = BeautifulSoup(link.text, "html.parser")
    tabelas = soup.find_all("table")

    resolut = []
    magnetico = []

    # Para filmes
    for tabela in range(0, len(tabelas)):
        single_table = BeautifulSoup(str(tabelas[tabela]), "html.parser")
        strong = single_table.find("strong")

        try:
            html_qualidades = single_table.find_all("td", {"class": "td-mv-res"})
            html_magnetic = single_table.find_all("td", {"class": "td-mv-dow"})

            for quali in range(0, len(html_qualidades)):
                resolut.append(f"{html_qualidades[quali].string} {strong.string}")

            for link_mag in range(len(html_magnetic)):
                magnetico.append(str(html_magnetic[link_mag]).split('"')[3])
        except Exception:
            pass

    # SE NÃO FOR UM FILME
    if len(magnetico) == 0:
        for tabela in range(0, len(tabelas)):
            single_table = BeautifulSoup(str(tabelas[tabela]), "html.parser")
            strong = single_table.find("strong")

            # HTML para episódios de séries
            html_num_epi = single_table.find_all("td", {"class": "td-ep-eps"})
            html_qualidades = single_table.find_all("td", {"class": "td-ep-res"})
            html_magnetic = single_table.find_all("td", {"class": "td-ep-dow"})

            for quali in range(0, len(html_qualidades)):
                resolut.append(
                    f"{html_num_epi[quali].string.replace('Ep.', '-')}"
                    f" {'->>'} {html_qualidades[quali].string} {strong.string}"
                )
                magnetico.append(str(html_magnetic[quali]).split('"')[3])

        magnetico.append("")
        resolut.append("")

        # Verifica se espaços em branco, se tiver ignora os primeiros
        space = 1
        for c in resolut:
            if len(c) != 0:
                print([space], c)
                space += 1
        #        if c == "" and space == 0:
        #            resolut.pop(c)
        #        else:
        #            space = 1
        #            print(c)

        selected_resolution = int(input("Esolha a resolução: "))
        mag_final = magnetico[selected_resolution - 1]
        # print(mag_final)

        if escolha == 0:
            print()
            print("Aguarde o carregamento... \nEnjoy!!")
            start = subprocess.check_call(["peerflix", mag_final, "--path", os.getcwd(), "--vlc"])

        elif escolha == 1:
            print()
            print("Download iniciado... ")
            start = subprocess.check_call(["peerflix", mag_final, "--path", os.getcwd()])

        elif escolha == 2:
            print()
            print("Link magnético:")
            print(mag_final)
            print()

    # SE FOR UM FILME
    else:
        for cont in range(0, len(magnetico)):
            print([cont + 1], resolut[cont])

        print()
        selected_resolution = int(input("Esolha a resolução: "))
        mag_final = magnetico[selected_resolution - 1]

        if escolha == 0:
            print()
            print("Aguarde o carregamento... \nEnjoy!!")
            start = subprocess.check_call(["peerflix", mag_final, "--path", os.getcwd(), "--vlc"])

        elif escolha == 1:
            print()
            print("Download iniciado... ")
            start = subprocess.check_call(["peerflix", mag_final, "--path", os.getcwd()])

        elif escolha == 2:
            print()
            print("Link magnético:")
            print(mag_final)
            print()


class Game:
    def __init__(self):
        #Setting up game menu displayed at start
        self.gameMenu = "********************\n"
        self.gameMenu += "|Welcome to Hangman|\n"
        self.gameMenu += "|                  |\n"
        self.gameMenu += "| 1.) Play Hangman |\n"
        self.gameMenu += "| 2.) Help         |\n"
        self.gameMenu += "| 3.) Quit         |\n"
        self.gameMenu += "|                  |\n"
        self.gameMenu += "********************\n"

        #Setting up initial game board
        #Top of Game Board
        self.gameBoardTop = "    ______\n"
        self.gameBoardTop += "   |      |\n"

        self.gameBoardHead = ["   |\n", "   |      O\n"]
        self.gameBoardArms = ["   |\n", "   |      |\n", "   |     /|\n", "   |     /|\\\n"]
        self.gameBoardLegs = ["   |\n", "   |     /\n", "   |     / \\\n"]

        self.gameBoardBottom = "___|______\n"

        self.gameWord = ""
        self.gameHiddenWord = ""
        self.gameFinished = 0
        self.numberMissed = 0

    def printMenu(self):
        print(self.gameMenu)

    def printBoard(self):
        if self.numberMissed == 0:
            print(self.gameBoardTop + self.gameBoardHead[0] + self.gameBoardArms[0] + self.gameBoardLegs[0] + self.gameBoardBottom)
        elif self.numberMissed == 1:
            print(self.gameBoardTop + self.gameBoardHead[1] + self.gameBoardArms[0] + self.gameBoardLegs[0] + self.gameBoardBottom)
        elif self.numberMissed == 2:
            print(self.gameBoardTop + self.gameBoardHead[1] + self.gameBoardArms[1] + self.gameBoardLegs[0] + self.gameBoardBottom)
        elif self.numberMissed == 3:
            print(self.gameBoardTop + self.gameBoardHead[1] + self.gameBoardArms[2] + self.gameBoardLegs[0] + self.gameBoardBottom)
        elif self.numberMissed == 4:
            print(self.gameBoardTop + self.gameBoardHead[1] + self.gameBoardArms[3] + self.gameBoardLegs[0] + self.gameBoardBottom)
        elif self.numberMissed == 5:
            print(self.gameBoardTop + self.gameBoardHead[1] + self.gameBoardArms[3] + self.gameBoardLegs[1] + self.gameBoardBottom)
        elif self.numberMissed == 6:
            print(self.gameBoardTop + self.gameBoardHead[1] + self.gameBoardArms[3] + self.gameBoardLegs[2] + self.gameBoardBottom)

    def printWord(self):
        print(self.gameWord)

    def printHiddenWord(self):
        print(self.gameHiddenWord)

    def isGameFinished(self):
        if self.gameFinished == 1:
            return True
        else:
            return False