import sys
from logger_file import logger
# from logger_module
from datetime_module.datetime_module import DateTimeModule
from utils import INDIA_TIMEZONE,USA_TIMEZONE,DAY_STRING

class MainClass():

    def __init__(self,task_type,user,country,start_time,end_time,day):
        self.task_type = task_type
        self.user = user
        self.country = country
        self.start_time = start_time
        self.end_time = end_time
        self.day = day

    def proceed_timezone_check(self):
        """

        :return:
        """
        try:
            if None  in (task_type,user,country,start_time,end_time):
                print ("Please pass all mandatory field.None value is not acceptable")
            else:
                dateTimeModule = DateTimeModule()
                if country is not None:
                    timezone = self.get_time_zone(country)
                    if timezone is not None:
                        curr_datteime_dict = dateTimeModule.current_datetime(timezone)
                        cur_date = curr_datteime_dict.get("IST_Date")
                        cur_datetime_iso_obj = curr_datteime_dict.get("cur_datetime_iso_obj")
                        current_day = curr_datteime_dict.get("day")
                        star_time_status = self.check_time_format(start_time)
                        end_time_status = self.check_time_format(end_time)
                        if star_time_status and end_time_status:
                            star_time_obj = dateTimeModule.convert_str_datetime_obj(cur_date,start_time)
                            end_time_obj = dateTimeModule.convert_str_datetime_obj(cur_date,end_time)
                            if day is None:
                                self.check_action_time_period(cur_datetime_iso_obj,star_time_obj,end_time_obj)
                            else:
                                day_status = self.check_day_format()
                                if day_status:
                                    self.check_action_day_time_period\
                                        (cur_datetime_iso_obj,star_time_obj,end_time_obj,current_day,timezone)

        except Exception as e:
            logger.exception(e)

    def get_time_zone(self,country):
        """

        :return:
        """
        timezone = None
        country_lower_case = country.lower()
        if country_lower_case == "india":
            timezone = INDIA_TIMEZONE
        elif country_lower_case == "usa":
            timezone = USA_TIMEZONE
        else:
            print ("Country name does not exist in our database. We can only proceed to India and USA.")
        return timezone

    def check_action_time_period(self,currnt_time, start_time_obj,end_time_obj):
        """

        :param currnt_time:
        :param start_time:
        :param end_time:
        :return:
        """
        try:
            if start_time_obj <= currnt_time <= end_time_obj:
                print ("True")
            else:
                print ("False")
                print (start_time)
        except Exception as e:
            logger.exception(e)

    def check_action_day_time_period(self,cur_datetime_iso_obj,star_time_obj,end_time_obj,
                                     current_day,timezone_name):
        """

        :return:
        """
        try:
            dateTimeModule = DateTimeModule()
            day_lst = day.split(",")
            day_lower_lst = map(lambda x: x.lower(), day_lst)
            if current_day in day_lower_lst:
                if star_time_obj <= cur_datetime_iso_obj <= end_time_obj:
                    print ("True")
            else:
                count = 1
                next_action_day = ""
                while(next_action_day not in day_lower_lst):
                    next_action_day = dateTimeModule.get_next_day_data(count,timezone_name)
                    count = count + 1
                print (next_action_day, str(start_time))

        except Exception as e:
            logger.exception(e)

    def check_time_format(self,time_data):
        """

        :param time_data:
        :return:
        """
        try:
            status = True
            time_lst = time_data.split(":")
            if len(time_lst) ==3:
                hour = time_lst[0]
                min = time_lst[1]
                sec = time_lst[2]
                if hour.isdigit() == False:
                    status = False
                    print ("Time does not consider any non-numeric value")
                else:
                    if int(hour) >= 24 or  int(hour) <0:
                        status = False
                        print ("Hour value must be in 0-23")
                if min.isdigit() == False:
                    print ("Time doest not consider any non-numeric value")
                else:
                    if int(min) >=60 or int(min) <0:
                        status = False
                        print ("Minute value must be in 0-59")

                if sec.isdigit() == False:
                    status = False
                    print ("Time doest not consider any non-numeric value")
                else:
                    if int(sec) >=60 or int(sec) <0:
                        status = False
                        print ("Second value must be in 0-59")
            else:
                status = False
                print ("Time format is not acceptable. It should be like that `HH:MM:SS`")
            return status
        except Exception as e:
            logger.exception(e)

    def check_day_format(self):
        """

        :param day:
        :return:
        """
        try:
            status = True
            all_day_lst = DAY_STRING.split(",")
            input_day_lst = day.split(",")
            for input_day in input_day_lst:
                if input_day.lower() not in all_day_lst:
                    status = False
                    print ("Input day must be in given format :-  "+"'"+DAY_STRING+"'")
            return status
        except Exception as e:
            logger.exception(e)

if __name__ == "__main__":
    task_type = sys.argv[1]
    user = sys.argv[2]
    country = sys.argv[3]
    start_time = sys.argv[4]
    end_time = sys.argv[5]
    arg_len=  (str(sys.argv))
    day = None
    len_data = len(arg_len.split(","))
    if len_data >= 7:
        day = sys.argv[6]
    main = MainClass(task_type,user,country,start_time,end_time,day)
    main.proceed_timezone_check()


# Problem Link: https://www.codewars.com/kata/526571aae218b8ee490006f4/train/python

def countBit(num):
    binary = [x for x in bin(num)]
    return len(list(filter(lambda x: x == '1', binary)))

value1 = 1234
print(countBit(value1))


import tensorflow as tf
import cv2
from tensorflow.python.ops import nn_ops, gen_nn_ops
import numpy as np
import matplotlib.pyplot as plt
import uuid

class Taylor:
    def __init__(self, input_image, init_fn, sess_config, traverse_graph, output_layer, epsilon=1e-10):
        self.epsilon = epsilon

        graph = tf.get_default_graph()
        #output_layer = graph.get_tensor_by_name('Softmax:0')
        layer = output_layer.op.inputs[0]
        relevances = [output_layer]
        relevances = traverse_graph(self, layer, relevances)

        self.init_fn = init_fn
        self.sess_config = sess_config
        self.input_image = input_image
        self.relevances = relevances

    def get_parent(self, child, num_skips):
        parent = child
        for i in range(num_skips):
            parent = [inp for inp in parent.op.inputs if not (inp.op.type=='Const')][0]
        return parent

    def backprop_conv(self, activation, weights, relevance, strides, padding):
        w_pos = tf.maximum(0., weights)
        z = tf.nn.conv2d(activation, w_pos, strides, padding) + self.epsilon
        s = relevance / z
        c = gen_nn_ops.conv2d_backprop_input(tf.shape(activation), w_pos, s, strides, padding)
        return activation * c

    def backprop_max_pool(self, activation, relevance, ksize, strides, padding):
        z = tf.nn.max_pool(activation, ksize, strides, padding) + self.epsilon
        #z = nn_ops.avg_pool(activation, ksize, strides, padding='SAME') + self.epsilon
        s = relevance / z
        #c = gen_nn_ops._avg_pool_grad(tf.shape(activation), s, ksize, strides, padding='SAME')
        c = gen_nn_ops.max_pool_grad_v2(activation, z, s, ksize, strides, padding)
        return activation * c

    def backprop_avg_pool(self, activation, relevance, ksize, strides, padding):
        z = tf.nn.avg_pool(activation, ksize, strides, padding) + self.epsilon
        s = relevance / z
        c = gen_nn_ops._avg_pool_grad(tf.shape(activation), s, ksize, strides, padding)
        return c * activation

    def backprop_inception(self, layer, activation, relevance):
        inputs = [inp for inp in layer.op.inputs if not (inp.op.type=='Const')]
        split_dim = tf.constant([int(inputs[0].shape[3]), int(inputs[1].shape[3]), int(inputs[2].shape[3]), int(inputs[3].shape[3])])
        r_1, r_3, r_5, r_p = tf.split(relevance, split_dim, axis=3)
        r_1x1 = self.backprop_1x1(inputs[0], activation, r_1)
        r_3x3 = self.backprop_nxn(inputs[1], activation, r_3)
        r_5x5 = self.backprop_nxn(inputs[2], activation, r_5)
        r_pool = self.backprop_inception_pool(inputs[3], activation, r_p)
        new_relevance = (r_1x1 + r_3x3 + r_5x5 + r_pool)
        return new_relevance

    def backprop_1x1(self, layer, activation, relevance):
        conv = self.get_parent(layer,2)
        weights = conv.op.inputs[1]
        strides = conv.op.get_attr('strides')
        padding = conv.op.get_attr('padding')
        return self.backprop_conv(activation, weights, relevance, strides, padding)

    def backprop_nxn(self, layer, activation_1x1, relevance_nxn):
        activation_nxn = self.get_parent(layer, 3)

        conv_nxn = self.get_parent(layer, 2)
        weights_nxn = conv_nxn.op.inputs[1]
        strides_nxn = conv_nxn.op.get_attr('strides')
        padding_nxn = conv_nxn.op.get_attr('padding')

        conv_1x1 = self.get_parent(conv_nxn, 3)
        weights_1x1 = conv_1x1.op.inputs[1]
        strides_1x1 = conv_1x1.op.get_attr('strides')
        padding_1x1 = conv_1x1.op.get_attr('padding')

        relevance_1x1 = self.backprop_conv(activation_nxn, weights_nxn, relevance_nxn, strides_nxn, padding_nxn)
        return self.backprop_conv(activation_1x1, weights_1x1, relevance_1x1, strides_1x1, padding_1x1)

    def backprop_inception_pool(self, layer, activation_pool, relevance_1x1):
        conv_1x1 = self.get_parent(layer, 2)
        activation_1x1 = self.get_parent(layer, 3)
        weights_1x1 = conv_1x1.op.inputs[1]
        ksize = activation_1x1.op.get_attr('ksize')
        strides = activation_1x1.op.get_attr('strides')
        padding = activation_1x1.op.get_attr('padding')
        strides_1x1 = conv_1x1.op.get_attr('strides')
        padding_1x1 = conv_1x1.op.get_attr('padding')
        relevance_pool = self.backprop_conv(activation_1x1, weights_1x1, relevance_1x1, strides_1x1, padding_1x1)
        return self.backprop_max_pool(activation_pool, relevance_pool, ksize, strides, padding)

    def backprop_conv_input(self, activation, weights, relevance, strides, padding, lowest=0., highest=1.):
        lowest = tf.reduce_min(activation)
        highest = tf.reduce_max(activation)
        W_p = tf.maximum(0., weights)
        W_n = tf.minimum(0., weights)

        L = tf.ones_like(activation, tf.float32) * lowest
        H = tf.ones_like(activation, tf.float32) * highest

        z_o = nn_ops.conv2d(activation, weights, strides, padding)
        z_p = nn_ops.conv2d(L, W_p, strides, padding)
        z_n = nn_ops.conv2d(H, W_n, strides, padding)

        z = z_o - z_p - z_n + 1e-10
        s = relevance / z

        c_o = nn_ops.conv2d_backprop_input(tf.shape(activation), weights, s, strides, padding)
        c_p = nn_ops.conv2d_backprop_input(tf.shape(activation), W_p, s, strides, padding)
        c_n = nn_ops.conv2d_backprop_input(tf.shape(activation), W_n, s, strides, padding)

        return activation * c_o - L * c_p - H * c_n

    def run_relevances(self, image, num_filters):
        sess = tf.Session(config=self.sess_config)
        self.init_fn(sess)
        relevances = sess.run(self.relevances, feed_dict={self.input_image: image})
        results = {}
        for r in range(len(relevances)):
            res = relevances[r]
            sorted_filters = []
            if len(res.shape) >=  4:
                for i in range(int(res.shape[3])):
                    filter = res[0,:,:,i]

                    filter_tuple = {}
                    filter_tuple['score'] = float(np.sum(filter))
                    filter_tuple['id'] = i
                    sorted_filters.append(filter_tuple)
                    #sorted_filters.append((su, i, filter))
                #sorted_filters = sorted(sorted_filters, reverse=True, key=lambda tup: tup[0])
                sorted_filters = sorted(sorted_filters, reverse=True, key=lambda tup: tup['score'])
                # x = []
                # z = []
                # for y in range(len(sorted_filters)):
                #     # float_img = sorted_filters[y][2]
                #     # float_img /= float_img.max()
                #     # float_img *= 255
                #     # img = cv2.resize(float_img, (224, 224), interpolation=0).astype(np.uint8)
                #     # img = cv2.applyColorMap(img, cv2.COLORMAP_JET)
                #     #
                #     # filepath = 'static/images/temp/filter_{0}_{1}_{2}.jpg'.format(str(self.relevances[r].name.split('/')[2]), y, sorted_filters[y][1])
                #     # cv2.imwrite(filepath, img)
                #     x.append(sorted_filters[y][0])
                #     z.append(y)
                # plt.bar(z, height=x)
                # #plt.xticks(z, z);
                # plt.show()
            #make sure layer is convolutional and size bigger than 1x1
            if(len(res.shape) >= 4 and res.shape[1] > 1):
                res = res[0,:,:,:]
                float_img = np.sum(res, axis=2)
                float_img /= float_img.max()
                float_img *= 255
                img = cv2.resize(float_img, (224, 224), interpolation=0).astype(np.uint8)
                img = cv2.applyColorMap(img, cv2.COLORMAP_JET)

                #filepath = 'static/images/temp/{0}_{1}.jpg'.format(r, np.sum(res))
                filepath = 'static/images/temp/'+ str(uuid.uuid4()) + '.jpg'

                cv2.imwrite(filepath, img)
                #filepaths.append(filepath)

                sorted_filters = sorted_filters[:num_filters]
                #filter_rankings[str(self.relevances[r].name)] = sorted_filters
                results[str(self.relevances[r].name.split('/')[-2])] = {'image_path': filepath, 'filter_rankings': sorted_filters}
        return results


