from ast import main
from json import load
import json
from random import randint
import pygame
import sys
from models.BugsStatic import BugStatic
from models.Bullet import Bullet
from models.Button import Button
from models.Platform import Platform
from models.Point import Point
from models.Text import Text
from colors import *
from Config import *

def exit():
    """Exits the game and prints a farewell message."""
    print('See you soon!')
    pygame.quit()
    sys.exit()

def randIntPos(axis: str, size):
    """Generates a random integer position within the specified axis and size limits."""
    if axis == 'x':
        return randint(size, LIMITWIDTHGROUND-size)
    else:
        return randint(150 + size, LIMITHEIGHTGROUND-size)

def createScreen():
    """Initializes the game screen and sets its caption."""
    try:
        screen = pygame.display.set_mode(SCREENSIZE)
        screen.fill(WHITE, pygame.Rect(
            0, 0, SCREENWIDTH, SCREENHEIGHT))
        pygame.display.set_caption("PokeBug")
        pygame.display.set_icon(pygame.image.load(
            os.path.join('assets', 'images', 'totodyle.png')))
        return screen
    except pygame.error as e:
        errMsg(e)

def cleanScreen(screen):
    """Clears the game screen by filling it with black color."""
    screenBackroundRect = pygame.Rect(0, 0, SCREENWIDTH, SCREENHEIGHT)
    screen.fill(BLACK, screenBackroundRect)

def drawBackground(screen: pygame.display, background):
    """Draws the specified background image on the game screen."""
    screenBackroundRect = pygame.Rect(0, 0, SCREENWIDTH, SCREENHEIGHT)
    screen.blit(background, screenBackroundRect)

def controlesMenu(screen, levelCanvas):
    """Displays the controls menu and handles user interaction."""
    image = BACKGROUNDCONTROLES
    rectImage = image.get_rect(center=(SCREENWIDTH/2, SCREENHEIGHT/2))
    screen.blit(image, rectImage)

    ButtonCross = Button(40, 40, rectImage.left+70, rectImage.top+70,
                         'X', screen, DARKBLUE, WHITE, 20)
    ButtonCross.CreateButtonMenu()
    pygame.display.flip()
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    exit()
                if event.key == pygame.K_p:
                    return
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    if ButtonCross.buttonPressed():
                        return Pause(screen, levelCanvas)

def Pause(screen, levelCanvas):
    """Displays the pause menu and handles user interaction."""
    muteValue = levelCanvas.getMuteValue()
    if muteValue:
        str = 'Mute On'
    else:
        str = 'Mute Off'

    image = BACKGROUNDPAUSE
    rectImage = image.get_rect(center=(SCREENWIDTH/2, SCREENHEIGHT/2))
    screen.blit(image, rectImage)
    ButtonCross = Button(40, 40, rectImage.left+70, rectImage.top+100,
                         'X', screen, DARKBLUE, WHITE, 20)
    ButtonCross.CreateButtonMenu()

    buttonMute = Button(150, 80, rectImage.centerx - 200, rectImage.centery+80,
                        f'{str}', screen, DARKBLUE, WHITE, 14)
    buttonMute.setFont(14)
    buttonMute.CreateButtonMenu()
    buttonControles = Button(180, 80, rectImage.centerx + 200, rectImage.centery+80,
                             'Controls', screen, DARKBLUE, WHITE, 14)
    buttonControles.setFont(14)
    buttonControles.CreateButtonMenu()

    pygame.display.flip()
    while True:
        if muteValue == False or muteValue == None:
            # ButtonMute.colorText = GREEN
            buttonMute.setText('Mute On', RED)
            # ButtonMute.CreateButtonMenu()
        else:
            # ButtonMute.colorText = RED
            buttonMute.setText('Mute Off', GREEN)
            # ButtonMute.CreateButtonMenu()
            # pygame.display.flip()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    exit()
                if event.key == pygame.K_p:
                    return
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    if buttonMute.buttonPressed():
                        muteValue = not muteValue
                        buttonMute.setFont(14)
                        buttonMute.CreateButtonMenu()
                        pygame.display.flip()
                    if buttonControles.buttonPressed():
                        controlesMenu(screen, levelCanvas)
                    if ButtonCross.buttonPressed():
                        return

def mainMenu(screen, mainMusic, muteValue: bool):

    if muteValue:
        mainMusic.set_volume(0)
    else:
        mainMusic.set_volume(0.5)
    """Displays the main menu and handles user interaction,game settings and credits screen."""
    background = BACKGROUNSEADAY
    drawBackground(screen, background)
    muteValue = False if muteValue == None else True
    ButtonStart = Button(BUTTONWIDTH, BUTTONHEIGHT,
                         (SCREENWIDTH)/2, (BUTTONHEIGHT*3), 'Start', screen)
    ButtonStart.CreateButtonMenu()
    ButtonOptions = Button(BUTTONWIDTH, BUTTONHEIGHT,
                           (SCREENWIDTH)/2, (SCREENHEIGHT)/2, 'Options', screen)
    ButtonOptions.CreateButtonMenu()
    ButtonExit = Button(BUTTONWIDTH, BUTTONHEIGHT,
                        (SCREENWIDTH)/2, (SCREENHEIGHT-BUTTONHEIGHT*3), 'Exit', screen)
    ButtonExit.CreateButtonMenu()
    pygame.display.flip()
    while True:

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    exit()
            if event.type == pygame.MOUSEBUTTONDOWN:

                if event.button == 1:
                    if ButtonStart.buttonPressed():
                        # enviar al usuario al level selector
                        return muteValue
                        # return muteValue
                    if ButtonOptions.buttonPressed():
                        optionMenu(screen, mainMusic, muteValue)
                        return
                    if ButtonExit.buttonPressed():
                        exit()

def optionMenu(screen, mainMusic, muteValue: bool):
    """Displays the options menu and handles user interaction."""
    muteValue = True if muteValue == None else False
    drawBackground(screen, BACKGROUNSEADAY)
    ButtonBack = Button(BUTTONWIDTH, BUTTONHEIGHT,
                        (SCREENWIDTH)/2, (BUTTONHEIGHT*3), 'Back', screen)
    ButtonBack.CreateButtonMenu()
    ButtonCredits = Button(BUTTONWIDTH, BUTTONHEIGHT, (SCREENWIDTH)/2,
                           (SCREENHEIGHT-BUTTONHEIGHT*3), 'Credits', screen)
    ButtonCredits.CreateButtonMenu()

    ButtonMute = Button(BUTTONWIDTH, BUTTONHEIGHT,
                        (SCREENWIDTH)/2, (SCREENHEIGHT)/2, f'Mute', screen, colorText=GREEN)
    ButtonMute.CreateButtonMenu()
    pygame.display.flip()

    while True:
        if muteValue == False or muteValue == None:
            # ButtonMute.colorText = GREEN
            ButtonMute.setText('Mute', RED)
            # ButtonMute.CreateButtonMenu()
        else:
            # ButtonMute.colorText = RED

            ButtonMute.setText('Mute', GREEN)
            # ButtonMute.CreateButtonMenu()
            # pygame.display.flip()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    exit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    if ButtonBack.buttonPressed():
                        mainMenu(screen, mainMusic, muteValue)
                        return
                    if ButtonCredits.buttonPressed():
                        creditsMenu(screen, mainMusic, muteValue)
                        return
                    if ButtonMute.buttonPressed():
                        muteValue = not muteValue
                        ButtonMute.CreateButtonMenu()
                        pygame.display.flip()

def creditsMenu(screen, mainMusic, muteValue: bool):
    """Displays the credits menu and handles user interaction."""
    background = BACKGROUNSEANIGHT
    drawBackground(screen, background)
    muteValue = muteValue

    ButtonBack = Button(BUTTONWIDTH, BUTTONHEIGHT-20,
                        (BUTTONWIDTH), (SCREENHEIGHT-BUTTONHEIGHT*1.5), 'Back', screen)
    ButtonBack.CreateButtonMenu(BLACK, borderRadius=8)

    ButtonExit = Button(BUTTONWIDTH, BUTTONHEIGHT-20, (SCREENWIDTH -
                        BUTTONWIDTH), (SCREENHEIGHT-BUTTONHEIGHT*1.5), 'Exit', screen)
    ButtonExit.CreateButtonMenu(BLACK, borderRadius=8)

    copywriteImg = loadImage('gameFreak.png')
    copyImgRect = copywriteImg.get_rect()
    copyImgRect = copywriteImg.get_rect(
        center=(copyImgRect.centerx, copyImgRect.centery))
    copyImgRect.center = (((SCREENWIDTH / 2), (0+BUTTONHEIGHT*3)))
    screen.blit(copywriteImg, copyImgRect)

    Text('Juego creado por Mateo Barbato', WHITE, 24, False).blitText(
        screen, (SCREENWIDTH/2, SCREENHEIGHT/2.5), None)
    Text('Idea originada con Pokemon dandole una vuelta creativa', WHITE,
         24, False).blitText(screen, (SCREENWIDTH/2, SCREENHEIGHT/2.25), None)
    Text('Assets obtenidos de la pagina Sprite Database', WHITE, 24,
         False).blitText(screen, (SCREENWIDTH/2, SCREENHEIGHT/2), None)

    pygame.display.flip()
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    exit()
            if event.type == pygame.MOUSEBUTTONDOWN:

                if event.button == 1:
                    if ButtonBack.buttonPressed():
                        optionMenu(screen, mainMusic, muteValue)
                        return
                    if ButtonExit.buttonPressed():
                        sys.exit()

def levelSelector(screen, dataStars):
    """Loads the specified level into the game.

    Parameters:
        spriteGroupAll (pygame.sprite.Group): The group of all sprites in the game.
        map (list of lists): The level map.

    Additional Explanation:
        This function reads the level map and creates the corresponding sprites for the level.
        It also sets the starting positions of the player and other objects in the level.
    """

    drawBackground(screen, BRACKGROUNDGRASS)
    drawBackground(screen, BRACKGROUNDTREES)
    ButtonHeight = 90
    ButtonWidth = 130
    ButtonCross = Button(40, 40, 150, 120,
                         'X', screen, colorbackground=LAVENDER, fontSize=20)
    # -------------------------------------------------------------------------
    Level1 = Button(ButtonWidth, ButtonHeight, SCREENWIDTH/3 - 80,
                    SCREENHEIGHT/2.5, 'Level 1', screen, GREENMENU, WHITE)
    Text(f'{dataStars["1"]}/3 Stars', YELLOW, 24, False).blitText(
        screen, (SCREENWIDTH/3 - 80, (SCREENHEIGHT/2.5)+70), None)
    # -------------------------------------------------------------------------
    Level2 = Button(ButtonWidth, ButtonHeight, SCREENWIDTH/2,
                    SCREENHEIGHT/2.5, 'Level 2', screen, GREENMENU, WHITE)
    Text(f'{dataStars["2"]}/3 Stars', YELLOW, 24, False).blitText(
        screen, (SCREENWIDTH/2, (SCREENHEIGHT/2.5)+70), None)
    # -------------------------------------------------------------------------
    Level3 = Button(ButtonWidth, ButtonHeight, SCREENWIDTH - SCREENWIDTH/3 + 80,
                    SCREENHEIGHT / 2.5, 'Level 3', screen, GREENMENU, WHITE)
    Text(f'{dataStars["3"]}/3 Stars', YELLOW, 24, False).blitText(
        screen, (SCREENWIDTH - SCREENWIDTH/3 + 80, (SCREENHEIGHT/2.5)+70), None)
    # -------------------------------------------------------------------------
    Level1.CreateButtonMenu()
    Level2.CreateButtonMenu()
    Level3.CreateButtonMenu()
    ButtonCross.CreateButtonMenu(borderRadius=5)
    pygame.display.flip()
    while True:

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    exit()
            if event.type == pygame.MOUSEBUTTONDOWN:

                if event.button == 1:
                    if Level1.buttonPressed():
                        return False, 1
                    if Level2.buttonPressed():
                        if dataStars['1'] > 1:
                            return False, 2
                        else:
                            pass
                    if Level3.buttonPressed():
                        if dataStars['2'] > 1:
                            return False, 3
                        else:
                            pass
                    if ButtonCross.buttonPressed():
                        return True, 0

