# -*- coding: utf-8 -*-
import datetime
from io import BytesIO

import pytz
from django.core.files.storage import default_storage
from django.http import HttpResponse
from ledger.payments.pdf import BrokenLine
from ledger.settings_base import TIME_ZONE
from reportlab.lib.colors import red, green, blue
from reportlab.lib.enums import TA_RIGHT, TA_CENTER
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, Paragraph, Spacer, Table, TableStyle, PageBreak
from reportlab.lib.styles import ParagraphStyle, StyleSheet1
from reportlab.lib.units import mm
from reportlab.lib import colors

from wildlifecompliance.components.main.pdf_utils import gap, ParagraphOffeset, ParagraphCheckbox, get_font_str

PAGE_MARGIN = 5 * mm
PAGE_WIDTH, PAGE_HEIGHT = A4

def _create_pdf(invoice_buffer, legal_case, offenders):
    every_page_frame = Frame(PAGE_MARGIN, PAGE_MARGIN, PAGE_WIDTH - 2 * PAGE_MARGIN, PAGE_HEIGHT - 2 * PAGE_MARGIN, id='EveryPagesFrame', )  #showBoundary=Color(0, 1, 0))
    every_page_template = PageTemplate(id='EveryPages', frames=[every_page_frame,], )
    doc = BaseDocTemplate(invoice_buffer, pageTemplates=[every_page_template, ], pagesize=A4,)  # showBoundary=Color(1, 0, 0))

    # Common
    col_width_head = [95*mm, 15*mm, 85*mm,]
    col_width_details = [28*mm, 28*mm, 71*mm, 23*mm, 41*mm]
    FONT_SIZE_L = 12
    FONT_SIZE_M = 10
    FONT_SIZE_S = 8
    topLeftTableRowHeights = [23.5*mm, ]
    topRightTableRowHeights = [7.8*mm, 15.6*mm, ]

    styles = StyleSheet1()
    styles.add(ParagraphStyle(name='Normal',
                              fontName='Helvetica',
                              fontSize=FONT_SIZE_M,
                              spaceBefore=2,  # space before paragraph
                              spaceAfter=2,   # space after paragraph
                              leading=11))       # space between lines
    styles.add(ParagraphStyle(name='BodyText',
                              parent=styles['Normal'],
                              spaceBefore=6))
    styles.add(ParagraphStyle(name='Italic',
                              parent=styles['BodyText'],
                              fontName='Helvetica-Italic'))
    styles.add(ParagraphStyle(name='Bold',
                              parent=styles['BodyText'],
                              fontName='Helvetica-Bold',
                              alignment = TA_CENTER))
    styles.add(ParagraphStyle(name='Right',
                              parent=styles['BodyText'],
                              alignment=TA_RIGHT))
    styles.add(ParagraphStyle(name='Centre',
                              parent=styles['BodyText'],
                              alignment=TA_CENTER))

    court_date_qs = legal_case.court_proceedings.court_dates.all().order_by('court_datetime')
    court_date_obj = None
    if court_date_qs:
        # Retrieve earliest one
        court_date_obj = court_date_qs[0]

    elements = []
    for offender in offenders:
        offender_full_name = ''
        court_date_txt = ''
        court_time_txt = ''
        court_place_txt = ''

        if offender.person:
            offender_full_name = offender.person.get_full_name()
        if court_date_obj and court_date_obj.court_datetime:
            local_datetime = court_date_obj.court_datetime.astimezone(pytz.timezone(TIME_ZONE))
            court_date_txt = local_datetime.strftime('%d/%m/%Y')
            court_time_txt = local_datetime.strftime('%H:%M')
        if court_date_obj and court_date_obj.court:
            court_place_txt = court_date_obj.court.location

        ###
        # 1st page
        ###

        # Header small text
        header_small_text_p1 = ParagraphOffeset('Copy to be attached to court copy of prosecution notice',
                                                styles['Right'],
                                                x_offset=-3*mm, y_offset=0)

        # Head (col, row)
        invoice_table_style = TableStyle([
            ('VALIGN', (0, 0), (-1, -1), 'TOP'),
            ('GRID', (0, 0), (-1, -1), 0, colors.white),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
        ])
        style_tbl_left = TableStyle([
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
        ])
        style_tbl_right = TableStyle([
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
        ])
        data_left = Table([
            [Paragraph('MAGISTRATES COURT of WESTERN
'
                       'AUSTRALIA
'
                       'COURT HEARING NOTICE
'
                       'Criminal Procedure Act 2004
'
                       'Criminal Procedure Regulations 2005 - Form 5', styles['Centre']),]
        ], style=style_tbl_left, rowHeights=topLeftTableRowHeights)
        data_right = Table([
            [Paragraph('Court number', styles['Normal']), ''],
            [Paragraph('Magistrates court at', styles['Normal']), ''],
        ], style=style_tbl_right, rowHeights=topRightTableRowHeights)
        tbl_head = Table([[data_left, '', data_right]], style=invoice_table_style, colWidths=col_width_head, )

        # Accused's Details, etc
        rowHeights = [6*mm, 6*mm, 6*mm, 30*mm, 6*mm]
        style_tbl_accused_details = TableStyle([
            ('VALIGN', (0, 0), (0, 0), 'MIDDLE'),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('SPAN', (0, 0), (0, 1)),
            ('SPAN', (2, 0), (4, 0)),
            ('SPAN', (2, 1), (4, 1)),
        ])
        data = []
        data.append([
            Paragraph('Accused\'s Details
', styles['Normal']),
            Paragraph('Full name', styles['Normal']),  # ,
            Paragraph(get_font_str(offender_full_name), styles['Normal']),
            '',
            '',
        ])
        data.append([
            '',
            Paragraph('Address', styles['Normal']),
            '', '', '',
        ])
        tbl_accused_details = Table(data, style=style_tbl_accused_details, colWidths=col_width_details, )  # rowHeights=rowHeights)

        # Hearing details, etc
        style_tbl_hearing_details = TableStyle([
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('SPAN', (1, 0), (4, 0)),
            ('SPAN', (1, 2), (4, 2)),
        ])
        data = []
        data.append([
            Paragraph('Hearing details', styles['Normal']),
            Paragraph('The charge(s) in the attached prosecution notice dated [insert date]
will be first dealt with by the above court at the time, date and place stated below.', styles['Normal']),
            '', '', '',
        ])
        data.append([
            Paragraph('Date and time', styles['Normal']),
            Paragraph('Date', styles['Normal']),
            Paragraph(get_font_str(court_date_txt), styles['Normal']),
            Paragraph('Time', styles['Normal']),
            Paragraph(get_font_str(court_time_txt), styles['Normal']),
        ])
        data.append([
            Paragraph('Place', styles['Normal']),
            Paragraph(get_font_str(court_place_txt), styles['Normal']),
            '', '', '',
        ])
        tbl_hearing_details = Table(data, style=style_tbl_hearing_details, colWidths=col_width_details, )  # rowHeights=rowHeights)

        # Notice to accused
        col_width_notice_to_accused = [28*mm, 163*mm, ]
        style_tbl_notice_to_accused = TableStyle([
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('VALIGN', (0, 0), (0, -1), 'TOP'),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
        ])
        data = []
        data.append([
            Paragraph('Notice to accused', styles['Normal']),
            Paragraph('Your options are set out below. You should read them carefully.
If you do not know what to do, you should get advice from a lawyer, the Legal Aid Commission or the Aboriginal Legal Service. If you will need an interpreter in court, please contact the court', styles['Normal']),
        ])
        data.append([
            Paragraph('Options', styles['Normal']),
            Paragraph('1. You can attend the above hearing.
'
                      '2. You can do nothing.
'
                      '3. You can plead not guilty in writing.
'
                      '4. You can plead guilty in writing.
'
                      'Options 2, 3 and 4 are explained below.', styles['Normal']),
        ])
        data.append([
            [
                Paragraph('Doing nothing', styles['Normal']),
                Spacer(0, 5*mm),
                Paragraph('[Options 2]', styles['Normal']),
            ],
            [
                Paragraph('If you do not appear at the above hearing and you do not send the court a written plea in time, the court may determine the charge(s) at the above hearing in your absence.', styles['Normal']),
                Paragraph('In some cases the court can take as proved any allegation in the attached prosecution notice without hearing evidence.', styles['Normal']),
                Paragraph('The court may decide to summons you to court or have you arrested and brought before the court.', styles['Normal']),
                Paragraph('If the court finds you guilty, it may fine you and order you to pay court costs and the prosecutor’s costs.', styles['Normal']),
            ],
        ])
        data.append([
            [
                Paragraph('Pleading not guilty in writing', styles['Normal']),
                Spacer(0, 5 * mm),
                Paragraph('[Option 3]', styles['Normal']),
            ],
            [
                Paragraph('Pleading not guilty to a charge in the prosecution notice means you do not admit the charge.', styles['Normal']),
                Paragraph('If you send the court a written plea of not guilty, you need not attend the above hearing. If the court receives your written plea in time it will send you a notice of another hearing, at which the court will deal with the charge(s) (in your absence if you are not there) and hear any evidence you wish to give and any witnesses you call.', styles['Normal']),
                Paragraph('To send the court a written plea of not guilty, fill out page 2 of this form and send page 2 to the address on it at least three days before the above hearing date.', styles['Normal']),
            ],
        ])
        data.append([
            [
                Paragraph('Pleading guilty in writing', styles['Normal']),
                Spacer(0, 5 * mm),
                Paragraph('[Option 4]', styles['Normal']),
            ],
            [
                Paragraph('Pleading guilty to a charge in the prosecution notice means you admit the charge.', styles['Normal']),
                Paragraph('If you send the court a written plea of guilty, you need not attend the above hearing unless you want to tell the court something.', styles['Normal']),
                Paragraph('If the court receives your written plea in time it will deal with the charge(s) at the above hearing (in your absence if you are not there) and may fine you and order you to pay court costs and the prosecutor’s costs.', styles['Normal']),
                Paragraph('To send the court a written plea of guilty, fill out page 2 of this form, include any written explanation or information you want the court to consider, and send it all to the address on the form at least three days before the above hearing date.', styles['Normal']),
                Paragraph('The court might not accept your plea of guilty if what you tell the court suggests you do not admit the charge. If that happens you will be notified.', styles['Normal']),
            ],
        ])
        tbl_notice_to_accused = Table(data, style=style_tbl_notice_to_accused, colWidths=col_width_notice_to_accused)

        # Issuing details
        col_width_issuing_details = col_width_notice_to_accused
        style_tbl_issuing_details = TableStyle([
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
        ])
        data = []
        data.append([
            Paragraph('Issuing details', styles['Normal']),
            [
                Paragraph('This notice is issued on [date]', styles['Normal']),
                Spacer(0, 8*mm),
                BrokenLine(50*mm),
                Paragraph('[Title of person issuing notice]', styles['Normal']),
            ]
        ])
        tbl_issuing_details = Table(data, style=style_tbl_issuing_details, colWidths=col_width_issuing_details)

        # Service details
        col_width_service_details = col_width_notice_to_accused
        style_tbl_service_details = TableStyle([
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('SPAN', (0, 0), (0, 1))
        ])
        data = []
        data.append([
            [
                Paragraph('Service details', styles['Normal']),
                Spacer(0, 5 * mm),
                Paragraph('[*Police only]', styles['Normal']),
            ],
            Paragraph('[Service must be in one of the manners in the CPA Schedule 2 clauses 2, 3 or 4 (see s. 33(3)). Insert here whichever manner of service was used.]', styles['Normal'])
        ])
        tbl_style_internal = TableStyle([
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
        ])
        data.append([
            '',
            [
                Paragraph('On' + gap(30) + '20' + gap(10) + ', the accused was served with a copy of this notice and the prosecution notice referred to above in the following manner:', styles['Normal']),
                Table([
                    [Paragraph('Name of server:', styles['Normal']), Paragraph('*Registered No:', styles['Normal'])],
                    [Paragraph('Signature:', styles['Normal']), Paragraph(gap(1) + 'Station:', styles['Normal'])],
                ], style=tbl_style_internal, rowHeights=[8*mm, 8*mm, ])
            ]
        ])
        tbl_service_details = Table(data, style=style_tbl_service_details, colWidths=col_width_service_details)

        ###
        # 2nd page
        ###
        # Head (col, row)
        data_left_p2 = Table([
            [Paragraph('MAGISTRATES COURT of WESTERN
'
                       'AUSTRALIA
'
                       'WRITTEN PLEA BY ACCUSED
'
                       'Criminal Procedure Act 2004
'
                       'Criminal Procedure Regulations 2005 - Form 5 page 2', styles['Centre']),]
        ], style=style_tbl_left, rowHeights=topLeftTableRowHeights)
        data_right_p2 = Table([
            [Paragraph('Court number', styles['Normal']), ''],
            [Paragraph('Magistrates court at', styles['Normal']), ''],
        ], style=style_tbl_right, rowHeights=topRightTableRowHeights)
        tbl_head_p2 = Table([[data_left_p2, '', data_right_p2]], style=invoice_table_style, colWidths=col_width_head, )

        # Accused's Details
        # This is common among the pages

        # Accused's plea
        col_width_p2 = [28*mm, 28*mm, 71*mm, 23*mm, 41*mm]
        tbl_style_p2 = (
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('VALIGN', (0, 0), (0, -1), 'TOP'),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('SPAN', (1, 0), (4, 0)),
            ('SPAN', (1, 1), (4, 1)),
            ('SPAN', (1, 2), (4, 2)),
            ('SPAN', (1, 3), (4, 3)),
            ('SPAN', (1, 4), (4, 4)),
            ('SPAN', (1, 5), (4, 5)),
            ('SPAN', (1, 6), (2, 6)),
            ('SPAN', (1, 7), (4, 7)),
            ('SPAN', (0, 5), (0, 6)),
        )
        data = []
        data.append([
            Paragraph('Accused\'s plea', styles['Normal']),
            [
                Paragraph('I have received a prosecution notice dated' + gap(40) + 'and a court hearing notice advising me of the hearing on [date]', styles['Normal']),
                Paragraph('I understand or have had explained to me the charge(s) in the prosecution notice and the contents of the court hearing notice and I understand the effect of this written plea I am sending to the court.', styles['Normal']),
            ],
            '', '', '',
        ])
        data.append([
            [
                Paragraph('Plea of guilty', styles['Normal']),
                Paragraph('[Tick on box]', styles['Normal']),
                Spacer(0, 20*mm),
                Paragraph('[Tick on box]', styles['Normal']),
            ],
            [
                ParagraphCheckbox('I plead guilty to the charge(s) in the prosecution notice.', styles['Normal']),
                ParagraphCheckbox('I plead guilty to the following charges in the prosecution notice.', styles['Normal']),
                Paragraph('[If the prosecution notice contains more than one charge and you want to plead guilty to only some of them, write the numbers of the charges here.]', styles['Normal']),
                Spacer(0, 8*mm),
                Paragraph('Attendance at court:', styles['Normal']),
                ParagraphCheckbox('I will be attending the hearing on the above date.', styles['Normal']),
                ParagraphCheckbox('I will not be attending the hearing on the above date.', styles['Normal']),
                Paragraph('I would like the court to take account of the following:', styles['Normal']),
                Paragraph('[If you are pleading guilty you can (but need not) explain why you committed the offence(s) and give any information that you want the court to consider when deciding what sentence to impose on you.]', styles['Normal']),
                Spacer(0, 10 * mm),
            ],
            '', '', '',
        ])
        data.append([
            [
                Paragraph('Plea of not guilty', styles['Normal']),
                Paragraph('[Tick on box]', styles['Normal']),
                Spacer(0, 20 * mm),
                Paragraph('[Tick on box]', styles['Normal']),
            ],
            [
                ParagraphCheckbox('I plead not guilty to the charge(s) in the prosecution notice.', styles['Normal']),
                ParagraphCheckbox('I plead not guilty to the following charges in the prosecution notice.', styles['Normal']),
                Paragraph('[If the prosecution notice contains more than one charge and you want to plead not guilty to only some of them, write the numbers of them here]', styles['Normal']),
                Spacer(0, 8 * mm),
                Paragraph('Attendance at court:', styles['Normal']),
                ParagraphCheckbox('I will be attending the hearing on the above date.', styles['Normal']),
                ParagraphCheckbox('I will not be attending the hearing on the above date.', styles['Normal']),
                Paragraph('At the trial of the charge(s) I intend to call' + gap(40) + 'witnesses (including myself).', styles['Normal']),
                Paragraph('[Please insert the number of witnesses to assist the court in deciding how long the trial might last]', styles['Normal']),
                Paragraph('When setting a date for the trial please take account of the following:', styles['Normal']),
                Paragraph('[Please provide any information that might assist the court when setting the date for the trial such as dates when you will be overseas or in hospital.]', styles['Normal']), Spacer(0, 10 * mm),
            ],
            '', '', '',
        ])
        data.append([
            Paragraph('Contact details', styles['Normal']),
            [
                Paragraph('My contact details are:', styles['Normal']),
                Spacer(0, 2*mm),
                Paragraph('Address (if different to the one above):', styles['Normal']),
                Spacer(0, 2*mm),
                Paragraph('Telephone no.' + gap(40) + 'Fax no.' + gap(40) + 'Mobile no.', styles['Normal']),
            ],
            '', '', '',
        ])
        data.append([
            [
                Paragraph('Lawyer\'s details', styles['Normal']),
                Paragraph('[If a lawyer will appear for you]', styles['Normal']),
            ],
            [
                Paragraph('Name:', styles['Normal']),
                Paragraph('Firm name', styles['Normal']),
            ],
            '', '', '',
        ])
        data.append([
            Paragraph('Accused\'s signature', styles['Normal']),
            Paragraph('This may be signed by the accused’s lawyer or, if the accused is a corporation, made in accordance with the Criminal Procedure Act 2004 section 154(1).', styles['Normal']),
            '', '', '',
        ])
        data.append([
            '',
            '',
            '',
            Paragraph('Date', styles['Normal']),
            '',
        ])
        data.append([
            Paragraph('Court address', styles['Normal']),
            [
                Paragraph('Send this document to:', styles['Normal']),
                Spacer(0, 2*mm),
                Paragraph('at:', styles['Normal']),
                Spacer(0, 2 * mm),
            ],
            '', '', '',
        ])
        tbl_main_p2 = Table(data, style=tbl_style_p2, colWidths=col_width_p2, )

        ###
        # 3rd page
        ###
        header_small_text_p3 = ParagraphOffeset('Copy to be attached to accused copy of prosecution notice',
                                                styles['Right'],
                                                x_offset=-3*mm, y_offset=0)

        ###
        # 4th page
        ###
        # Same as 2nd page

        ###
        # 5th page
        ###
        header_small_text_p5 = ParagraphOffeset('Return of service copy',
                                                styles['Right'],
                                                x_offset=-3*mm, y_offset=0)

        ###
        # 6th page
        ###

        gap_between_tables = 1.5*mm
        odd_page = []
        odd_page.append(tbl_head)
        odd_page.append(tbl_accused_details)
        odd_page.append(Spacer(0, gap_between_tables))
        odd_page.append(tbl_hearing_details)
        odd_page.append(Spacer(0, gap_between_tables))
        odd_page.append(tbl_notice_to_accused)
        odd_page.append(Spacer(0, gap_between_tables))
        odd_page.append(tbl_issuing_details)
        odd_page.append(Spacer(0, gap_between_tables))
        odd_page.append(tbl_service_details)
        even_page = []
        even_page.append(tbl_head_p2)
        even_page.append(tbl_accused_details)
        even_page.append(Spacer(0, gap_between_tables))
        even_page.append(tbl_main_p2)

        # 1st page
        elements.append(header_small_text_p1)
        elements += odd_page
        elements.append(PageBreak())
        # 2nd page
        elements += even_page
        elements.append(PageBreak())
        # 3rd page
        elements.append(header_small_text_p3)
        elements += odd_page
        elements.append(PageBreak())
        # 4th page
        elements += even_page
        elements.append(PageBreak())
        # 5th page
        elements.append(header_small_text_p5)
        elements += odd_page
        elements.append(PageBreak())
        # 6th page
        elements += even_page

    doc.build(elements)
    return invoice_buffer

def create_court_hearing_notice_pdf_bytes(filename, legal_case):
    with BytesIO() as invoice_buffer:
        _create_pdf(invoice_buffer, legal_case)

        # # Get the value of the BytesIO buffer
        # value = invoice_buffer.getvalue()
        #
        # # START: Save the pdf file to the database
        # document = legal_case.documents.create(name=filename)
        # path = default_storage.save('wildlifecompliance/{}/{}/documents/{}'.format(legal_case._meta.model_name, legal_case.id, filename), invoice_buffer)
        # document._file = path
        # document.save()
        # invoice_buffer.close()
        # return document
    invoice_buffer.seek(0)

    response = HttpResponse(invoice_buffer, content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)
    return response


import numpy as np
import pycuda.autoinit
import pycuda.driver as drv
from pycuda.compiler import SourceModule

mod = SourceModule("""
  __global__ void evaluate(float *c, float *a, float *b)
  {
    const int i = threadIdx.x;
    c[i] = 2*a[i] + 3*b[i];
  }
""")

evaluate = mod.get_function("evaluate")

a = np.random.uniform(0, 1, 1000).astype(np.float32)
b = np.random.uniform(0, 1, 1000).astype(np.float32)
c = np.zeros_like(a)

evaluate(drv.Out(c), drv.In(a), drv.In(b), block=(400,1,1), grid=(1,1))


import os
from lxml import etree
from io import StringIO
import codecs

__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))

filename = __location__ + "/html/allcameras.html"

file = codecs.open(filename, 'r', 'utf-8')

content = file.read()
file.close()

parser =etree.HTMLParser()

page = etree.parse(StringIO(content), parser).getroot()

cameras = page.xpath('//div[contains(@class, "pane")]/table//tr/td/table')

print("Found %s cameras" % len(cameras))

for camera in cameras:
    rows = camera.xpath('.//tr')
    # print("%s rows" % len(rows))

    url = rows[1].xpath('.//a')[0].get('href')

    print('Url: %s' % url)


#!/usr/bin/python3
import pdb
import math
from lib.board import Board
from IPython import embed

def setup(ships_each):
    for j in range(2):
        print('player ' + str(j) + ' selct your ships!')
        for i in range(ships_each):
            while True:
                print('Ship ' + str(i))
                name = input('Name your ship (must be unique): ')
                name = "%s%s" % (name, str(j)) # this is how we identify the ship
                point_x = input('Initial point(x): ')
                point_y = input('Initial point(y): ')
                point = (int(point_y),int(point_x))
                direction = input('Direction (N,S,E,W): ')
                if board.insert_ship(point, direction, 4, name):
                    break

def play():
    i=0
    while True:
        # check winner condition
        ships = board.ships_by_player()
        if len(ships) is 1: # there is a winner
            first = ship[0]
            player = first[len(first)-1] # ships last character is actually the id
            print('Player ' + player + ' wins')
            return

        # there is no winner we must continue the battle(ship)
        player = "1" if i % 2 is 0 else "2"
        print('move ' + str(i) + ' player ' + player + "'s move")
        print('player ' + player + ' launch #' + str(math.ceil((i+1)/2)))
        point_x = input('strike point(x): ')
        point_y = input('strike point(y): ')
        point = (int(point_y),int(point_x))
        print('target hit!') if board.attack(point) else print('target miss!')
        i += 1

board = Board(16)
setup(1)
play()


import os
import string
import random
from datetime import datetime
from aws_lambda_powertools import Tracer
from aws_lambda_powertools import Logger
from pynamodb.models import Model
from pynamodb.attributes import (
    UnicodeAttribute, UTCDateTimeAttribute
)

logger = Logger()
tracer = Tracer()

if 'USER_TABLE' not in os.environ or os.environ['USER_TABLE'] is None:
    raise RuntimeError('USER_TABLE env var is not set')

USER_TABLE = os.environ['USER_TABLE']

class User(Model):
    """Model for a User to be inserted in DynamoDB"""

    class Meta:
        """Metadata for User Model (pynamodb)"""
        table_name = USER_TABLE
        region = os.environ['AWS_REGION']

    id = UnicodeAttribute(hash_key=True)
    lastname = UnicodeAttribute(range_key=True)
    firstname = UnicodeAttribute()
    birthdate = UnicodeAttribute()
    birthcountry = UnicodeAttribute()
    address = UnicodeAttribute()
    email = UnicodeAttribute()
    idcardref = UnicodeAttribute()
    created_at = UTCDateTimeAttribute()
    updated_at = UTCDateTimeAttribute()

@tracer.capture_lambda_handler()
@logger.inject_lambda_context
def handler(event, _):

    characters = string.ascii_letters + string.digits
    user_id = ''.join(random.choice(characters) for i in range(16))
    now = datetime.utcnow()

    user = User(id = user_id,
        lastname=event['user']['lastname'],
        firstname=event['user']['firstname'],
        birthdate=event['user']['birthdate'],
        birthcountry=event['user']['countrybirth'],
        address=event['user']['address'],
        email=event['user']['email'],
        idcardref=event['user']['idcard'],
        created_at = now,
        updated_at = now
    )
    user.save()

    event['user']['id'] = user_id
    return event['user']


import keras
from keras.models import Sequential
from keras.layers.core import Dense
from keras.optimizers import Adam
from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import StandardScaler
import numpy as np
import random
from keras.constraints import max_norm
from keras.models import model_from_yaml

MUTATION_RANGE = 0.5
MUTATION_CHANCE = 0.1
MUTATION_BIAS_CHANCE = 0.1

CROSSOVER_RANGE = 0.9
CROSSOVER_CHANCE = 0.5
CROSSOVER_BIAS_CHANCE = 0.5

class Mlp():

	def __init__(self):
		self.model = Sequential([
			Dense(2, input_shape=(2,), activation="relu", kernel_constraint=max_norm(1.)),
			Dense(6, activation="relu", kernel_constraint=max_norm(1.)),
			Dense(2, activation="softmax", kernel_constraint=max_norm(1.))
			])
		#print(self.model.summary())
		self.model.compile(Adam(lr=0.0001), loss='sparse_categorical_crossentropy', metrics=['accuracy'])
		#w = self.model.layers[0].get_weights()
		#print('------------w-----------------')
		#w = self.model.get_weights()
		#print(w)
		#print(w)

	def set_train(self, train, labels):
		print(train)
		scaler = MinMaxScaler(feature_range=(0,1))
		scaled_train = scaler.fit_transform((train))
		self.scaled_train = scaled_train
		self.train_labels = labels

	def train(self):
		self.model.fit(self.scaled_train, self.train_labels, batch_size=1, epochs=1, shuffle=True, verbose=2)
		w = self.model.layers[0].get_weights()
		print(w)
		new_w = []
		new_w.append(np.array([[1, 2], [3,4]], float))
		new_w.append(w[1])
		self.model.layers[0].set_weights(new_w)
		w = self.model.layers[0].get_weights()
		print(w)

	def predict(self, test):
		#predictions = self.model.predict(self.scaled_train, batch_size=10, verbose=0)
		scaler = MinMaxScaler(feature_range=(0,1))
		test = np.array([test[0][0], test[0][1]], dtype=np.float)
		test = test.reshape(1,-1)
		test = np.vstack((test, [-500, -300]))
		test = np.vstack((test, [500, 300]))

		#print(test)
		scaled_test = scaler.fit_transform(test)
		#print('parameterssss scaled', scaled_test[0].reshape(1,-1))
		rounded_predictions = self.model.predict_classes(scaled_test[0].reshape(1,-1), batch_size=1, verbose=0)
		#rounded_predictions = self.model.predict(scaled_test, batch_size=10, verbose=0)
		#print('rounded', rounded_predictions)
		#if(rounded_predictions[0][0] > rounded_predictions[0][1]):
		#	rounded_predictions = [0]
		#else:
		#		rounded_predictions = [1]
		return rounded_predictions

	def weight_mutation(self):
		number_of_layers = int(len(self.model.get_weights())/2)
		layer_len = [2]
		layer_len += [len(self.model.layers[i].get_weights()[0][0]) for i in range(number_of_layers)]
		#print(layer_len)
		#print(self.model.layers[0].get_weights())
		#print(self.model.layers[0].get_weights()[0][0][0])
		for layer in range(1, number_of_layers+1):
			for i in range(int(layer_len[layer]*layer_len[layer-1]*MUTATION_RANGE)):
				var = random.randint(1,100)
				if (var <= 100*MUTATION_CHANCE):
					new_weigth = self.model.layers[layer-1].get_weights()
					index_i = random.randint(0, layer_len[layer-1]-1)
					index_j = random.randint(0, layer_len[layer]-1)
					#print('layer', layer, layer_len[layer]-1, layer_len[layer-1]-1)
					value = random.uniform(-1,1)
					#print(new_weigth)
					new_weigth[0][index_i][index_j] = value
					self.model.layers[layer-1].set_weights(new_weigth)
			self.bias_mutation(layer-1, layer_len[1:])

	def bias_mutation(self, layer, layer_len):
		for i in range(int(layer_len[layer]*MUTATION_RANGE)):
			var = random.randint(1,100)
			if (var <= 100*MUTATION_BIAS_CHANCE):
				new_weigth = self.model.layers[layer].get_weights()
				index = random.randint(0, layer_len[layer]-1)
				value = random.uniform(-1,1)
				new_weigth[1][index] = value
				self.model.layers[layer].set_weights(new_weigth)
		#print('layer 2', self.model.layers[3].get_weights())

	def crossover(self, mlp):
		number_of_layers = int(len(self.model.get_weights())/2)
		layer_len = [2]
		layer_len += [len(self.model.layers[i].get_weights()[0][0]) for i in range(number_of_layers)]

		for layer in range(1, number_of_layers+1):
			for i in range(int(layer_len[layer]*layer_len[layer-1]*CROSSOVER_RANGE)):
				var = random.randint(1,100)
				if (var <= 100*CROSSOVER_CHANCE):
					new_weigth = self.model.layers[layer-1].get_weights()
					parent_weight = mlp.model.layers[layer-1].get_weights()
					index_i = random.randint(0, layer_len[layer-1]-1)
					index_j = random.randint(0, layer_len[layer]-1)
					new_weigth[0][index_i][index_j] = (new_weigth[0][index_i][index_j]+
														parent_weight[0][index_i][index_j])/2
					self.model.layers[layer-1].set_weights(new_weigth)
			layerb = layer-1
			layer_lenb = layer_len[1:]
			for i in range(int(layer_lenb[layerb]*CROSSOVER_RANGE)):
				var = random.randint(1,100)
				if (var <= 100*CROSSOVER_BIAS_CHANCE):
					new_weigth = self.model.layers[layerb].get_weights()
					parent_weight = mlp.model.layers[layerb].get_weights()
					index = random.randint(0, layer_lenb[layerb]-1)

					new_weigth[1][index] = (new_weigth[1][index]+parent_weight[1][index])/2
					self.model.layers[layerb].set_weights(new_weigth)

	def save_mlp(self):
		# serialize model to YAML
		model_yaml = self.model.to_yaml()
		with open("model.yaml", "w") as yaml_file:
			yaml_file.write(model_yaml)
		# serialize weights to HDF5
		self.model.save_weights("model.h5")

	def load_mlp(self):
		# load YAML and create model
		yaml_file = open('model.yaml', 'r')
		loaded_model_yaml = yaml_file.read()
		yaml_file.close()
		self.model = model_from_yaml(loaded_model_yaml)
		# load weights into new model
		self.model.load_weights("model.h5")


import datetime
import math
import sys
import itertools
import copy
import csv
t = datetime.datetime.now()
coins = []*8
"""for i in coins:
	i = []*100

for i in range(0, 8):
	coins.append([])

for i in range (0,1):
	coins[0].append(200)
for i in range (0,2):
	coins[1].append(100)
for i in range (0,4):
	coins[2].append(50)
for i in range (0,10):
	coins[3].append(20)
for i in range (0,20):
	coins[4].append(10)
for i in range (0,40):
	coins[5].append(5)
for i in range (0,100):
	coins[6].append(2)
for i in range (0,200):
	coins[7].append(1)"""
coins = [200,100,50,20,10,5,2,1]
#combination =[]
amountToPay = 200
global teller
teller = 0
combinations =[]
combination = []

def addCoins(coinle, currentAmount,thread):
	#bereken hoeveel keer deze munt maximaal in resterend bedrag past
	# probeer alle mogelijkheden toe te voegen
	callingAmount = currentAmount
	coin = coins[coinle]
	maxCoins = int((amountToPay-currentAmount) / coin)
	if(coin==1):
		thread.append(str(maxCoins)+'*$'+str(coin))
		currentAmount += maxCoins*coin
		combinations.append(thread)
	else:
		for nrOfCoins in range(0, maxCoins+1):
			currentAmount = callingAmount
			tak = copy.deepcopy(thread)
			addition = coin*nrOfCoins
			if coinle < len(coins)-1 and currentAmount+addition<amountToPay:
				if(nrOfCoins > 0):
					tak.append(str(nrOfCoins)+'*$'+str(coin))
					currentAmount += addition
					if currentAmount == amountToPay:
						#print (tak, currentAmount)
						combinations.append(tak)

				addCoins(coinle+1,currentAmount, copy.deepcopy(tak))
			else:
				currentAmount += addition
				if(nrOfCoins>0 and currentAmount <= amountToPay):
					tak.append(str(nrOfCoins)+'*$'+str(coin))
					#print(tak,currentAmount)
					combinations.append(tak)

addCoins(0,0,[])
print (len(combinations))
#print (a)

#print(combination, sum, i, len(combinations))
#for combination in combinations:
#	print ((combination))

runtime  = datetime.datetime.now() - t
print (runtime)

###


#!/bin/python
# coding: utf-8

import re

def getEcharData():
	#read file into line
	log_data_file=open('./getNum.log')
	lines = log_data_file.readlines()
	count_line = len(lines)

	batch_num = count_line/5
	xAxis_data=[]
	sys_data=[]
	gen_data=[]
	event_data=[]

	for batch_index in range(0,batch_num):
		index_lines = lines[batch_index*5:batch_index*5+5]

		time = index_lines[0].split("################")[1].strip()
		sys_num = index_lines[1].strip('\n')
		gen_num = index_lines[2].strip('\n')
		event_num = index_lines[3].strip('\n')

		xAxis_data.append(time)
		sys_data.append(sys_num)
		gen_data.append(gen_num)
		event_data.append(event_num)

	return [xAxis_data,sys_data,gen_data,event_data]

def geneEcharOption():
	data_arr = getEcharData()

	xAxis_data=str(data_arr[0])
	sys_data=str(data_arr[1])
	gen_data=str(data_arr[2])
	event_data=str(data_arr[3])

	old_file='/home/workspace/showlogechart/echar_render.js'
	new_file='/home/workspace/showlogechart/echar_render_tmp.js'
	fopen=open(old_file,'r')

	w_str=""
	for line in fopen:
	        if re.search('\$xAxis\$',line):
	                line=re.sub('\$xAxis\$',xAxis_data,line)
	                w_str+=line
	        elif re.search('\$sys\$',line):
	                line=re.sub('\$sys\$',sys_data,line)
	                w_str+=line
	        elif re.search('\$gen\$',line):
	                line=re.sub('\$gen\$',gen_data,line)
	                w_str+=line
	        elif re.search('\$event\$',line):
	                line=re.sub('\$event\$',event_data,line)
	                w_str+=line
	        else:
	                w_str+=line

	wopen=open(new_file,'w')
	wopen.write(w_str)
	fopen.close()
	wopen.close()

if __name__=='__main__':
	data_arr = getEcharData()

	# print data_arr
	geneEcharOption()


s=input()
st=list(s)
l=len(s)
if (l%2==0):
	p=l//2
	st[p]='*'
	st[p-1]='*'
	st="".join(st)
	print(st)
else:
	p=l//2
	st[p]='*'
	st="".join(st)
	print(st)


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

"""
Helper functions to work with the csv format provided by Kaggle.

Created on Tue Dec 19 2017

@author: Andrea Manzini, Lorenzo Lazzara, Farah Charab
"""

def reformat_dataset(path_dataset, path_formatted):
    """ Reformat dataset to easily read it with surprise library"""

    #path_dataset = '../data/data_train.csv'
    #path_formatted = '../data/formatted_data.csv'

    def deal_line(line):
        pos, rating = line.split(',')
        row, col = pos.split("_")
        row = row.replace("r", "")
        col = col.replace("c", "")
        return ('{r},{c},{rat}\n'.format(r=row.strip(), c=col.strip(), rat=rating.strip()))

    # read text file from path
    fp = open(path_dataset, "r")
    data = fp.read().splitlines()[1:]
    fp.close()

    data = [deal_line(line) for line in data]

    fp = open(path_formatted, 'w+')
    fp.writelines(data)
    fp.close()

def reduced_dataset(path_dataset, path_formatted):
    def deal_line(line):
        pos, rating = line.split(',')
        row, col = pos.split("_")
        row = row.replace("r", "")
        col = col.replace("c", "")
        return (int(row.strip()), int(col.strip()), int(rating.strip()))

    # read text file from path
    fp = open(path_dataset, "r")
    data = fp.read().splitlines()[1:]
    fp.close()

    reduced_data = []
    for i in range(len(data)):
        new_line = deal_line(data[i])
        if (new_line[0] < 500) and (new_line[1] < 50):
            reduced_data.append('{r},{c},{rat}\n'.format(r=new_line[0], c=new_line[1], rat=new_line[2]))

    fp = open(path_formatted, 'w+')
    fp.writelines(reduced_data)
    fp.close()

def export_prediction(prediction):
    """ Export prediction to kaggle format"""
    # Store users, items and ratings in three arrays

    header = 'Id,Prediction\n'

    N = len(prediction)
    users = []
    items = []
    rat = []

    for j, pred in enumerate(prediction):
        users.append(pred.uid)
        items.append(pred.iid)
        rat.append(pred.est)

    # Format preditions in the kaggle format
    data = []
    data.append(header) # Add header at the start of the text file
    for j in range(N):
        data.append('r{u}_c{i},{r}\n'.format(u=users[j], i=items[j], r = rat[j]))

    # Write predictions in a csv file
    fp = open('../data/final_prediction.csv', 'w')
    fp.writelines(data)
    fp.close()


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018-11-24 09:39
# @Author  : zhdya@zhdya.cn
# @File    : Python_Monday.py

##    id username age classs phone_number gender
##    6 zhdya 28 python666 18862223222 Man

menu = ['id', 'username', 'age', 'class', 'phone_number', 'gender']

def select():
    while 1:
        input_str = input("Pls input the select command like: [select * from asd], [quit] for exit!: ")
        if input_str == 'quit':
            break
        if input_str.startswith('select') and input_str.split()[1] == '*' and input_str.split()[2] == 'from' and input_str.split()[3] == 'asd':
            with open('asd.txt', 'r', encoding='utf-8') as f:
                for line in f:
                    print(line)
            break
        if input_str.startswith('select') and input_str.split()[1] in menu:
            chx = input_str.split()[1]
            if chx == 'username':
                with open('asd.txt', 'r', encoding='utf-8') as f:
                    for line in f:
                        newline = line.split()[1]
                        print(newline)
                break
        if input_str.startswith('select') and input_str.split()[1] in menu:
            chx = input_str.split()[1]
            if chx == 'id':
                with open('asd.txt', 'r', encoding='utf-8') as f:
                    for line in f:
                        newline = line.split()[0]
                        print(newline)
                break
        if input_str.startswith('select') and input_str.split()[1] in menu:
            chx = input_str.split()[1]
            if chx == 'age':
                with open('asd.txt', 'r', encoding='utf-8') as f:
                    for line in f:
                        newline = line.split()[2]
                        print(newline)
                break
        else:
            print("you input was wrong, pls checking it and input it again!!")

def insert():
    while 1:
        input_str = input("Pls input the insert command like: [insert into asd values ( id username age class phone_number gender )], [quit] for exit!: ")
        if input_str == 'quit':
            break
        if input_str.startswith('insert') and input_str.split()[1] == 'into' and input_str.split()[2] == 'asd' and input_str.split()[3] == 'values':
            newinput = input_str.split('(')[1].split(')')[0]
            with open('asd.txt', 'a', encoding='utf-8') as f:
                f.writelines('\n' + newinput)
                print("successfully import data: <{0}>".format(newinput))
            break
        else:
            print("you input was wrong, pls checking it and input it again!!")

def delete():
    while 1:
        input_str = input("Pls input the delete command like: [delete from asd where id= 1], [quit] for exit!: ")
        if input_str == 'quit':
            break
        if input_str.split('delete') and input_str.split()[1] == 'from' and input_str.split()[2] == 'asd' and input_str.split()[3] == 'where' and input_str.split()[4] == 'id=':
            newinput = input_str.split()[5]
            with open('asd.txt', 'r', encoding='utf-8') as f:
                datas = f.readlines()
                with open('asd.txt','w',encoding='utf-8') as fw:
                    for line in datas:
                        if newinput == line.split()[0]:
                            continue
                        fw.write(line)
                    break
        else:
            print("you input was wrong, pls checking it and input it again!!")

if __name__ == '__main__':
    print('1:select\n2:add\n3:delete\n4:update')
    input_num = input('Pls choice the number: ')
    if input_num.isdigit():
        input_num = int(input_num)
        if(input_num==1):
            select()
        elif(input_num==2):
            insert()
        elif(input_num==3):
            delete()
        elif(input_num==4):
            update()
        else:
            print("pls just input 1, 2, 3, 4")
    else:
        print("you input was wrong!!")


import argparse
import serial
import serial.tools.list_ports
import matplotlib.pyplot as plt
import os

def display(ser):
    buffer_len = 50
    buffer = [0] * buffer_len
    fig, axs = plt.subplots(1, 1)
    while True:
        raw_line = ser.readline()
        line = raw_line.decode("utf-8").strip()
        print(line)
        if line.startswith("anom_score"):
            line_info = line.split(":")
            anomaly_score = float(line_info[1])
            # Add anomaly score to buffer
            buffer.append(anomaly_score)
            buffer = buffer[1:]
            # Plot buffer
            # Set axis limits
            axs.set_ylim(0, 1)
            axs.set_xlim(0, buffer_len)
            # Set title
            axs.set_title("Anomaly Score")
            axs.plot(buffer, color="red", linewidth=1)
            # Draw plot to screen
            fig.tight_layout()
            fig.canvas.draw()
            plt.pause(0.001)
            axs.clear()

if __name__ == "__main__":
    ports = list(serial.tools.list_ports.comports())
    for i, p in enumerate(ports):
        print(f"{i}: {p}")
        print(p.name)
    port_id = input("Select port to connect to: ")
    port_id = int(port_id)

    ser = serial.Serial(port=ports[port_id].device, timeout=0.1)

    display(ser)


import numpy as np
import pandas as pd
import pry
import sys

class Simulation:
    def __init__(self):
        self.rho=0.5                        #Thinning probability
        self.ETBA=5                         #Expected Time Between Arrival

        self.clock=0.0                      #simulation clock
        self.num_arrivals=0                 #total number of arrivals
        self.t_arrival=self.gen_int_arr()   #time of next arrival
        self.t_landing=float('inf')         #landing time from server
        self.land_sum=0                      #Sum of landing times
        self.server_state=0                 #current state of server (binary)
        self.total_wait_time=0.0            #total wait time
        self.num_in_q=0                     #current number in queue
        self.tot_in_queue=0                 #planes who had to wait in line

    def time_adv(self):
        t_next_event=min(self.t_arrival,self.t_landing)
        self.total_wait_time += (self.num_in_q*(t_next_event-self.clock))
        self.clock=t_next_event

        if self.t_arrival<self.t_landing:
            self.arrival()
        else:
            self.landing()
        print()

    def arrival(self):
        self.num_arrivals += 1
        self.tot_in_queue += 1

        if self.num_in_q == 0:                                 #schedule next departure or arrival depending on state of servers
            if self.server_state==1:
                self.num_in_q+=1
                self.tot_in_queue+=1
            else:
                self.server_state=1
                self.land= self.gen_landing_time()
                self.land_sum += self.land
                self.t_landing=self.clock + self.land
        else:
            self.num_in_q+=1
            self.tot_in_queue+=1

        self.t_arrival=self.clock + self.gen_int_arr()  # generate next arrival time

    def landing(self):
        if self.num_in_q>0:
            self.land= self.gen_landing_time()
            self.land_sum += self.land
            self.t_landing=self.clock + self.land
            self.num_in_q-=1
        else:
            self.t_landing=float('inf')
            self.server_state=0

    def gen_int_arr(self):
        # return (-np.log(1-(np.random.uniform(low=0.0,high=1.0))) * 5)  # exponential arrivals
        if np.random.uniform() < self.rho:
        	self.clock += np.random.uniform()*self.ETBA
        return np.random.uniform()*self.ETBA

    def gen_landing_time(self):
        # return (-np.log(1-(np.random.uniform(low=0.0,high=1.0))) * 1.2)   # exponential service time
        return 1  # deterministic service time

# ---------------------------------------------------

s = Simulation()
df = pd.DataFrame(columns=['Average interarrival time','Utilization track','Planes who had to wait in line','Total average wait time'])

for i in range(1):
    np.random.seed(i)
    # pry()
    s.__init__()
    while s.clock <= 24:
        print(s.clock,  s.server_state, s.num_in_q, end =" ")
        s.time_adv()
    a=pd.Series([s.clock/s.num_arrivals, s.land_sum/s.clock, s.tot_in_queue,s.total_wait_time],index=df.columns)
    df=df.append(a,ignore_index=True)

df.to_excel('results.xlsx')


import sys

import petsc4py

petsc4py.init(sys.argv)
# from scipy.io import savemat, loadmat
# from src.ref_solution import *
# import warnings
# from memory_profiler import profile
# from time import time
from src.myio import *
from src.objComposite import *
from src.StokesFlowMethod import *
from src.geo import *
from src import stokes_flow as sf
from src import slender_body as slb
from codeStore.helix_common import *

def get_problem_kwargs(**main_kwargs):
    problem_kwargs = get_solver_kwargs()
    OptDB = PETSc.Options()
    fileHandle = OptDB.getString('f', 'obj_helicoid')
    OptDB.setValue('f', fileHandle)
    problem_kwargs['fileHandle'] = fileHandle

    kwargs_list = (get_obj_helicoid_kwargs(), get_helix_SLB_kwargs(),
                   get_forcefree_kwargs(), main_kwargs,)
    for t_kwargs in kwargs_list:
        for key in t_kwargs:
            problem_kwargs[key] = t_kwargs[key]
    return problem_kwargs

def print_case_info(**problem_kwargs):
    fileHandle = problem_kwargs['fileHandle']
    print_solver_info(**problem_kwargs)
    print_forcefree_info(**problem_kwargs)
    print_helix_SLB_info(fileHandle, **problem_kwargs)
    print_obj_helicoid_info(**problem_kwargs)
    return True

def main_resistanceMatrix_SLB(**main_kwargs):
    # code results are wrong.
    assert 1 == 2

    # OptDB = PETSc.Options()
    main_kwargs['zoom_factor'] = 1
    problem_kwargs = get_problem_kwargs(**main_kwargs)
    matrix_method = problem_kwargs['matrix_method']
    fileHandle = problem_kwargs['fileHandle']
    pickProblem = problem_kwargs['pickProblem']
    print_case_info(**problem_kwargs)

    # create SLB_helix
    rh1 = problem_kwargs['rh1']
    rh2 = problem_kwargs['rh2']
    ch = problem_kwargs['ch']
    center = problem_kwargs['center']
    ph = problem_kwargs['ph']
    n_segment = problem_kwargs['n_segment']
    n_tail = problem_kwargs['n_tail']
    # left_hand = problem_kwargs['left_hand']
    rel_Uh = problem_kwargs['rel_Uh']
    check_nth = problem_kwargs['check_nth']
    slb_geo_fun = problem_kwargs['slb_geo_fun']

    # tobj_list = uniqueList()
    # for i0, theta0 in enumerate(np.linspace(0, 2 * np.pi, n_tail, endpoint=False)):
    #     hlx1_geo = slb_geo_fun(ph, ch, rh1, rh2, theta0=theta0)
    #     hlx1_geo.create_nSegment(n_segment, check_nth=check_nth)
    #     hlx1_obj = sf.StokesFlowObj()
    #     obj_name = 'helix%d' % i0
    #     hlx1_obj.set_data(hlx1_geo, hlx1_geo, name=obj_name)
    #     tobj_list.append(hlx1_obj)
    err_msg = 'current version, n_tail==1'
    assert n_tail == 1, err_msg
    hlx1_geo = slb_geo_fun(ph, ch, rh1, rh2, theta0=0)
    hlx1_geo.create_nSegment(n_segment, check_nth=check_nth)
    hlx1_obj = sf.StokesFlowObj()
    hlx1_obj.set_data(hlx1_geo, hlx1_geo, name='helix0')
    helicoid_comp = obj2helicoid_comp(hlx1_obj, **problem_kwargs)
    # helicoid_obj_list = np.array(helicoid_comp.get_obj_list())[[0, 3, 6, 9]]
    helicoid_obj_list = np.array(helicoid_comp.get_obj_list())
    helicoid_center = helicoid_comp.get_center()

    problem = slb.problem_dic[matrix_method](**problem_kwargs)
    for tobj in helicoid_obj_list:
        problem.add_obj(tobj)
    problem.print_info()
    problem.create_matrix()
    # PETSc.Sys.Print(problem.get_obj_list()[0].get_u_nodes()[:10])
    # PETSc.Sys.Print(problem.get_M()[:5, :5])
    # PETSc.Sys.Print(helicoid_center)
    AtBtCt_full(problem, save_vtk=False, pick_M=False, print_each=False,
                center=helicoid_center)
    return True

def main_resistanceMatrix_part(**main_kwargs):
    OptDB = PETSc.Options()
    main_kwargs['zoom_factor'] = 1
    save_vtk = OptDB.getBool('save_vtk', False)
    main_kwargs['save_vtk'] = save_vtk

    problem_kwargs = get_problem_kwargs(**main_kwargs)
    matrix_method = problem_kwargs['matrix_method']
    fileHandle = problem_kwargs['fileHandle']
    # pickProblem = problem_kwargs['pickProblem']
    print_case_info(**problem_kwargs)

    # create SLB_helix
    rh1 = problem_kwargs['rh1']
    rh2 = problem_kwargs['rh2']
    ch = problem_kwargs['ch']
    center = problem_kwargs['center']
    ph = problem_kwargs['ph']
    n_segment = problem_kwargs['n_segment']
    n_tail = problem_kwargs['n_tail']
    # left_hand = problem_kwargs['left_hand']
    # rel_Uh = problem_kwargs['rel_Uh']
    check_nth = problem_kwargs['check_nth']
    slb_geo_fun = problem_kwargs['slb_geo_fun']
    slb.check_matrix_method(matrix_method)

    err_msg = 'current version, n_tail==1'
    assert n_tail == 1, err_msg
    hlx1_geo = slb_geo_fun(ph, ch, rh1, rh2, theta0=0)
    hlx1_geo.create_nSegment(n_segment, check_nth=check_nth)
    hlx1_obj = slb.obj_dic[matrix_method]()
    hlx1_obj.set_data(hlx1_geo, hlx1_geo, name='helix0')

    # solve
    problem = slb.problem_dic[matrix_method](**problem_kwargs)
    problem.add_obj(hlx1_obj)
    problem.print_info()
    problem.create_matrix()
    At, Bt1, Bt2, Ct = AtBtCt_pickInfo(problem=problem, pick_M=False, save_vtk=save_vtk,
                                       center=center, print_each=False, save_name=fileHandle)
    # At, Bt, Ct, ftr_info, frt_info = AtBtCt_SBT(problem=problem, pick_M=False, save_vtk=save_vtk,
    #                                             center=center, print_each=False)
    PETSc.Sys.Print('Tr(A)=%f, Tr(B1)=%f, Tr(B2)=%f, ' %
                    (np.trace(At), np.trace(Bt1), np.trace(Bt2)))
    return True

def main_dbg(**main_kwargs):
    # OptDB = PETSc.Options()
    main_kwargs['zoom_factor'] = 1
    problem_kwargs = get_problem_kwargs(**main_kwargs)
    matrix_method = problem_kwargs['matrix_method']
    fileHandle = problem_kwargs['fileHandle']
    pickProblem = problem_kwargs['pickProblem']
    print_case_info(**problem_kwargs)

    # create SLB_helix
    rh1 = problem_kwargs['rh1']
    rh2 = problem_kwargs['rh2']
    ch = problem_kwargs['ch']
    center = problem_kwargs['center']
    ph = problem_kwargs['ph']
    n_segment = problem_kwargs['n_segment']
    n_tail = problem_kwargs['n_tail']
    # left_hand = problem_kwargs['left_hand']
    rel_Uh = problem_kwargs['rel_Uh']
    check_nth = problem_kwargs['check_nth']
    slb_geo_fun = problem_kwargs['slb_geo_fun']
    slb.check_matrix_method(matrix_method)
    problem = slb.problem_dic[matrix_method](**problem_kwargs)

    for i0, theta0 in enumerate(np.linspace(0, 2 * np.pi, n_tail, endpoint=False)):
        hlx1_geo = slb_geo_fun(ph, ch, rh1, rh2, theta0=theta0)
        hlx1_geo.create_nSegment(n_segment, check_nth=check_nth)
        hlx1_obj = sf.StokesFlowObj()
        obj_name = 'helix%d' % i0
        hlx1_obj.set_data(hlx1_geo, hlx1_geo, name=obj_name)
        problem.add_obj(hlx1_obj)

    # for tobj in problem.get_obj_list():
    #     tobj.node_rotation(norm=np.array((1, 0, 0)), theta=np.pi / 2)
    problem.print_info()
    problem.create_matrix()
    # PETSc.Sys.Print(problem.get_obj_list()[0].get_u_nodes()[:10])
    # PETSc.Sys.Print(problem.get_M()[:5, :5])
    AtBtCt_full(problem, save_vtk=False, pick_M=False, print_each=False,
                center=np.array((-1, 0, 0)))
    return True

if __name__ == '__main__':
    OptDB = PETSc.Options()
    if OptDB.getBool('main_resistanceMatrix_SLB', False):
        OptDB.setValue('main_fun', False)
        main_resistanceMatrix_SLB()

    if OptDB.getBool('main_resistanceMatrix_part', False):
        OptDB.setValue('main_fun', False)
        main_resistanceMatrix_part()

    if OptDB.getBool('main_dbg', False):
        OptDB.setValue('main_fun', False)
        main_dbg()

    # if OptDB.getBool('main_fun', True):
    #     main_fun()


import cx_Freeze

executables = [cx_Freeze.Executable('teste.pygame.py')]

cx_Freeze.setup(
    name="Breakout GAME",
    options={'build_exe': {'packages':['pygame'],
                           'include_files':['Som']}},

    executables = executables

)

# No cmd instalar o cx-Freeze
# 'cx-Freeze'
# Abrir diretorio da pasta no cmd
# 'cd + diretorio da pasta'
# Executar para criar o executável do jogo
# 'python setup.py build'


# %%
from functools import partial
import tensorflow as tf

# %%
def phase(
    dim_sizes,
    pos_low: float = -1,
    pos_high: float = 1,
    centered: bool = True,
    dtype=tf.float32,
):
    """
    Basically a clone of `encode_positions`,
    but reimplemented here to keep the other thing unpickling correctly.
    """

    def generate_grid(size):
        width = (pos_high - pos_low) / size
        if centered:
            left = pos_low + width / 2
            right = pos_high - width / 2
        else:
            left = pos_low
            right = pos_high - width
        return tf.linspace(left, right, num=size)

    grid_list = list(map(generate_grid, dim_sizes))
    grid = tf.stack(tf.meshgrid(*grid_list, indexing="ij"), axis=-1)
    return grid

@tf.function
def manual_rfft2d(x):
    x = tf.signal.rfft(x)
    x = tf.cast(x, tf.complex64)
    x = tf.signal.fft(tf.transpose(x, perm=[0, 1, 3, 2]))
    x = tf.transpose(x, perm=[0, 1, 3, 2])
    return x

@tf.function
def manual_irfft2d(x):
    x = tf.signal.ifft(tf.transpose(x, perm=[0, 1, 3, 2]))
    x = tf.transpose(x, perm=[0, 1, 3, 2])
    x = tf.signal.irfft(x)
    return x

# %%
class FourierLayer2dLite(tf.keras.layers.Layer):
    def __init__(self, in_dim, out_dim, n_modes):
        super(FourierLayer2dLite, self).__init__()
        self.in_dim = in_dim
        self.out_dim = out_dim
        self.n_modes = n_modes
        self.linear = tf.keras.layers.Dense(out_dim)
        self.act = tf.keras.layers.ReLU()

        # fourier_weight = [
        #     tf.Variable(
        #         tf.random.normal(
        #             shape=(in_dim, out_dim, n_modes, n_modes, 2),
        #             stddev=1 / (in_dim * out_dim),
        #         )
        #     )
        #     for _ in range(2)
        # ]
        # self.fourier_weight = fourier_weight

        # Create the first variable using add_weight
        self.fourier_weight_1 = self.add_weight(
            shape=(in_dim, out_dim, n_modes, n_modes, 2),
            initializer="glorot_uniform",
            trainable=True,
            name="FourierLayer2dLite/fourier_weight_1",
        )

        # Create the second variable using add_weight
        self.fourier_weight_2 = self.add_weight(
            shape=(in_dim, out_dim, n_modes, n_modes, 2),
            initializer="glorot_uniform",
            trainable=True,
            name="FourierLayer2dLite/fourier_weight_2",
        )

    @staticmethod
    def complex_matmul_2d(a, b):
        # (batch, in_channel, x, y), (in_channel, out_channel, x, y) -> (batch, out_channel, x, y)
        # assert they have the dimension
        op = partial(tf.einsum, "bixy,ioxy->boxy")
        return tf.stack(
            [
                op(a[..., 0], b[..., 0]) - op(a[..., 1], b[..., 1]),
                op(a[..., 1], b[..., 0]) + op(a[..., 0], b[..., 1]),
            ],
            axis=-1,
        )

    def call(self, inputs):
        # x.shape == [batch_size, grid_size, grid_size, in_dim]
        _, M, N, I = inputs.shape
        dynamic_shape = tf.shape(inputs)

        inputs = tf.transpose(inputs, perm=[0, 3, 1, 2])
        # x.shape == [batch_size, in_dim, grid_size, grid_size]

        # x_ft = tf.signal.rfft2d(inputs, fft_length=[M, N])
        x_ft = manual_rfft2d(inputs)

        scale = tf.sqrt(tf.cast(tf.reduce_prod(dynamic_shape[-2:]), tf.complex64))
        x_ft /= scale

        x_ft = tf.stack([tf.math.real(x_ft), tf.math.imag(x_ft)], axis=4)
        # x_ft.shape == [batch_size, in_dim, grid_size, grid_size // 2 + 1, 2]

        out_ft = self.complex_matmul_2d(
            x_ft[:, :, : self.n_modes, : self.n_modes], self.fourier_weight_1
        )
        # out_ft.shape = (batch_size, in_dim, n_modes, n_modes, 2)
        # dynamic shape
        out_ft_zero = tf.zeros(
            [dynamic_shape[0], I, N - self.n_modes * 2, self.n_modes, 2],
            dtype=tf.float32,
        )
        # out_ft_zero.shape = (batch_size, in_dim, grid_size - n_modes * 2, n_modes, 2)
        out_ft = tf.concat([out_ft, out_ft_zero], axis=-3)
        # out_ft.shape = (batch_size, in_dim, grid_size - n_modes, n_modes, 2)
        out_ft = tf.concat(
            [
                out_ft,
                self.complex_matmul_2d(
                    x_ft[:, :, -self.n_modes :, : self.n_modes], self.fourier_weight_2
                ),
            ],
            axis=-3,
        )
        # out_ft.shape = (batch_size, in_dim, grid_size , n_modes, 2)
        out_ft = tf.concat(
            [out_ft, tf.zeros([dynamic_shape[0], I, N, M // 2 + 1 - self.n_modes, 2])],
            axis=-2,
        )
        # out_ft.shape = (batch_size, in_dim, grid_size , grid_size // 2 + 1, 2)
        out_ft = tf.complex(out_ft[..., 0], out_ft[..., 1])

        # inputs = tf.signal.irfft2d(out_ft, fft_length=[N, M])
        inputs = manual_irfft2d(out_ft)
        scale = tf.sqrt(tf.cast(tf.reduce_prod(tf.shape(out_ft)[-2:]), tf.float32))
        inputs *= scale

        inputs = tf.transpose(inputs, perm=[0, 2, 3, 1])

        res = self.linear(inputs)
        res = self.act(res + inputs)
        return res

# %%
class FourierLayer2d(tf.keras.layers.Layer):
    def __init__(self, in_dim, out_dim, n_modes, residual=True):
        super(FourierLayer2d, self).__init__()
        self.in_dim = in_dim
        self.out_dim = out_dim
        self.n_modes = n_modes
        self.linear = tf.keras.layers.Dense(out_dim)
        self.residual = residual
        self.act = tf.keras.layers.ReLU()

        fourier_weight = [
            tf.Variable(
                tf.random.normal(
                    shape=(in_dim, out_dim, n_modes, n_modes, 2),
                    stddev=1 / (in_dim * out_dim),
                )
            )
            for _ in range(2)
        ]
        self.fourier_weight = fourier_weight

    @staticmethod
    def complex_matmul_2d(a, b):
        # (batch, in_channel, x, y), (in_channel, out_channel, x, y) -> (batch, out_channel, x, y)
        # assert they have the dimension
        op = partial(tf.einsum, "bixy,ioxy->boxy")
        return tf.stack(
            [
                op(a[..., 0], b[..., 0]) - op(a[..., 1], b[..., 1]),
                op(a[..., 1], b[..., 0]) + op(a[..., 0], b[..., 1]),
            ],
            axis=-1,
        )

    def call(self, x):
        # x.shape == [batch_size, grid_size, grid_size, in_dim]
        _, M, N, I = x.shape
        dynamic_shape = tf.shape(x)

        x = tf.transpose(x, perm=[0, 3, 1, 2])
        assert x.dtype == tf.float32
        # x.shape == [batch_size, in_dim, grid_size, grid_size]

        # x_ft = tf.signal.rfft2d(x, fft_length=[M, N])
        x_ft = manual_rfft2d(x)

        x_ft = tf.stack([tf.math.real(x_ft), tf.math.imag(x_ft)], axis=-1)

        # downcast to float32, see https://www.tensorflow.org/api_docs/python/tf/signal/rfft2d, since tf.signal.rfft2d returns complex64 and input is float32
        x_ft = tf.cast(x_ft, tf.float32)

        # x_ft.shape == [batch_size, in_dim, grid_size, grid_size // 2 + 1, 2]

        # x_ft_stacked = tf.stack([x_ft_real, x_ft_imag], axis=-1)
        # x_ft_stacked.shape == [batch_size, in_dim, grid_size, grid_size // 2 + 1, 2]
        out_ft = self.complex_matmul_2d(
            x_ft[:, :, : self.n_modes, : self.n_modes], self.fourier_weight[0]
        )
        # out_ft.shape=(batch_size, in_dim, n_modes, n_modes, 2)
        out_ft_zero = tf.zeros(
            [dynamic_shape[0], I, N - self.n_modes * 2, self.n_modes, 2],
            dtype=tf.float32,
        )
        out_ft = tf.concat([out_ft, out_ft_zero], axis=-3)
        out_ft = tf.concat(
            [
                out_ft,
                self.complex_matmul_2d(
                    x_ft[:, :, -self.n_modes :, : self.n_modes], self.fourier_weight[1]
                ),
            ],
            axis=-3,
        )
        out_ft = tf.concat(
            [out_ft, tf.zeros([dynamic_shape[0], I, N, M // 2 + 1 - self.n_modes, 2])],
            axis=-2,
        )

        out_ft = tf.complex(out_ft[..., 0], out_ft[..., 1])

        # x = tf.signal.irfft2d(out_ft, fft_length=[N, M])
        x = manual_irfft2d(out_ft)

        # x_ift_real = tf.signal.irfft(out_ft, fft_length=M, name="irfft_real")
        # x_ift_real.shape == [batch_size, grid_size, grid_size, in_dim]

        x = tf.transpose(x, perm=[0, 2, 3, 1])

        if self.residual:
            res = self.linear(x)
            x = self.act(x + res)
        else:
            x = self.act(x)
        return x


import random
import math

n = int(input())

def test_ferma(n):
	if n <= 1:
		return False

	r = 10 ** 6

	i = 0

	while i < 100:
		rand = random.randint(1, r)

		if math.gcd(n, rand) != 1:
			continue

		if rand ** (n - 1) % n != 1:
			return False

		i += 1

	return True

print(test_ferma(n))


import numpy as np
from scipy.stats import pearsonr, spearmanr
import src.data_preprocessing.utils as utils
import pandas as pd
import numpy.testing as nptest

def test_assign_continents():
    continents = utils.assign_continents()
    assert continents.loc['Russia', 'continent'] == 'Europe'
    assert continents.loc['Kazakhstan', 'continent'] == 'Asia'
    assert continents.loc['Czechia', 'continent'] == 'Europe'

def test_get_continents():
    print(utils.get_continents())

class TestComputeDependencyMatrix:

    def test_compute_pearson_dependency(self):
        X = np.arange(0, 10)
        Y = X * 2 + 1
        metrics = pd.DataFrame(data=np.c_[X, Y])
        nptest.assert_almost_equal(np.array([[1.0, 1], [0, 1]]),
                                   utils.compute_dependency_matrix(metrics, pearsonr), decimal=1)

    def test_compute_spearmanr_dependency(self):
        X = np.arange(0, 10)
        Y = X * 2 + 1
        metrics = pd.DataFrame(data=np.c_[X, Y])
        nptest.assert_almost_equal(np.array([[1.0, 1], [0, 1]]),
                                   utils.compute_dependency_matrix(metrics, spearmanr), decimal=1)


import os
import numpy as np
import pandas as pd
from datetime import datetime as dt
import logging
import csv
import time

from telemanom.helpers import Config
from telemanom.errors import Errors
import telemanom.helpers as helpers
from telemanom.channel import Channel
from telemanom.modeling import Model
from telemanom.find_hp import FindHP
from pathlib import Path
from functools import reduce

logger = helpers.setup_logging()

def secondsToStr(t):
    return "%dh:%02dm:%02ds.%d" % \
           reduce(lambda ll, b: divmod(ll[0], b) + ll[1:],
                  [(t * 1000,), 1000, 60, 60])

def write_csv(first_part_path, row, col_header):
    path = first_part_path+"_ms.csv"
    csv_file = Path(path)
    if csv_file.is_file():
        with open(path, 'a', newline='') as filedata:
            writer = csv.DictWriter(filedata, delimiter=',', fieldnames=col_header)
            writer.writerow(row)
    else:
        with open(path, 'a', newline='') as filedata:
            writer = csv.DictWriter(filedata, delimiter=',', fieldnames=col_header)
            writer.writeheader()
            writer.writerow(row)

    for key in row:
        if key == "model":
            continue
        else:
            row[key] = secondsToStr(float(row[key]))

    path = first_part_path+".csv"
    csv_file = Path(path)
    if csv_file.is_file():
        with open(path, 'a', newline='') as filedata:
            writer = csv.DictWriter(filedata, delimiter=',', fieldnames=col_header)
            writer.writerow(row)
    else:
        with open(path, 'a', newline='') as filedata:
            writer = csv.DictWriter(filedata, delimiter=',', fieldnames=col_header)
            writer.writeheader()
            writer.writerow(row)

class Detector:
    def __init__(self, labels_path=None, result_path='results/',
                 config_path='config.yaml'):
        """
        Top-level class for running anomaly detection over a group of channels
        with values stored in .npy files. Also evaluates performance against a
        set of labels if provided.

        Args:
            labels_path (str): path to .csv containing labeled anomaly ranges
                for group of channels to be processed
            result_path (str): directory indicating where to stick result .csv
            config_path (str): path to config.yaml

        Attributes:
            labels_path (str): see Args
            results (list of dicts): holds dicts of results for each channel
            result_df (dataframe): results converted to pandas dataframe
            chan_df (dataframe): holds all channel information from labels .csv
            result_tracker (dict): if labels provided, holds results throughout
                processing for logging
            config (obj):  Channel class object containing train/test data
                for X,y for a single channel
            y_hat (arr): predicted channel values
            id (str): datetime id for tracking different runs
            result_path (str): see Args
        """

        self.labels_path = labels_path
        self.results = []
        self.result_df = None
        self.chan_df = None

        self.precision = None
        self.recall = None

        self.result_tracker = {
            'true_positives': 0,
            'false_positives': 0,
            'false_negatives': 0,
            'true_negatives': 0
        }

        self.config = Config(config_path)
        self.y_hat = None

        # trains new models
        if self.config.execution == "train" or self.config.execution == "train_and_predict":
            if self.config.use_id != "":
                self.id = self.config.use_id
            else:
                architecture = self.config.model_architecture
                name = self.config.name
                self.id = "{}_{}_{}".format(architecture, name, dt.now().strftime('%Y-%m-%d_%H.%M.%S'))

        # load existing models or predictions
        if self.config.execution == "predict" or self.config.execution == "search_p":
            self.id = self.config.use_id

        if self.config.execution == "find_hp":
            architecture = self.config.model_architecture
            name = self.config.name
            self.id = "{}_{}_{}".format(architecture, name, dt.now().strftime('%Y-%m-%d_%H.%M.%S'))

        helpers.make_dirs(self.id)

        # add logging FileHandler based on ID
        hdlr = logging.FileHandler('data/logs/%s.log' % self.id)
        formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
        hdlr.setFormatter(formatter)
        logger.addHandler(hdlr)

        self.result_path = result_path

        if self.labels_path:
            self.chan_df = pd.read_csv(labels_path)
        else:
            chan_ids = [x.split('.')[0] for x in os.listdir('data/test/')]
            self.chan_df = pd.DataFrame({"chan_id": chan_ids})

        logger.info("{} channels found for processing."
                    .format(len(self.chan_df)))

    def evaluate_sequences(self, errors, label_row):
        """
        Compare identified anomalous sequences with labeled anomalous sequences.

        Args:
            errors (obj): Errors class object containing detected anomaly
                sequences for a channel
            label_row (pandas Series): Contains labels and true anomaly details
                for a channel

        Returns:
            result_row (dict): anomaly detection accuracy and results
        """

        result_row = {
            'false_positives': 0,
            'false_negatives': 0,
            'true_positives': 0,
            'fp_sequences': [],
            'tp_sequences': [],
            'num_true_anoms': 0
        }

        matched_true_seqs = []

        label_row['anomaly_sequences'] = eval(label_row['anomaly_sequences'])
        result_row['num_true_anoms'] += len(label_row['anomaly_sequences'])
        result_row['scores'] = errors.anom_scores

        if len(errors.E_seq) == 0:
            result_row['false_negatives'] = result_row['num_true_anoms']

        else:
            true_indices_grouped = [list(range(e[0], e[1]+1)) for e in label_row['anomaly_sequences']]
            true_indices_flat = set([i for group in true_indices_grouped for i in group])

            for e_seq in errors.E_seq:
                i_anom_predicted = set(range(e_seq[0], e_seq[1]+1))

                matched_indices = list(i_anom_predicted & true_indices_flat)
                valid = True if len(matched_indices) > 0 else False

                if valid:

                    result_row['tp_sequences'].append(e_seq)

                    true_seq_index = [i for i in range(len(true_indices_grouped)) if
                                      len(np.intersect1d(list(i_anom_predicted), true_indices_grouped[i])) > 0]

                    if not true_seq_index[0] in matched_true_seqs:
                        matched_true_seqs.append(true_seq_index[0])
                        result_row['true_positives'] += 1

                else:
                    result_row['fp_sequences'].append([e_seq[0], e_seq[1]])
                    result_row['false_positives'] += 1

            result_row["false_negatives"] = len(np.delete(label_row['anomaly_sequences'],
                                                          matched_true_seqs, axis=0))

        if self.config.execution != "search_p":
            logger.info('Channel Stats: TP: {}  FP: {}  FN: {}'.format(result_row['true_positives'],
                                                                   result_row['false_positives'],
                                                                   result_row['false_negatives']))

        for key, value in result_row.items():
            if key in self.result_tracker:
                self.result_tracker[key] += result_row[key]

        return result_row

    def log_final_stats(self):
        """
        Log final stats at end of experiment.
        """
        if self.config.execution == "search_p":
            logger.info('P value: {}'.format(self.config.p))

        if self.labels_path:

            logger.info('Final Totals:')
            logger.info('-----------------')
            logger.info('True Positives: {}'
                        .format(self.result_tracker['true_positives']))
            logger.info('False Positives: {}'
                        .format(self.result_tracker['false_positives']))
            logger.info('False Negatives: {}'
                        .format(self.result_tracker['false_negatives']))
            try:
                self.precision = float(self.result_tracker['true_positives']) / (float(self.result_tracker['true_positives'] + self.result_tracker['false_positives']))
                self.recall = float(self.result_tracker['true_positives']) / (float(self.result_tracker['true_positives'] + self.result_tracker['false_negatives']))

                self.f1 = 2*((self.precision*self.recall)/(self.precision+self.recall))

                #calcola f1 score e scrivi nel file di log

                logger.info('Precision: {0:.2f}'.format(self.precision))
                logger.info('Recall: {0:.2f}'.format(self.recall))
                logger.info('F1 Score: {0:.2f}\n'.format(self.f1))
            except ZeroDivisionError:

                logger.info('Precision: NaN')
                logger.info('Recall: NaN')
                logger.info('F1 Score: NaN\n')

        else:
            logger.info('Final Totals:')
            logger.info('-----------------')
            logger.info('Total channel sets evaluated: {}'
                        .format(len(self.result_df)))
            logger.info('Total anomalies found: {}'
                        .format(self.result_df['n_predicted_anoms'].sum()))
            logger.info('Avg normalized prediction error: {}'
                        .format(self.result_df['normalized_pred_error'].mean()))
            logger.info('Total number of values evaluated: {}\n'
                        .format(self.result_df['num_test_values'].sum()))

    def execute_detection(self):
        col_header = ["model", "total_elapsed_time"]
        training_times_row = {
            'model': self.id,
            'total_elapsed_time': 0
        }

        execution_times_row = {
            'model': self.id,
            'total_elapsed_time': 0
        }

        training_total_elapsed_time = 0
        training_start_time = 0
        training_end_time = 0

        execution_total_elapsed_time = 0
        execution_start_time = 0
        execution_end_time = 0

        if self.config.execution == "train":
            filename = "./data/{}/losses.csv".format(self.id)
            if os.path.isfile(filename):
                losses_df = pd.read_csv(filename)
            else:
                losses_df = pd.DataFrame()
                losses_df["Channel"] = self.chan_df["chan_id"]

            train_loss = []
            validation_loss = []

            path = './data/{}/models/seeds.log'.format(self.id)
            seed_file = Path(path)
            if seed_file.is_file():
                os.remove(path)

        for i, row in self.chan_df.iterrows():
            if self.config.execution != "search_p" and self.config.execution != "find_hp":
                logger.info('Stream # {}: {}'.format(i + 1, row.chan_id))

            channel = Channel(self.config, row.chan_id)
            channel.load_data()

            if self.config.execution == "train":
                model = Model(self.config, self.id, channel)
                train_loss.append(model.history.history["loss"][-1])
                validation_loss.append(model.history.history["val_loss"][-1])
                continue

            elif self.config.execution == "find_hp":
                training_start_time = time.time()
                tuner = FindHP(self.id, channel, self.config, self.config.model_architecture)
                training_end_time = (time.time() - training_start_time)

                f = open('hp/{}/times.log'.format(self.id), "a")
                f.write("{} {}\n".format(row.chan_id, training_end_time))
                f.close()

                col_header.append(row.chan_id)
                training_times_row[row.chan_id] = training_end_time

                training_total_elapsed_time += training_end_time

                training_start_time = 0
                training_end_time = 0
                continue

            elif self.config.execution == "train_and_predict" or self.config.execution == "predict":
                if self.config.execution == "train_and_predict":
                    training_start_time = time.time()
                    execution_start_time = training_start_time

                model = Model(self.config, self.id, channel)

                if self.config.execution == "train_and_predict":
                    training_end_time = (time.time() - training_start_time)

                    col_header.append(row.chan_id)
                    training_times_row[row.chan_id] = training_end_time

                    training_total_elapsed_time += training_end_time

                    training_start_time = 0
                    training_end_time = 0

                channel = model.batch_predict(channel)

            elif self.config.execution == "search_p":
                channel.y_hat = np.load(os.path.join('data', self.id, 'y_hat',
                                                     '{}.npy'
                                                     .format(channel.id)))

            errors = Errors(channel, self.config, self.id)
            errors.process_batches(channel)
            if self.config.execution == "search_p":
                result_row = {
                    'run_id': self.id+"_{}".format(str(self.config.p)),
                    'chan_id': row.chan_id,
                    'num_train_values': len(channel.X_train)+len(channel.X_valid),
                    'num_test_values': len(channel.X_test),
                    'n_predicted_anoms': len(errors.E_seq),
                    'normalized_pred_error': errors.normalized,
                    'anom_scores': errors.anom_scores
                }
            else:
                result_row = {
                    'run_id': self.id,
                    'chan_id': row.chan_id,
                    'num_train_values': len(channel.X_train) + len(channel.X_valid),
                    'num_test_values': len(channel.X_test),
                    'n_predicted_anoms': len(errors.E_seq),
                    'normalized_pred_error': errors.normalized,
                    'anom_scores': errors.anom_scores
                }

            if self.labels_path:
                result_row = {**result_row,
                              **self.evaluate_sequences(errors, row)}
                result_row['spacecraft'] = row['spacecraft']
                result_row['anomaly_sequences'] = row['anomaly_sequences']
                result_row['class'] = row['class']
                self.results.append(result_row)

                if self.config.execution != "search_p":
                    logger.info('Total true positives: {}'
                                .format(self.result_tracker['true_positives']))
                    logger.info('Total false positives: {}'
                                .format(self.result_tracker['false_positives']))
                    logger.info('Total false negatives: {}'
                                .format(self.result_tracker['false_negatives']))

            else:
                result_row['anomaly_sequences'] = errors.E_seq
                self.results.append(result_row)

                if self.config.execution != "search_p":
                    logger.info('{} anomalies found'
                                .format(result_row['n_predicted_anoms']))
                    logger.info('anomaly sequences start/end indices: {}'
                                .format(result_row['anomaly_sequences']))
                    logger.info('number of test values: {}'
                                .format(result_row['num_test_values']))
                    logger.info('anomaly scores: {}\n'
                                .format(result_row['anom_scores']))

            if self.config.execution != "search_p":
                self.result_df = pd.DataFrame(self.results)
                self.result_df.to_csv(
                    os.path.join(self.result_path, '{}.csv'.format(self.id)),
                    index=False)

            if self.config.execution == "train_and_predict":
                execution_end_time = (time.time() - execution_start_time)
                execution_times_row[row.chan_id] = execution_end_time
                execution_total_elapsed_time += execution_end_time

                execution_start_time = 0
                execution_end_time = 0

        if self.config.execution == "train":
            columns = list(losses_df.columns)
            columns_number=1
            for elem in columns:
                if "train" in elem:
                    columns_number+=1

            losses_df["train_loss_"+str(columns_number)] = train_loss
            losses_df["valid_loss_"+str(columns_number)] = validation_loss

            losses_df.to_csv('./data/{}/losses.csv'.format(self.id), sep=',', index=False)

        if self.config.execution != "train" and self.config.execution != "find_hp":
            self.log_final_stats()

        if self.config.execution == "find_hp":
            first_part_path = "./hp/hp_times".format(self.id)
            training_times_row["total_elapsed_time"] = training_total_elapsed_time
            write_csv(first_part_path, training_times_row, col_header)

        if self.config.execution == "train_and_predict":

            training_times_row["total_elapsed_time"] = training_total_elapsed_time
            execution_times_row["total_elapsed_time"] = execution_total_elapsed_time

            write_csv("./results/training_times", training_times_row, col_header)
            write_csv("./results/execution_times", execution_times_row, col_header)

    def run(self):
        """
        Initiate processing for all channels.
        """
        logger.info("Execution mode: {}\n".format(self.config.execution))

        if self.config.execution == "search_p":
            # header for csv file
            col_header = ["P", "Precision", "Recall", "Total True Positives", "Total False Positives", "Total False Negatives"]

            df = pd.DataFrame(columns=col_header)

            # creates the array of values for p
            array = np.linspace(0.00, 1, 100).tolist()
            formatted_array = [round(elem, 2) for elem in array]

            i=0
            for elem in formatted_array:
                self.config.p = elem

                self.execute_detection()

                row = [self.config.p, self.precision, self.recall, self.result_tracker['true_positives'],
                       self.result_tracker['false_positives'], self.result_tracker['false_negatives']]

                df.loc[i] = row
                i += 1

                self.result_tracker = {
                    'true_positives': 0,
                    'false_positives': 0,
                    'false_negatives': 0
                }
            df.to_csv('./data/{}/p_values.csv'.format(self.id), sep=',')

        else:
            self.execute_detection()