# -*- coding: utf-8 -*-
"""
Created on Wed May 10 13:14:21 2017

@author: Matt
"""

"""
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.

Find the largest palindrome made from the product of two 3-digit numbers.
"""

#I'm thinking about brute forcing

best=0
best_pair=(0,0)

x=9000

while x < 10000:
    y=9000
    while y < 10000:
        product=x*y
        s_prod=str(product)
        if s_prod == s_prod[::-1]:
            if product > best:
                best=product
                best_pair = (x,y)
                x = max(x,y)
        y+=1
    x+=1

print("the best pair is",best_pair)
print("and the product is", best)


def minimumSwaps(arr):
    # Which sorting algorithm takes minimum number of swaps?
    # try to implement a plain selection sort

    # set count to zero
    count = 0

    # loop for all items in arr
    for i in range(len(arr)):
        # set min_index to current index
        min_index = i

        # loop from next index to the end of arr
        for j in range(i + 1, len(arr)):
            # if current item is less than item at min_index
            if arr[j] < arr[min_index]:
                # set min_index to current index
                min_index = j

        # check to see if min_index is not equal i
        if min_index != i:
            # swap item at min_index with item at current index
            arr[min_index], arr[i] = arr[i], arr[min_index]
            # increment count
            count += 1

    # return count
    return count

print(minimumSwaps([7, 1, 3, 2, 4, 5, 6]))  # 5
print(minimumSwaps([4, 3, 1, 2]))  # 3
print(minimumSwaps([2, 3, 4, 1, 5]))  # 3
print(minimumSwaps([1, 3, 5, 2, 4, 6, 7]))  # 3


import copy

# https://www.cs.cmu.edu/~112/notes/notes-strings.html#basicFileIO
def readFile(path):
    with open(path, "rt") as f:
        return f.read()

def writeFile(path, contents):
    with open(path, "wt") as f:
        f.write(contents)

def modelDay(fishList):
    newCount = 0
    for i in range(len(fishList)):
        fishList[i] -= 1
        if fishList[i] < 0:
            newCount += 1
            fishList[i] = 6
    newFish = [8 for _ in range(newCount)]
    fishList.extend(newFish)

def modelGrowth(fishList, dayCount):
    for _ in range(dayCount):
        modelDay(fishList)

def quickModelDay(fishDict):
    newEight = fishDict.get(0, 0)
    # for key in fishDict:
    #     fishDict[key] = fishDict.get(key + 1, 0)
    for i in range(9):
        fishDict[i] = fishDict.get(i + 1, 0)
    fishDict[8] = newEight
    fishDict[6] += newEight

def quickModelGrowth(fishList, dayCount):
    fishDict = dict()
    for fish in fishList:
        fishDict[fish] = fishDict.get(fish, 0) + 1
    for day in range(dayCount):
        quickModelDay(fishDict)
    res = 0
    print(sorted(fishDict.keys()))
    for key in fishDict:
        res += fishDict[key]
    return res

def main():
    fileName = 'input.txt'
    fishList = list(map(lambda x: int(x), readFile(fileName).split(',')))
    secondFishList = copy.deepcopy(fishList)
    modelGrowth(fishList, 80)
    dictModelCount = quickModelGrowth(secondFishList, 256)
    print(f'fishCount = {len(fishList)}') # 395627
    print(f'256 day fishCount = {dictModelCount}')

if __name__ == '__main__':
    main()


lst = [11, 25, 46, 78, 99, 265]
n = int(input('>>>'))

# 从中间分开，一半一半的查找

left = 0
right = len(lst) - 1

mid = (left + right) // 2
while left <= right:
    if n > lst[mid]:
        left = mid + 1
    elif n < lst[mid]:
        right = mid - 1
    else:
        print('找到了', mid)
        break
else:
    print('没找到')


import json
def show():
    with open('sw_templates.json') as f:
        contact_book=json.load(f)
    result=''
    for i,j in contact_book.items():
        result+=i+'\n'
        for k,n in j.items():
            if isinstance(n,list):
                result+=k+' : '+' , '.join(n)+'\n'
            else:
                result+=k+' : '+n+' \n'
        result+='\n'+'\n'
    result=result[:-4]
    return result

def serch_in_book(name):
    with open('sw_templates.json') as f:
        contact_book=json.load(f)
    result=False
    if name in contact_book:
        result=name+'\n'
        for i,j in contact_book[name].items():
            if isinstance(j,list):
                result+=i+' : '+' , '.join(j)+'\n'
            else:
                result+=i+' : '+j+' \n'
    return result


import pygame
import random
import math

# Inicialização
pygame.init()

# Cores
WHITE = (255, 255, 255)
GREEN = (0, 128, 0)
RED = (255, 0, 0)

# Dimensões
WIDTH, HEIGHT = 800, 600

# Adicione isso no começo para definir as fontes
pygame.font.init()
font = pygame.font.SysFont(None, 36)

# Janela
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("GeneSys")