# def loadLevel(spriteGroupAll, map):
def levelFinished(screen, background, currentLevel, lastScore, bestScores):
    """Displays the level finished screen and handles user interaction.

    Parameters:
        screen (pygame.Surface): The pygame Surface object representing the game screen.
        background (pygame.Surface): The background image to draw.
        currentLevel (int): The current level number.
        lastScore (int): The score for the current level.
        bestScores (list of dicts): The list of best scores for each level.

    Return Value:
        A tuple of two booleans:
            * The first boolean indicates whether to restart the current level.
            * The second boolean indicates whether to go to the level selector.

    Additional Explanation:
        This function displays the level finished screen, showing the player's score and the best scores.
        It handles user interaction by checking for mouse clicks on the buttons.
    """
    drawBackground(screen, background)
    if bestScores == 0:
        pass
    else:
        highScores = bestScores
    Text('Your score', WHITE, 42, False).blitText(
        screen, (SCREENWIDTH/2, SCREENHEIGHT/5), WHITE)
    Text(str(lastScore), WHITE, 42, True).blitText(
        screen, (SCREENWIDTH/2, SCREENHEIGHT/4), WHITE)
    print(len(highScores))
    for i, value in enumerate(highScores, 1):

        Text(f'Player {i} : {value["score"]}', WHITE, 22, True).blitText(
            screen, (SCREENWIDTH/2, SCREENHEIGHT/4 + 80*i), WHITE)

    ButtonLevels = Button(180, 40, 150, 120,
                          'Levels', screen, colorbackground=LAVENDER, fontSize=20)
    Restart = Button(160, 70, SCREENWIDTH/2 - 250,
                     SCREENHEIGHT-SCREENHEIGHT/7, 'Restart', screen)
    Continue = Button(160, 70, SCREENWIDTH/2 + 250,
                      SCREENHEIGHT-SCREENHEIGHT/7, 'Continue', screen)
    Restart.setFont(18)
    Restart.CreateButtonMenu()
    Continue.setFont(18)
    Continue.CreateButtonMenu()
    ButtonLevels.CreateButtonMenu(borderRadius=5)
    pygame.display.flip()
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    exit()
            if event.type == pygame.MOUSEBUTTONDOWN:

                if event.button == 1:
                    if Restart.buttonPressed():
                        return True, (currentLevel)
                    if Continue.buttonPressed():
                        if currentLevel == 1:
                            newLevel = 2
                            if lastScore > 60:
                                return True, newLevel
                            else:
                                pass
                        if currentLevel == 2:
                            newLevel = 3
                            if lastScore > 60:
                                return True, newLevel
                            else:
                                pass
                        if currentLevel == 3:
                            return False, 0

                    if ButtonLevels.buttonPressed():
                        return False, 0

def saveScores(data, scoreTotal, levelSelected):
    """
    This function saves the scores of the game in a JSON file.

    Args:
        data (dict): The JSON data that contains the scores of the game.
        scoreTotal (int): The score of the current game.
        levelSelected (int): The level of the game that was played.

    Returns:
        list: The list of the top 5 scores for the selected level.
    """
    if levelSelected == 1:
        scoreList = data['Level 1']
    elif levelSelected == 2:
        scoreList = data['Level 2']
    elif levelSelected == 3:
        scoreList = data['Level 3']
    saved = False
    scoreList = sorted(
        scoreList, key=lambda k: k['score'], reverse=True)
    for i in range(len(scoreList)):
        if scoreList[i]['score'] < scoreTotal and saved == False:
            aux = dict()
            aux['score'] = scoreTotal
            scoreList.append(aux)
            saved = True
    scoreList = sorted(
        scoreList, key=lambda k: k['score'], reverse=True)

    if levelSelected == 1:
        data['Level 1'] = scoreList[0:5]
    elif levelSelected == 2:
        data['Level 2'] = scoreList[0:5]
    elif levelSelected == 3:
        data['Level 3'] = scoreList[0:5]

    try:
        with open(r"./db.json", 'w') as dataEnd:
            json.dump(data, dataEnd, indent=2)
    except OSError.filename as Err:
        errMsg(
            "Error while writing the scores to the datafile. The score wont be saved")
        print(Err)
        errMsg(
            'Please validate the files and check again. If the problem persist re-install the files')
    return scoreList[0:5]

def saveScoresLevel(dataStars, lastScore, levelSelected):
    # dict['1'] : 0, 112, '1'
    levelSelected = str(levelSelected)
    dictionarioLevel = dataStars
    if lastScore > 60 and lastScore < 120:
        dictionarioLevel[levelSelected] = 1
    elif lastScore > 120 and lastScore < 180:
        dictionarioLevel[levelSelected] = 2
    elif lastScore > 180:
        dictionarioLevel[levelSelected] = 3
    else:
        dictionarioLevel[levelSelected] = 0

    try:
        with open(r"./dbLevel.json", 'w') as dataEnd:
            json.dump(dictionarioLevel, dataEnd, indent=2)
    except OSError.filename as Err:
        errMsg(
            "Error while writing the scores to the datafile. The score wont be saved")
        print(Err)
        errMsg(
            'Please validate the files and check again. If the problem persist re-install the files')

    pass

def createDefaultDb():
    """
    This function creates a default JSON file with empty data for the scores of the game.

    Returns:
        dict: The JSON data with the empty scores.
    """
    data = dict()

    for i in range(1, 4):
        arrLevel = []
        for j in range(1, 6):
            arr = dict()
            arr['score'] = 0
            arrLevel.append(arr)
        data[f'Level {i}'] = arrLevel
    return data

def loadDb():
    try:
        # Intento abrir la base de datos.
        with open('./db.json') as db:
            data = json.load(db)
        # Si abre asigno los datos a las variables del juego ( maxScore y Attempts a superar el max score)
        return data
    except FileNotFoundError as Err:
        # Si falla por no encontrar el archivo me guardo el mensaje del except como Err
        # Despues creo una base de datos nueva (todo en 0) y la utilizo para cargar los datos a mis variables
        # (tambien podes hacer esto al final de juego, yo lo hice del principio para atajarme de errores en medio de la partida)
        data = createDefaultDb()
        with open('./db.json', 'w') as file:
            json.dump(data, file, indent=2)
        # Le muestro los mensajes default y el mensaje de Err que me viene del except
        # la funcion errMsg es una funcion propia que solo aniade espacios arriba y abajo para que sea mas legible todo pero nada mas
        errMsg("Error while trying to read data for the scores")
        print(Err)
        errMsg('Please validate the install and try again. The game can run without it but the db has been reseted to default (0)')
        # por ultimo asigno los datos de la nueva base a las nuevas variables
        return data

def createDefaultLevelDb():
    """
    This function creates a default JSON file with empty data for the scores of the Levels.

    Returns:
        dict: The JSON data with the empty scores.
    """
    data = dict()

    for i in range(1, 4):
        data[f'{i}'] = 0
    return data

def loadLevelDb():
    try:
        # Intento abrir la base de datos.
        with open('./dbLevel.json') as db:
            data = json.load(db)
        # Si abre asigno los datos a las variables del juego ( maxScore y Attempts a superar el max score)
        return data
    except FileNotFoundError as Err:
        # Si falla por no encontrar el archivo me guardo el mensaje del except como Err
        # Despues creo una base de datos nueva (todo en 0) y la utilizo para cargar los datos a mis variables
        # (tambien podes hacer esto al final de juego, yo lo hice del principio para atajarme de errores en medio de la partida)
        data = createDefaultLevelDb()
        with open('./dbLevel.json', 'w') as file:
            json.dump(data, file, indent=2)
        # Le muestro los mensajes default y el mensaje de Err que me viene del except
        # la funcion errMsg es una funcion propia que solo aniade espacios arriba y abajo para que sea mas legible todo pero nada mas
        errMsg("Error while trying to read data for the scores")
        print(Err)
        errMsg('Please validate the install and try again. The game can run without it but the db has been reseted to default (0)')
        # por ultimo asigno los datos de la nueva base a las nuevas variables
        return data


import json
from django.db.models import Q
from rest_framework.response import Response
from django.shortcuts import get_object_or_404
from rest_framework.permissions import AllowAny
from rest_framework.decorators import api_view, permission_classes

from .models import Materia, parseParams

# Create your views here.

@api_view(['GET'])
@permission_classes([AllowAny])
def getAllMaterias(request):
    if request.method == 'GET':
        materias = Materia.objects.all()
        materias_list = [materia.to_dict() for materia in materias]
        return Response(materias_list)

@api_view(['GET'])
@permission_classes([AllowAny])
def getMateriaById(request, id):
    if request.method == 'GET':
        materia = get_object_or_404(Materia, materia_id=id)
        return Response(materia.to_dict())

@api_view(['GET'])
@permission_classes([AllowAny])
def getMateriasByName(request):
    if request.method == 'GET':
        materia = parseParams(request)
        materias = Materia.objects.filter(
            name__startswith=materia["name"].upper())

        materias_list = [materia.to_dict() for materia in materias]
        return Response(materias_list)


'''
THIS IS A MEMORY MODULE ON THE SREVER WHICH ACTS LIKE MEMORY OF FILE SYSTEM. ALL THE OPERATIONS REGARDING THE FILE SYSTEM OPERATES IN
THIS MODULE. THE MODULE HAS POINTER TO DISK AND HAS EXACT SAME LAYOUT AS UNIX TYPE FILE SYSTEM.
'''
import config, DiskLayout, client_stub, pickle, hashlib

#ORIENTED TO LOWER INTERFACES
sblock = DiskLayout.SuperBlock()
client = client_stub.client_stub()
fail_servers = []

#RAID-5 LOGIC
def __ascii_2_str__(b_data):
	data = ''
	for byte in range(len(b_data)/8): data += chr(int(b_data[byte*8: byte*8+8], 2))

	return data

def __str_2_ascii__(string):
	b_data = ''
	for word in string:
		b_data += bin(ord(word) | 0b100000000).replace('0b1', '', 1)

	return b_data

def __checksum__(data):
	md5 = hashlib.md5(data)
	retVal = md5.hexdigest()
	checksum_buf = []
	for i in range(0,len(retVal)):
		checksum_buf.append(bin(int(retVal[i],16)).replace('0b','').zfill(4))
	checksum_md5 = ''.join(checksum_buf)
	return checksum_md5

def __if_data_block_match_checksum__(data):
	return data[config.BLOCK_SIZE*8 : config.WHOLE_BLOCK_SIZE*8] == __checksum__(data[: config.BLOCK_SIZE*8])