class Snake:
    def __init__(self):
        self.segments = [(WIDTH // 2, HEIGHT // 2)]
        self.angle = random.uniform(0, 2*math.pi)
        self.speed = 5
        self.length = 30
        self.angle_variation = 0.1
        self.sin_wave = 0
        self.sin_frequency = 0.1
        self.sin_amplitude = 0.5
        self.health = 100
        self.max_speed = 5
        self.radioactivity = 5 # Define quão rápido a saúde diminui por frame
        self.original_radioactivity = 5

    def adjust_radioactivity(self, value):
        self.radioactivity += value
        # Garante que a radioatividade nunca seja negativa e não exceda o valor original
        self.radioactivity = max(0, min(self.original_radioactivity, self.radioactivity))

    def reset_radioactivity(self):
        # Aumenta gradualmente a radioatividade em direção ao valor original
        if self.radioactivity < self.original_radioactivity:
            self.adjust_radioactivity(0.02)

    def update_health(self):
        self.health -= self.radioactivity*0.01
        self.health = max(0, self.health)  # Saúde nunca fica abaixo de 0
        self.speed = self.max_speed * (self.health / 100.0)  # Ajusta a velocidade com base na saúde

    def move_towards(self, target):
        dx = target[0] - self.segments[0][0]
        dy = target[1] - self.segments[0][1]
        target_angle = math.atan2(dy, dx)
        angle_diff = (target_angle - self.angle) % (2*math.pi)
        if angle_diff > math.pi:
            angle_diff -= 2*math.pi

        if abs(angle_diff) < self.angle_variation:
            self.angle = target_angle
        elif angle_diff > 0:
            self.angle += self.angle_variation
        else:
            self.angle -= self.angle_variation

        self.angle += 0.3 * self.sin_amplitude * math.sin(self.sin_wave)
        self.sin_wave += self.sin_frequency

    def update(self):
        dx = self.speed * math.cos(self.angle)
        dy = self.speed * math.sin(self.angle)
        new_segment = (self.segments[0][0] + dx, self.segments[0][1] + dy)
        self.segments.insert(0, new_segment)
        while len(self.segments) > self.length:
            self.segments.pop()

    def draw(self, screen):
        for segment in self.segments:
            pygame.draw.circle(screen, GREEN, (int(segment[0]), int(segment[1])), 7)  # Raio ajustado para 7

class Food:
    def __init__(self):
        self.position = [random.randint(0, WIDTH), random.randint(0, HEIGHT)]

    def draw(self, screen):
        pygame.draw.circle(screen, RED, (int(self.position[0]), int(self.position[1])), 8)

    def randomize_position(self):
        self.position = [random.randint(0, WIDTH), random.randint(0, HEIGHT)]

class Machine:
    def __init__(self, x, y):
        self.position = [x, y]
        self.effect_radius = 100

    def draw(self, screen):
        pygame.draw.rect(screen, (0, 0, 255), (self.position[0] - 10, self.position[1] - 10, 20, 20))
        pygame.draw.circle(screen, (173, 216, 230, 80), self.position, self.effect_radius, 2)

class SpecialFood:
    def __init__(self, x, y):
        self.position = [x, y]

    def draw(self, screen):
        pygame.draw.circle(screen, (255, 165, 0), self.position, 10)

    def eaten_by(self, snake):
        distance_to_snake = math.sqrt((self.position[0] - snake.segments[0][0])**2 + (self.position[1] - snake.segments[0][1])**2)
        return distance_to_snake < 20

snake = Snake()
food = Food()
machines = []
special_foods = []

running = True
while running:
    screen.fill(WHITE)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        # Permitindo ao usuário colocar máquinas e comidas especiais
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:  # Botão esquerdo do mouse
                machines.append(Machine(event.pos[0], event.pos[1]))
            elif event.button == 3:  # Botão direito do mouse
                special_foods.append(SpecialFood(event.pos[0], event.pos[1]))

    if special_foods:
        closest_special_food = min(special_foods, key=lambda x: math.sqrt((x.position[0] - snake.segments[0][0])**2 + (x.position[1] - snake.segments[0][1])**2))
        snake.move_towards(closest_special_food.position)
    else:
        snake.move_towards(food.position)
    snake.update()

    distance_to_food = math.sqrt((food.position[0] - snake.segments[0][0]) ** 2 + (food.position[1] - snake.segments[0][1]) ** 2)
    if distance_to_food < 15:  # Ajustado para 15
        food.randomize_position()

    snake.draw(screen)
    food.draw(screen)

    snake.update_health()

    # Renderizar a saúde na tela
    health_surface = font.render(f'Health: {int(snake.health)}', True, (0, 0, 0))
    screen.blit(health_surface, (10, 10))

    # Renderizar o nível de radioatividade na tela
    radio_surface = font.render(f'Radioactivity: {snake.radioactivity:.2f}', True, (0, 0, 0))
    screen.blit(radio_surface, (10, 50))

    near_machine = False  # Esta flag verifica se a cobra está perto de alguma máquina

    for machine in machines:
        machine.draw(screen)
        distance_to_machine = math.sqrt((machine.position[0] - snake.segments[0][0])**2 + (machine.position[1] - snake.segments[0][1])**2)
        if distance_to_machine < machine.effect_radius:
            near_machine = True
            snake.health += 0.03  # Recupera um pouco de saúde
            snake.adjust_radioactivity(-0.01)  # Diminui a radioatividade de maneira mais gradual

    if not near_machine:
        snake.reset_radioactivity()  # Aumenta gradualmente a radioatividade até o valor original

    for special_food in special_foods:
        special_food.draw(screen)
        if special_food.eaten_by(snake):
            snake.health += 20  # Aumenta a saúde da cobra
            special_foods.remove(special_food)  # Remove a comida especial

    # Verificar se a cobrinha morreu
    if snake.health <= 0:
        running = False
        death_surface = font.render('C. Elegans Died!', True, (255, 0, 0))
        screen.blit(death_surface, (WIDTH // 2 - 100, HEIGHT // 2))
        pygame.display.flip()
        pygame.time.wait(2000)  # Espera 2 segundos antes de fechar

    pygame.display.flip()

    pygame.time.Clock().tick(60)


import os
try:
    from setuptools import setup
except ImportError:
    from distutils.core import setup

with open(os.path.join(os.path.dirname(__file__), 'README.md')) as readme_file:
    README = readme_file.read()

setup(
    name="autograder-contrib",
    description=(
        "A command-line http client and other utilities for "
        "writing applications that use the autograder.io API."
    ),
    long_description=README,
    long_description_content_type='text/markdown',
    version="1.0.0",
    author="James Perretta",
    author_email="jameslp@umich.edu",
    url="https://github.com/eecs-autograder/autograder-contrib",
    license="GNU Lesser General Public License v3",
    packages=["ag_contrib"],
    keywords=["autograder"],
    install_requires=[
        "requests"
    ],
    classifiers=['Programming Language :: Python :: 3.6'],

    # Python command line utilities will be installed in a PATH-accessible bin/
    entry_points={
        'console_scripts': [
            'agcli = ag_contrib.http_client:main',
        ]
    },
)


import re
from pathlib import Path
from typing import List

from . import context, md
from .names import valid_name, reset_names
from ..models import Book, Section, Task
from .consts import LANG_TO_EMOJI

MD_IF_REGEX = re.compile(r"```(if(?:-not)?):(.*?)\n(.*?)```", re.MULTILINE | re.DOTALL)
STYLE_REGEX = re.compile(r"<style(?:.*?)>(.*?)</style>", re.MULTILINE | re.DOTALL)

LANG_TO_PRETTY_LANG = {
    "javascript": "JavaScript",
    "coffeescript": "CoffeeScript",
}

def extract_css_styles(content: str) -> str:
    styles = STYLE_REGEX.findall(content)

    if styles:
        content = STYLE_REGEX.sub("", content)

        for style in styles:
            add_styles(style)

    return content

def add_styles(style: str):
    style_path = context.WEBSITE_CSS.get()

    old_styles = style_path.read_text(encoding="utf-8")
    style_path.write_text(f"{old_styles}\n{style}", encoding="utf-8")

def solve_if_logic(task: Task):
    if "```if:" in task.description:
        supported_lags = {*task.solutions}

        def replacer(match: re.Match) -> str:
            if_type, langs, if_content = match.groups()
            if_langs = {*langs.strip().split(",")}

            if (if_type == "if") == bool(supported_lags & if_langs):
                return if_content

            return ""

        return MD_IF_REGEX.sub(replacer, task.description)

    return task.description

def generate_task(parent: Path, task: Task):
    def _generate_task():
        yield md.header(md.link(task.name, task.link))
        yield
        yield extract_css_styles(solve_if_logic(task))
        yield
        yield md.header("Solutions")

        for lang, (solution, *_) in task.solutions.items():
            pretty_lang = LANG_TO_PRETTY_LANG.get(lang.lower(), lang.title())

            yield md.header(f"{LANG_TO_EMOJI[lang.lower()]} {pretty_lang}", important=4)
            yield md.code(solution.code, lang)

        yield

    md.readme(parent, _generate_task(), f"{valid_name(task.name, unique=True)}.md")

def generate_section(parent: Path, section: Section):
    root = parent / valid_name(section.name)
    root.mkdir(parents=True, exist_ok=True)

    for task in section.tasks:
        generate_task(root, task)

def generate_book(book: Book):
    root = context.DOCS.get() / valid_name(book.name)

    for section in book.sections:
        generate_section(root, section)

def generate_summary(books: List[Book]):
    def section_summary(parent: str, section: Section):
        yield md.option(
            md.link(
                name=section.name,
                url=f"/{parent}/{valid_name(section.name)}",
                wrap=True,
            )
        )

        for task in section.tasks:
            yield md.option(
                md.link(
                    name=task.name,
                    url=f"/{parent}/{valid_name(section.name)}/{valid_name(task.name, unique=True)}.md",
                    wrap=True,
                ),
                ident=4,
            )

    def book_summary(book: Book):
        yield
        yield md.header(book.name)

        for section in book.sections:
            yield from section_summary(valid_name(book.name), section)

    def summary():
        yield md.header("Codding Challenges тнР", important=1)

        for book in books:
            yield from book_summary(book)

    md.readme(context.DOCS.get(), summary(), "SUMMARY.md")
    reset_names()

def generate_docs(books: List[Book], docs_path: Path):
    context.init_context(docs_path)
    generate_summary(books)

    for book in sorted(books, key=lambda b: b.name):
        generate_book(book)

__all__ = ["generate_docs"]


dx = [1, 1, 1, 0]
dy = [-1, 0, 1, 1]

def five_mok(x, y):
    global check
    for i in range(4):
        count = 1
        nx = x + dx[i]
        ny = y + dy[i]
        while count < 5:
            if nx < 0 or nx > N-1 or ny < 0 or ny > N -1:
                break
            elif table[nx][ny] == 'o':
                count += 1
                nx += dx[i]
                ny += dy[i]
            else:
                break
        if count == 5:
            check = True
            return

T = int(input())

for tc in range(1, T+1):
    N = int(input())

    table = [list(input()) for _ in range(N)]
    check = False
    for i in range(N):
        for j in range(N):
            if table[i][j] == 'o':
                five_mok(i, j)
            if check:
                break
        if check:
            break

    if check:
        print(f'#{tc} YES')
    else:
        print(f'#{tc} NO')


#Write the python program to find the fibonacci series in the given range.

#Solution:
low = int(input("Enter the lower range:"))
high = int(input("Enter the upper range:"))
def fibonacci(lower, upper):
    container = []
    a = 0
    b = 1
    c = 1
    #
    while a <= upper:
        if a >= lower:
            container.append(a) # 0 1 1
        a = b
        b = c
        c = a+b
    return container

print("The fibonacci series in the given range is :", fibonacci(low,high))

'''Output:
Enter the lower range:5
Enter the upper range:20
The fibonacci series in the given range is : [5, 8, 13]

Process finished with exit code 0'''


"""
- 11. Container With Most Water
    각 height가 주어진 array에서 두 개의 height 를 뽑아 물을 담을 수 있는 가장 큰 container의 크기를 return하는 문제
    https://leetcode.com/problems/container-with-most-water/

- fail to solve (official: Medium / for me: ★★★☆☆)

    1) Brute Force한 방법으로는 풀었으나, 이는 time compexity를 만족하지 못한 solution이었다.

    2) width가 크고, height가 높아야 한다는 관점에서 linear time에 해결할 수 있었다.
        아래 Optimal solution 참고

- 깨달은 점
    연습을 더 많이 해야겠다. 왜 width 관점에서 줄여야 한다고 보이지 않았을까.
    #Array #Two Pointers

"""

# Optimal solution
class Solution:
    def maxArea(self, height: List[int]) -> int:
        res = 0
        l,r = 0, len(height)-1

        while l <= r : # width가 가장 긴 조건에서 시작
            ar = (r-l) * min(height[l], height[r])
            res = max(ar, res)

            if height[l] > height[r] : # height가 더 작은 부분을 하나씩 변경해 나간다.
                r -= 1
            else :
                l += 1

        return res

# My solution - Brute Force , O(n^2)
class Solution:
    def maxArea(self, height: List[int]) -> int:

        # n * logn 을 계산하는 것보다 더 효율적인 방법이 있을텐데.
        # 처음부터 계산을 하는데, 다음 바의 높이차이가 더 많이 나야 계산할 가치가 있지

        max_area = 0

        for i in range(len(height)):
            for j in range(i+1, len(height)):
                ar = (j-i)*min(height[i], height[j])
                max_area = max(ar, max_area)

        return max_area


"""
Test for the design class

Created on: 09/02/2023
Author: Alexandre Bohyn
"""
import numpy as np
import pandas as pd  # type: ignore
import pytest  # type: ignore

from collections import Counter

import fatld
import random

class TestDesignErrors:
    def test_wrong_init(self):
        assert True

class TestDesignMethods:
    # Design 6 from Table 3 of Wu (1993)
    design = fatld.Design(runsize=32, m=1, cols=[29, 26, 22])
    relation = fatld.relation.Relation(["bcef", "bdeg", "acdeh"], m=1)

    def test_twlp(self):
        twlp = self.design.twlp(max_length=5)
        assert twlp == [[0, 0], [1, 4], [0, 2]]

    def test_twlp_type1(self):
        twlp = self.design.twlp(type_0=False, max_length=5)
        assert twlp == [[0, 0], [4, 1], [2, 0]]

    def test_wlp(self):
        wlp = self.design.wlp(max_length=5)
        assert wlp == [0, 5, 2]

    def test_flatten(self):
        flat_array = self.design.flatten()
        assert all(np.unique(flat_array) == [0, 1])

    def test_flatten_zero_coding(self):
        flat_array = self.design.flatten(zero_coding=False)
        assert all(np.unique(flat_array) == [-1, 1])

    def test_relation(self):
        rel = self.design.defining_relation()
        assert rel.words == self.relation.words

class TestCols:
    design = fatld.Design(runsize=32, m=1, cols=[29, 27])

    def test_add_cols(self):
        design_more = self.design.add_factor(22)
        assert design_more.cols == [4, 8, 16, 22, 27, 29]

    def test_add_wrong_col(self):
        with pytest.raises(ValueError):
            self.design.add_factor(72)

    def test_add_already_used_cols(self):
        with pytest.raises(ValueError):
            self.design.add_factor(4)

    def test_remove_cols(self):
        design_less = self.design.remove_factor(29)
        assert design_less.cols == [4, 8, 16, 27]

    def test_remove_wrong_cols(self):
        with pytest.raises(ValueError):
            self.design.remove_factor(17)

class TestClarity:
    design = fatld.Design(32, 1, [27, 29])
    df = pd.DataFrame(
        {
            "4-4 clear": [0, 15, 10, 25],
            "4-2 clear": [0, 15, 4, 19],
            "2-2 clear": [0, 9, 10, 19],
            "Totally clear": [0, 9, 4, 13],
        },
        dtype=int,
    )
    df = df.set_index(pd.Index(["4-4", "4-2", "2-2", "Any type"]))

    design2 = fatld.Design(runsize=32, m=2, cols=[17, 21, 25, 29, 31])
    df2 = pd.DataFrame(
        {
            "4-4 clear": [9, 36, 8, 53],
            "4-2 clear": [9, 4, 15, 28],
            "2-2 clear": [2, 36, 9, 47],
            "Totally clear": [2, 4, 2, 8],
        },
        dtype=int,
    )
    df2 = df2.set_index(pd.Index(["4-4", "4-2", "2-2", "Any type"]))

    def test_clarity(self):
        tfi = self.design.clarity()
        assert tfi.equals(self.df)

    def test_clarity_m2(self):
        tfi = self.design2.clarity()
        assert tfi.equals(self.df2)

    def test_clear(self):
        assertion_list = []
        for row in ["4-4", "4-2", "2-2"]:
            if row == "Any type":
                row_index = "all"
            else:
                row_index = row
            for col in [
                "4-4 clear",
                "4-2 clear",
                "2-2 clear",
                "Totally clear",
            ]:
                if col == "Totally clear":
                    col_index = "all"
                else:
                    col_index = col.replace(" clear", "")
                assertion_list.append(
                    self.design.clear(row_index, col_index)
                    == self.df.loc[row, col]
                )
        assert all(assertion_list)

    def test_clear_error(self):
        with pytest.raises(ValueError):
            self.design.clear("4-2", "4-3")

def test_from_array():
    D = fatld.Design(32, 1, [17, 21, 29, 31])
    mat = D.array
    newD = fatld.design.from_array(mat)
    assert D.cols == newD.cols

def test_beta_wlp():
    D = fatld.Design(32, 2, [17, 18, 20, 24, 19, 28, 5, 9, 6, 10, 7, 11, 13])
    vec, perm = D.beta_wlp(max_length=5)
    assert vec == [8.0, 37.0, 107.0]

def test_beta_aberration_low_n():
    D = fatld.Design(
        32, 2, [31]
    )  # Here n = 2 which is lower than the max_length set
    qvec, perm = D.beta_wlp(max_length=6)
    assert qvec == [0.0, 0.0, 0.0, 1.0]

def test_number_interactions():
    assert fatld.main.nbr_interactions(7, 5) == 119

def test_tfi_model_matrix():
    tfi_model_matrix = fatld.design.build_tfi_model_matrix(n=7, max_length=5)
    int_length = np.sum(tfi_model_matrix, axis=0).tolist()
    c = Counter(int_length)
    d = dict(c)
    assert d == {1: 7, 2: 21, 3: 35, 4: 35, 5: 21}

def test_beta_star_m3():
    """Test the computation of B* vector for m=3"""
    D = fatld.Design(64, 3, [22, 27, 41, 46])
    b, p = D.beta_star_wlp(max_length=6)
    assert b == [[0.0, 0], [0.1, 0], [3.2, 0], [2.9, 0]]

def test_beta_star_sum():
    """
    Test that for any design, the sum of A_i^0  words is equal to the sum of
    the beta* values
    """
    available_cols = [
        i for i in range(1, 32) if i not in [1, 2, 3, 4, 8, 12, 16]
    ]
    cols = random.sample(available_cols, 5)
    D = fatld.Design(32, 2, cols)
    ai_values = [sum(i[1:]) for i in D.twlp(type_0=True)]
    beta_values = [b[0] for b in D.beta_star_wlp()[0]]
    assert np.round(sum(ai_values)) == np.round(sum(beta_values))


import pytest

from ethecycle.blockchains import *
from ethecycle.blockchains.ethereum import Ethereum
from ethecycle.models.token import Token
from ethecycle.models.transaction import Txn
from ethecycle.models.wallet import Wallet
from ethecycle.util.string_constants import *

EXTRACTION_TIMESTAMP_STR = '2020-02-20T02:20:20'
TEST_DATA_SOURCE = 'the_pharcyde/bypass'
TEST_TXN_HASH = '0x666_TRANSACTION_HASHING_OF_THE_BEAST_666'
TEST_TXN_LOG_LEVEL = '777'

@pytest.fixture(scope='session')
def ethereum_of_the_beast(prep_db, token_of_the_beast):
    """Add token to Ethereum ChainInfo in memory."""
    Token.chain_addresses()[ETHEREUM][token_of_the_beast.address] = token_of_the_beast
    Token._by_blockchain_symbol[ETHEREUM][token_of_the_beast.symbol] = token_of_the_beast
    return Ethereum

@pytest.fixture(scope='session')
def wallet_1(prep_db) -> Wallet:
    return Wallet(
        address='0xPHAT_WALLET_ADDRESS_1',
        chain_info=Ethereum,
        name='Gabriel',
        category=CEX,
        data_source=TEST_DATA_SOURCE,
        extracted_at=EXTRACTION_TIMESTAMP_STR
    )

@pytest.fixture(scope='session')
def wallet_2() -> Wallet:
    return Wallet(
        address='0xPHAT_WALLET_ADDRESS_2',
        chain_info=Ethereum,
        name='Lucifer',
        category=CEX,
        data_source=TEST_DATA_SOURCE,
        extracted_at='2020-02-20T02:20:20'
    )

@pytest.fixture(scope='session')
def token_of_the_beast() -> Token:
    return Token(
        chain_info=Ethereum,
        address='0x666_TOKEN_ADDRESS_OF_THE_BEAST_666',
        symbol='S1X',
        name='Token Of The Beast',
        decimals=6,
        token_type=ERC20,
        data_source=TEST_DATA_SOURCE,
        extracted_at=EXTRACTION_TIMESTAMP_STR
    )

@pytest.fixture(scope='session')
def transaction_of_the_beast(ethereum_of_the_beast, token_of_the_beast, wallet_1, wallet_2) -> Txn:
    return Txn(
        token_address=token_of_the_beast.address,
        from_address=wallet_1.address,
        to_address=wallet_2.address,
        csv_value='6000000',
        transaction_hash=TEST_TXN_HASH,
        log_index=TEST_TXN_LOG_LEVEL,
        block_number=666666,
        chain_info=Ethereum,
        extracted_at=EXTRACTION_TIMESTAMP_STR
    )


N = int(input())
arr = []
for i in range(N):
    arr.append(list(map(int, input().split())))

def cut(arr, n):
    global blue
    global white

    a, b, c, d = [], [], [], []

    for i in range(n//2):
        a.append(arr[i][:n//2])
        b.append(arr[i][n//2:n])
        c.append(arr[n//2+i][:n//2])
        d.append(arr[n//2+i][n//2:n])

    lst = [a, b, c, d]

    for l in lst:
        white_cnt = 0
        blue_cnt = 0

        for i in l:
            white_cnt += i.count(0)
            blue_cnt += i.count(1)

        if white_cnt == 0:
            blue += 1
        elif blue_cnt == 0:
            white += 1
        else:
            cut(l, n//2)

white = 0
blue = 0
for i in arr:
    white += i.count(0)
    blue += i.count(1)

if white == N**2:
    print("1")
    print("0")
elif blue == N**2:
    print("0")
    print("1")

else:
    white = 0
    blue = 0
    cut(arr, N)
    print(white)
    print(blue)


import os
import argparse
import fcntl
import time
import urllib.request, urllib.parse, urllib.error
import urllib.request, urllib.error, urllib.parse
import logging
from logging.handlers import RotatingFileHandler
import traceback
from tl_tweets import tweet_string, tweet_price
from tl_email import email
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
import csv
import json
import datetime
from dateutil import parser
from dateutil.relativedelta import relativedelta
import calendar
import random
from tl_weather import get_daytime_weather_data
import requests
from bs4 import BeautifulSoup
from pythonjsonlogger import jsonlogger

# Wait time for page loads
PAGE_LOAD_TIMEOUT = 240 * 1000

# Where logging output from this tool goes. Modify path as needed
LOGFILE = os.environ.get('SOLAR_LOGFILE')
if not LOGFILE:
    LOGFILE = os.path.expanduser("~/script/logs/solarcity.log")

# Data file containing all the saved state information
DATA_FILE = "solarcity.json"

# Some of the tweets attach pictures. They're randomly chosen from this path
PICTURES_PATH = "images/solar"

# Logging setup
log = logging.getLogger(__name__)
loglevel = logging.INFO
DEF_FRMT = "%(asctime)s : %(levelname)-8s : %(funcName)-25s:%(lineno)-4s: %(message)s"
loghandler1 = RotatingFileHandler(LOGFILE, maxBytes=5 * 1024 * 1024, backupCount=8)
loghandler2 = RotatingFileHandler(LOGFILE + '.json', maxBytes=5 * 1024 * 1024, backupCount=8)
loghandler1.setFormatter(logging.Formatter(DEF_FRMT))
loghandler2.setFormatter(jsonlogger.JsonFormatter())
log.addHandler(loghandler1)
log.addHandler(loghandler2)
log.setLevel(loglevel)

# Get the collection of pictures
SOLAR_IMAGES = []
if os.path.exists(PICTURES_PATH):
    SOLAR_IMAGES = [os.path.join(PICTURES_PATH, f) for f in os.listdir(PICTURES_PATH) if not f.startswith('.')]

# Set to true to disable tweets/data file updates
DEBUG_MODE = False

# Get SolarCity information from environment
if not 'SOLARCITY_USER' in os.environ:
    raise Exception("SOLARCITY_USER missing")
else:
    SOLARCITY_USER = os.environ['SOLARCITY_USER']

# Get SolarCity referral information from environment
if not 'SOLARCITY_REFERRAL' in os.environ:
    SOLARCITY_REFERRAL = ''
else:
    SOLARCITY_REFERRAL = os.environ['SOLARCITY_REFERRAL']

# Get your SITE_ID by logging into https://solarguard.solarcity.com/Kiosk/SolarGuard.aspx and
# extract the SITE_ID from the URL once logged in
if not 'SOLARCITY_SITE_ID' in os.environ:
    raise Exception("SOLARCITY_SITE_ID missing")
else:
    SOLARCITY_SITE_ID = os.environ['SOLARCITY_SITE_ID']

# Main URL to SolarCity
SOLARCITY_URL = 'https://mysolarcity.com/Share/%s#/monitoring/historical/day' % SOLARCITY_SITE_ID

SOLARGUARD_URL = 'https://solarguard.solarcity.com/Kiosk/SolarGuard.aspx' \
                '?ID=&JID=%s' \
                '&GroupID=0' \
                '&AutoDemo=1' \
                '&Timeout=480' \
                '&Share=0' \
                '&RangeType=Day' \
                '&ChartMode=Stack' \
                '&Consumption=1' \
                '&Min=30' \
                '&ExportLifetime=0' % SOLARCITY_SITE_ID

def get_day_data(day=None):
    append = ''
    if day:
        append = '?date=%d-%02d-%02d' % (day.year, day.month, day.day)

    chrome_options = Options()
    chrome_options.add_argument("--headless")
    driver = webdriver.Chrome(options=chrome_options)
    driver.get(SOLARCITY_URL)
    time.sleep(10)
    driver.get(SOLARCITY_URL + append)
    time.sleep(10)
    data = driver.find_element(By.CSS_SELECTOR, "div.consumption-production-panel").text
    if data and len(data.split()) > 0:
        production = float(data.split()[0])
    else:
        production = 0

    if day:
        ts = datetime.datetime.combine(day, datetime.datetime.max.time()).strftime("%s")
    else:
        ts = time.time()
    ts = datetime.datetime.fromtimestamp(ts).strftime("%Y-%m-%d")
    w = get_daytime_weather_data(log, ts)
    cloud_cover = w['cloud_cover']
    daylight_hours = w["daylight"]

    # If we get here everything worked, shut down the browser
    driver.quit()

    if os.path.exists("geckodriver.log"):
        os.remove("geckodriver.log")

    return daylight_hours, cloud_cover, production

def get_solarguard_day_data(day=None):
    append = ''
    if day:
        append = '&ChartDate=%d_%d_%d' % (day.month, day.day, day.year)
    r = requests.get(SOLARGUARD_URL + append)
    soup = BeautifulSoup(r.text, features="html.parser")

    daylight_hours = 0
    cloud_cover = 0

    production = float(soup.find(id='ctl00_cphMain_lbProdTotalByChart').text)

    if not day and production == 0 and cloud_cover == 0 and daylight_hours == 0:
        raise Exception("Problem getting current production level: %.1f, %d, %.1f" % (production,
                                                                                cloud_cover, daylight_hours))

    if daylight_hours == 0:
        """
        SolarCity has had outages where they cant provide the cloud cover/weather information.
        If the weather data appears empty here, we'll go get it from another source
        """
        if day:
            ts = datetime.datetime.combine(day, datetime.datetime.max.time()).strftime("%s")
        else:
            ts = time.time()
        ts = datetime.datetime.fromtimestamp(ts).strftime("%Y-%m-%d")
        w = get_daytime_weather_data(log, ts)
        cloud_cover = w["cloud_cover"]
        daylight_hours = w["daylight"]

    return daylight_hours, cloud_cover, production

def solar_image():
    if SOLAR_IMAGES:
        return random.choice(SOLAR_IMAGES)

def tweet_production(daylight_hours, cloud_cover, production, special):
    if special == "high":
        extra = "A new high record :) "
    elif special == "low":
        extra = ":( A new low "
    else:
        extra = ""

    if daylight_hours and daylight_hours > 0.0:
        message = "Todays @Tesla Solar Production: %s with %.1f hrs of daylight and it was %s. %s" \
                  "#gosolar #bot %s" % \
                  (show_with_units(production), daylight_hours, cloud_cover, extra, SOLARCITY_REFERRAL)
    else:
        message = "Todays @Tesla Solar Production: %s (daylight/cloud cover not reported) %s" \
                  "#gosolar #bot %s" % \
                  (show_with_units(production), extra, SOLARCITY_REFERRAL)

    if DEBUG_MODE:
        print("Would tweet:\n%s" % message)
        log.info("DEBUG mode, not tweeting: %s", message)
    else:
        media = solar_image()
        log.info("Using media: %s", media)
        tweet_string(message=message, log=log, media=media)

def tweet_down():
    daysdown = (datetime.datetime.now() - datetime.datetime(2019, 8, 27)).days
    message = "@Tesla Solar system (17.6kW) was taken offline by @Tesla on 8/29/19, %d days ago. " \
              "No repair possible for months." % daysdown
    if DEBUG_MODE:
        print("Would tweet:\n%s" % message)
        log.info("DEBUG mode, not tweeting: %s", message)
    else:
        media = random.choice(SOLAR_IMAGES)
        log.info("Using media: %s", media)
        tweet_string(message=message, log=log, media=media)

def tweet_month(data):
    generated_this_week, generated_this_month, generated_this_year, total_generation = compute_generation_data(data)

    message = "This months @Tesla Solar Production was %s. %s generated in the last 365 days. #gosolar #bot %s" % \
              (show_with_units(generated_this_month), show_with_units(generated_this_year), SOLARCITY_REFERRAL)
    if DEBUG_MODE:
        print("Would tweet:\n%s" % message)
        log.info("DEBUG mode, not tweeting: %s", message)
    else:
        tweet_string(message=message, log=log, media=solar_image())

def tweet_year(data):
    generated_this_week, generated_this_month, generated_this_year, total_generation = compute_generation_data(data)

    message = "This years @Tesla Solar Production was %s! %s generated since install :) #gosolar #bot %s" % \
              (show_with_units(generated_this_year), show_with_units(total_generation), SOLARCITY_REFERRAL)
    if DEBUG_MODE:
        print("Would tweet:\n%s" % message)
        log.info("DEBUG mode, not tweeting: %s", message)
    else:
        tweet_string(message=message, log=log, media=random.choice(SOLAR_IMAGES))

def load_data():
    if os.path.exists(DATA_FILE):
        log.debug("Loading existing Solarcity database")
        data = json.load(open(DATA_FILE, "r"))
        log.debug("   %d entries loaded", len(data['data']))
        if 'config' not in data:
            data['config'] = {'lastdailytweet': '20010101'}
        # Manual insertion if needed
        #data['data']['20150620'] = {'production': 61.5, 'cloud': 68, 'daylight': 15.3}

    else:
        log.debug("No existing Solarcity database found")
        data = {'config': {'lastdailytweet': '20010101'}, 'data': {}}
    return data

def load_historical_data(data):
    """
    This lets you export historical data from SolarCity.com and import it into this tool to
    combine old data with current data.

    Go to your mySolarCity page and download the PowerGuide data and put it in historical.csv
    """
    if len(data['data']) < 5 and os.path.exists('historical.csv'):
        # Only need to load it once
        log.debug("Loading historical data")
        with open('historical.csv') as csvfile:
            reader = csv.DictReader(csvfile)
            for row in reader:
                if row['Energy In Interval (kWh)'] == 'NULL':
                    continue
                process_date = "%s%s%s" % (row['Timestamp'][0:4], row['Timestamp'][5:7], row['Timestamp'][8:10])
                if process_date in data['data']:
                    if 'cloud' not in data['data'][process_date]:
                        data['data'][process_date]['production'] += float(row['Energy In Interval (kWh)'])
                else:
                    data['data'][process_date] = {'production': float(row['Energy In Interval (kWh)'])}
    else:
        log.debug("Skipping load of historical data")
    return data

def populate_missing_data(data):
    today = datetime.datetime.now().date()
    first = None
    last = None
    data_changed = False
    for d in data['data']:
        t = parser.parse(d).date()
        if not first:
            first = t
        last = t
    while last < today - datetime.timedelta(days=1):
        last = last + datetime.timedelta(days=1)
        current_day = last.strftime("%Y%m%d")
        if current_day in data['data']:
            log.info("Skipping %s" % current_day)
            continue
        try:
            daylight_hours, cloud_cover, production = get_day_data(last)
        except:
            print("Error fetching %s" % last)
            continue
        log_str = "populating missing: %s: daylight: %s cloud cover: %s production: %s" % \
                  (last, daylight_hours, cloud_cover, production)
        print(log_str)
        log.info(log_str)
        data['data'][current_day] = {'daylight': daylight_hours, 'cloud': cloud_cover, 'production': production}
        data_changed = True
        save_data(data)
        upload_to_pvoutput(data, current_day)
        time.sleep(20)
    return data_changed

def analyze_data(data):
    production_max = 0
    production_max_day = None
    production_min = 999999
    production_min_day = None
    total_generation = 0

    for day in data['data']:
        d = data['data'][day]
        # Special handling here where SolarCity provided data thats not credible
        if day in ('20150610',):
            # Bad data days
            continue
        total_generation += d['production']
        if d['production'] > production_max:
            production_max = d['production']
            production_max_day = day
        if d['production'] < production_min:
            production_min = d['production']
            production_min_day = day

    log.info("Max: %s on %s, Min: %s on %s." % (show_with_units(production_max), production_max_day,
                                                 show_with_units(production_min), production_min_day))
    log.info("Total: %s" % show_with_units(total_generation))
    return production_max_day, production_min_day, total_generation

def analyze_weather(data):
    """
    SolarCity has had outages where they cant provide the cloud cover/weather information.
    This compares SolarCity reported weather data with other weather data.
    """
    print("Apple killed Dark Sky, weather not available")
    return
    # for day in sorted(data['data']):
    #     d = data['data'][day]
    #     if "weather_api" not in d:
    #         time_value = time.mktime(time.strptime("%s2100" % day, "%Y%m%d%H%M"))
    #         w = get_daytime_weather_data(log, time_value)
    #         cloud_cover = w["cloud_cover"]
    #         daylight_hours = w["daylight"]
    #         if 'cloud' in d:
    #             ss_cloud = d['cloud']
    #         else:
    #             ss_cloud = 0
    #         if 'daylight' in d:
    #             ss_daylight = d['daylight']
    #         else:
    #             ss_daylight = 0
    #
    #         print("%s Cloud: %d%% Daylight: %.1f (API Cloud: %d%%, Daylight: %.1f)" % (day, ss_cloud,
    #                                                                                ss_daylight, cloud_cover,
    #                                                                                daylight_hours))
    #     else:
    #         if 'cloud' in d:
    #             cloud_cover = d['cloud']
    #         else:
    #             cloud_cover = 0
    #         if 'daylight' in d:
    #             daylight_hours = d['daylight']
    #         else:
    #             daylight_hours = 0
    #         print("%s API Cloud: %d%% API Daylight: %.1f" % (day, cloud_cover, daylight_hours))

def save_data(data):
    log.debug("Save Solarcity database")
    if not DEBUG_MODE:
        json.dump(data, open(DATA_FILE + ".tmp", "w"))
        if os.path.exists(DATA_FILE):
            os.remove(DATA_FILE)
        os.rename(DATA_FILE + ".tmp", DATA_FILE)
    else:
        log.debug("   Skipped saving due to debug mode")
        print(data)

def show_with_units(generation):
    for units in ('kWh', 'MWh', 'GWh'):
        if generation < 1000:
            break
        generation /= 1000
    message = "{:,.1f}".format(generation)
    message += " " + units
    return message

def compute_generation_data(data):
    w = datetime.date.today() - datetime.timedelta(days=7)
    this_week = int(w.strftime("%Y%m%d"))

    m = datetime.date.today() - datetime.timedelta(days=30)
    this_month = int(m.strftime("%Y%m%d"))

    y = datetime.date.today() - datetime.timedelta(days=365)
    this_year = int(y.strftime("%Y%m%d"))

    generated_this_week = 0
    generated_this_month = 0
    generated_this_year = 0
    total_generation = 0

    log.info("   This week: %d, last month: %d, last year: %d", this_week, this_month, this_year)

    for a in data['data']:
        production = data['data'][a]['production']
        total_generation += production

        if int(a) > this_week:
            generated_this_week += production
        if int(a) > this_month:
            generated_this_month += production
        if int(a) > this_year:
            generated_this_year += production

    return generated_this_week, generated_this_month, generated_this_year, total_generation

def solarcity_report(data, no_email=False, no_tweet=False):
    log.info("Report on SolarCity Generation")
    generated_this_week, generated_this_month, generated_this_year, total_generation = compute_generation_data(data)

    message = "Hi there, below is the weekly SolarCity generation report:\n\n"
    message += "Total production this week: %s\n" % show_with_units(generated_this_week)
    message += "Total production in the last 30 days: %s\n" % show_with_units(generated_this_month)

    message += "Total production in the last 365 days: %s\n" % show_with_units(generated_this_year)

    message += "\nLifetime generation is %s.\n" % show_with_units(total_generation)
    message += "\nRegards,\n"
    message += "Teslaliving\nhttp://teslaliving.net"

    if no_email or DEBUG_MODE:
        print("Would email message:\n%s" % message)
    else:
        log.info("   email report")
        email(email=SOLARCITY_USER, message=message, subject="Weekly SolarCity Report")

    if not no_tweet:
        tweet_message = "%s generated last week with @Tesla Solar. " % show_with_units(generated_this_week)
        tweet_message += "%s generated in the last 30 days. #GoSolar #bot %s" % \
                         (show_with_units(generated_this_month), SOLARCITY_REFERRAL)
        if DEBUG_MODE:
            print("Would Tweet string:\n%s" % tweet_message)
        else:
            tweet_string(message=tweet_message, log=log, media=solar_image())

def upload_to_pvoutput(data, day):
    # Get pvoutput.org login information from environment
    if 'PVOUTPUT_ID' not in os.environ:
        raise Exception("PVOUTPUT_ID missing")
    else:
        pvoutput_id = os.environ['PVOUTPUT_ID']
    if 'PVOUTPUT_KEY' not in os.environ:
        raise Exception("PVOUTPUT_KEY missing")
    else:
        pvoutput_key = os.environ['PVOUTPUT_KEY']

    log.info("Report weather info to pvoutput.org for %s", day)

    time_value = time.mktime(time.strptime("%s2100" % day, "%Y%m%d%H%M"))
    time_value = datetime.datetime.fromtimestamp(time_value).strftime("%Y-%m-%d")
    w = get_daytime_weather_data(log, time_value)

    short_description = w["description"]
    # if "partly cloudy" in w["description"].lower():
    #     short_description = "Partly Cloudy"
    # if "mostly cloudy" in w["description"].lower():
    #     short_description = "Mostly Cloudy"
    # elif "snow" in w["description"].lower():
    #     short_description = "Snow"
    # elif "rain" in w["description"].lower():
    #     short_description = "Showers"
    # elif "clear" in w["description"].lower():
    #     short_description = "Fine"

    pvdata = {}
    pvdata["d"] = day
    pvdata["g"] = data["data"][day]["production"] * 1000
    pvdata["cd"] = short_description
    pvdata["tm"] = "%.1f" % ((w["low_temp"] - 32) * 5.0 / 9.0)
    pvdata["tx"] = "%.1f" % ((w["high_temp"] - 32) * 5.0 / 9.0)
    # pvdata["cm"] = "Daylight hours: %.1f, Cloud cover: %d%%" % (data["data"][day]["daylight"],
    #                                                             data["data"][day]["cloud"])
    pvdata["cm"] = "Daylight hours: %.1f" % (data["data"][day]["daylight"])
    data = urllib.parse.urlencode(pvdata)

    headers = {}
    headers["X-Pvoutput-Apikey"] = pvoutput_key
    headers["X-Pvoutput-SystemId"] = pvoutput_id

    req = urllib.request.Request("http://pvoutput.org/service/r2/addoutput.jsp", data.encode('utf-8'), headers)
    response = urllib.request.urlopen(req)
    output = response.read()
    log.info("   Upload response: %s", output)

def main():
    parser = argparse.ArgumentParser(description='SolarCity Reporting')
    parser.add_argument('--no_email', help='Dont send emails', required=False, action='store_true')
    parser.add_argument('--force', help='Force update', required=False, action='store_true')
    parser.add_argument('--details', help='Output detailed blog output', required=False, action='store_true')
    parser.add_argument('--no_tweet', help='Dont post tweets', required=False, action='store_true')
    parser.add_argument('--report', help='Generate report', required=False, action='store_true')
    parser.add_argument('--blog', help='Generate html report page', required=False, action='store_true')
    parser.add_argument('--daily', help='Report on daily generation', required=False, action='store_true')
    parser.add_argument('--monthly', help='Report on monthly generation', required=False, action='store_true')
    parser.add_argument('--yearly', help='Report on yearly generation', required=False, action='store_true')
    parser.add_argument('--weather', help='Report weather for given date (YYYYMMDD)', required=False, type=str)
    parser.add_argument('--pvoutput', help="Send data for date (YYYYMMDD) to PVOutput.org", required=False, type=str)
    parser.add_argument('--down', help="Tweet system down", required=False, action='store_true')
    parser.add_argument('--missing', help="Fill in missing data", required=False, action='store_true')
    args = parser.parse_args()

    # Make sure we only run one instance at a time
    if not args.blog:
        fp = open('/tmp/solarcity.lock', 'w')
        try:
            fcntl.flock(fp.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
        except:
            log.debug("Sorry, someone else is running this tool right now. Please try again later")
            return -1

    log.debug("--- solarcity.py start ---")

    data = load_data()
    data_changed = False

    data = load_historical_data(data)
    production_max, production_min, total_generation = analyze_data(data)

    if args.missing:
        data_changed = populate_missing_data(data)

    if args.down:
        tweet_down()

    if args.monthly:
        # First check if its last day of the month
        log.info("Check for monthly update")
        now = datetime.datetime.now()
        dow, last_day = calendar.monthrange(now.year, now.month)
        log.info("Last day of month: %d. Current day: %d", last_day, now.day)
        if last_day == now.day:
            log.info("   Last day of month.")
            current_month = time.strftime("%Y%m")
            if 'lastmonthlytweet' not in data['config'] or data['config']['lastmonthlytweet'] != current_month:
                tweet_month(data)
                data['config']['lastmonthlytweet'] = current_month
                data_changed = True
        else:
            log.info("   Not last day of month, skipping. ")

    if args.yearly:
        # First check if its last day of the year
        log.info("Check for annual update")
        now = datetime.datetime.now()
        if now.month == 12:
            dow, last_day = calendar.monthrange(now.year, now.month)
            log.info("Last day of month: %d. Current day: %d", last_day, now.day)
            if last_day == now.day:
                log.info("   Last day of year.")
                current_month = time.strftime("%Y%m")
                if 'lastyearlytweet' not in data['config'] or data['config']['lastyearlytweet'] != current_month:
                    tweet_year(data)
                    data['config']['lastyearlytweet'] = current_month
                    data_changed = True
            else:
                log.info("   Not last day of year, skipping. ")

    if args.weather is not None:
        log.info("Check weather data")
        if int(args.weather) == 0:
            int(time.time())
        else:
            time_value = time.mktime(time.strptime("%s2100" % args.weather, "%Y%m%d%H%M"))
        time_value = datetime.datetime.fromtimestamp(time_value).strftime("%Y-%m-%d")
        w = get_daytime_weather_data(log, time_value)
        print("Weather as of %s:" % datetime.datetime.fromtimestamp(time_value))
        print("   Average temperature: %.1fF" % w["avg_temp"])
        print("   Low temperature: %.1fF" % w["low_temp"])
        print("   Conditions: %s" % w["cloud_cover"])
        print("   Daylight hours: %.1f" % w["daylight"])
        print("   Description: %s" % w["description"])
        # print("   Precipitation type: %s" % w["precip_type"])
        # print("   Precipitation Chance: %d%%" % w["precip_probability"])
        analyze_weather(data)

    if args.daily:
        log.info("Check for daily update")
        current_day = time.strftime("%Y%m%d")
        if data['config']['lastdailytweet'] != current_day or DEBUG_MODE or args.force:
            daylight_hours, cloud_cover, production = get_day_data()
            data['data'][current_day] = {'daylight': daylight_hours, 'cloud': cloud_cover, 'production': production}
            special = None
            if production_max is None or production > data['data'][production_max]['production']:
                special = "high"
            elif production_min is None or production < data['data'][production_min]['production']:
                special = "low"
            if not args.no_tweet:
                tweet_production(daylight_hours, cloud_cover, production, special)
                data['config']['lastdailytweet'] = current_day
            data_changed = True
            if args.pvoutput is not None:
                # Now upload to pvoutput
                upload_to_pvoutput(data, current_day)

    elif args.pvoutput is not None:
        if int(args.pvoutput) == 0:
            print("Uploading historical data to pvoutput.org")
            for d in data["data"]:
                if int(d) < 20150224:
                    continue
                print("   Processing date %s" % d)
                try:
                    upload_to_pvoutput(data, d)
                except:
                    print("      problem with date %s" % d)
                print("      Sleeping")
                # You'll need longer sleeps if you didnt donate, try 120
                time.sleep(120)
        else:
            today = datetime.datetime.now().date()
            last = datetime.datetime.strptime(args.pvoutput, '%Y%m%d').date()
            while True:
                if last >= today - datetime.timedelta(days=1):
                    break
                current_day = last.strftime("%Y%m%d")
                error = False
                if current_day not in data["data"]:
                    try:
                        daylight_hours, cloud_cover, production = get_day_data(last)
                    except:
                        print("Error fetching %s" % last)
                        log.debug("Error fetching %s" % last)
                        error = True
                    if not error:
                        log_str = "populating missing: %s: daylight: %s cloud cover: %s production: %s" % \
                                  (last, daylight_hours, cloud_cover, production)
                        print(log_str)
                        log.info(log_str)
                        data['data'][current_day] = {'daylight': daylight_hours, 'cloud': cloud_cover, 'production': production}
                        data_changed = True
                        save_data(data)
                if not error and current_day in data["data"]:
                    log.debug("would upload to pvoutput %s" % last)
                    #upload_to_pvoutput(data, args.pvoutput)
                    #time.sleep(10)
                last = last + datetime.timedelta(days=1)

    if args.report:
        # Send/Run weekly solarcity summary report
        solarcity_report(data, args.no_email, args.no_tweet)

    if args.blog:
        # Export all entries found for posting to static page on blog: teslaliving.net/solarcity
        log.info("Reporting on SolarCity generation for blog")
        print('<a href="http://ts.la/rob6663">@Tesla Solar</a> Solar Installation')
        print('<h3>System Results</h3>')
        print("<b>%s total power generated via @Tesla Solar as of %s</b>" % (show_with_units(total_generation),
                                                                    time.strftime("%Y%m%d")))
        print("%s day max on %s" % (show_with_units(data['data'][production_max]['production']), production_max))
        print("%s day min on %s" % (show_with_units(data['data'][production_min]['production']), production_min))
        print("<b>%s daily average production</b>" % (show_with_units(total_generation / len(data['data']))))
        print('<h3>System Details</h3>')
        print("System size is 69 panels at 255W each = %.1fkW" % (69 * .255))
        r = relativedelta(datetime.datetime.now(), datetime.datetime.strptime("2015-02-23", '%Y-%m-%d'))
        elapsed_months = r.years * 12 + r.months
        print("System was turned on February 23, 2015 (%d months ago)" % elapsed_months)
        print("Panel info: ")
        print("* Size: 1638 x 982 x 40mm (64.5 x 38.7 x 1.57in)")
        print("* Vendor: <a href='http://www.canadiansolar.com/solar-panels/cs6p-p.html'>CanadianSolar CS6P-P</a>")
        print("Inverter info: ")
        print("* <a href='http://www.solaredge.com/sites/default/files/se-single-phase-us-inverter-datasheet.pdf'>SolarEdge SE6000A</a>")
        print(" ")
        print('Sign up for <a href="http://ts.la/rob6663">Tesla Solar</a> and save on electric!')

        print('<h3>Chart via <a href="http://pvoutput.org/list.jsp?id=48753&sid=44393">PVOutput</a></h3>[hoops name="pvoutput"]')
        if args.details:
            print('<h3>Daily Log:</h3>')
            print("%s%s%s  %s  %s" % ("Date", " " * 11, "Production", "Daylight", "Cloud Cover"))
            d = data['data']
            for e in sorted(d, reverse=True):
                production = d[e]['production']
                if 'daylight' in d[e] and d[e]['daylight'] > 0:
                    daylight = d[e]['daylight']
                    if 'cloud' in d[e]:
                        cloud = d[e]['cloud']
                    else:
                        cloud = 0
                else:
                    pass
                    # w = get_daytime_weather_data(log, time.mktime(time.strptime("%s2100" % e, "%Y%m%d%H%M")))
                    # d[e]['daylight'] = w['daylight']
                    # daylight = w['daylight']
                    # d[e]['weather_api'] = True
                    # d[e]['cloud'] = w['cloud_cover']
                    # cloud = w['cloud_cover']
                    # d[e]['weather_api'] = True
                    # data_changed = True

                if production is not None and daylight is not None and cloud is not None:
                    print('%s' % e, '    %s %.1f hrs %d%%' % \
                                    (show_with_units(production), daylight, cloud))
                else:
                    print('%s' % e, '    %s' % show_with_units(production))

            print('\nSign up for <a href="http://ts.la/rob6663">Tesla Solar</a> and save on electric!')
        print('\nFollow <a href="https://twitter.com/teslaliving">@TeslaLiving</a>.')
        print('\n<ul>')
        print('<li><i>Note 1: Detailed generation tracking started 20150612.</i></li>')
        print('<li><i>Note 2: Cloud/Daylight data <a href="http://forecast.io">Powered by Forecast</a> when ' \
              'Tesla Solar data missing.</i></li>')
        print('<li><i>Note 3: System was degraded from 20170530 to 20170726. Up to 30 panels offline.</i></li>')
        print('<li><i>Note 4: System was degraded from 20190828 to 201909. All panels offline.</i></li>')
        print('</ul>')

    if data_changed:
        save_data(data)

    log.debug("--- solarcity.py end ---")

if __name__ == '__main__':
    try:
        main()
    except SystemExit:
        pass
    except:
        log.exception("Exception encountered")
        message = "There was a problem during solarcity updates:\n\n"
        message += traceback.format_exc()
        message += "\nPlease investigate."
        if DEBUG_MODE:
            raise
        else:
            email(email=SOLARCITY_USER, message=message, subject="Solarcity Poll Error")


import sys
import os
import random
import shutil

import numpy as np
from pathlib import Path

sys.path.append(str(Path(__file__).parent.parent.parent.absolute()))

from auxiliary_partition.config import raw_dir, utk_dir, TRAIN_SPLIT, VALIDATION_SPLIT, TEST_SPLIT

def remove_og_dir():
    try:
        shutil.rmtree(raw_dir/'train')
        shutil.rmtree(raw_dir/'validation')
        shutil.rmtree(raw_dir/'test')
    except:
        print("Directories already deleted.")

def create_dirs():
    os.system('mkdir {dir}'.format(dir=raw_dir/'train'))
    os.system('mkdir {dir}'.format(dir=raw_dir/'validation'))
    os.system('mkdir {dir}'.format(dir=raw_dir/'test'))

def randomly_generate_dirs():
    for f in os.listdir(utk_dir):
        r = random.random()
        if r < TRAIN_SPLIT:
            new_dir = raw_dir / 'train'
        elif r < TRAIN_SPLIT + VALIDATION_SPLIT:
            new_dir = raw_dir / 'validation'
        else:
            new_dir = raw_dir / 'test'
        command = "cp {og_fp} {new_fp}".format(
            og_fp = utk_dir / f,
            new_fp = new_dir / f,
        )
        os.system(command)

if __name__ == "__main__":
    remove_og_dir()
    create_dirs()
    randomly_generate_dirs()


n = int(input())
a = input().split()
m = int(input())
b = input().split()

for i in reversed(range(n)):
    suf = a[i:]
    pref = b[:min(n-i, len(b))]
    if suf == pref:
        print(' '.join(a), ' '.join(b[min(n-i, len(b)):]))
        exit()

print('HOLIDAYS RUINED')


#
#  file:  cifar10_one_vs_many.py
#
#  Compare a single multiclass model vs individual binary models
#
#  RTK, 21-Oct-2019
#  Last update:  06-Nov-2019
#
################################################################

import numpy as np
from keras.models import load_model

def main():
    x_test = np.load("../data/cifar10/cifar10_test_images.npy")/255.0
    y_test = np.load("../data/cifar10/cifar10_test_labels.npy")

    #  Load the models
    mm = load_model("cifar10_cnn_model.h5")
    m = []
    for i in range(10):
        m.append(load_model("cifar10_cnn_%d_model.h5" % i))

    #  Multiclass predictions
    mp = np.argmax(mm.predict(x_test), axis=1)

    #  Individual binary predictions
    p = np.zeros((10,10000), dtype="float32")

    for i in range(10):
        p[i,:] = m[i].predict(x_test)[:,1]

    bp = np.argmax(p, axis=0)

    #  Confusion matrices
    cm = np.zeros((10,10), dtype="uint16")
    cb = np.zeros((10,10), dtype="uint16")

    for i in range(10000):
        cm[y_test[i],mp[i]] += 1
        cb[y_test[i],bp[i]] += 1

    np.save("cifar10_multiclass_conf_mat.npy", cm)
    np.save("cifar10_binary_conf_mat.npy", cb)

    #  Confusion matrices
    print()
    print("One-vs-rest confusion matrix (rows true, cols predicted):")
    print("%s" % np.array2string(100*(cb/1000.0), precision=1))
    print()
    print("Multiclass confusion matrix:")
    print("%s"  % np.array2string(100*(cm/1000.0), precision=1))

    #  Report on differences
    db = np.diag(100*(cb/1000.0))
    dm = np.diag(100*(cm/1000.0))
    df = db - dm
    sb = np.array2string(db, precision=1)[1:-1]
    sm = np.array2string(dm, precision=1)[1:-1]
    sd = np.array2string(df, precision=1)[1:-1]
    print()
    print("Comparing per class accuracies, one-vs-rest or multiclass:")
    print()
    print("    one-vs-rest: %s" % sb)
    print("    multiclass : %s" % sm)
    print("    difference : %s" % sd)

    #  Report overall accuracies
    print()
    print("Overall accuracy:")
    print("    one-vs-rest: %0.1f%%" % np.diag(100*(cb/1000.0)).mean())
    print("    multiclass : %0.1f%%" % np.diag(100*(cm/1000.0)).mean())
    print()

main()


import pdb
import threading
import tensorflow as tf
import tensorflow.keras as tf_keras
import tensorflow.keras.models as tf_models
import tensorflow.keras.layers as tf_layers
import tensorflow.keras.regularizers as tf_regularizers
import tensorflow.keras.initializers as tf_initializers

from modules.model_layers import *
from utils.misc import *
'''

tf.compat.v1.enable_eager_execution(
    config=None,
    device_policy=None,
    execution_mode=None
)
'''

# class ModelManager:
#    def __init__(self, opt,log_manager):
#        self.opt = opt
#        self.log_manager = log_manager
#        self.input_shape = (32,32,3)
#        self.psi_factor = 0.2
#         if self.opt.base_network == 'resnet9':
#             self.shapes = [
#                 (3,3,3,64),
#                 (3,3,64,128),
#                 (3,3,128,128),
#                 (3,3,128,128),
#                 (3, 3, 128, 256),
#                 (3, 3, 256, 512),
#                 (3, 3, 512, 512),
#                 (3, 3, 512, 512),
#                 (512, self.opt.num_classes)]
#         self.layers = {}
#         self.lock = threading.Lock()
#         self.initializer = tf_initializers.VarianceScaling(seed=opt.seed)

class ModelManager:

    def __init__(self, opt, log_manager):
        self.opt = opt
        self.log_manager = log_manager
        self.input_shape = (32,32,3)
        self.psi_factor = 0.2
        if self.opt.base_network == 'resnet9':
            self.shapes = [
                (3,3,3,64),
                (3,3,64,128),
                (3,3,128,128),
                (3,3,128,128),
                (3, 3, 128, 256),
                (3, 3, 256, 512),
                (3, 3, 512, 512),
                (3, 3, 512, 512),
                (512, self.opt.num_classes)]
        self.layers = {}
        self.lock = threading.Lock()
        self.initializer = tf_initializers.VarianceScaling(seed=opt.seed)

    def init_state(self, client_id):
        self.state = { 'client_id': client_id }

    def load_state(self, client_id):
        self.state = np_load(os.path.join(self.opt.state_dir, '{}_model_manager.npy'.format(client_id))).item()
        if 'fedmatch' in self.opt.model:
            for i, psi in enumerate(self.state['psi']):
                self.psi[i].assign(psi)
                self.sigma[i].assign(self.state['sigma'][i])

    def save_state(self):
        if 'fedmatch' in self.opt.model:
            self.state['psi'] = [psi.numpy() for psi in self.psi]
            self.state['sigma'] = [sigma.numpy() for sigma in self.sigma]
        np_save(self.opt.state_dir, '{}_model_manager.npy'.format(self.state['client_id']), self.state)

    def build_resnet9_plain(self):
        self.lock.acquire()
        def conv_block(in_channels, out_channels, pool=False, pool_no=2):
            layers = [tf_layers.Conv2D(out_channels, kernel_size=(3, 3), padding='same', use_bias=False, strides=(1, 1),
                                            kernel_initializer=self.initializer,  kernel_regularizer=tf_regularizers.l2(self.opt.wd)),
                            tf.keras.layers.ReLU()]
            if pool: layers.append(tf_layers.MaxPooling2D(pool_size=(pool_no, pool_no)))
            return tf_models.Sequential(layers)

        inputs = tf_keras.Input(shape=self.input_shape)
        out = conv_block(self.input_shape[-1], 64)(inputs)
        out = conv_block(64, 128, pool=True, pool_no=2)(out)
        out = tf_models.Sequential([conv_block(128, 128), conv_block(128, 128)])(out) + out
        out = conv_block(128, 256, pool=True)(out)
        out = conv_block(256, 512, pool=True, pool_no=2)(out)
        out = tf_models.Sequential([conv_block(512, 512), conv_block(512, 512)])(out) + out

        out = tf_models.Sequential([tf_layers.MaxPooling2D(pool_size=4),tf_layers.Flatten(),tf_layers.Dense(self.opt.num_classes, use_bias=False, activation='softmax')])(out)
        model = tf_keras.Model(inputs=inputs, outputs=out)

        #############################################
        wgts = model.get_weights()
        for i, w in enumerate(wgts):
            wgts[i] = w*(1+self.psi_factor)
        model.set_weights(wgts)
        #############################################

        self.lock.release()
        return model

    def build_resnet9_decomposed(self):
        self.lock.acquire()
        self.sigma = [ self.create_variable(name='sigma_{}'.format(i), shape=shape) for i, shape in enumerate(self.shapes)]#监督学习
        self.psi = [ self.create_variable(name='psi_{}'.format(i), shape=shape) for i, shape in enumerate(self.shapes)]#无监督学习
        for i, sigma in enumerate(self.sigma):
            self.psi[i].assign(sigma.numpy()*self.psi_factor)
        self.lid = 0

        def conv_block(in_channels, out_channels, pool=False, pool_no=2):
            self.layers[self.lid] = self.conv_decomposed(self.lid, out_channels, (3,3), (1,1), 'same', None)
            layers = [self.layers[self.lid], tf.keras.layers.ReLU()]
            self.lid += 1
            if pool: layers.append(tf_layers.MaxPooling2D(pool_size=(pool_no, pool_no)))
            return tf_models.Sequential(layers)

        inputs = tf_keras.Input(shape=self.input_shape)
        out = conv_block(self.input_shape[-1], 64)(inputs)
        out = conv_block(64, 128, pool=True, pool_no=2)(out)
        out = tf_models.Sequential([conv_block(128, 128), conv_block(128, 128)])(out) + out
        out = conv_block(128, 256, pool=True)(out)
        out = conv_block(256, 512, pool=True, pool_no=2)(out)
        out = tf_models.Sequential([conv_block(512, 512), conv_block(512, 512)])(out) + out

        out = tf_models.Sequential([tf_layers.MaxPooling2D(pool_size=4),tf_layers.Flatten(),self.dense_decomposed(8, self.opt.num_classes, 'softmax')])(out)

        model = tf_keras.Model(inputs=inputs, outputs=out)
        self.lock.release()
        return model

    def conv_decomposed(self, lid, filters, kernel_size, strides, padding, acti):
        if 'fedmatch' in self.opt.model:
            return DecomposedConv(
                name        = 'layer-{}'.format(lid),
                filters     = filters,
                kernel_size = kernel_size,
                strides     = strides,
                padding     = padding,
                activation  = acti,
                use_bias    = False,
                theta_sup   = self.sigma[lid],
                theta_unsup = self.psi[lid],
                l1_thres    = self.opt.l1_thres,
                kernel_regularizer = tf_regularizers.l2(self.opt.wd))

    def dense_decomposed(self, lid, units, acti):
        if 'fedmatch' in self.opt.model:
            return DecomposedDense(
                name = 'layer-{}'.format(lid),
                units       = units,
                activation  = acti,
                use_bias    = False,
                theta_sup   = self.sigma[lid],
                theta_unsup = self.psi[lid],
                l1_thres    = self.opt.l1_thres)

    def create_variable(self, name, shape):
        return tf.Variable(self.initializer(shape), name=name)

    def get_psi(self):
        return self.psi

    def get_sigma(self):
        return self.sigma


import numpy as np

from eot.categories.dataset_categories import DatasetCategories
from eot.categories.dataset_category import DatasetCategory

class CategoryComparison:

    true_positive_name = "prediction and reference (true positive)"
    false_positive_name = "prediction and not reference (false positive)"
    false_negative_name = "not prediction and reference (false negative)"
    true_negative_name = "not prediction and not reference (true negative)"

    def __init__(
        self,
        ground_truth_mask,
        prediction_mask,
        category_name,
        comparison_categories=None,
    ):
        if comparison_categories is None:
            comparison_categories = self._get_default_comparison_categories()
        self.comparison_categories = comparison_categories
        self.palette_colors = (
            comparison_categories.get_category_palette_colors(
                only_active=False, include_ignore=True
            )
        )

        self.category_name = category_name

        # NB: Mask consist of boolean values, while mat contains integer values
        self.comparison_mat = np.zeros_like(ground_truth_mask, dtype=int)

        # https://en.wikipedia.org/wiki/Sensitivity_and_specificity
        # True positive
        true_positive_mask = np.logical_and(prediction_mask, ground_truth_mask)
        true_positive_index = self.comparison_categories.get_category(
            self.__class__.true_positive_name
        ).palette_index
        self.comparison_mat[true_positive_mask] = true_positive_index

        # False positive
        false_positive_mask = np.logical_and(
            prediction_mask, np.logical_not(ground_truth_mask)
        )
        false_positive_index = self.comparison_categories.get_category(
            self.__class__.false_positive_name
        ).palette_index
        self.comparison_mat[false_positive_mask] = false_positive_index

        # False negative
        false_negative_mask = np.logical_and(
            np.logical_not(prediction_mask), ground_truth_mask
        )
        false_negative_index = self.comparison_categories.get_category(
            self.__class__.false_negative_name
        ).palette_index
        self.comparison_mat[false_negative_mask] = false_negative_index

        # # True negative
        true_negative_mask = np.logical_and(
            np.logical_not(prediction_mask), np.logical_not(ground_truth_mask)
        )
        true_negative_index = self.comparison_categories.get_category(
            self.__class__.true_negative_name
        ).palette_index
        self.comparison_mat[true_negative_mask] = true_negative_index

    @classmethod
    def _get_default_comparison_categories(cls):
        # fmt:off
        true_positive_category = DatasetCategory(name=cls.true_positive_name, palette_index=1, palette_color=(0, 0, 127))       # noqa
        false_positive_category = DatasetCategory(name=cls.false_positive_name, palette_index=2, palette_color=(0, 127, 0))     # noqa
        false_negative_category = DatasetCategory(name=cls.false_negative_name, palette_index=3, palette_color=(127, 0, 0))     # noqa
        true_negative_category = DatasetCategory(name=cls.true_negative_name, palette_index=4, palette_color=(127, 127, 127))   # noqa
        # fmt:on
        comparison_categories = DatasetCategories(
            [
                true_positive_category,
                false_positive_category,
                true_negative_category,
                false_negative_category,
            ]
        )
        return comparison_categories


import json
import vntypes

class NovelJSONEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, vntypes.Novel):
            base = {"id": o.vndb_id, "name": o.name}
            if o.characters is not None:
                base["characters"] = [self.default(c) for c in o.characters]
            return base
        elif isinstance(o, vntypes.Character):
            base = {"id": o.vndb_id, "name": o.name}
            if o.novels is not None:
                base["novels"] = [self.default(n) for n in o.novels]
            return base
        elif isinstance(o, vntypes.Quote):
            return {
                "text": o.text,
                "character": self.default(o.character),
                "novel": self.default(o.novel)
            }
        else:
            return super(NovelJSONEncoder, self).default(o)

def dumps(o):
    return json.dumps(o, cls=NovelJSONEncoder)


from io import BytesIO
from xml.parsers.expat import ExpatError

import pytest

from pubtools.pulplib import YumRepository

def test_upload_comps_xml(client, requests_mocker):
    """A client can upload expected units from within a comps.xml."""

    repo_id = "repo1"
    repo = YumRepository(id=repo_id)
    repo.__dict__["_client"] = client

    # Some XML to upload.
    # This is fairly minimal as this test focuses on upload functionality.
    # There are other tests exercising the XML parser more thoroughly.
    xml = BytesIO(
        b"""
        <comps>
            <group>
                <id>3d-printing</id>
                <name>3D Printing</name>
                <name xml:lang="af">3D-drukwerk</name>
                <description>3D printing software</description>
                <packagelist>
                    <packagereq type="default">admesh</packagereq>
                    <packagereq>blender</packagereq>
                </packagelist>
            </group>

            <category>
                <id>kde-desktop-environment</id>
                <name>KDE Desktop</name>
                <display_order>10</display_order>
                <grouplist>
                    <groupid>kde-office</groupid>
                    <groupid>kde-telepathy</groupid>
                </grouplist>
            </category>

            <environment>
                <id>basic-desktop-environment</id>
                <name>Basic Desktop</name>
                <name xml:lang="af">Basiese werkskerm</name>
                <description>X Window System with a choice of window manager.</description>
                <grouplist>
                    <groupid>networkmanager-submodules</groupid>
                    <groupid>standard</groupid>
                </grouplist>
                <optionlist>
                    <groupid default="true">xmonad</groupid>
                    <groupid>xmonad-mate</groupid>
                </optionlist>
            </environment>

            <langpacks>
                <match install="stardict-dic-%s" name="stardict"/>
                <match install="tkgate-%s" name="tkgate"/>
            </langpacks>
        </comps>
    """
    )

    # Set up the requests it'll do:
    #
    # It should unassociate previous units
    requests_mocker.post(
        "https://pulp.example.com/pulp/api/v2/repositories/repo1/actions/unassociate/",
        json={"spawned_tasks": [{"task_id": "remove-task"}]},
    )

    # It'll search for the status of tasks.
    # Note: to avoid an overly complex mock we just let every task search return all
    # tasks rather than differentiating between remove and upload tasks
    upload_count = 4
    requests_mocker.post(
        "https://pulp.example.com/pulp/api/v2/tasks/search/",
        json=[{"task_id": "remove-task", "state": "finished"}]
        + [
            {"task_id": "upload-task-%d" % i, "state": "finished"}
            for i in range(0, upload_count)
        ],
    )

    # It will request various uploads
    requests_mocker.post(
        "https://pulp.example.com/pulp/api/v2/content/uploads/",
        [{"json": {"upload_id": "upload-%d" % i}} for i in range(0, upload_count)],
    )

    # It'll do an import against the uploads
    requests_mocker.post(
        "https://pulp.example.com/pulp/api/v2/repositories/repo1/actions/import_upload/",
        [
            {"json": {"spawned_tasks": [{"task_id": "upload-task-%d" % i}]}}
            for i in range(0, upload_count)
        ],
    )

    # It'll clean up the uploads
    for i in range(0, upload_count):
        requests_mocker.delete(
            "https://pulp.example.com/pulp/api/v2/content/uploads/upload-%d/" % i
        )

    # Mocker setup is complete.

    # It should start the upload OK
    upload_f = repo.upload_comps_xml(xml)

    # I can await the result
    tasks = upload_f.result()

    # There should be various tasks returned from the API
    assert sorted([t.id for t in tasks]) == [
        "upload-task-0",
        "upload-task-1",
        "upload-task-2",
        "upload-task-3",
    ]

    # Each task should be successful
    for t in tasks:
        assert t.completed
        assert t.succeeded

    # Gather info on exactly what the client imported
    imported_units = []
    for req in requests_mocker.request_history:
        if req.url.endswith("/import_upload/"):
            imported_units.append(req.json()["unit_metadata"])

    imported_units.sort(key=lambda u: u["_content_type_id"])

    # Did we import exactly the expected units?
    assert imported_units == [
        {
            "_content_type_id": "package_category",
            "id": "kde-desktop-environment",
            "name": "KDE Desktop",
            "display_order": 10,
            "packagegroupids": ["kde-office", "kde-telepathy"],
            "repo_id": "repo1",
        },
        {
            "_content_type_id": "package_environment",
            "id": "basic-desktop-environment",
            "name": "Basic Desktop",
            "translated_name": {"af": "Basiese werkskerm"},
            "description": "X Window System with a choice of window manager.",
            "group_ids": ["networkmanager-submodules", "standard"],
            "options": [
                {"group": "xmonad", "default": True},
                {"group": "xmonad-mate", "default": False},
            ],
            "repo_id": "repo1",
        },
        {
            "_content_type_id": "package_group",
            "id": "3d-printing",
            "name": "3D Printing",
            "translated_name": {"af": "3D-drukwerk"},
            "description": "3D printing software",
            "default_package_names": ["admesh"],
            "mandatory_package_names": ["blender"],
            "repo_id": "repo1",
        },
        {
            "_content_type_id": "package_langpacks",
            "matches": [
                {"install": "stardict-dic-%s", "name": "stardict"},
                {"install": "tkgate-%s", "name": "tkgate"},
            ],
            "repo_id": "repo1",
        },
    ]

def test_upload_empty_comps_xml(client, requests_mocker):
    """A client can upload an empty comps.xml, which merely removes existing units."""

    repo_id = "repo1"
    repo = YumRepository(id=repo_id)
    repo.__dict__["_client"] = client

    xml = BytesIO(b"<comps/>")

    # Set up the requests it'll do:
    #
    # It should unassociate previous units
    requests_mocker.post(
        "https://pulp.example.com/pulp/api/v2/repositories/repo1/actions/unassociate/",
        json={"spawned_tasks": [{"task_id": "remove-task"}]},
    )

    # It'll search for the status of tasks.
    requests_mocker.post(
        "https://pulp.example.com/pulp/api/v2/tasks/search/",
        json=[{"task_id": "remove-task", "state": "finished"}],
    )

    # And... that's it.

    # It should start the upload OK
    upload_f = repo.upload_comps_xml(xml)

    # I can await the result
    tasks = upload_f.result()

    # It should just return the removal task
    assert [t.id for t in tasks] == ["remove-task"]
    assert tasks[0].completed
    assert tasks[0].succeeded

    # Check exactly the removed types
    assert requests_mocker.request_history[0].json() == {
        "criteria": {
            "type_ids": [
                "package_group",
                "package_category",
                "package_environment",
                "package_langpacks",
            ]
        }
    }

def test_bad_comps_xml(client, requests_mocker, tmpdir):
    """A client requested to upload an invalid comps.xml will raise immediately
    without making any requests to Pulp."""

    repo_id = "repo1"
    repo = YumRepository(id=repo_id)
    repo.__dict__["_client"] = client

    comps_xml = tmpdir.join("comps.xml")
    comps_xml.write(b"Oops not valid comps")

    # It should raise
    with pytest.raises(ExpatError):
        repo.upload_comps_xml(str(comps_xml))

    # As we did not register anything in requests_mocker, we've already
    # implicitly tested that no requests happened. But just to be clear...
    assert not requests_mocker.request_history


# -*- coding: UTF-8 -*-
import shell

def run(client, module):
    args = module.get('args')
    if args:
        directory = args.get('dir')
        file_name = args.get('file')
        mod = {
            "shell": "openssl md5 {file} | cut -d' ' -f2".format(file=file_name),
            'args': {
                'chdir': directory
            }
        }
        return shell.run(client, mod)