def __raid_block_mapping__(block_number):
	server_sets_size = config.TOTAL_NO_OF_BLOCKS * (4 - 1)		# DATA BLOCKS NUMBER (NOT PARITY BLOCKS)
	server_sets_offset = block_number / server_sets_size
	block_offset = block_number % server_sets_size
	stripe_num = block_offset / 3
	stripe_offset = block_offset % 3
	parity_in_stripe_offset = stripe_num % 4

	server_block_num = stripe_num
	server_id = 8000 + server_sets_offset * 4 + stripe_offset
	if stripe_offset >= parity_in_stripe_offset:
		server_id += 1

	parity_server_id = 8000 + server_sets_offset * 4 + parity_in_stripe_offset
	return [server_id, server_sets_offset, server_block_num, parity_server_id]

def __raid_read_block__(block_number):
	# No response from one server, regenerate data from redundancy servers.
	# data is binary
	if client.raid_mode == 1:
		if block_number >= sblock.VALID_DATA_BLOCK_NUM:	return -1
		for server_id in range(client.proxys_num):
			server_id += 8000
			if server_id in fail_servers: continue
			response = client.read(server_id, block_number*config.WHOLE_BLOCK_SIZE, config.WHOLE_BLOCK_SIZE)
			if response != None:
				if __if_data_block_match_checksum__(response):	return response[: config.BLOCK_SIZE*8]
			else: fail_servers.append(server_id)
		print('FATAL ERROR! ALL DISKS FAIL!')
		quit()

	else:
		if block_number >= sblock.VALID_DATA_BLOCK_NUM:	return -1
		des_server_id, server_sets_offset, server_block_num, _ = __raid_block_mapping__(block_number)

		if des_server_id not in fail_servers:
			response = client.read(des_server_id, server_block_num*config.WHOLE_BLOCK_SIZE, config.WHOLE_BLOCK_SIZE)
			if response != None:
				if __if_data_block_match_checksum__(response):	return response[: config.BLOCK_SIZE*8]
			else:	fail_servers.append(des_server_id)

		rec_data = []
		for server_id in range(server_sets_offset*4, server_sets_offset*4+4):
			server_id += 8000
			if server_id == des_server_id: continue
			if server_id in fail_servers:
				print('FATAL ERROR! MORE THAN TWO RAID DISKS DECAY!')
				quit()
			response = client.read(server_id, server_block_num*config.WHOLE_BLOCK_SIZE, config.WHOLE_BLOCK_SIZE)
			if response == None:
				print('FATAL ERROR! MORE THAN TWO RAID DISKS DECAY!')
				quit()
			else:
				if not __if_data_block_match_checksum__(response):
					print('FATAL ERROR! MORE THAN TWO RAID DISKS DECAY!')
					quit()
				rec_data.append(int(response[: config.BLOCK_SIZE*8],2))

		new_data = bin(rec_data[0] ^ rec_data[1] ^ rec_data[2]).replace('0b', '', 1).zfill(config.BLOCK_SIZE*8)
		print('BLOCK ' + str(block_number) + ' WAS DAMAGED, AND IS NOW REPAIRED')
		return new_data

def __raid_write_block__(block_number, data):
	# data is binary
	if client.raid_mode == 1:
		if block_number >= sblock.VALID_DATA_BLOCK_NUM or len(data)/8 != config.BLOCK_SIZE:	return -1
		for server_id in range(client.proxys_num):
			server_id += 8000
			if server_id in fail_servers: continue
			rx_data = data + __checksum__(data)
			response = client.write(server_id, block_number*config.WHOLE_BLOCK_SIZE, rx_data)
			if response == None: fail_servers.append(server_id)

	else:
		if block_number >= sblock.VALID_DATA_BLOCK_NUM or len(data)/8 != config.BLOCK_SIZE:	return -1
		des_server_id, server_sets_offset, server_block_num, parity_server_id = __raid_block_mapping__(block_number)
		fail_count = 0
		parity_data = []
		parity = None
		des = None
		data = int(data, 2)

		# check servers
		for server_id in range(server_sets_offset*4, server_sets_offset*4+4):
			server_id += 8000
			if server_id in fail_servers:
				if server_id != des_server_id and server_id != parity_server_id: parity_data.append(None)
				fail_count += 1
				continue
			response = client.read(server_id, server_block_num*config.WHOLE_BLOCK_SIZE, config.WHOLE_BLOCK_SIZE)
			if response == None:
				fail_servers.append(server_id)
				parity_data.append(None)
				fail_count += 1
				continue
			if server_id == des_server_id:
				if __if_data_block_match_checksum__(response):	des = int(response[: config.BLOCK_SIZE*8], 2)
				else: fail_count += 1
			elif server_id == parity_server_id:
				if __if_data_block_match_checksum__(response):	parity = int(response[: config.BLOCK_SIZE*8], 2)
				else: fail_count += 1
			else:
				if __if_data_block_match_checksum__(response):	parity_data.append(int(response[: config.BLOCK_SIZE*8], 2))
				else: fail_count += 1

		# calculate parity according to failure condition
		if fail_count >= 2:
			print('FATAL ERROR! MORE THAN 2 DISKS FAIL & SYS FAILS!')
			quit()
		elif fail_count == 1:
			if des == None:
				parity = data
				for pdata in parity_data:	parity ^= pdata
			elif parity == None: pass
			else:
				fail_index = parity_data.index(None)
				parity_data.pop(fail_index)
				rec_data = des ^ parity
				for pdata in parity_data:	rec_data ^= pdata		# use old parity to reconstruct bad data
				parity_data.insert(fail_index, rec_data)
				parity = data
				for pdata in parity_data:	parity ^= pdata 		# then use reconstructed data to build new parity
		else:
				parity = data
				for pdata in parity_data: parity ^= pdata

		# write parity and data
		if des != None:
			data = bin(data).replace('0b', '', 1).zfill(config.BLOCK_SIZE*8)
			data += __checksum__(data)
			response = client.write(des_server_id, server_block_num*config.WHOLE_BLOCK_SIZE, data)
			if response == None:
				fail_servers.append(des_server_id)
				# return -1

		if parity != None:
			parity = bin(parity).replace('0b', '', 1).zfill(config.BLOCK_SIZE*8)
			parity += __checksum__(parity)
			response = client.write(parity_server_id, server_block_num*config.WHOLE_BLOCK_SIZE, parity)
			if response == None:
				fail_servers.append(parity_server_id)

def __initialize__(server_num, raid_mode):
	client.add_proxys(server_num)
	client.set_raid_mode(raid_mode)
	if raid_mode == 1:
		sblock.TOTAL_NO_OF_BLOCKS = config.TOTAL_NO_OF_BLOCKS
		sblock.VALID_DATA_BLOCK_NUM = sblock.TOTAL_NO_OF_BLOCKS
	else:
		sblock.TOTAL_NO_OF_BLOCKS = config.TOTAL_NO_OF_BLOCKS * server_num
		sblock.VALID_DATA_BLOCK_NUM = int(sblock.TOTAL_NO_OF_BLOCKS * float(3) / float(4))
	#FLUSHING EMPTY DATA WITH CHECKSUM TO ALL DISKS
	init_data = __str_2_ascii__('\0' * config.BLOCK_SIZE)
	init_data += __checksum__(init_data)
	init_data *= config.TOTAL_NO_OF_BLOCKS
	for server_id in range(server_num): client.write(server_id+8000, 0, init_data)
	#ALLOCATING BITMAP BLOCKS 0 AND 1 BLOCKS ARE RESERVED FOR BOOT BLOCK AND SUPERBLOCK
	sblock.BITMAP_BLOCKS_OFFSET, count = 2, 2
	bitmap_block_num = sblock.TOTAL_NO_OF_BLOCKS / sblock.BLOCK_SIZE
	if raid_mode != 1: bitmap_block_num = int(bitmap_block_num * float(3) / 4)
	for _ in range(0, bitmap_block_num):
		bitmap_block = '0' * config.BLOCK_SIZE
		bitmap_block = __str_2_ascii__(bitmap_block)
		__raid_write_block__(count, bitmap_block)
		count += 1
	#ALLOCATING INODE BLOCKS
	sblock.INODE_BLOCKS_OFFSET = count
	for _ in range(0, (sblock.MAX_NUM_INODES * sblock.INODE_SIZE) / sblock.BLOCK_SIZE):		#for Inode blocks
		init_data = __str_2_ascii__('\0' * config.BLOCK_SIZE)
		__raid_write_block__(count, init_data)
		count  += 1
	#ALLOCATING DATA BLOCKS
	sblock.DATA_BLOCKS_OFFSET = count
	for blk_num in range(count, sblock.VALID_DATA_BLOCK_NUM):
		init_data = __str_2_ascii__('\0' * config.BLOCK_SIZE)
		__raid_write_block__(blk_num, init_data)
	#MAKING BLOCKS BEFORE DATA BLOCKS UNAVAILABLE FOR USE SINCE OCCUPIED BY SUPERBLOCK, BOOTBLOCK, BITMAP AND INODE TABLE
	bitmap_block = '2' * sblock.DATA_BLOCKS_OFFSET
	if len(bitmap_block) % config.BLOCK_SIZE != 0:
		bitmap_block += '0' * (config.BLOCK_SIZE - len(bitmap_block) % config.BLOCK_SIZE)
	for b_blk in range(len(bitmap_block) / config.BLOCK_SIZE):
		data = __str_2_ascii__(bitmap_block[b_blk*config.BLOCK_SIZE : (b_blk+1)*config.BLOCK_SIZE])
		b_blk += sblock.BITMAP_BLOCKS_OFFSET
		__raid_write_block__(b_blk, data)

#OPERATIONS ON FILE SYSTEM
class Operations():
	def initialize(self, server_num, raid_mode):
		__initialize__(server_num, raid_mode)

	#RETURNS THE DATA OF THE BLOCK
	def get_data_block(self, block_number):
		if block_number == 0: print("Memory: Reserved for Boot Block")
		elif block_number == 1: print("Memory: Reserved for Super Block")

		elif block_number >= sblock.BITMAP_BLOCKS_OFFSET and block_number < sblock.INODE_BLOCKS_OFFSET:
			bit_map_blk = list(__ascii_2_str__(__raid_read_block__(block_number)))
			for index in range(len(bit_map_blk)):
				bit = bit_map_blk[index]
				if bit == '2': bit_map_blk[index] = -1
				else: bit_map_blk[index] = int(bit)
			return bit_map_blk

		elif block_number >= sblock.INODE_BLOCKS_OFFSET and block_number < sblock.DATA_BLOCKS_OFFSET:
			inode_block = []
			inode_offset = (block_number - sblock.INODE_BLOCKS_OFFSET) * sblock.INODES_PER_BLOCK
			for inode_number in range(inode_offset, inode_offset + sblock.INODES_PER_BLOCK):
				inode_block.append(self.inode_number_to_inode(inode_number))
			return inode_block

		elif block_number >= sblock.DATA_BLOCKS_OFFSET and block_number < sblock.TOTAL_NO_OF_BLOCKS:
			return list(__ascii_2_str__(__raid_read_block__(block_number)))
		else: print("Memory: Block index out of range or Wrong input!")

		return -1

	#RETURNS THE BLOCK NUMBER OF AVAIALBLE DATA BLOCK
	def get_valid_data_block(self):
		for blk_index in range(sblock.BITMAP_BLOCKS_OFFSET, sblock.INODE_BLOCKS_OFFSET):
			bit_map_blk = list(__ascii_2_str__(__raid_read_block__(blk_index)))
			for bit_index in range(len(bit_map_blk)):
				bit = bit_map_blk[bit_index]
				if bit == '0':
					bit_map_blk[bit_index] = '1'
					bit_map_blk = ''.join(bit_map_blk)
					__raid_write_block__(blk_index, __str_2_ascii__(bit_map_blk))
					return ((blk_index-sblock.BITMAP_BLOCKS_OFFSET)*config.BLOCK_SIZE + bit_index)

		print("Memory: No valid blocks available")
		return -1

	#REMOVES THE INVALID DATA BLOCK TO MAKE IT REUSABLE
	def free_data_block(self, block_number):
		bit_map_blk_num = sblock.BITMAP_BLOCKS_OFFSET + block_number / config.BLOCK_SIZE
		bit_map_index = block_number % config.BLOCK_SIZE
		bit_map_blk = list(__ascii_2_str__(__raid_read_block__(bit_map_blk_num)))
		bit_map_blk[bit_map_index] = '0'
		bit_map_blk = ''.join(bit_map_blk)
		__raid_write_block__(bit_map_blk_num, __str_2_ascii__(bit_map_blk))

		empty_block = __str_2_ascii__('\0' * config.BLOCK_SIZE)
		__raid_write_block__(block_number, empty_block)

	#WRITES TO THE DATA BLOCK
	def update_data_block(self, block_number, block_data):
		old_block_data = __ascii_2_str__(__raid_read_block__(block_number))
		block_data += old_block_data[len(block_data) :]
		__raid_write_block__(block_number, __str_2_ascii__(block_data))
		if client.raid_mode == 1:
			print('WRITING TO ALL SERVERS ...')
		else:
			print('WRITING TO SERVER: ' + str(__raid_block_mapping__(block_number)[0]) + '...')

	#UPDATES INODE TABLE WITH UPDATED INODE
	def update_inode_table(self, inode, inode_number):
		# Need convert array-inode to raw-data
		# If array-inode's size is not full, append \0 (str)
		r_inode = ''

		if inode == False:	r_inode = __str_2_ascii__('\0' * config.INODE_SIZE)
		else:
			r_inode += __str_2_ascii__('0'+str(inode[0]))			# type => 2 bytes
			r_inode += bin(int(__str_2_ascii__(inode[1]), 2) | int('1' + '0'*config.MAX_FILE_NAME_SIZE*8, 2)).replace('0b1', '', 1)				# Name => 16 bytes
			r_inode += bin(inode[2] | 2**(2*8)).replace('0b1', '', 1)			# links num	=> 2 bytes
			r_inode += bin(int(__str_2_ascii__(inode[3]), 2) | int('1' + '0'*19*8, 2)).replace('0b1', '', 1)				# Time created	=> 19 bytes
			r_inode += bin(int(__str_2_ascii__(inode[4]), 2) | int('1' + '0'*19*8, 2)).replace('0b1', '', 1)				# Time accessed	=> 19 bytes
			r_inode += bin(int(__str_2_ascii__(inode[5]), 2) | int('1' + '0'*19*8, 2)).replace('0b1', '', 1)				# Time modified => 19 bytes
			r_inode += bin(inode[6] | 2**(2*8)).replace('0b1', '', 1)			# Inode size => 2 bytes
			if inode[0] == 0:
				for blk in inode[7]:
					if blk == -1:	r_inode += __str_2_ascii__('-1')		# '-1' takes 2 bytes by storing str
					else: r_inode += bin(blk | 2**(2*8)).replace('0b1', '', 1)	# else blk num store true number
			else:
				for entry in inode[7]:
					for word in entry:	r_inode += __str_2_ascii__(word)

			if len(r_inode)/8 < config.INODE_SIZE:
				r_inode += __str_2_ascii__('\0'*(config.INODE_SIZE - len(r_inode)/8))

		inode_blk_num = sblock.INODE_BLOCKS_OFFSET + inode_number / sblock.INODES_PER_BLOCK
		inode_offset = inode_number % sblock.INODES_PER_BLOCK
		inode_blk = __raid_read_block__(inode_blk_num)
		inode_blk = inode_blk[: inode_offset*config.INODE_SIZE*8] + r_inode + inode_blk[(inode_offset+1)*config.INODE_SIZE*8 :]
		__raid_write_block__(inode_blk_num, inode_blk)
		# return r_inode

	#RETURNS THE INODE FROM INODE NUMBER
	def inode_number_to_inode(self, inode_number):
		inode_blk_num = sblock.INODE_BLOCKS_OFFSET + inode_number / sblock.INODES_PER_BLOCK
		inode_offset = inode_number % sblock.INODES_PER_BLOCK
		r_inode = __raid_read_block__(inode_blk_num)[inode_offset*config.INODE_SIZE*8 : (inode_offset+1)*config.INODE_SIZE*8]
		inode = [None for _ in range(8)]
		count = 0

		if int(r_inode, 2) == 0: return False

		inode[0] = int(__ascii_2_str__(r_inode[:2*8]))
		count += 2*8
		name = bin(int(r_inode[count:count+config.MAX_FILE_NAME_SIZE*8], 2) | 0).replace('0b', '', 1)
		inode[1] = __ascii_2_str__(name.zfill(len(name)+(8-len(name)%8)))
		count += config.MAX_FILE_NAME_SIZE*8
		inode[2] = int(r_inode[count:count+2*8], 2)
		count += 2*8
		inode[3] = __ascii_2_str__(r_inode[count:count+19*8])
		count += 19*8
		inode[4] = __ascii_2_str__(r_inode[count:count+19*8])
		count += 19*8
		inode[5] = __ascii_2_str__(r_inode[count:count+19*8])
		count += 19*8
		inode[6] = int(r_inode[count:count+2*8], 2)
		count += 2*8
		inode[7] = []
		if inode[0] == 0:
			max_data_blocks_allocated = (config.INODE_SIZE - 63 - config.MAX_FILE_NAME_SIZE) / 2
			for _ in range(max_data_blocks_allocated):
				blk = __ascii_2_str__(r_inode[count:count+2*8])
				if blk == '-1': inode[7].append(-1)
				else: inode[7].append(int(r_inode[count:count+2*8], 2))
				count += 2*8
		else:
			entry_size = config.MAX_FILE_NAME_SIZE + len(str(config.MAX_NUM_INODES))
			max_entries = (config.INODE_SIZE - 63 - config.MAX_FILE_NAME_SIZE ) / entry_size
			for _ in range(max_entries):
				entry = __ascii_2_str__(r_inode[count:count+entry_size*8])
				inode[7].append(list(entry))
				count += entry_size * 8

		return inode

	#SHOWS THE STATUS OF DISK LAYOUT IN MEMORY
	def status(self):
		counter = 1
		string = ""
		string += "\n----------BITMAP: ----------(Block Number : Valid Status)\n"
		block_number = 0
		for i in range(2, sblock.INODE_BLOCKS_OFFSET):
			string += "Bitmap Block : " + str(i - 2) + "\n"
			b = self.get_data_block(i)
			for j in range(0, len(b)):
				if j == 20: break   #only to avoid useless data to print
				string += "\t\t[" + str(block_number + j) + "  :  "  + str(b[j]) + "]  \n"
			block_number += len(b)
			if counter == 1: break
		string += ".....showing just part(20) of 1st bitmap block!\n"

		string += "\n\n----------INODE Blocks: ----------(Inode Number : Inode(Address)\n"
		inode_number = 0
		for i in range(sblock.INODE_BLOCKS_OFFSET, sblock.DATA_BLOCKS_OFFSET):
			string += "Inode Block : " + str(i - sblock.INODE_BLOCKS_OFFSET) + "\n"
			b = self.get_data_block(i)
			for j in range(0, len(b)):
				string += "\t\t[" + str(inode_number + j) + "  :  "  + str(bool(b[j])) + "]  \n"
			inode_number += len(b)

		string += "\n\n----------DATA Blocks: ----------\n  "
		counter = 0
		for i in range(sblock.DATA_BLOCKS_OFFSET, sblock.TOTAL_NO_OF_BLOCKS):
			if counter == 25:
				string += "......Showing just part(25) data blocks\n"
				break
			string += (str(i) + " : " + "".join(self.get_data_block(i))) + "  "
			counter += 1

		string += "\n\n----------HIERARCHY: ------------\n"
		for i in range(sblock.INODE_BLOCKS_OFFSET, sblock.DATA_BLOCKS_OFFSET):
			for j in range(0, sblock.INODES_PER_BLOCK):
				inode = self.get_data_block(i)[j]
				if inode and inode[0]:
					string += "\nDIRECTORY: " + inode[1] + "\n"
					for x in inode[7]: string += "".join(x[:config.MAX_FILE_NAME_SIZE]) + " || "
					string += "\n"

		return string

	def server_request_counter(self):
		retVal = client.server_request_count()
		return retVal

if __name__ == '__main__':
	# sblock = DiskLayout.SuperBlock()
	# sblock = pickle.dumps(sblock)
	# print len(sblock)
	# b_sblock = ''
	# for byte in sblock:
	# 	ascii_code = bin(ord(byte) | 0b100000000).replace('0b1', '', 1)
	# 	print ascii_code
	# 	print bin(ascii_code | 0b100000000) + ' ' + byte
  #   ascii_code = ascii_code.replace('0b', '0', 1)
  #   b_sblock += ascii_code

	# print len(sblock)

	# for num in range(12):
	# 	print __raid_block_mapping__(num), ' ', num

	# string = 'abc'
	# print __ascii_2_str__(__str_2_ascii__(string))
	# print type(__str_2_ascii__(string))

	# print int(__ascii_2_str__(__str_2_ascii__('0'+ str('1'))))
	# print len(bin(int(__str_2_ascii__(str(1)), 2) | int('1' + '0'*2*8, 2)).replace('0b1', '', 1)) / 8

	# t_inode = InodeOps.Table_Inode(0)
	# t_inode.name = 'AA'
	# t_inode.blk_numbers[0] = 19
	# t_inode.size = 4485
	# t_inode.time_accessed = str(datetime.datetime.now())[:19]
	# t_inode.time_created = str(datetime.datetime.now())[:19]
	# t_inode.time_modified = str(datetime.datetime.now())[:19]
	# t_inode.directory = {'1.txt': 20}

	# iop = InodeOps.InodeOperations()
	# a_inode = iop.convert_table_to_array(t_inode)

	# op = Operations()
	# temp = op.update_inode_table(a_inode, 1)
	# print a_inode
	# print
	# print a_inode == op.inode_number_to_inode(1, temp)

	# data= '01' * config.BLOCK_SIZE * 4
	# t = data
	# data = int(data, 2)
	# data = bin(data).replace('0b', '', 1).zfill(config.BLOCK_SIZE*8)
	# print data == t

	__initialize__(4)
	# data = 'ab' * (496/2)
	# data = __str_2_ascii__(data)
	# __raid_write_block__(50, data)
	# print data == __raid_read_block__(50)


import argparse
import sys
import matplotlib
#matplotlib.use('agg')
import matplotlib.pyplot as plt
import re
import matplotlib.pylab as pylab

def parselogfile(logfile):
    with open(logfile) as f:
        lines = [line.rstrip("\n") for line in f.readlines()]
    iters = []
    train_loss = []
    valid_loss = []
    for line in lines:
        if len(line) == 0:
            continue
        parts = re.split(" ", line)
        if "iters:" in parts and "train_loss:" in parts and "valid_loss:" in parts:
            for i in range(len(parts)):
                if parts[i]=="iters:":
                    iters.append(int(parts[i+1]))
                if parts[i]=="train_loss:":
                    train_loss.append(float(parts[i+1]))
                if parts[i]=="valid_loss:":
                    valid_loss.append(float(parts[i+1]))
        else:
            continue
    return iters, train_loss, valid_loss

def main(argv):

    ap = argparse.ArgumentParser()
    ap.add_argument("--log1", required=True, help = "path to log file")
    ap.add_argument("--log2", required=True, help = "path to log file")
    args = ap.parse_args()

    iters1, train1, valid1 = parselogfile(args.log1)
    iters2, train2, valid2 = parselogfile(args.log2)

    params = {'legend.fontsize': 'xx-large',
              'figure.figsize': (15, 5),
              'axes.labelsize': 'xx-large',
              'axes.titlesize':'xx-large',
              'xtick.labelsize':'xx-large',
              'ytick.labelsize':'xx-large'}
    pylab.rcParams.update(params)

    plt.plot(iters1[3:60], valid1[3:60], 'r', label="Loss = log1_valid_loss", linewidth=5.0)
    plt.plot(iters2[3:60], valid2[3:60], 'g', label="Loss = log2_valid_loss", linewidth=5.0)

    plt.xlabel('Epochs', fontsize=20)
    plt.ylabel('Validation loss', fontsize=20)
    plt.grid()
    plt.legend(loc='upper right')
    plt.show()

if __name__ == "__main__":
    main(sys.argv)


import sys
from collections import deque, Counter, defaultdict
sys.setrecursionlimit(5 * 10 ** 5)
# from pypyjit import set_param
# set_param('max_unroll_recursion=-1')
input = lambda: sys.stdin.readline().rstrip()
ii = lambda: int(input())
mi = lambda: map(int, input().split())
li = lambda: list(mi())
inf = 2 ** 63 - 1

MOD = 1000000007

def devide(n):
    ret = defaultdict(int)
    i = 2
    while n > 1:
        if n % i ==0:
            n //= i
            ret[i] += 1
        else:
            i += 1
    return ret

def solve(N: int):
    t = defaultdict(int)
    for i in range(1,N+1):
        ret = devide(i)
        for k,v in ret.items():
            t[k] += v

    ans = 1
    for i,v in t.items():
        if i == 1:
            continue
        ans = (ans * (v+1)) % MOD

    print(ans)

def main():
    N = ii()  # type: int
    solve(N)
    return

main()


import numpy as np
from itertools import combinations
for _ in range(int(input())):
    N, M = map(int, input().split())
    L = []
    for i in range(N):
        x = list(map(int, list(input())))
        L.append(x)
    a = np.array(L).T
    c = 0
    for i in a:
        ones = i.sum()
        c += len(list(combinations(range(ones), 2)))
    print(c)


import pandas as pd
import numpy as np
import warnings
from scipy.stats import binom
import snf
import os
#from creation_matrices import adj_to_list
os.environ["MKL_NUM_THREADS"] = "10"
os.environ["NUMEXPR_NUM_THREADS"] = "10"
os.environ["OMP_NUM_THREADS"] = "10"
os.environ["OPENBLAS_NUM_THREADS"] = "10"
os.environ["VECLIB_MAXIMUM_THREADS"] = "10"

warnings.filterwarnings('ignore')

#Takes the adjacency matrix and transform it into a list of edges and saves it into output_filename
def adj_to_list(A):
    List=[]
    A=pd.DataFrame(A)
    for source in A.index.values:
        for target in A.index.values:
            if source>target:
                if A[source][target]!=0:
                    List.append((target,source,A[source][target]))
    List1=pd.DataFrame(List)
    return List1

#It allows to read a file (as a Dataframe) that has 3 or more columns (sep: tab) nd one line header with column names
# ('src' and 'trg' that indicates the source and destination, the column of interest indicate the weights)
#It return the parsed network data, the number of nodes in the network and the number of edges.
def read(filename, column_of_interest, consider_self_loops = True, drop_zeroes = True):
   table = pd.read_csv(filename, sep = '\t')
   table = table[["src", "trg", column_of_interest]]
   table.rename(columns = {column_of_interest: "nij"}, inplace = True)

   if drop_zeroes:
      table = table[table["nij"] > 0]
   if not consider_self_loops:
      table = table[table["src"] != table["trg"]]

   original_nodes = len(set(table["src"]) | set(table["trg"]))
   original_edges = table.shape[0]
   return table, original_nodes, original_edges

#Reads a preprocessed edge table and returns only the edges supassing a significance threshold.
def thresholding(table, threshold):
   table = table.copy()
   if "sdev_cij" in table:
      return table[(table["score"] - (threshold * table["sdev_cij"])) > 0][["src", "trg", "nij", "score"]]
   else:
      return table[table["score"] > threshold][["src", "trg", "nij", "score"]]

#It allows to correct the noise of the  table
def noise_corrected(table, return_self_loops = False, calculate_p_value = False):
   table = table.copy()
   src_sum = table.groupby(by = "src").sum()[["nij"]]
   table = table.merge(src_sum, left_on = "src", right_index = True, suffixes = ("", "_src_sum"))
   trg_sum = table.groupby(by = "trg").sum()[["nij"]]
   table = table.merge(trg_sum, left_on = "trg", right_index = True, suffixes = ("", "_trg_sum"))
   table.rename(columns = {"nij_src_sum": "ni.", "nij_trg_sum": "n.j"}, inplace = True)
   table["n.."] = table["nij"].sum()
   table["mean_prior_probability"] = ((table["ni."] * table["n.j"]) / table["n.."]) * (1 / table["n.."])

   if calculate_p_value:
      table["score"] = binom.cdf(table["nij"], table["n.."], table["mean_prior_probability"])
      return table[["src", "trg", "nij", "score"]]

   table["kappa"] = table["n.."] / (table["ni."] * table["n.j"])
   table["score"] = ((table["kappa"] * table["nij"]) - 1) / ((table["kappa"] * table["nij"]) + 1)
   table["var_prior_probability"] = (1 / (table["n.."] ** 2)) * (table["ni."] * table["n.j"] * (table["n.."] - table["ni."]) * (table["n.."] - table["n.j"])) / ((table["n.."] ** 2) * ((table["n.."] - 1)))
   table["alpha_prior"] = (((table["mean_prior_probability"] ** 2) / table["var_prior_probability"]) * (1 - table["mean_prior_probability"])) - table["mean_prior_probability"]
   table["beta_prior"] = (table["mean_prior_probability"] / table["var_prior_probability"]) * (1 - (table["mean_prior_probability"] ** 2)) - (1 - table["mean_prior_probability"])
   table["alpha_post"] = table["alpha_prior"] + table["nij"]
   table["beta_post"] = table["n.."] - table["nij"] + table["beta_prior"]
   table["expected_pij"] = table["alpha_post"] / (table["alpha_post"] + table["beta_post"])
   table["variance_nij"] = table["expected_pij"] * (1 - table["expected_pij"]) * table["n.."]
   table["d"] = (1.0 / (table["ni."] * table["n.j"])) - (table["n.."] * ((table["ni."] + table["n.j"]) / ((table["ni."] * table["n.j"]) ** 2)))
   table["variance_cij"] = table["variance_nij"] * (((2 * (table["kappa"] + (table["nij"] * table["d"]))) / (((table["kappa"] * table["nij"]) + 1) ** 2)) ** 2)
   table["sdev_cij"] = table["variance_cij"] ** .5

   if not return_self_loops:
      table = table[table["src"] != table["trg"]]

   return table[["src", "trg", "nij", "score", "sdev_cij"]]

#It computes the disparity filter for a matrix
def disparity_filter(table, return_self_loops = False):

   table = table.copy()
   table_sum = table.groupby(table["src"]).sum().reset_index()
   table_deg = table.groupby(table["src"]).count()["trg"].reset_index()
   table = table.merge(table_sum, on = "src", how = "left", suffixes = ("", "_sum"))
   table = table.merge(table_deg, on = "src", how = "left", suffixes = ("", "_count"))
   table["score"] = 1.0 - ((1.0 - (table["nij"] / table["nij_sum"])) ** (table["trg_count"] - 1))
   table["variance"] = (table["trg_count"] ** 2) * (((20 + (4.0 * table["trg_count"])) / ((table["trg_count"] + 1.0) * (table["trg_count"] + 2) * (table["trg_count"] + 3))) - ((4.0) / ((table["trg_count"] + 1.0) ** 2)))

   if not return_self_loops:
      table = table[table["src"] != table["trg"]]

   return table[["src", "trg", "nij", "score", "variance"]]

#To pass from edgelist to adjacency matrix
def from_edgelist_to_matrix(A, length):
    List=np.zeros((length,length))
    for source in A.index:
            List[A['src'][source],A['trg'][source]]=A['nij'][source]
            List[A['trg'][source],A['src'][source]]=A['nij'][source]
    return List

class fusion_snf:
    def __init__(self, normal_sum, cancer_sum, tumor):
        self.tumor=tumor
        self.normal=normal_sum
        self.cancer=cancer_sum
        self.both=[self.normal,self.cancer]
        self.fused=pd.DataFrame(snf.snf(self.both,  K=20))
        self.fused_edgelist=adj_to_list(self.fused)
        self.fused_edgelist.columns=['src', 'trg', 'weight']
        self.fused_edgelist.to_csv('./Networks/fused_edgelist_'+ str(self.tumor)+'.csv', sep = '\t')

        self.fused_thr=self.threshold_snf()
        np.save('./Networks/fused_'+ str(self.tumor)+'.npy',self.fused_thr)

    #Threshold the fused matrix
    def threshold_snf(self):
        [fused, nodes, edges]=read('./Networks/fused_edgelist_'+ str(self.tumor)+'.csv', 'weight')
        fused=noise_corrected(fused)
        fused_df=disparity_filter(fused)
        quantiles = [99,99.5,99.8]
        for q in quantiles:
            thr=np.percentile(fused_df['score'].values, q)
            fused_dfThr=thresholding(fused_df, thr)

            #200000 is the threshold for Gephi to represent relevant edges
            if str(len(fused_dfThr))< 200000:
                break

        print('fused: ' + str(len(fused_dfThr)))
        fused=from_edgelist_to_matrix(fused_dfThr, len(self.normal))
        return fused


# https://cses.fi/problemset/task/1618
#from internet
c=0
n=int(input())
i=5
while n / i > 0:
    c += n//i
    i *= 5

print(c)
"""
# mine is too slow for 3 cases
n=int(input())+1

e,x,c=list(range(5,n,5)),1,0

while x<n:
    c+=len(e[x-1::x])
    x*=5
print(c)
"""


import random
from pprint import pprint

import chardet
import requests
from datetime import date, timedelta
from Crawler.settings import CRAWL_DELAY_DAY

class TengxunExpend:

    def returnThemeCode(self, theme):  # 这个是有用的，用来组合主题代码url的
        ent_Theme = 1537876288634
        sport_Theme = 1537877689177
        finance_Theme = 1537878365483
        tech_Theme = 1537879684280
        auto_Theme = 1537887032223
        house_Theme = 1537887128904
        news_Theme = 1537874915062
        if theme == 'news':
            return news_Theme
        if theme == 'ent':
            return ent_Theme
        if theme == 'sports':
            return sport_Theme
        if theme == 'tech':
            return tech_Theme
        if theme == 'auto':
            return auto_Theme
        if theme == 'house':
            return house_Theme
        if theme == 'finance':
            return finance_Theme

    def getThemeUrl(self, theme, today, pageNumber):
        rawUrl = "http://roll.news.qq.com/interface/cpcroll.php"
        rawReferer = '.qq.com/articleList/rolls/'  # 'http://news   前面还有这个东西
        print(theme)
        print(today)
        print(pageNumber)

        my_headers = [
            'Mozilla/5.0 (Windows NT 5.2) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.122 Safari/534.30',
            'Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0',
            'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET4.0E; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C)',
            'Opera/9.80 (Windows NT 5.1; U; zh-cn) Presto/2.9.168 Version/11.50',
            'Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1',
            'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET4.0E; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C)']
        headers = {"User-Agent": random.choice(my_headers), 'Referer': 'http://' + theme + rawReferer}  # 默认值
        rawUrl = rawUrl + "?callback=rollback&mode=1&cata=&_=" + str(
            self.returnThemeCode(theme)) + "&site=" + theme + "&page=" + str(pageNumber) + "&date=" + today
        print(rawUrl)
        try:
            rawhtml = requests.get(rawUrl, headers=headers, allow_redirects=False,
                                   timeout=30)  # 一般提取文本的话，那就用text，如果是文件就content
            rawhtml.encoding = chardet.detect(rawhtml.content)['encoding']
            # print(rawhtml.url)
            print("状态码" + str(rawhtml.status_code))
            if rawhtml.status_code == 504:
                print(504)
                return
            print("页面的读取结果为")
            # print(rawhtml.text)
            if rawhtml.text.find('rollback') == 0:
                jsonString = rawhtml.text.split("rollback")[1]  # 把js提取出来就可以了
            else:
                jsonString = rawhtml.text
            print(jsonString)
            dicData = eval(jsonString)
            print(type(jsonString))
            print(jsonString)
            # print(dicData['data']['article_info'])
            print(len(dicData['data']['article_info']))
            if dicData['data'] == "":
                print("超过了最大页数了，跳出了就可以了")
                return
            urllist = []
            for one in dicData['data']['article_info']:
                # print(one['url'])
                print(one['url'].replace("\\", "/"))  # 还需要检查一下这个和之前的那种野蛮是不是一样的
                urllist.append(one['url'].replace("\\", "/"))
            return urllist
        except Exception as e:
            # print(e)
            return []

    def pageUrlMain(self, date=(date.today() + timedelta(days=-CRAWL_DELAY_DAY)).strftime("%Y-%m-%d") ):  # 写入url进入数据库，并且写入分类
        resultUrlDic = {}  # 写入数据库使用这个
        tempList = []
        themeList = ['news', 'ent', 'tech', 'auto', 'house', 'finance', 'sports']  # 一共有7个主题，其实不止这7个的
        for theme in themeList:
            print("第一个主题是")
            tempDList = []
            for i in range(1, 12):  # 一般是10页就很多的了。10页以内
                print("第" + str(i) + "页")
                responseList = self.getThemeUrl(theme, date, i)
                if len(responseList) == 0:
                    print("最大页数为" + str(i - 1) + "页")
                    break
                else:
                    tempList = tempList + responseList
                    tempDList += responseList
            resultUrlDic[theme] = tempDList
            print(resultUrlDic)
        tempList = set(tempList)
        count = 0
        print("列表的url数量有：" + str(len(tempList)))
        for key in resultUrlDic:
            count += len(resultUrlDic[key])
        print("url总共有" + str(count))

        print("这个是PageUrls内的提取到的url")
        # pprint(resultUrlDic)
        print(len(resultUrlDic))

        print("这个开始是list类型的结果")
        # print(tempList)

        pprint(tempList)

        # self.dbhelper.saveDicToMysql(resultUrlDic,date,"tengxun")   #参数，字典结果集，时间，分类,这儿是不需要写的。
        return list(tempList)  # 直接这儿去重后

class WangyiExpend:  # 这个是网易爬虫需要获得新闻页面的拓展的部分，直接构造成start_urls,再来做别的操作。
    def getRollUrlList(self,date=(date.today() + timedelta(days=-CRAWL_DELAY_DAY)).strftime("%Y-%m-%d") ):  #这个打开会是手机端的东西    #又重写了一遍了这个东西
        rollLatest = "http://news.163.com/latest/"  #这个就是默认新闻
        requestURL ="http://news.163.com/special/0001220O/news_json.js?0.3699326344116929"

        my_headers = [                       #这边为了得到直接的手机端的页面代码返回，直接使用手机ua
            'Mozilla/5.0 (Linux; Android 7.1.1; MI 6 Build/NMF26X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.49 Mobile MQQBrowser/6.2 TBS/043508 Safari/537.36 MicroMessenger/6.5.13.1100 NetType/WIFI Language/zh_CN',
            'Mozilla/5.0 (Linux; Android 7.1.1; MI 6 Build/NMF26X) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 Mobile Safari/537.36 Maxthon/3047',
            # 'Mozilla/5.0 (iPhone 84; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.0 MQQBrowser/7.8.0 Mobile/14G60 Safari/8536.25 MttCustomUA/2 QBWebViewType/1 WKType/1',
            'Mozilla/5.0 (Linux; U; Android 7.0; zh-cn; STF-AL00 Build/HUAWEISTF-AL00) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 Chrome/37.0.0.0 MQQBrowser/7.9 Mobile Safari/537.36',
            'Mozilla/5.0 (Linux; U; Android 6.0.1; zh-CN; SM-C7000 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/40.0.2214.89 UCBrowser/11.6.2.948 Mobile Safari/537.36',
            'Mozilla/5.0 (Linux; Android 7.0; STF-AL10 Build/HUAWEISTF-AL10; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.49 Mobile MQQBrowser/6.2 TBS/043508 Safari/537.36 V1_AND_SQ_7.2.0_730_YYB_D QQ/7.2.0.3270 NetType/4G WebP/0.3.0 Pixel/1080']

        headers = {"User-Agent": random.choice(my_headers), 'Referer': "http://news.163.com/latest/"}  # 默认值

        try:
            rawhtml = requests.get(requestURL, headers=headers, allow_redirects=False,
                                   timeout=30)  # 一般提取文本的话，那就用text，如果是文件就content
            rawhtml.encoding = "GBK"  ##gbk>gb2312   使用这种方式尚且还有乱码的情况，部分乱码，那就是gbk可以修复
            # print(chardet.detect(rawhtml.content)['encoding'])
            if rawhtml.status_code == 504:
                print(504)
                return
            # print(rawhtml.url)
            print("状态码" + str(rawhtml.status_code))
            # print("页面的读取结果为")
            html = rawhtml.text

            result10=[]
            if html.find('"news":')!=-1:
                rawjsonString = html.split('"news":')[1].replace("};","")
                jsDic = eval("("+rawjsonString+")")
                for i in jsDic:
                    if len(i)!=0:
                        for content in i:
                            if content['p'].split(" ")[0]==date:   #这个是今天的
                                url = content['l']
                                if url.find("photoview")==-1:            #不是图片的写入这儿
                                    result10.append(content['l'])
                                else:
                                    pass

                # print("插入了"+str(len(result10)))
                print(result10)
                # self.saveListToMysql(result10, date)  # todo  这儿做了注释，不写入数据库，方便进行测试/

                return result10          #这个是返回前一天的所有的url链接放在这儿，大概200条以内，又变少了啊
        except Exception as e:
            print(e)
            return   #返回为空
if __name__ == '__main__':
    # 腾讯的获得新闻列表的模块测试
    # tengxun_expend =TengxunExpend()
    # tengxun_expend.pageUrlMain()

    # 网易的获得新闻的列表的模块测试
    wangyi_expend =WangyiExpend()
    print(wangyi_expend.getRollUrlList())  # 默认都是获得昨天的新闻。


# -*- coding: utf-8 -*-
"""
Created on Thu Nov  1 01:08:54 2018

@author: admin
"""

def rsum(n):
    if n <= 1:
        return n
    else:
        return n + rsum(n-1)

num = int(input("Enter a number: "))
ttl=rsum(num)
print("The sum is",ttl)


'''
https://leetcode.com/problems/remove-element/
Given an array nums and a value val, remove all instances of that value in-place and return the new length.

Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

The order of elements can be changed. It doesn't matter what you leave beyond the new length.
'''

'''
Method below uses 2 pointers.
Time:O(n)
Space:O(1)
'''

class Solution(object):
    def removeElement(self, nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        i=0
        for j in range(len(nums)):
            if nums[j]!=val:
                nums[i]=nums[j]
                i += 1
        return i

class Solution(object):
    def removeElement(self, nums, val):
        i,j=0,len(nums)
        while i<j:
            if nums[i]==val:
                nums[i]=nums[j-1]
                j -= 1
            else:
                i += 1
        return j

'''
Method below doesn't use pointers
'''
class Solution(object):
    def removeElement(self, nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        while val in nums:
            nums.remove(val)
        return len(nums)


import sys
sys.stdin = open('삼성시의 버스 노선.txt')

T = int(input())
for test_case in range(1, T + 1):
    N = int(input())
    no_sun = [list(map(int, input().split())) for _ in range(N)]
    P = int(input())
    bus_stop = list()
    for i in range(P):
        bus_stop.append(int(input()))
    max_bus = max(bus_stop)
    temp_list = [0] * (5001)

    for row in range(N):
        for i in range(no_sun[row][0], no_sun[row][1] + 1):
            temp_list[i] += 1
    print('#{}'.format(test_case),end=' ')
    for i in bus_stop:
        if i == bus_stop[-1]:
            print(temp_list[i])
        else:
            print(temp_list[i], end= ' ')

삼성시의 버스 노선.py


x="witam serdecznie w ten piekny lutowy dzien"
def high(x):
    val=0
    highestValue=0
    highestValueWord=""
    alph="abcdefghijklmnopqrstuvwxyz"
    value=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]
    tab=x.split(" ")
    for i in tab:
        for j in i:
            val+=value[alph.index(j)]
            if val>highestValue:
                highestValue=val
                highestValueWord=i
    return highestValueWord

print(high(x))


import pygame

# Initialize Pygame
pygame.init()

# Set up the screen
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Moving Ball")
# icon = pygame.image.load(r'C:\Users\Batyrkhan\OneDrive\Рабочий стол\PYTHON GITHUB\TSIS_7\ball movement\Fasticon-Angry-Birds-Red-bird.32.png')
# pygame.display.set_icon(icon)
# Set up the ball
ball_radius = 25
ball_pos_x = screen_width // 2
ball_pos_y = screen_height // 2
ball_color = (255, 0, 0)  # Red
ballX_change = 0
ballY_change = 0

# Main game loop
running = True
while running:
    # Event handling
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        # if keystroke is pressed check whether its right or left
        if event.type ==pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                ballX_change = -0.3
            if event.key == pygame.K_RIGHT:
                ballX_change = 0.3
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                ballX_change = 0

        if event.type ==pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                ballY_change = -0.3
            if event.key == pygame.K_DOWN:
                ballY_change = 0.3
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                ballY_change = 0

    ball_pos_x += ballX_change
    ball_pos_y += ballY_change

    if ball_pos_x <= 25:
        ball_pos_x = 25
    elif ball_pos_x >= 775:
        ball_pos_x = 775
    if ball_pos_y >= 572:
        ball_pos_y = 572
    elif ball_pos_y <= 25:
        ball_pos_y = 25

    # Fill the screen with white color
    screen.fill((255, 255, 255))

    # Draw the ball
    pygame.draw.circle(screen, ball_color, (ball_pos_x, ball_pos_y), ball_radius)

    # Update the screen
    pygame.display.flip()

# Quit Pygame
pygame.quit()


import numpy as np
import pandas as pd
import os
from sklearn.model_selection import train_test_split, GroupShuffleSplit

class Preprocessing:
    def form_time_sequences(self, data_df, cols, window_size=40, overlap_factor=2):
        """ Produce overlapping time-sequences from our data for use
            in a time-sequencing deep learning model, e.g. LSTM / CNN """
        # keep only desired columns
        lean_df = data_df.loc[:, cols].copy()
        output_data = []
        for i in range(0, lean_df.shape[0] - window_size,
                       int(window_size / overlap_factor)):
            output_data.append(lean_df.iloc[i : (i + window_size)])
        return np.stack(output_data)

    def get_class_trajectories(self, class_name, data_dir, col_names, window_size,
                               overlap_factor=2):
        """ Helper function for creating a dataset of sub-trajectories
            from the chosen class directory and higher-level data
            directory. Each sub-trajectory has a window size equal
            to the given window_size argument.
        """
        flt_filenames = [x for x in os.listdir(os.path.join(data_dir, class_name))
                    if x.endswith('.csv')]

        if 'est_z' in col_names:
            altitude = True
        else:
            altitude = False

        subtrajs = []
        labels = []
        flight_refs = []

        for filename in flt_filenames:
            flt_df = pd.read_csv(os.path.join(data_dir,
                                              class_name,
                                              filename))

            # if window size too large, skip flight
            if flt_df.shape[0] <= window_size + 1:
                continue

            # get sub-trajectories for this flight
            sub_trajs = self.form_time_sequences(flt_df, col_names,
                                            window_size,
                                            overlap_factor)

            # append to all of our sub-trajectories
            subtrajs.append(sub_trajs)

            # get original flight filename for reference
            original_ref = "_".join(filename.split('_')[:-1])

            # give each sub-traj the same filename reference
            flt_refs = np.array([original_ref for _
                                 in range(sub_trajs.shape[0])])
            flight_refs.append(flt_refs)

            # also add correct number of labels to align with sub-trajs
            sub_traj_labels = np.array([class_name for _
                                        in range(sub_trajs.shape[0])])
            labels.append(sub_traj_labels)

        # convert data into numpy arrays
        subtrajs = np.concatenate(subtrajs)
        labels = np.concatenate(labels)
        flight_refs = np.concatenate(flight_refs)
        trajs_std = subtrajs.copy()

        # get first x,y,z co-ordinates of each sub-traj
        n_rows = subtrajs.shape[0]
        x0 = subtrajs[:, 0, 0].reshape((n_rows, 1))
        y0 = subtrajs[:, 0, 1].reshape((n_rows, 1))
        if altitude:
            z0 = subtrajs[:, 0, 2].reshape((n_rows, 1))

        # centralise sub-trajectories to start at (0,0,0)
        trajs_std[:, :, 0] = subtrajs[:, :, 0] - x0
        trajs_std[:, :, 1] = subtrajs[:, :, 1] - y0
        if altitude:
            trajs_std[:, :, 2] = subtrajs[:, :, 2] - z0

        # re-order results into convenient order for processing later
        # (row, features, timestep)
        trajs_std = np.transpose(trajs_std, (0, 2, 1))

        return trajs_std, labels, flight_refs

    def OutliersRemoval(self, UAV_TYPE_IDX, X, y, flight_refs, ANOMALOUS_THRESHOLD = 11000):
        """Remove Outliers from the data in accordance with a user-defined threshold"""

        anomalous_mask = X[:,:UAV_TYPE_IDX,:].max(axis=(1,2))>ANOMALOUS_THRESHOLD
        print(flight_refs[anomalous_mask])

        X = X[~anomalous_mask]
        y = y[~anomalous_mask]
        flight_refs = flight_refs[~anomalous_mask]

        return X, y, flight_refs

    def Train_Val_Test_Split(self, X, y, flight_refs, random_state, n_splits = 1, test_size = 0.10, val_size = 0.20):
        """ Creates training, validation and testing datasets"""

        train_test_splitter = GroupShuffleSplit(n_splits = n_splits, test_size = test_size, random_state = random_state)
        train_test_split = train_test_splitter.split(X, y, groups = flight_refs)
        train_idx, test_idx = next(train_test_split)

        X_temp = X[train_idx]
        y_temp = y[train_idx]
        flight_refs_temp = flight_refs[train_idx]
        X_test = X[test_idx]
        y_test = y[test_idx]

        # split again to get validation data (20% of remaining training data)
        train_val_splitter = GroupShuffleSplit(n_splits = n_splits, test_size = val_size, random_state = random_state)
        train_val_split = train_val_splitter.split(X_temp, y_temp, groups = flight_refs_temp)
        train_idx, val_idx = next(train_val_split)

        X_train = X_temp[train_idx]
        y_train = y_temp[train_idx]
        X_val = X_temp[val_idx]
        y_val = y_temp[val_idx]

        train_flight_refs = flight_refs_temp[train_idx]
        val_flight_refs = flight_refs_temp[val_idx]
        test_flight_refs = flight_refs[test_idx]

        print(X_train.shape, y_train.shape, X_test.shape,
              y_test.shape, X_val.shape, y_val.shape,
             np.unique(train_flight_refs).shape, np.unique(val_flight_refs).shape, np.unique(test_flight_refs).shape)
        return X_train, y_train, X_test, y_test, X_val, y_val, train_flight_refs, val_flight_refs, test_flight_refs

    def time_seqs_with_lookahead(self, data_df, cols, window_size=20,
                                  overlap_factor=10, lookahead=20):
        """ Produce overlapping time-sequences from our data for use
            in a time-sequencing deep learning model, e.g. LSTM / CNN """
        # keep only desired columns
        lean_df = data_df.loc[:, cols].copy()

        max_idx = lean_df.shape[0]
        subtrajs = []
        lookahead_seqs = []

        for i in range(0, max_idx - (lookahead + window_size),
                       int(max(1, window_size / overlap_factor))):
            # append subtrajectory
            subtrajs.append(lean_df.iloc[i : (i + window_size)])

            # also get sequence ahead of current sub-trajectory
            lookahead_seqs.append(lean_df.iloc[i + window_size :
                                               (i + window_size + lookahead)])

        return np.stack(subtrajs), np.stack(lookahead_seqs)

    def get_min_max_differences(self, sub_traj, lookahead_traj):
        """ Determine the minimum and maximum difference between
        the las timestep on the given sub-trajectory and the
        co-ordinates in the lookahead trajectory """
        # get first timestep co-ordinates (x,y,z) for lookahead
        last_timestep = sub_traj[:, -1, :3]

        # get maximum bounds for lookahead seq
        max_lookaheads = lookahead_traj[:, :, :3].max(axis=1)
        min_lookaheads = lookahead_traj[:, :, :3].min(axis=1)

        # find maximum bounds relative to last input timestep
        max_diffs = max_lookaheads - last_timestep
        min_diffs = min_lookaheads - last_timestep

        # combine into one set of labels (xmin,ymin,zmin,xmax,ymax,zmax)
        min_max_diffs = np.hstack([min_diffs, max_diffs])

        return min_max_diffs

    def get_class_reg_trajectories(self, class_name, data_dir,
                                   col_names, window_size=10,
                                   overlap_factor=5, lookahead=30,
                                   sample_times=[10, 20, 30, 40]):
        """ Helper function for creating a dataset of sub-trajectories
            from the chosen class directory and higher-level data
            directory for maximum / minimum bounds regression.

            Labels are created from the lookahead sequences corresponding
            to maximum bounds (in 3D) for each of the given time intervals
            in the argument (sample_times)
        """
        flt_filenames = [x for x in os.listdir(os.path.join(data_dir, class_name))
                         if x.endswith('.csv')]

        all_subtrajs = []
        all_lookaheads = []
        flight_refs = []

        for filename in flt_filenames:
            flt_df = pd.read_csv(os.path.join(data_dir,
                                              class_name,
                                              filename))

            # if window size too large, skip flight
            if flt_df.shape[0] <= window_size + lookahead + 1:
                continue

            # add intent type to data
            flt_df['uav_intent'] = class_name

            # get sub-trajectories for this flight
            sub_trajs, lookaheads = self.time_seqs_with_lookahead(flt_df, col_names,
                                                                  window_size,
                                                                  overlap_factor,
                                                                  lookahead)

            # append to all of our sub-trajectories & lookaheads
            all_subtrajs.append(sub_trajs)
            all_lookaheads.append(lookaheads)

            # get original flight filename for reference
            original_ref = "_".join(filename.split('_')[:-1])

            # give each sub-traj the same filename reference
            flt_refs = np.array([original_ref for _
                                 in range(sub_trajs.shape[0])])
            flight_refs.append(flt_refs)

        # convert data into numpy arrays
        all_subtrajs = np.concatenate(all_subtrajs)
        all_lookaheads = np.concatenate(all_lookaheads)
        flight_refs = np.concatenate(flight_refs)

        # standardise all sub-trajs to start at (0,0,0)
        trajs_std = all_subtrajs.copy()
        lookahead_std = all_lookaheads.copy()

        # get first x,y,z co-ordinates of each sub-traj
        n_rows = all_subtrajs.shape[0]
        x0 = all_subtrajs[:, 0, 0].reshape((n_rows, 1))
        y0 = all_subtrajs[:, 0, 1].reshape((n_rows, 1))
        z0 = all_subtrajs[:, 0, 2].reshape((n_rows, 1))

        # centralise sub-trajectories to start at (0,0,0)
        trajs_std[:, :, 0] = all_subtrajs[:, :, 0] - x0
        trajs_std[:, :, 1] = all_subtrajs[:, :, 1] - y0
        trajs_std[:, :, 2] = all_subtrajs[:, :, 2] - z0

        # also re-centre lookahead trajectories using above translations
        lookahead_std[:, :, 0] = all_lookaheads[:, :, 0] - x0
        lookahead_std[:, :, 1] = all_lookaheads[:, :, 1] - y0
        lookahead_std[:, :, 2] = all_lookaheads[:, :, 2] - z0

        # get min/max bound labels for each sample time
        min_max_labels = []
        for sample_time in sample_times:
            sample_min_maxes = self.get_min_max_differences(trajs_std,
                                                            lookahead_std[:, :sample_time, :])
            min_max_labels.append(sample_min_maxes)

        # horizontally stack labels into array of labels for each input
        min_max_labels = np.hstack(min_max_labels)

        # re-order results into more convenient order:
        # (row, features, timestep)
        trajs_std = np.transpose(trajs_std, (0, 2, 1))
        lookahead_std = np.transpose(lookahead_std, (0, 2, 1))

        return trajs_std, lookahead_std, min_max_labels, flight_refs

    def DataSplitter(self, X, y, y_lookaheads, flight_refs,
                     val_size = 0.20, test_size = 0.10,
                     n_splits = 1, random_state = 18):
        """Creates training, validation, and testing datasets for
        the high-level intent regression models"""
        train_test_splitter = GroupShuffleSplit(test_size = test_size, n_splits = 1, random_state = random_state )
        train_test_split = train_test_splitter.split(X, y, groups=flight_refs)
        train_idx, test_idx = next(train_test_split)

        X_temp = X[train_idx].copy()
        y_temp = y[train_idx].copy()
        y_temp_traj = y_lookaheads[train_idx].copy()
        flight_refs_temp = flight_refs[train_idx].copy()
        X_test = X[test_idx].copy()
        y_test = y[test_idx].copy()
        y_test_traj = y_lookaheads[test_idx].copy()
        y_test_refs = flight_refs[test_idx].copy()

        # split again to get validation data (val_size of remaining training data)
        train_val_splitter = GroupShuffleSplit(test_size = val_size, n_splits = 1, random_state = random_state)
        train_val_split = train_val_splitter.split(X_temp, y_temp, groups=flight_refs_temp)
        train_idx, val_idx = next(train_val_split)

        X_train = X_temp[train_idx].copy()
        y_train = y_temp[train_idx].copy()
        y_train_traj = y_temp_traj[train_idx].copy()
        y_train_refs = flight_refs_temp[train_idx].copy()

        X_val = X_temp[val_idx].copy()
        y_val = y_temp[val_idx].copy()
        y_val_traj = y_temp_traj[val_idx].copy()
        y_val_refs = flight_refs_temp[val_idx].copy()

        print(X_train.shape, y_train.shape, y_train_traj.shape)
        print(X_val.shape, y_val.shape, y_val_traj.shape)
        print(X_test.shape, y_test.shape, y_test_traj.shape)
        return (X_train, y_train, y_train_traj,
                X_val, y_val, y_val_traj,
                X_test, y_test, y_test_traj)


#Definicja klasy
class Krzeslo(object):

    #konstruktor klasy, dzięki któremu możemy utworzyć obiekt o odpowiednich atrybutach
    #jest to metoda double under score która wykonuje się automatycznie podczas wywołania konstrukcji: NazwaKlasy()
    def __init__(self, nazwa='Wing', ilosc_nog=4, material='sklejka', kolor='jasny', cena_netto=20, marza=10):
        self.ilosc_nog = ilosc_nog
        self.ilosc_podlokietnikow = 0
        self.oparcie = True
        self.wymiary = (80,40,40)
        self.producent = 'Bodzio'

        self.nazwa = nazwa
        self.material = material
        self.kolor = kolor
        self.cena_netto = cena_netto

        self.marza = marza

        self.cena_do_sprzedazy = None

    #metoda obiektu do pobierania informajcji na podstawie atrybutóœ
    def cena_sprzedazy(self):
        self.cena_do_sprzedazy = self.cena_netto * (1 + self.marza/100)

        return self.cena_do_sprzedazy

    def cena_brutto(self):
        return self.cena_sprzedazy() * 1.23

    def cena_brutto_euro(self):
        return self.cena_sprzedazy() * 4.30

    #przeciążanie znaku <
    def __lt__(self, other):
        if self.ilosc_nog < other.ilosc_nog:
            print("{} jest bardziej stabilny".format(other.nazwa))
        #ciało funkcji

    #definicja metody która będzie wykonana gdy na obiekcie użyjemy metody len()
    def __len__(self):
        return self.ilosc_nog

    #definicja metody która będzie wykonana gdy na obiekcie użyjemy metody len()
    def __add__(self, other):
        return self.ilosc_nog + other.ilosc_nog

    # definicja metody która będzie wykonana gdy na obiekcie użyjemy metody print()
    def __str__(self):
        return "jestem {} i mam {} nog".format(self.nazwa, self.ilosc_nog)

    def wyswietl(self, lang='pl'):
        if (lang == 'en'):
            return "I'm {} and I have {} legs".format(self.nazwa, self.ilosc_nog)
        elif (lang == 'pl'):
            return "Jestem {} i mam {} nog".format(self.nazwa, self.ilosc_nog)
        else:
            print('WARNNIG: Language "{}" not suported :)'. format(lang))
            return "Jestem {} i mam {} nog".format(self.nazwa, self.ilosc_nog)

#tworzenie obiektów (w tym momencie wywołuje się metoda __init__())
obiekt_1 = Krzeslo("Wing", 4)
#odpowiednik (którego nie używamy :)) wywołania
#obiekt_1 = Krzeslo.__init__("Wing", 4)

obiekt_2 = Krzeslo("Better Wing", 8)

print("{:*^80}".format(" Atrybuty i metody "))

#pobieranie atrybutu obiektu
print(obiekt_2.cena_do_sprzedazy)
#wywałonie metody obiektu
obiekt_2.cena_sprzedazy()
print(obiekt_2.cena_do_sprzedazy)

print("{:*^80}".format(" Przeciążanie metod "))

obiekt_1 < obiekt_2
## Better Wing jest bardziej stabilny

#dodawanie (magiczne wywołanie metody __add__())
print(obiekt_1 + obiekt_2)

#lub
print(obiekt_1.__add__(obiekt_2))

print("{:*^80}".format(" Sposoby na tekstową reprezentację obiektów "))

print(obiekt_2)
print("jestem {} i mam {} nog".format(obiekt_2.nazwa, obiekt_2.ilosc_nog)) #najmniej poprawny :)
print("-" * 40)
print(obiekt_2.wyswietl('pl')) #definiowane różnych metod jest okej gdy potrzebujemy różnych form wyświetlenia, albo parametryzacji
print(obiekt_2.wyswietl('en'))
print(obiekt_2.wyswietl('es'))

print("{:*^80}".format(" Metoda len() i __len__() "))

print(len(obiekt_1))
print(len("AAAAAA")) #string to też obiekt i też ma swoją definicję metody __len__()


import numpy as np

def predict_(theta, X):

	"""
	Description:
	Prediction of output using the hypothesis function (linear model).
	Args:
	theta: has to be a numpy.ndarray, a vector of dimension (number of
	features + 1, 1).
	X: has to be a numpy.ndarray, a matrix of dimension (number of
	training examples, number of features).
	Returns:
	pred: numpy.ndarray, a vector of dimension (number of the training
	examples,1).
	None if X does not match the dimension of theta.
	Raises:
	This function should not raise any Exception.
	"""

	if theta.ndim != 2 or X.ndim != 2 or theta.shape[1] != 1 or X.shape[1] + 1 != theta.shape[0]:
		print("Incompatible dimension match between X and theta.")
		return None
	X = np.insert(X, 0, 1., axis=1)
	return X.dot(theta)

X1 = np.array([[0.], [1.], [2.], [3.], [4.]])
theta1 = np.array([[2.], [4.]])
print(predict_(theta1, X1))
X2 = np.array([[1], [2], [3], [5], [8]])
theta2 = np.array([[2.]])
print(predict_(theta2, X2))
X3 = np.array([[0.2, 2., 20.], [0.4, 4., 40.], [0.6, 6., 60.], [0.8, 8.,
80.]])
theta3 = np.array([[0.05], [1.], [1.], [1.]])
print(predict_(theta3, X3))


from pytz import utc
from datetime import datetime

from django.utils import timezone
from django.utils.timezone import utc
from rest_framework import serializers

GMT_FORMAT = '%a, %d %b %Y %H:%M:%S GMT'

def time_to_gmt(value):
    """
    :param value: datetime()
    :return:
        GMT time string
    """
    try:
        return serializers.DateTimeField(format=GMT_FORMAT, default_timezone=utc).to_representation(value)
    except Exception as e:
        return ''

def datetime_from_gmt(value):
    """
    :param value: gmt格式时间字符串
    :return:
        datetime() or None
    """
    try:
        t = datetime.strptime(value, GMT_FORMAT)
        return t.replace(tzinfo=utc)
    except Exception as e:
        return None

def time_to_local_naive_by_utc(value=None):
    '''
    时间转本地时间,如果无时区信息默认按utc时间

    :param value: datetime对象
    :return: datetime对象
    '''
    if value is None:
        value = timezone.now()

    # 无时区信息按UTC
    if timezone.is_naive(value):
        value = value.replace(tzinfo=utc)

    return timezone.localtime(value)

def to_localtime_string_naive_by_utc(value, fmt="%Y-%m-%d %H:%M:%S"):
    '''
    时间转本地时间字符串,如果无时区信息默认按utc时间

    :param value: datetime对象
    :param fmt: 时间格式字符串
    :return: 错误返回空字符串
    '''
    try:
        time = time_to_local_naive_by_utc(value).strftime(fmt)  # 本地时区时间
    except:
        time = ''
    return time

def to_django_timezone(value):
    """
    转换datetime到django设置的当前时区

    :return:
        若django未设置时区， 返回不带时区的datetime
        若django设置时区， 返回带时区的datetime
        如转换错误，返回原datetime
    """
    ctz = timezone.get_current_timezone()

    if ctz is not None:
        if timezone.is_aware(value):
            try:
                return value.astimezone(ctz)
            except OverflowError as e:
                return value
        try:
            return timezone.make_aware(value, ctz)
        except ValueError as e:
            return value
    elif (ctz is None) and timezone.is_aware(value):
        return timezone.make_naive(value, utc)
    return value


########################################################################
# Operators Beginner
########################################################################

    # Beginner Question 1
    # Get two numbers from the user and print the sum
    # make sure you get the right kind of data by
    # using float(input()) or float(variable)

y = float(input("What is the first number: "))
z = float(input("What is the second number: "))

x = y + z

print(f"{x} is the sum of {y} and {z}")

########################################################################
# Operators Intermediate
########################################################################

    # Intermediate Question 1
    # Ask user for the gas price (float), how many gallons they bought(float),
    # how many gallons they have(float) and aproximate gas mileage (int)
    # display how much money they spent, and how far they can travel.
    # travel distance = total gallons of gas * gas mileage

gas_price = float(input("What is the gas price: "))
gallons_purchased = float(input("How many gallons of gas did you purchase: "))
current_gallons = float(input("How many gallons do you have currently: "))
gas_mileage = int(input("What is your gas mileage to the closest mile: "))

amount_spent = gas_price * gallons_purchased
distance_can_travel = (gallons_purchased + current_gallons) * gas_mileage

print(f"Amount you spent: {amount_spent:.2f}")
print(f"distance you can travel: {distance_can_travel:.2f}")

########################################################################
# Operators Advanced check WEEK 07 for how to make for loops
########################################################################

    # Advanced Question 1
    # Use a for loop to calculate any factorial
    # factorial:
    # 10! == 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 == 3628800
    ####################################################################

fact = 1
user_num = int(input("What integer would you like the factorial of: "))

for i in range(1, user_num + 1):
    fact *= i

print(f"The factorial of {user_num} is {fact}")

#################################################################
# DEBUG: Fix the code
#################################################################

    # DEBUG Question 1
    # There are 3 errors
    # Expected output: My number is: 10
    ################################

num1 = "4"
num2 = "6"
Print(f"My number is: {num1 + num2}")

#################################################################
# DEBUG: Fix the code
#################################################################

    # DEBUG Question 1
    # There are 3 errors
    # Expected output: My number is: 10
    ################################

#Solution#
# The numbers were being stored as strings,
# so this means that the + put the two strings
# together instead of adding the numbers
num1 = 4
num2 = 6

# print should not be capitalized
print(f"My number is: {num1 + num2}")


def solve(arr):
    l = len(arr)
    T = [1] * l
    for i in range(1, l):
        M = 0
        for k in range(i):
            if arr[i] > arr[k]:
                M = max(M, T[k])
        T[i] += M
    print(T)
    return max(T)

arr = [3, 10, 2, 1, 20]
# arr = [10, 9, 2, 5, 3, 7, 101, 18]
print(solve(arr))