#!/usr/bin/env python
'''
Lê Đức Dũng, Phạm Nhật Hải, Đồng Đan Hoài
Mancala AI Bot
	Link tham thảo :https://github.com/138paulmiller/Mancala-AI-Bot (Mã nguồn)
	                https://www.mathplayground.com/mancala.html
					Target :
'''
import multiprocessing
import random
import sys # used to catch interrupts

# use these variables for players to prevent error checking on board
DEBUG = True

class Board:
	def __init__(self, other=None):
		if other: #make copy
			self.board = [4,4,4,4,4,4,4,4,4,4,4,4]
			for i in range(0, len(other.board)):
				self.board[i] = other.board[i]
			self.bowl = [other.bowl[0], other.bowl[1]]
			self.move_num = other.move_num
		else:
			# player 0's side of board is board[0] and bowl[0]
			# Thiết lập bàn chơi:
			# Mỗi bên có 6 slot(mỗi slot có 6 pieces) và 2 bowl(dùng để tính điểm player)
			self.board = [4,4,4,4,4,4,4,4,4,4,4,4]
			self.bowl = [0,0]
			self.move_num = 0
 #sân chơi của 1  và 2 :D

	def move(self, player, slot): #<Hoài_Done>
		# rải đá mỗi ô 1 viên đến cuối cùng vẫn tiếp tục khi
		# nó đi bth , bỏ qua ô quan của người khác
		# viên đá cuối ở trong ô quan của bản thân, tiếp tục lượt chơi của mình
		# slot (0, 5), player (0,1)
		slot = slot + (player)*6; #định hình lại lĩnh vực của người chơi
		pieces = self.board[slot] #số đá
		self.board[slot] = 0 #khi mình cầm số đá tại ô slot

		###
		next_player = player
		while pieces > 0:
			slot = (slot+1)%12 #rải đến ô bao nhiêu
			# đối với ô quan của người chơi
			if slot == (player+1)*6%12:	# vị trí ô quan
				self.bowl[player]+=1
				next_player = player
				pieces -= 1
			 # drop piece in players bowl
			# if pieces, continue dropping in slots
			if pieces > 0:
				# cộng thêm piece vào slot
				self.board[slot]+=1
				next_player = (player+1)%2 # next player
			pieces-=1
			# if no more pieces, and on player side, add those pieces if >1(just added)
			# Nếu không còn đá, và trên sân người chơi, và trong ô đó không có đá thì sẽ ăn điểm ô đối diện
			if pieces == 0 and slot < (player+1)*6 and slot > (player)*6 and self.board[slot] == 1:
				slot = 11 - slot
				if self.board[slot] > 0:
					self.bowl[player] = self.bowl[player] + self.board[slot]
					self.board[slot] = 0
		self.move_num += 1
		return next_player

	def get_score(self, player):
		return self.bowl[player]	# số 	đá trong ô quan

	def check_move(self, player, move):
		return ( move >= 0 and move <= 6) and  0 != self.board[player*6+move]
		#check
	def get_pieces(self, player):
		# điểm điểm đá
		pieces = 0
		for i in range(0, 6):
			pieces += self.board[player*6+i]
		return pieces

	def has_move(self, player): #< Hải >
		#nếu mà người chơi không đi được nữa thì
		i = 0
		while i < 6 and  self.board[(player)*6+i] == 0:
			i+=1
		# đến cuối cùng thì số đá ko = 0
		return i != 6

	def game_over(self):
		# game kết thúc :D  khi và chỉ khi  2 ô quan có tổng = 48  (4*6 + 4*6)
		return (self.bowl[0] + self.bowl[1]) == 48

	def __repr__(self): #chỉ là hiển lại cho người chơi coi Dũng
		layout = '--------------'+ str(self.move_num) + '---------------\n'
		layout += 'P2:' + str(self.bowl[1]) + '      6 <-- 1   |\n       |'
		# show in reverse for player 1
		for p in reversed(self.board[6:14]):
			layout += str(p) + ' '
		layout += '|                    \n\n       |'
		for p in self.board[0:6]:
			layout += str(p) + ' '
		layout += '|\n       |  1 --> 6      P1: ' + str(self.bowl[0]) + '\n--------------------------------'
		return layout

class AI:
	def __init__(self, player, lookahead, relative_score= False, horde=False, relative_horde=False):
		self.player = player
		# other player to opponent
		self.opponent = (player+1)%2 #đối thủ
		self.search_count = 0 # is not locked, does not update in parallel move
		self.lookahead = lookahead
		self.board = None
		self.horde = horde #đánh giá số đá của bot
		self.relative_score = relative_score
		self.relative_horde = relative_horde #đánh giá đối thử

	def eval_heuristic(self, board): #truy vết (#Dũng_done )
		score =  board.get_score(self.player)
		pieces = 0
		if self.horde:
			if self.relative_horde:
				pieces = (pieces - board.get_pieces(self.opponent))
			else:
				pieces = board.get_pieces(self.player)
		if self.relative_score:
			score = (score - board.get_score(self.opponent))
		return score + pieces

	def alphabeta(self, board, alpha, beta, player, depth):
		value = 0
		# Lỗi : nó không đúng khi phân luồng, xâu chuỗi và chỉ hoạt động khi di chuyển nối tiếp
		self.search_count += 1
		# xét hết không gian trạng thái để tìm được hướng đi tốt nhất
		if board.game_over() or depth == 0:
			value = self.eval_heuristic(board)
		elif player == self.player:
			cut = False
			value = -48
			i = 0
			while i < 6 and not cut:
				board_copy = Board(board)
				if board_copy.check_move(self.player, i):
					next_player = board_copy.move(self.player, i)
					value = max(value, self.alphabeta(board_copy, alpha, beta, next_player, depth-1))
					alpha  = max(value, alpha)
					if alpha >= beta:
						cut = True
				else:
					#ko di chuyển
					alpha = -48
				i+=1
		else: # về phía đối thủ
			cut = False
			value = 48
			i = 0
			#đối với mỗi nước đi của đối thủ,kiểm tra xem nó có hợp lệ không, nếu có thì lấy giá trị của nước đi có thể tiếp theo
			while i < 6 and not cut:
				board_copy = Board(board)
				# nếu đó là 1 nước đi oke
				if board_copy.check_move(self.opponent, i):
					next_player = board_copy.move(self.opponent, i)
					value = min(value, self.alphabeta(board_copy, alpha, beta, next_player, depth-1))
					beta  = min(value, beta)
					if alpha >= beta:
						cut = True
				else: #nó không di chuyển
					beta = 48
				i+=1
		return value

	def get_move_score(self, move): #<Dũng>
		value = -50
		board_copy = Board(self.board)
		next_player = self.player
		# repeats are prioritized by increasing score
		while next_player == self.player and board_copy.check_move(self.player, move):
			next_player = board_copy.move(self.player, move)
			#nếu người chơi tiếp theo không có nước đi, hãy đổi sang người chơi khác
			if not board_copy.has_move(self.player):
				next_player = (next_player+1)%2
			value = max(value, self.alphabeta(board_copy, -48, 48, next_player, self.lookahead))
		return value

	def move_parallel(self, board):
		move = 0
		#print('AI Thinking...')
		try:
			pool = multiprocessing.Pool(multiprocessing.cpu_count())
			move = 0
			self.board = board
			# map all possible plays to unpack
			scores = pool.map_async(unpack_get_move_score, [(self,0), (self,1), (self,2), (self,3), (self,4), (self,5)]).get(60)
			scores = list(scores)
			# allow keyboard intteruptions
			for i in range(0, 6): # ignore first move, already chosen
				if scores[move] < scores[i]:
					move = i
		except KeyboardInterrupt:
			pool.terminate()
			sys.exit(-1)
		finally:
			pool.close()
		pool.join()
		return move

	# Simple NON-parallel approach <hải>
	def move_serial(self, board):
		alpha = -48
		beta = 48
		value = alpha
		i = move = 0
		# foreach move possible
		cut = False
		self.search_count = 0
		print ('AI Thinking...')
		# for each move, check if its valid, if so get the value of the next possible move
		while i < 6 and not cut:
			board_copy = Board(board)
			# if i is a valid move, else ignore
			if board_copy.check_move(self.player, i):
				next_player = board_copy.move(self.player, i)
				# if the next player has no move, change to other player
				if not board_copy.has_move(self.player):
					next_player = (next_player+1)%2
				# get next max move
				value = max(value, self.alphabeta(board_copy, alpha, beta, next_player, self.lookahead))
				if alpha < value:
					alpha = value
					move = i
				if alpha > beta:
					cut = True
			i+=1
		print ('Searched ', self.search_count, ' possibilities' )
		return move

	def move(self, board, parallel):
		if parallel:
			return self.move_parallel(board)
		else:
			return self.move_serial(board)

#			 Helper functions
# upack the async map args , expecting (ai_obj, move)
def unpack_get_move_score(args):
	score = args[0].get_move_score(args[1])
	return score

def get_user_move(board, player): #<Dũng_done>
	#if DEBUG:
	#	return random.randint(0,5)
	valid = False
	move = 0
	while not valid:
		try:
			# get move input (1-6), offset to index (0-5)
			move = input('      	P1 pick ')
			move = int(move)-1
			while move < 0 or move > 5:
				print ('Chọn một số trong các số từ 1-6 ')
				move = int(	input('      	P1 pick '))-1
			valid = True
		except:
			if move == 'quit':
				valid = True
			else:
				print( 'chỉ chọn từ 1 đến 6 thôi')
				valid = False
	return move

def main():
	P1 = 0
	P2 = 1
	# multiprocess computaion
	parallel = True
	lookahead = 2 # Thiết lập độ sâu : tăng mức khó dễ ,....
	board = Board()
	# ai Player
	ai = AI(P2, lookahead)
	# thiết lập người chơi 2 đi đầu
	current_player = 1
	next = 0
	move = 0
	while not board.game_over() and move != 'quit':
		print (board)
		print ('\nP'+str(current_player+1) + '\'s Turn' )
		# nếu người chơi hiện tại di chuyển, else switch
		if board.has_move(current_player):
			# ko phải ai thì là lượt của bạn
			if current_player != ai.player:
				move = ''
				next = current_player
				while current_player == next and board.has_move(current_player) and move != 'quit':
					move = get_user_move(board, current_player)
					if not board.check_move(current_player, move) :
						print( 'No pieces', move	)
					if move != 'quit':
						next = board.move(current_player, move)
						print( board)
						print ('Play again!')
						print ('\nP'+str(current_player+1) )

			else:
				# ai turn
				move = ai.move(board, parallel)
				# get the move cho ai
				print ( '\tAI picked ', move+1	)
				next = board.move(ai.player, move)
				# trong khi thằng ai ko còn lượt chơi thì ....
				while ai.player == next and board.has_move(ai.player) and move != 'quit':
					print (board	)
					print ('\tAI Playing Again...')
					move = ai.move(board, parallel)
					print ('\tAI picked ', move+1	)
					next = board.move(ai.player, move)
			# set cho đứa tiếp theo chơi
			current_player = next
		else:
			print ('\n P'+str(current_player+1) + ' has no moves!')
			current_player = (current_player+1)%2

	# Khi game kết thúc
	if move != 'quit':
		print (' 		FINAL')
		print (board)
		p1_score = board.get_score(P1)
		p2_score = board.get_score(P2)
		if p1_score > p2_score:
			print ('Player 1 Wins!')
		elif p1_score < p2_score:
			print ('Player 2 Wins!')
		else:
			print ('It\'s a tie !')
	print ('Goodbye!')
if __name__ == '__main__':
	main()  # user interactive


from collections import namedtuple
from pdfreader import PageDoesNotExist, SimplePDFViewer

CandidateData = namedtuple('CandidateData', 'office district party candidate')

class PDFStringIterator:
    def __init__(self, strings):
        self._strings = strings
        self._strings_offset = 0

    def __iter__(self):
        while True:
            if not self.has_next():
                raise StopIteration
            yield next(self)

    def __next__(self):
        s = self.peek()
        self._strings_offset += 1
        return s

    def peek(self):
        return self._strings[self._strings_offset]

    def has_next(self):
        return self._strings_offset < len(self._strings)

class PDFPageIterator:
    def __init__(self, filename):
        self._pdf_viewer = None
        self._page_number = 0
        self._rendered = False
        if filename:
            self._pdf_viewer = SimplePDFViewer(open(filename, 'rb'))

    def __iter__(self):
        return self

    def __next__(self):
        try:
            self._go_to_next_pdf_page()
            return self
        except PageDoesNotExist as e:
            raise StopIteration(e)

    def get_page_number(self):
        return self._page_number

    def get_strings(self):
        if not self._rendered:
            self._pdf_viewer.render()
            self._rendered = True
        return self._pdf_viewer.canvas.strings

    def _go_to_next_pdf_page(self):
        if self._page_number != 0:
            self._pdf_viewer.next()
        self._page_number += 1
        self._rendered = False

class TableHeader:
    _congressional_keywords = None
    _party_map = None
    _subheader_to_candidate_mapping = None
    _raw_office_to_office_and_district_mapping = None

    def __init__(self, table_headers, raw_header_strings, party):
        self._party = party
        self._candidate_data = list(self._candidate_data_iter(table_headers))
        self._raw_header_strings = raw_header_strings

    def __iter__(self):
        return iter(self._candidate_data)

    def raw_header_strings(self):
        return self._raw_header_strings

    def get_party(self):
        return self._party

    def _candidate_data_iter(self, table_headers):
        for header, subheaders in table_headers:
            party, office, district = self._parse_column_header(*header)
            if party:
                self._party = party
            for subheader in subheaders:
                candidate = self._subheader_to_candidate_mapping.get(subheader, subheader)
                yield CandidateData(office.title(), district, self._party, candidate.title())

    def _parse_column_header(self, office, extra=''):
        district = ''
        party = ''
        if extra in self._party_map:
            party = self._party_map[extra]
        else:
            office = ' '.join([office, extra])
        office = office.strip()
        if office in self._raw_office_to_office_and_district_mapping:
            office, district = self._raw_office_to_office_and_district_mapping[office]
        return party, office.strip(), district

class TableHeaderParser:
    _first_subheader_string = None
    _terminal_header_string = None
    _terminal_subheader_strings = None
    _writein_substring = None
    _valid_subheaders = None
    _table_header_clazz = None

    def __init__(self, string_iterator, continued_table_header, continued_table_party):
        self._string_iterator = string_iterator
        self._continued_table_header = continued_table_header
        self._continued_table_party = continued_table_party
        self._table_headers = []  # list of strings with their subheaders
        self._table_header = None  # class for managing table headers
        # temporary parsing management fields
        self._in_subheader_block = False
        self._active_header = []
        self._active_subheader = []
        self._active_subheaders = []

    def get_header(self):
        if not self._table_header:
            if self._continued_table_header:
                self._parse_continued_table_header()
            else:
                self._parse()
        return self._table_header

    def get_party(self):
        return self._table_header.get_party()

    def _parse_continued_table_header(self):
        expected_header_strings = self._continued_table_header.raw_header_strings()
        actual_header_strings = [next(self._string_iterator) for _ in range(len(expected_header_strings))]
        assert (expected_header_strings == actual_header_strings)
        self._table_header = self._continued_table_header

    def _parse(self):
        raw_header_strings = []
        while not self._table_header_is_done():
            s = next(self._string_iterator)
            raw_header_strings.append(s)
            self._process_string(s)
        if self._active_subheaders:
            assert(not self._active_subheader)
            self._finalize_header_block()
        self._table_header = self._table_header_clazz(self._table_headers, raw_header_strings,
                                                      self._continued_table_party)
        next(self._string_iterator)  # skip terminal string

    def _table_header_is_done(self):
        return self._string_iterator.peek() == self._terminal_header_string

    def _process_string(self, s):
        self._process_start_subheader_state(s)
        if not self._in_subheader_block:
            self._process_header_string(s)
        else:
            self._process_subheader_string(s)

    def _process_header_string(self, s):
        self._active_header.append(s)

    def _process_subheader_string(self, s):
        if s == self._writein_substring and not self._active_subheader:
            self._active_subheaders[-1] += ' ' + self._writein_substring
        else:
            self._active_subheader.append(s)
            self._process_active_subheader()
            self._process_end_subheader_state(s)

    def _process_active_subheader(self):
        active_subheader_string = ' '.join(self._active_subheader)
        if active_subheader_string in self._valid_subheaders:
            self._active_subheaders.append(active_subheader_string)
            self._active_subheader = []

    def _process_start_subheader_state(self, s):
        if s == self._first_subheader_string:
            self._in_subheader_block = True
            if self._active_subheaders:
                self._finalize_header_block()

    def _process_end_subheader_state(self, s):
        if s in self._terminal_subheader_strings:
            self._in_subheader_block = False
            self._finalize_header_block()

    def _finalize_header_block(self):
        self._table_headers.append((self._active_header, self._active_subheaders))
        self._active_header = []
        self._active_subheaders = []

class TableBodyParser:
    TURNOUT_OFFICE = 'Turnout'
    SKIPPED_TURNOUT_SUBHEADERS = ('% Turnout', 'Blank')
    SKIPPED_CANDIDATE_SUBHEADERS = ('Registered Voters', 'Total Votes')

    def __init__(self, string_iterator, table_headers):
        self._string_iterator = string_iterator
        self._is_office_section_active = True
        self._table_headers = table_headers
        self._jurisdiction = None

    def __iter__(self):
        while self._string_iterator.has_next():
            self._jurisdiction = next(self._string_iterator)
            if self._jurisdiction == 'Total':
                self._is_office_section_active = False
            if self._is_office_section_active:
                yield from self.iterate_jurisdiction_fields()

    def iterate_jurisdiction_fields(self):
        raise NotImplementedError

    def is_office_section_active(self):
        return self._is_office_section_active

    @staticmethod
    def _is_turnout_header(candidate_data):
        return candidate_data.office == TableBodyParser.TURNOUT_OFFICE

    @staticmethod
    def _skipped_subheader(candidate_data):
        if TableBodyParser._is_turnout_header(candidate_data):
            return candidate_data.candidate in TableBodyParser.SKIPPED_TURNOUT_SUBHEADERS
        return candidate_data.candidate in TableBodyParser.SKIPPED_CANDIDATE_SUBHEADERS

    def _populate_jurisdiction_data(self, candidate_data_to_votes, candidate_data):
        if self._skipped_subheader(candidate_data):
            next(self._string_iterator)  # metadata field
        else:
            vote_count = next(self._string_iterator)
            vote_count = int(vote_count if vote_count != '-' else 0)
            if not self._is_turnout_header(candidate_data):
                next(self._string_iterator)  # vote percent
            else:
                # Registered Voters and Ballot Cast are treated as `office` instead of `candidate`
                candidate_data = CandidateData(candidate_data.candidate, '', '', '')
            candidate_data_to_votes[candidate_data].append(vote_count)

class PDFPageParser:
    _standard_header = None
    _table_header_parser = None
    _table_body_parser = None

    def __init__(self, page, continued_table_header, continued_party):
        strings = page.get_strings()
        string_iterator = PDFStringIterator(strings)
        self._validate_header(string_iterator, page.get_page_number())
        table_header_parser = self._table_header_parser(string_iterator, continued_table_header, continued_party)
        self._table_headers = table_header_parser.get_header()
        self._party = table_header_parser.get_party()
        self._table_body_parser = self._table_body_parser(string_iterator, self._table_headers)

    def __iter__(self):
        return iter(self._table_body_parser)

    def get_continued_table_header(self):
        if not self._table_body_parser.is_office_section_active():
            return None
        return self._table_headers

    def get_continued_party(self):
        return self._party

    def _validate_header(self, string_iterator, page_number):
        header = [next(string_iterator) for _ in range(len(self._standard_header))]
        page_number_string = next(string_iterator)
        assert(header == self._standard_header)
        assert(page_number_string.split('/')[0].split()[-1] == str(page_number))

def pdf_to_csv(pdf, csv_writer, pdf_page_parser_clazz):
    csv_writer.writeheader()
    previous_table_header = None
    previous_party = ''
    for page in pdf:
        print(f'processing page {page.get_page_number()}')
        pdf_page_parser = pdf_page_parser_clazz(page, previous_table_header, previous_party)
        for row in pdf_page_parser:
            csv_writer.writerow(row._asdict())
        previous_table_header = pdf_page_parser.get_continued_table_header()
        previous_party = pdf_page_parser.get_continued_party()


import os
import torch
import argparse
import numpy as np
import pandas as pd
from torch import nn
import torch
from gensim.models import word2vec
from torch import nn
import torch.optim as optim
import torch.nn.functional as F
from gensim.models import Word2Vec
from sklearn.model_selection import train_test_split
from torch.utils import data

from tensorflow import keras
from tensorflow.keras.models import Sequential
from tensorflow.keras import optimizers
from tensorflow.keras.layers import Embedding, Dense, Dropout, Activation, Flatten, LSTM, Bidirectional, LeakyReLU, GRU, BatchNormalization
from tensorflow.keras.callbacks import ReduceLROnPlateau, EarlyStopping, ModelCheckpoint, CSVLogger

def load_testing_data(path='testing_data.txt'):
    with open(path, 'r') as f:
        lines = f.readlines()

        X = ["".join(line.strip('\n').split(",")[1:]).strip() for line in lines[1:]]
        print(len(X))
        X = [sen.split(' ') for sen in X]
        print(len(X))
    return X

class Preprocess():
    def __init__(self, sentences, sen_len, w2v_path="w2v.model"):
        self.w2v_path = w2v_path
        self.sentences = sentences
        self.sen_len = sen_len
        self.idx2word = []
        self.word2idx = {}
        self.embedding_matrix = []
    def get_w2v_model(self):
        # 把之前訓練好的 word to vec 模型讀進來
        self.embedding = Word2Vec.load(self.w2v_path)
        self.embedding_dim = self.embedding.vector_size
    def add_embedding(self, word):
        # 把 word 加進 embedding，並賦予他一個隨機生成的 representation vector
        # word 只會是 "<PAD>" 或 "<UNK>"
        vector = torch.empty(1, self.embedding_dim)
        torch.nn.init.uniform_(vector)
        self.word2idx[word] = len(self.word2idx)
        self.idx2word.append(word)
        self.embedding_matrix = torch.cat([self.embedding_matrix, vector], 0)
    def make_embedding(self, load=True):
        print("Get embedding ...")
        # 取得訓練好的 Word2vec word embedding
        if load:
            print("loading word to vec model ...")
            self.get_w2v_model()
        else:
            raise NotImplementedError
        # 製作一個 word2idx 的 dictionary
        # 製作一個 idx2word 的 list
        # 製作一個 word2vector 的 list
        for i, word in enumerate(self.embedding.wv.vocab):
            print('get words #{}'.format(i+1), end='\r')
            #e.g. self.word2index['he'] = 1
            #e.g. self.index2word[1] = 'he'
            #e.g. self.vectors[1] = 'he' vector
            self.word2idx[word] = len(self.word2idx)
            self.idx2word.append(word)
            self.embedding_matrix.append(self.embedding[word])
        print('')
        self.embedding_matrix = torch.tensor(self.embedding_matrix)
        # 將 "<PAD>" 跟 "<UNK>" 加進 embedding 裡面
        self.add_embedding("<PAD>")
        self.add_embedding("<UNK>")
        print("total words: {}".format(len(self.embedding_matrix)))
        return self.embedding_matrix
    def pad_sequence(self, sentence):
        # 將每個句子變成一樣的長度
        if len(sentence) > self.sen_len:
            sentence = sentence[:self.sen_len]
        else:
            pad_len = self.sen_len - len(sentence)
            for _ in range(pad_len):
                sentence.append(self.word2idx["<PAD>"])
        assert len(sentence) == self.sen_len
        return sentence
    def sentence_word2idx(self):
        # 把句子裡面的字轉成相對應的 index
        sentence_list = []
        for i, sen in enumerate(self.sentences):
            print('sentence count #{}'.format(i+1), end='\r')
            sentence_idx = []
            for word in sen:
                if (word in self.word2idx.keys()):
                    sentence_idx.append(self.word2idx[word])
                else:
                    sentence_idx.append(self.word2idx["<UNK>"])
            # 將每個句子變成一樣的長度
            sentence_idx = self.pad_sequence(sentence_idx)
            sentence_list.append(sentence_idx)
        return torch.LongTensor(sentence_list)
    def labels_to_tensor(self, y):
        # 把 labels 轉成 tensor
        y = [int(label) for label in y]
        return torch.LongTensor(y)

# class TwitterDataset(data.Dataset):
#     """
#     Expected data shape like:(data_num, data_len)
#     Data can be a list of numpy array or a list of lists
#     input data shape : (data_num, seq_len, feature_dim)

#     __len__ will return the number of data
#     """
#     def __init__(self, X, y):
#         self.data = X
#         self.label = y
#     def __getitem__(self, idx):
#         if self.label is None: return self.data[idx]
#         return self.data[idx], self.label[idx]
#     def __len__(self):
#         return len(self.data)

# class LSTM_Net(nn.Module):
#     def __init__(self, embedding, embedding_dim, hidden_dim, num_layers, dropout=0.5, fix_embedding=True):
#         super(LSTM_Net, self).__init__()
#         # 製作 embedding layer
#         self.embedding = torch.nn.Embedding(embedding.size(0),embedding.size(1))
#         self.embedding.weight = torch.nn.Parameter(embedding)
#         # 是否將 embedding fix 住，如果 fix_embedding 為 False，在訓練過程中，embedding 也會跟著被訓練
#         self.embedding.weight.requires_grad = False if fix_embedding else True
#         self.embedding_dim = embedding.size(1)
#         self.hidden_dim = hidden_dim
#         self.num_layers = num_layers
#         self.dropout = dropout
#         self.lstm = nn.LSTM(embedding_dim, hidden_dim, num_layers=num_layers, batch_first=True , bidirectional= True)
#         self.classifier = nn.Sequential( nn.ReLU(),
#                                          nn.Dropout(dropout),
#                                          nn.Linear(hidden_dim*2 , 32),
#                                          nn.BatchNorm1d(32) ,
#                                          nn.ReLU(),
#                                          nn.Dropout(dropout),
#                                          nn.Linear(32, 4),
#                                          nn.BatchNorm1d(4) ,
#                                          nn.ReLU(),
#                                          nn.Dropout(dropout),
#                                          nn.Linear(4, 1),
#                                          nn.Sigmoid() )
#     def forward(self, inputs):
#         inputs = self.embedding(inputs)
#         x, _ = self.lstm(inputs, None)
#         # x 的 dimension (batch, seq_len, hidden_size)
#         # 取用 LSTM 最後一層的 hidden state
#         x = x[:, -1, :]
#         x = self.classifier(x)
#         return x

# def testing(batch_size, test_loader, model, device):
#     model.eval()     # 将 model 的模式设为 eval，这样 model 的参数就会被固定住
#     ret_output = []   # 返回的output
#     with torch.no_grad():
#         for i, inputs in enumerate(test_loader):
#             inputs = inputs.to(device, dtype=torch.long)
#             outputs = model(inputs)
#             outputs = outputs.squeeze()
#             outputs[outputs>=0.5] = 1 # 大于等于0.5为正面
#             outputs[outputs<0.5] = 0 # 小于0.5为负面
#             ret_output += outputs.int().tolist()

#     return ret_output

def keras_test(x_test):
    model = keras.models.load_model('keras_model.h5')
    y_predict = model.predict(x_test)

    return y_predict

def main():
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    print("loading testing data ...")
    test_x = load_testing_data('testing_data.txt')
    w2v_path = 'w2v_all.model'
    sen_len = 20
    fix_embedding = True # fix embedding during training
    batch_size = 128
    epoch = 5
    lr = 0.001

    # 对test_x作预处理
    preprocess = Preprocess(test_x, sen_len, w2v_path=w2v_path)
    embedding = preprocess.make_embedding(load=True)
    test_x = preprocess.sentence_word2idx()

    Y_preds_label = keras_test(test_x.numpy())
    print(Y_preds_label.shape)

    ans = []
    for i in range(Y_preds_label.shape[0]):
        sum = 0
        for j in range(Y_preds_label.shape[1]):
            sum += Y_preds_label[i][j]
        ans.append(sum / Y_preds_label.shape[1])

        if(ans[i]>=0.5):
            ans[i] = 1
        else:
            ans[i] = 0
    print(ans[:10])
    #test_dataset = TwitterDataset(X=test_x, y=None)
    #test_loader = torch.utils.data.DataLoader(test_dataset, batch_size = batch_size, shuffle = False, num_workers = 8)

    # # 读取模型
    # print('\nload model ...')
    # model = torch.load('ckpt.model')
    # # 测试模型
    # outputs = testing(batch_size, test_loader, model, device)

    # # 保存为 csv
    tmp = pd.DataFrame({"id":[str(i) for i in range(len(ans))],"label":ans})
    print("save csv ...")
    tmp.to_csv('predict.csv', index=False)
    print("Finish Predicting")

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


#!/usr/bin/env python3

import rospy
import selectors
import socket
from std_msgs.msg import String, Int64

pub = None
led = None

def accept(sock, mask):
    global sel
    conn, addr = sock.accept()
    print('accepted', addr)
    conn.setblocking(False)
    sel.register(conn, selectors.EVENT_READ, read)

def read(conn, mask):
    global pos, led, sel
    data = conn.recv(1000)
    if data:
        data = data.decode('ascii').split()
        led_state = int(data[-1])
        positions = data[:-1]
        pos.publish(' '.join(positions))
        led.publish(led_state)
    else:
        print('closing', conn)
        sel.unregister(conn)
        conn.close()

def talker():
    global pos, led, sel
    sel = selectors.DefaultSelector()
    pos = rospy.Publisher('positions', String, queue_size=10)
    led = rospy.Publisher('led', Int64, queue_size=10)
    rospy.init_node('tcp_server', anonymous=True)
    sock = socket.socket()
    sock.bind(('192.168.10.112', 11000))
    sock.listen(100)
    sock.setblocking(False)
    sel.register(sock, selectors.EVENT_READ, accept)
    while not rospy.is_shutdown():
        events = sel.select()
        for key, mask in events:
            callback = key.data
            callback(key.fileobj, mask)

if __name__ == '__main__':
    try:
        talker()
    except rospy.ROSInterruptException:
        pass


from django.urls import path
from .views import Register, delete, registercomp, deletecomp, update, loginfunc, logoutfunc

urlpatterns = [
    path('', Register.as_view(), name='register'),
    path('delete/<int:pk>', delete, name='delete'),
    path('register_comp/', registercomp, name='register_comp'),
    path('delete_comp/', deletecomp, name='delete_comp'),
    path('update/<int:pk>', update, name='update'),
    #path('login/', Login.as_view(), name='login'),
    path('login/', loginfunc, name='login'),
    path('logout/', logoutfunc, name='logout'),
    #path('signup/', signupfunc, name='signup'),
]


#from __future__ import print_function
import tensorflow as tf
import numpy as np
#import tqdm
from utils import dataset_input, data_prepro, batch_generator
from tensorflow.nn.rnn_cell import LSTMCell
from tensorflow.nn import bidirectional_dynamic_rnn as BiRNN
#from tensorflow.contrib.rnn import MultiRNNCell
from Embedding import Embedding
from Attention import Attention

#Data preprocess
seq_maxlen = 200

(train_data, y_train_all, test_data, y_test) = dataset_input()
x_train_list = data_prepro(train_data)
x_test_list = data_prepro(test_data)

#Embedding: each squence is a 300*5000 matrix
embed_size = 25
split_frac = 0.9

Embed = Embedding()
x_train_all = Embed.wordsToVec(x_train_list)
x_test = Embed.wordsToVec(x_test_list)

split_index = int(split_frac * len(x_train_all))
x_train, x_val = x_train_all[:split_index], x_train_all[split_index:]
y_train, y_val = y_train_all[:split_index], y_train_all[split_index:]

#Build the graph
tf.reset_default_graph()
##Input
with tf.name_scope('Input'):
    batch_ph = tf.placeholder(tf.float32, [None, seq_maxlen, embed_size], name='batch_placeholder')
    output_ph = tf.placeholder(tf.float32, [None, 6], name='output_placeholder')
    keep_prob_ph = tf.placeholder(tf.float32, name='keep_prob_placeholder')
    keep_prob_ph_rnn = tf.placeholder(tf.float32, name='keep_prob_placeholder_rnn')

'''
##Embedding
embed_size = 25

with tf.name_scope('Embedding Layer'):
    embedding = tf.Variable(tf.random_uniform([vocabulary_size, embed_size], -1, 1))
    embeded = tf.nn.embedding_lookup(embedding, batch_ph)
    tf.summary.histogram('embedding', embedding)
'''

##RNN layers
lstm_size = 32
lstm_layers = 3

output = batch_ph
for i in range(lstm_layers):
    with tf.variable_scope('BiLSTM_Layer_{}'.format(i)):
        lstm_fw = LSTMCell(lstm_size) #, initializer=tf.truncated_normal_initializer(-0.1, 0.1, seed=2)
        lstm_bw = LSTMCell(lstm_size)
        cell_fw = tf.contrib.rnn.DropoutWrapper(lstm_fw, output_keep_prob=keep_prob_ph_rnn)
        cell_bw = tf.contrib.rnn.DropoutWrapper(lstm_bw, output_keep_prob=keep_prob_ph_rnn)

        (output_fw, output_bw), final_state = BiRNN(cell_fw, cell_bw, output, dtype=tf.float32)
        output = tf.concat((output_fw, output_bw), 2)

##Attention + Dropout
with tf.variable_scope('BiLSTM_Layer_{}'.format(lstm_layers)):
    lstm_fw = LSTMCell(lstm_size)
    lstm_bw = LSTMCell(lstm_size)
    (output_fw, output_bw), final_state = BiRNN(lstm_fw, lstm_bw, output, dtype=tf.float32)
    output = tf.concat((output_fw, output_bw), 2)
    attention = Attention(output)
    drop = tf.nn.dropout(attention, keep_prob_ph)
    tf.summary.histogram('RNN_output', output)

##FC layers
with tf.name_scope('Fully_connected_Layers'):
    prediction = tf.contrib.layers.fully_connected(drop, 6, activation_fn=tf.nn.sigmoid)
    tf.summary.histogram('Prediction', prediction)

with tf.name_scope('Loss'):
    logistic_loss = tf.nn.sigmoid_cross_entropy_with_logits(labels=output_ph, logits=prediction)
    loss = tf.reduce_mean(logistic_loss)
    tf.summary.scalar('loss', loss)

optimizer = tf.train.AdamOptimizer(learning_rate=1e-2).minimize(loss)
#( ,6) == ( ,6)
correct_pred = tf.reduce_all(tf.equal(tf.cast(tf.round(prediction), tf.int32), tf.cast(output_ph, tf.int32)), axis=1)

accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
tf.summary.scalar('accuracy', accuracy)

merged = tf.summary.merge_all()

train_writer = tf.summary.FileWriter('./logdir/train', accuracy.graph)
val_writer = tf.summary.FileWriter('./logdir/val', accuracy.graph)
saver = tf.train.Saver()

#Training and Evaluation
epoch = 5
batch_size = 16
batch_size_val = 64

with tf.Session() as sess:

    sess.run(tf.global_variables_initializer())
    print('start training...')

    for m in range(epoch):

        print('Epoch: {} start!'.format(m + 1))
        gen_batch_train = batch_generator(x_train, y_train, batch_size)
        iteration = 50#np.int(y_train.shape[0] / batch_size)
        for n in range(iteration):
            (x_batch, y_batch) = next(gen_batch_train)
            loss_train,  _, summary = sess.run([loss, optimizer, merged],
                                               feed_dict={batch_ph: x_batch,
                                                          output_ph: y_batch,
                                                          keep_prob_ph: 0.5,
                                                          keep_prob_ph_rnn: 0.7})
            train_writer.add_summary(summary, n+m*iteration)
            #Each 100 iterations, run a valadition
            if (n + 1) % 10 == 0:
                val_acc = 0
                gen_batch_val = batch_generator(x_val, y_val, batch_size_val)
                itr_val = np.int(y_val.shape[0] / batch_size_val)
                for k in range(itr_val):
                    (x_batch, y_batch) = next(gen_batch_val)
                    accuracy_val, summary = sess.run([accuracy, merged],
                                                     feed_dict={batch_ph: x_batch,
                                                                output_ph: y_batch,
                                                                keep_prob_ph: 1,
                                                                keep_prob_ph_rnn: 1})
                    val_acc += accuracy_val
                print('Iteration: {}'.format(n+1),
                      'Train loss: {:.5f}'.format(loss_train),
                      'Val accuracy: {:.8f}'.format(val_acc/itr_val))
                val_writer.add_summary(summary, n+m*iteration)

        print('Epoch: {} finished!'.format(m+1), 'Train loss: {:.3f}'.format(loss_train))
        saver.save(sess, './model/intermediate.ckpt')
    print('**********************TRAINING FINISHED!**********************')
    saver.save(sess, './model/final.ckpt')

train_writer.close()
val_writer.close()

#Testing
batch_s = 64

with tf.Session() as sess:
    saver.restore(sess, './model/final.ckpt')
    iteration = np.int(y_test.shape[0] / batch_s)
    gen_batch_test = batch_generator(x_test, y_test, batch_s)
    test_acc = 0

    for i in range(iteration):
        (x_batch, y_batch) = next(gen_batch_test)
        test_accuracy = sess.run(accuracy,
                                 feed_dict={batch_ph: x_batch,
                                            output_ph: y_batch,
                                            keep_prob_ph: 1,
                                            keep_prob_ph_rnn: 1})
        test_acc += test_accuracy

    print('Test Accuracy: {:.3f}'.format(test_acc/iteration))


import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('../images/brain_MRI.jpg', 0)

# Binarize the image
ret, bin_img = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# Erode the image
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
erosion = cv2.erode(bin_img, kernel, iterations=1)

# Find the components
n, mask = cv2.connectedComponents(erosion)
mask[mask != 4] = 0
mask[mask != 0] = 1

mask = cv2.dilate(mask.astype(np.uint8), kernel, iterations=1)

# Final image
brain_img = img * mask

plt.subplot(2, 2, 1), plt.title('Original image')
plt.imshow(img, cmap='gray')
plt.xticks([]), plt.yticks([])

plt.subplot(2, 2, 2), plt.title('Eroded image')
plt.imshow(erosion, cmap='gray')
plt.xticks([]), plt.yticks([])

plt.subplot(2, 2, 3), plt.title('Mask')
plt.imshow(mask, cmap='gray')
plt.xticks([]), plt.yticks([])

plt.subplot(2, 2, 4), plt.title('Segmented Brain')
plt.imshow(brain_img, cmap='gray')
plt.xticks([]), plt.yticks([])

plt.show()


import graph
import heap
import aStarNode
import coordinates
import math

class AStarLibrary(object):
    """Defines a library for finding shortest paths using A*.

    Author: Aleksandar Mitrevski

    """
    def __init__(self, nodeGraph):
        """Creates a new A* search library.

        Keyword arguments:
        graph -- A 'Graph' object.

        """
        self.nodeGraph = nodeGraph

    def find_shortest_path(self, source, goal):
        """Finds a shortest path between 'source' and 'goal'.

        Keyword arguments:
        source -- Either a label of a node in the graph or a 'Coordinates' object representing the coordinates of the initial position.
        goal -- Either a label of a node in the graph or a 'Coordinates' object representing the coordinates of the goal position.

        """
        stationsExist = True
        if not isinstance(source, coordinates.Coordinates) and not self.nodeGraph.node_exists(source):
            stationsExist = False

        if not isinstance(goal, coordinates.Coordinates) and not self.nodeGraph.node_exists(goal):
            stationsExist = False

        if not stationsExist:
            return 'At least one of the specified stations does not exist'

        if isinstance(source, coordinates.Coordinates):
            source = self._find_closest_neighbour(source)

        if isinstance(goal, coordinates.Coordinates):
            goal = self._find_closest_neighbour(goal)

        openList = heap.MinHeap()
        closedList = []

        sourceNode = aStarNode.AStarNode(source, self.nodeGraph.nodes[source].coordinates, -1, 0, 0)
        openList.insert(sourceNode)

        pathFound = False
        while not openList.empty() and not pathFound:
            currentNode = openList.extract_min()
            closedList.append(currentNode)

            if currentNode.nodeLabel == goal:
                pathFound = True
                continue

            adjacent = self._get_adjacent_nodes(currentNode, goal)
            for _,node in enumerate(adjacent):
                nodePosition = openList.get_index(node)
                if nodePosition != -1:
                    if openList.nodes[nodePosition].totalCost > node.totalCost:
                        openList.nodes[nodePosition] = node
                        openList.bubble_up(nodePosition)
                else:
                    nodeClosed = False
                    for _,closedNode in enumerate(closedList):
                        if node.nodeLabel == closedNode.nodeLabel:
                            nodeClosed = True
                            break

                    if not nodeClosed:
                        openList.insert(node)

        if currentNode.nodeLabel != goal:
            return 'A path between the stations was not found'
        else:
            shortestPath = []
            shortestPath.append(closedList[len(closedList)-1].nodeLabel)
            parentNode = closedList[len(closedList)-1].parent

            if parentNode != -1:
                while True:
                    shortestPath.append(parentNode)
                    for _,node in enumerate(closedList):
                        if node.nodeLabel == parentNode:
                            parentNode = node.parent
                            break

                    if parentNode == -1:
                        break

            return shortestPath[::-1]

    def _get_adjacent_nodes(self, currentNode, goal):
        """Returns a list of 'AStarNode' objects representing the nodes adjacent to 'currentNode'.

        Keyword arguments:
        currentNode -- An 'AStarNode' object representing a node currently processed by the search algorithm.
        goal -- A node label (an integer) representing the goal node.

        """
        adjacentNodes = []

        for _,child in enumerate(self.nodeGraph.nodes[currentNode.nodeLabel].children):
            childLabel = child.connectedNode
            childCoordinates = self.nodeGraph.nodes[childLabel].coordinates
            cost = currentNode.cost + child.cost
            heuristic = self._calculate_heuristic(childLabel, goal)
            totalCost = cost + heuristic

            newNode = aStarNode.AStarNode(childLabel, childCoordinates, currentNode.nodeLabel, cost, totalCost)
            adjacentNodes.append(newNode)

        return adjacentNodes

    def _calculate_heuristic(self, node, goal):
        """Calculates a value for the heuristic between 'node' and 'goal'.

        Keyword arguments:
        node -- A node label (an integer) representing a node in the graph.
        goal -- A node label (an integer) representing the goal node.

        """
        nodeCoordinates = self.nodeGraph.nodes[node].coordinates
        goalCoordinates = self.nodeGraph.nodes[goal].coordinates

        distance = math.sqrt((nodeCoordinates.x - goalCoordinates.x)**2 + (nodeCoordinates.y - goalCoordinates.y)**2)
        return distance

    def _find_closest_neighbour(self, nodeCoordinates):
        """Returns the key of a node (an integer) representing the graph node
        whose coordinates are closest (using a straight-line distance) to 'nodeCoordinates'.

        Keyword arguments:
        nodeCoordinates -- A 'Coordinates' object representing the coordinates of a point.

        """
        minKey = -1
        minDistance = 10000000000000000.0
        for key, value in self.nodeGraph.nodes.items():
            distance = math.sqrt((value.coordinates.x - nodeCoordinates.x)**2 + (value.coordinates.y - nodeCoordinates.y)**2)
            if distance < minDistance:
                minDistance = distance
                minKey = key

        return minKey


import scrapy
from dateutil.parser import parse

from core.models import Article, Site
from core.sites import MIT_NEWS
from .utils import CheckTimeMixin
from ..items import ArticleItem

class MITSpider(scrapy.Spider, CheckTimeMixin):

    name = 'mit_news'
    site = Site.objects.get(name=MIT_NEWS)
    start_urls = [site.url_to_crawl]
    last_timestamp = Article.objects.filter(site=site).order_by('-timestamp')[0].timestamp \
        if Article.objects.filter(site=site) else None

    def parse(self, response):
        for article in response.css('li.views-row'):
            title = article.css('h3.title a::text').extract_first()
            link = article.css('h3.title a::attr(href)').extract_first()
            timestamp = article.css('em.date::text').extract_first()
            if title and link and timestamp:
                tm_with_tz = timestamp + ' 00:00:00 UTC+0'
                full_link = MITSpider.site.get_full_link(link)
                if MITSpider.posted_after(tm_with_tz, MITSpider.last_timestamp):
                    yield ArticleItem(title=title, link=full_link, timestamp=parse(tm_with_tz),
                                      site=MITSpider.site)
                else:
                    return


import doctest
import os
import sys
import django
from selenium import webdriver
from django.test import TestCase
from django.urls import reverse
from django.http import HttpRequest

sys.path.append(os.path.abspath('../..'))

os.environ['DJANGO_SETTINGS_MODULE'] = 'App.settings'

django.setup()

from CinnamonSwirl import apps, auth, filters, forms, managers, models, tables, views

def load_tests(loader, tests, ignore):
    modules = (apps, auth, filters, forms, managers, models, tables, views)
    for module in modules:
        tests.addTests(doctest.DocTestSuite(module))
    return tests

class MockUser:
    def __init__(self):
        self.id = 0

class MockSession:
    def __init__(self):
        pass

class MockPOST:
    def __init__(self):
        self.values = {'recipient': 0, 'message': "TEST", 'schedule_units': 'MINUTELY', 'schedule_interval': 1,
                       'startDate': '2022-12-01', 'startTime': '09:00', 'timezone': 'US/Central'}

    def get(self, value, default=None):
        if value in self.values.keys():
            return self.values[value]
        return default

    def getlist(self, value, default=None):
        return self.get(value, default)

class MockRequest(HttpRequest):
    def __init__(self):
        super(MockRequest).__init__()
        self.session = MockSession()
        self.POST = MockPOST()
        self.user = MockUser()

class Tests(TestCase):

    def test_homepage(self):
        response = self.client.get('/')
        self.assertEqual(response.status_code, 200)

    def test_mock_reminder(self):
        request = MockRequest()
        parsed = views.parse_reminder(request)
        self.assertTrue(parsed)

        reminder = models.Reminder.objects.get(recipient=0)
        self.assertEqual(reminder.message, 'TEST')

    def test_selenium_homepage(self):
        # IN PROGRESS
        driver = webdriver.Chrome('./chromedriver')
        driver.get("http://127.0.0.1:80")
        print(driver.title)


# importing relevant libraries for the program
import socket
import sys
import os

# storing the PORT number
PORT = int(sys.argv[1])

# creating a socket object and specifying number of bytes to be read everytime
server = socket.socket()
BYTES_TO_READ = 1000

"""
For the simple socket implementation, geeksforgeeks.org was used for reference
The article used was contributed by Kishlay Verma
Client-server architecture of geeksforgeeks.org was followed
Copied the code to establish connection

"""

# binding the port and listening to connections
server.bind(('', PORT))
server.listen()

# helper function to do the remapping of the file
def remappingFile(file_to_write, line, remapNumber):
    line_list = line.split() # splitting in word into a list
    line_remapped = ""
    # for each letter of each word, map the strings by referring dictionaries created below mapping letters to numbers and vice versa
    for word in line_list:
        remapString = ""
        for letter in word:
            letter_number = letters_to_numbers[letter]
            letter_number = letter_number + remapNumber
            if (letter_number > 26): # if mapping number exceeds 26 (number of alphabets), subtract it with 26 and start from the beginning of the dictionary
                letter_number = letter_number - 26
                letter_from_number = numbers_to_letters[letter_number]
            else:
                letter_from_number = numbers_to_letters[letter_number]
            remapString = remapString + letter_from_number # construct the remapped string
        line_remapped = line_remapped + remapString + " " # construct the remapped line
    # print(line_remapped)
    file_to_write.write(line_remapped) # write the line into file specified
    file_to_write.write("\n") # go to the next line

# helper function to read the files line by line
def readWriteFiles(file_to_read, file_to_write, size):
    # if there is line to read, send it to remappingFile helper function or else break loop
    while True:
        line = file_to_read.readline()
        #print(line)
        if not line:
            break
        remappingFile(file_to_write, line, size)

# initializing list of alphabets and numbers
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
numbers = [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]

# mapping letters to numbers for remapping function
letters_to_numbers = {
    key: value
    for key, value
    in zip(letters, numbers)
}

# mapping numbers to letters for remapping function
numbers_to_letters = {
    key: value
    for key, value
    in zip(numbers, letters)
}

while True:
    # establish a connection with the client
    connection, address = server.accept()
    file_length_message = connection.recv(1024).decode("utf-8") # receive the file length sent by the client

    # send confirmation to client from server
    connection.send("File size received".encode())
    connection.settimeout(1)

    # if it times out before data is sent after file size is sent, connection will close
    try:
        recv_data = connection.recv(1000).decode("utf-8")
    except TimeoutError:
        print("Did not receive data. Terminating")
        connection.close()
        break

    # opening file to be written and transfered
    # server acting as a receiver in this case
    file_to_receive = open("recv.txt", "w")
    # while there is data to be received
    while recv_data:
        # if it is end of file, send FIN message to client and break the connection
        if(recv_data == "EOF"):
            connection.send("FIN".encode())
            break

        # if data is being received, send acknowledgements and set timeout
        file_to_receive.write(recv_data)
        connection.send("ACK".encode())
        connection.settimeout(1)

        # if data is not received before timer runs out, connection closes
        try:
            recv_data = connection.recv(1000).decode("utf-8")
            #print("data received!")
        except TimeoutError:
            print("Data transmission terminated prematurely")
            connection.close()

    # once file all of the file is received, client sends message
    signal = connection.recv(1024).decode("utf-8")
    # file renaming is done to reduce confusion and redundancy of files
    if signal == "done":
        if os.path.isfile("data.txt"):
            os.remove("data.txt")

        if os.path.isfile("recv.txt"):
            os.rename("recv.txt", "data.txt")

        # message sent to client that file is uploaded which will be decoded at the client side
        connection.send("Server Response: File uploaded.".encode())

    # message to remap is received
    connection.settimeout(None)
    message_to_remap = connection.recv(1024).decode("utf-8").split()

    # files to read and write are opened
    file_to_write = open("test_remap.txt", "w")
    file_to_read = open(message_to_remap[2], "r")

    # calling the readWriteFiles which will call the remapper function
    readWriteFiles(file_to_read, file_to_write, int(message_to_remap[1]))

    # closing the files after use
    file_to_write.close()
    file_to_read.close()

    # once remapped, message is sent to client
    remap_completion_message = "Server Response: File " + message_to_remap[2] + " remapped. Output file is test_remap.txt"
    connection.send(remap_completion_message.encode())

    # server side acting as a the sender in the stop-wait-protocol to send remapped file
    file_to_send = open("test_remap.txt", "r")

    # if client asks for get
    get_message = connection.recv(1024).decode("utf-8").split()
    if get_message[0] == "get":
        #print("get command initiated")
        # data is read from the file
        data_to_send = file_to_send.read(BYTES_TO_READ)
        message_from_receiver = None
        while True:
            # if there is no data to be read, send end of file to client and wait for message back and break the loop
            if not data_to_send:
                connection.send("EOF".encode())
                #print("EOF")
                message_from_receiver = connection.recv(1024).decode("utf-8")
                #print(message_from_receiver)
                if message_from_receiver == "FIN" or None:
                    #print("FIN")
                    connection.send("done".encode())
                    break
            # if there is data to be read, send data and read the next bytes of data to be sent
            connection.send(data_to_send.encode())
            data_to_send = file_to_send.read(BYTES_TO_READ)
            # set a timeout and if data is not received within the timeframe, connection closes
            connection.settimeout(1)
            try:
                message_from_receiver = connection.recv(1024).decode("utf-8")
                #print(message_from_receiver)
            except TimeoutError:
                print("Did not receive ACK. Terminating")
                connection.close()
                break

    # once remapped file is transferred, quit the program
    connection.settimeout(None)
    get_message = connection.recv(1024).decode("utf-8")
    if(get_message == "quit"):
        connection.close()
        break

    # close the connection and break the loop
    connection.close()
    break


from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("https://demo.nopcommerce.com")

# click on link
# driver.find_element(By.LINK_TEXT,"Digital downloads").click()
# driver.find_element(By.PARTIAL_LINK_TEXT,"Digital").click()

# find number of links in page
# using tag name
links = driver.find_elements(By.TAG_NAME,'a')
# using xpath
# links = driver.find_elements(By.XPATH,'//a')
print("Total number of links:", len(links))

# print all link text
for link in links:
    print(link.text)


import json
import random

with open("dummydata.json") as f:
    data = json.load(f)
    print(type(data))
    handles = set()
    # loaded = json.loads(data)
    # print(loaded)
    for k, v in data.items():
        print(v["twitter"])
        handles.add(v["twitter"])
    new_json = {}
    for handle in handles:
        sample = random.sample(handles, random.randint(0, 15))
        new_json[handle] = [t for t in sample if t != handle]
    print(new_json)
with open('data.json', 'w+') as f:
    json.dump(new_json, f)


# Link: https://leetcode.com/explore/challenge/card/30-day-leetcoding-challenge/528/week-1/3285/
# reference: https://www.youtube.com/watch?v=86CQq3pKSUw

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        curr_max , global_max = 0, min(nums)

        for i in nums:

            # current maximum sum at perticular index can be current element
            # or the sum of elements before it and current element
            curr_max = max(i , curr_max + i)

            # If current max is more than the global max which we found
            # erlier than updat the global max
            global_max = max(global_max, curr_max)
        return global_max


import os

import pandas as pd
import numpy as np
import scipy.io

import time

from PIL import Image

import cv2
import matplotlib.pyplot as plt

from keras.models import Model, Sequential
from keras.layers import Input, Convolution2D, ZeroPadding2D, MaxPooling2D, Flatten, Dense, Dropout, Activation
from keras.preprocessing.image import load_img, save_img, img_to_array
from keras.applications.imagenet_utils import preprocess_input
from keras.preprocessing import image
#-----------------------
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

def preprocess_image(image_path):
    img = load_img(image_path, target_size=(224, 224))
    img = img_to_array(img)
    img = np.expand_dims(img, axis=0)

    #preprocess_input normalizes input in scale of [-1, +1]. You must apply same normalization in prediction.
    #Ref: https://github.com/keras-team/keras-applications/blob/master/keras_applications/imagenet_utils.py (Line 45)
    img = preprocess_input(img)
    return img

def loadVggFaceModel():
	model = Sequential()
	model.add(ZeroPadding2D((1,1),input_shape=(224,224, 3)))
	model.add(Convolution2D(64, (3, 3), activation='relu'))
	model.add(ZeroPadding2D((1,1)))
	model.add(Convolution2D(64, (3, 3), activation='relu'))
	model.add(MaxPooling2D((2,2), strides=(2,2)))

	model.add(ZeroPadding2D((1,1)))
	model.add(Convolution2D(128, (3, 3), activation='relu'))
	model.add(ZeroPadding2D((1,1)))
	model.add(Convolution2D(128, (3, 3), activation='relu'))
	model.add(MaxPooling2D((2,2), strides=(2,2)))

	model.add(ZeroPadding2D((1,1)))
	model.add(Convolution2D(256, (3, 3), activation='relu'))
	model.add(ZeroPadding2D((1,1)))
	model.add(Convolution2D(256, (3, 3), activation='relu'))
	model.add(ZeroPadding2D((1,1)))
	model.add(Convolution2D(256, (3, 3), activation='relu'))
	model.add(MaxPooling2D((2,2), strides=(2,2)))

	model.add(ZeroPadding2D((1,1)))
	model.add(Convolution2D(512, (3, 3), activation='relu'))
	model.add(ZeroPadding2D((1,1)))
	model.add(Convolution2D(512, (3, 3), activation='relu'))
	model.add(ZeroPadding2D((1,1)))
	model.add(Convolution2D(512, (3, 3), activation='relu'))
	model.add(MaxPooling2D((2,2), strides=(2,2)))

	model.add(ZeroPadding2D((1,1)))
	model.add(Convolution2D(512, (3, 3), activation='relu'))
	model.add(ZeroPadding2D((1,1)))
	model.add(Convolution2D(512, (3, 3), activation='relu'))
	model.add(ZeroPadding2D((1,1)))
	model.add(Convolution2D(512, (3, 3), activation='relu'))
	model.add(MaxPooling2D((2,2), strides=(2,2)))

	model.add(Convolution2D(4096, (7, 7), activation='relu'))
	model.add(Dropout(0.5))
	model.add(Convolution2D(4096, (1, 1), activation='relu'))
	model.add(Dropout(0.5))
	model.add(Convolution2D(2622, (1, 1)))
	model.add(Flatten())
	model.add(Activation('softmax'))

	#you can download pretrained weights from https://drive.google.com/file/d/1CPSeum3HpopfomUEK1gybeuIVoeJT_Eo/view?usp=sharing
	from keras.models import model_from_json
	model.load_weights('vgg_face_weights.h5')

	vgg_face_descriptor = Model(inputs=model.layers[0].input, outputs=model.layers[-2].output)

	return vgg_face_descriptor

model = loadVggFaceModel()
print("vgg face model loaded")

#------------------------
exists = os.path.isfile('representations.pkl')

if exists != True: #initializations lasts almost 1 hour. but it can be run once.

	#download imdb data set here: https://data.vision.ee.ethz.ch/cvl/rrothe/imdb-wiki/ . Faces only version (7 GB)
	mat = scipy.io.loadmat('imdb_data_set/imdb.mat')
	print("imdb.mat meta data file loaded")

	columns = ["dob", "photo_taken", "full_path", "gender", "name", "face_location", "face_score", "second_face_score", "celeb_names", "celeb_id"]

	instances = mat['imdb'][0][0][0].shape[1]

	df = pd.DataFrame(index = range(0,instances), columns = columns)

	for i in mat:
		if i == "imdb":
			current_array = mat[i][0][0]
			for j in range(len(current_array)):
				#print(j,". ",columns[j],": ",current_array[j][0])
				df[columns[j]] = pd.DataFrame(current_array[j][0])

	print("data frame loaded (",df.shape,")")

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

	#remove pictures does not include any face
	df = df[df['face_score'] != -np.inf]

	#some pictures include more than one face, remove them
	df = df[df['second_face_score'].isna()]

	#discard inclear ones
	df = df[df['face_score'] >= 5]

	#-------------------------------
	#some speed up tricks. this is not a must.

	#discard old photos
	df = df[df['photo_taken'] >= 2000]

	print("some instances ignored (",df.shape,")")
	#-------------------------------

	def extractNames(name):
		return name[0]

	df['celebrity_name'] = df['name'].apply(extractNames)

	def getImagePixels(image_path):
		return cv2.imread("imdb_data_set/%s" % image_path[0]) #pixel values in scale of 0-255

	tic = time.time()
	df['pixels'] = df['full_path'].apply(getImagePixels)
	toc = time.time()

	print("reading pixels completed in ",toc-tic," seconds...") #3.4 seconds

	def findFaceRepresentation(img):
		detected_face = img

		try:
			detected_face = cv2.resize(detected_face, (224, 224))
			#plt.imshow(cv2.cvtColor(detected_face, cv2.COLOR_BGR2RGB))

			#normalize detected face in scale of -1, +1

			img_pixels = image.img_to_array(detected_face)
			img_pixels = np.expand_dims(img_pixels, axis = 0)
			img_pixels /= 127.5
			img_pixels -= 1

			representation = model.predict(img_pixels)[0,:]
		except:
			representation = None

		return representation

	tic = time.time()
	df['face_vector_raw'] = df['pixels'].apply(findFaceRepresentation) #vector for raw image
	toc = time.time()
	print("extracting face vectors completed in ",toc-tic," seconds...")

	tic = time.time()
	df.to_pickle("representations.pkl")
	toc = time.time()
	print("storing representations completed in ",toc-tic," seconds...")

else:
	#if you run to_pickle command once, then read pickle completed in seconds in your following runs
	tic = time.time()
	df = pd.read_pickle("representations.pkl")
	toc = time.time()
	print("reading pre-processed data frame completed in ",toc-tic," seconds...")

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

print("data set: ",df.shape)

cap = cv2.VideoCapture(0) #webcam

while(True):
	ret, img = cap.read()
	faces = face_cascade.detectMultiScale(img, 1.3, 5)

	resolution_x = img.shape[1]; resolution_y = img.shape[0]

	for (x,y,w,h) in faces:
		if w > 0:
			#cv2.rectangle(img,(x,y),(x+w,y+h),(128,128,128),1)
			detected_face = img[int(y):int(y+h), int(x):int(x+w)] #crop detected face

			#add 5% margin around the face
			try:
				margin = 0 #5
				margin_x = int((w * margin)/100); margin_y = int((h * margin)/100)
				if y-margin_y > 0 and x-margin_x > 0 and y+h+margin_y < resolution_y and x+w+margin_x < resolution_x:
					detected_face = img[int(y-margin_y):int(y+h+margin_y), int(x-margin_x):int(x+w+margin_x)]
			except:
				print("detected face has no margin")

			detected_face = cv2.resize(detected_face, (224, 224)) #resize to 224x224

			img_pixels = image.img_to_array(detected_face)
			img_pixels = np.expand_dims(img_pixels, axis = 0)
			#normalize in scale of [-1, +1]
			img_pixels /= 127.5
			img_pixels -= 1

			captured_representation = model.predict(img_pixels)[0,:]
			#----------------------------------------------

			def findCosineSimilarity(source_representation, test_representation=captured_representation):
				try:
					a = np.matmul(np.transpose(source_representation), test_representation)
					b = np.sum(np.multiply(source_representation, source_representation))
					c = np.sum(np.multiply(test_representation, test_representation))
					return 1 - (a / (np.sqrt(b) * np.sqrt(c)))
				except:
					return 10 #assign a large value. similar faces will have small value.

			df['similarity'] = df['face_vector_raw'].apply(findCosineSimilarity)

			#look-alike celebrity
			min_index = df[['similarity']].idxmin()[0]
			instance = df.ix[min_index]

			name = instance['celebrity_name']
			similarity = instance['similarity']
			similarity = (1 - similarity)*100

			#print(name," (",similarity,"%)")

			if similarity > 50:
				full_path = instance['full_path'][0]
				celebrity_img = cv2.imread("imdb_data_set/%s" % full_path)
				celebrity_img = cv2.resize(celebrity_img, (112, 112))

				try:
					img[y-120:y-120+112, x+w:x+w+112] = celebrity_img

					label = name+" ("+"{0:.2f}".format(similarity)+"%)"
					cv2.putText(img, label, (x+w-10, y - 120 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)

					#connect face and text
					cv2.line(img,(x+w, y-64),(x+w-25, y-64),(67,67,67),1)
					cv2.line(img,(int(x+w/2),y),(x+w-25,y-64),(67,67,67),1)
				except Exception as e:
					print("exception occured: ", str(e))

	cv2.imshow('img',img)

	if cv2.waitKey(1) & 0xFF == ord('q'): #press q to quit
		break

#kill open cv things
cap.release()
cv2.destroyAllWindows()


"""Convert C/C++ code into a token stream so that we can work with it.

Here's a brief overview of what a tokenizer does, if you haven't taken
compilers. (You should take compilers.)

The front-end of compilation typically consists of two steps:

 1) *Lex* the source code into a series of *tokens*. A token is the smallest
 meaningful) lexical unit. For example, in the statement `foo(bar + 3)`, we
 have the following tokens:

     * `foo`
     * `(`
     * `bar`
     * `+`
     * `3`
     * `)`

 However, whitespace is not significant at all for the semantics of the
 program, and therefore there are no whitespace tokens.

 2) Once we have a list of tokens, *parse* the tokens into an abstract syntax
 tree (AST), which forms the tree structure of the program. In this linter, we
 don't try to parse the code, because it would require a nearly-full
 implementation of the C/C++ grammars. On the other hand, writing a reasonable
 tokenizer for C/C++ can be done in a few hundred lines.

Most of the errors that we want to flag would actually be best done at the AST
level, because then we would know "does this string of characters represent a
identifier? What is its type?" and so on. But it's infeasible to implement.

Instead, we can parse the list of tokens to get the information we directly
need. For example, it's easily possible to determine the operands in a
statement like `using Foo = Bar;` just by starting a range going from a token
with value `using` to a token with value `;`, and looking at the tokens in
between. See `matcher.py` for utility functions to this end.

This file provides a relatively poor implementation of a tokenizer for C/C++
code.
"""
import collections
import re

class Position(collections.namedtuple("Position", [
    "row",
    "column",
])):
    """A position of a token in the source code.

    We use this information to be able to provide line numbers corresponding to
    a flagged token, for example.

    This scheme fails when we have tabs in our code, because the tab character
    corresponds to an unknowable, variable number of columns.

    :ivar int row: The row (line number) of the position. 0-indexed.
    :ivar int column: The column of the position. 0-indexed.
    """

    @property
    def line_display(self):
        """Return the position as a line/column number.

        :returns str: The description of the position.
        """
        return "line {line}, column {column}".format(
            line=self.row + 1,
            column=self.column + 1,
        )

Token = collections.namedtuple("Token", [
    "type",
    "value",
    "start",
    "end",
])
"""A token in the list of tokens in the source file.

:ivar str type: The type of the token, such as "identifier". This value is not
    especially meaningful; many values are shunted into a category such as
    "identifier" or "grouping" when it's not terribly accurate.
:ivar str value: The string value of the token. For example, for an identifier,
    this is the name of the identifier as a string.
:ivar Position start: The start position of the token.
:ivar Position end: The end position of the token. This could be on a different
    line from the start position, such as for a multiline comment.
"""

def tokenize(string):
    """Tokenize a string.

    :returns list: A list of `Token`s in the string.
    """
    return list(_Tokenizer(string).tokenize())

class _Tokenizer:
    """Tokenize C/C++ code.

    Note that tokenizing C++ is really hard. This doesn't even try to be good
    at it.
    """

    _TOKEN_PATTERNS = [
        ("number", r"""
        [0-9]+

        # Optional decimal point.
        (\.?[0-9]*)
        """),

        ("keyword", r"""
        (
            auto |
            break |
            case |
            char |
            const |
            continue |
            default |
            do |
            double |
            else |
            enum |
            extern |
            float |
            for |
            goto |
            if |
            int |
            long |
            register |
            return |
            short |
            signed |
            sizeof |
            static |
            struct |
            switch |
            typedef |
            union |
            unsigned |
            void |
            volatile |
            while
        )"""),

        ("identifier", r"""
        # Possibly a preprocessor directive.
        [#]?

        [_a-zA-Z]([_a-zA-Z0-9]+)?
        """),

        ("comment", r"""
        //.+
        """),

        ("unary_operator", r"""
        (
            \+\+ | -- | ! | ~
        )
        """),

        # Two-character operators.
        ("binary_operator", r"""
        (
            # Relational.
            ==  | != | <= | >=

            # Arithmetic.
            \+= | -= | \*= | /= | %= |

            # Logical.
            &&  | \|\| |

            # Bitwise.
            <<= | >>= | &= | \|= | \^= |
            <<  | >>  |
        )
        """),

        # One-character operators.
        ("binary_operator", r"""
        [
            + \- * / %
            ^ & |
            < >
            =
        ]
        """),

        ("grouping", r"""
        (
            \( | \) |
            \[ | \] |
            \{ | \} |
            ::      |
            ,  | ;  |
            \.      |
            \? | :
        )
        """),
    ]
    _TOKEN_PATTERNS = [(group, re.compile(pattern, re.VERBOSE))
                       for group, pattern in _TOKEN_PATTERNS]

    def __init__(self, string):
        """Prepare to tokenize the provided code.

        :param str string: The source code, as a string.
        """
        assert "\t" not in string, (
            "Remove tabs from code before attempting to tokenize. "
            "We don't provide meaningful token positions for code "
            "that has tabs in it."
        )

        # Add a dummy whitespace character to end the last token.
        self._string = string + "\n"

        # The 'cursor' is the index into the source code string where we
        # currently are. We advance this as we consume tokens.
        self._cursor = 0

        # The row and column corresponding to the cursor. When we hit a newline
        # character, the row increments and the column is set to zero.
        self._row = 0
        self._column = 0

    def _char(self):
        """Get the character under the cursor.

        :returns str: The current character.
        """
        assert self._cursor >= 0
        return self._string[self._cursor]

    def _advance_cursor(self):
        """Advance the cursor by one character."""
        if self._char() == "\n":
            self._row += 1
            self._column = 0
        else:
            self._column += 1

        self._cursor += 1

    def _position(self):
        """Get the position of the cursor.

        :return Position: The position of the cursor.
        """
        assert 0 <= self._row < len(self._string)
        assert 0 <= self._column < len(self._string)
        return Position(row=self._row, column=self._column)

    def tokenize(self):
        """Tokenize the provided string.

        This assumes that the string is a snippet of valid  code; it is not
        guaranteed to work on code that doesn't preserve a semblance of correct
        syntax. It also may not work if the code has nefarious macros that
        upset the syntactic structure (such as a macro that has a closing
        parenthesis but not an opening one).

        :returns list: A list of `Token`s in the string.
        """
        while self._consume_whitespace():
            token = self._get_next_token()
            yield token
            self._advance_cursor()

    def _get_next_token(self):
        """Get the next token from the input string.

        This leaves the cursor at the last character of the returned token.

        :returns Token: The next token in the input.
        """
        # Special cases that we need to handle with higher priority or aren't
        # easily handled by regexes.
        special_consumers = [self._consume_string,
                             self._consume_multiline_comment]
        for consumer in special_consumers:
            token = consumer()
            if token:
                return token

        # Try to match each of our token patterns
        token_values = [(group, self._match_pattern(pattern))
                        for group, pattern in self._TOKEN_PATTERNS]

        # Get only the patterns that successfully matched something.
        token_values = [(group, value)
                        for group, value in token_values
                        if value]

        if not token_values:
            raise ValueError("Couldn't parse token at {}"
                             .format(self._position().line_display))

        # Maximal munch -- pick the longest token.
        token_values.sort(key=lambda i: len(i[1]),
                          reverse=True)
        group, value = token_values[0]

        start_position = self._position()
        # Advance our cursor until it reaches the character at the end of the
        # token.
        for _ in range(len(value) - 1):
            self._advance_cursor()
        end_position = self._position()
        return Token(type=group,
                     value=value,
                     start=start_position,
                     end=end_position)

    def _match_pattern(self, pattern):
        """If the pattern appears at the beginning of the stream, return it.

        :param pattern: A compiled regex.
        :returns str: The matched pattern, or `None` if there was no
            such token.
        """
        match = pattern.match(self._string[self._cursor:])
        if match:
            return match.group()
        else:
            return None

    def _consume_whitespace(self):
        """Remove whitespace from the beginning of the stream.

        :returns bool: Whether there is anything else left in the stream.
        """
        while self._cursor < len(self._string):
            if self._char().isspace():
                self._advance_cursor()
            else:
                return True
        return False

    def _consume_string(self):
        """Get a string or character literal from the stream, if possible.

        :returns Token: The string token, or `None` if there was no string at
            the current position.
        :raises ValueError: There was an unterminated string literal.
        """
        # This handles only string and character literals denoted with single
        # or double quotes. It doesn't handle raw string literals.
        if self._char() == '"':
            quote = '"'
        elif self._char() == "'":
            quote = "'"
        else:
            return None

        start_index = self._cursor
        start_position = self._position()

        # Skip the current quotation mark.
        self._advance_cursor()

        while self._cursor < len(self._string):
            if self._char() == "\\":
                # Ignore backslash escape sequences.
                self._advance_cursor()
            elif self._char() == quote:
                end_index = self._cursor
                end_position = self._position()
                break
            self._advance_cursor()
        else:
            raise ValueError("Unterminated string literal at {}"
                             .format(self._position().line_display))

        return Token(type="string",
                     value=self._string[start_index:end_index + 1],
                     start=start_position,
                     end=end_position)

    def _consume_multiline_comment(self):
        """Get a multiline comment from the stream, if possible.

        :returns Token: The multiline comment, or `None` if there was no
            multiline comment at the current position.
        :raises ValueError: There was an unterminated multiline comment.
        """
        def peek_two():
            # Note that this may result in only one character when at the end
            # of the stream, which is fine.
            return self._string[self._cursor:self._cursor + 2]

        if peek_two() != "/*":
            return None

        start_position = self._position()
        start_index = self._cursor

        while self._cursor < len(self._string):
            if peek_two() == "*/":
                # Move cursor to the "/".
                self._advance_cursor()

                end_index = self._cursor
                end_position = self._position()
                break
            self._advance_cursor()
        else:
            raise ValueError("Unterminated multiline comment at {}"
                             .format(self._position().line_display))

        return Token(type="comment",
                     value=self._string[start_index:end_index + 1],
                     start=start_position,
                     end=end_position)


import torch as t
from torch import nn
from torch import optim

class Linear(nn.Moudle):
    def __init__(self, in_features, out_features):
        super(Linear, self).__init__()
        self.w = nn.Parameter(t.randn(in_features, out_features))
        self.b = nn.Parameter(t.randn(out_features))

    def forward(self, x):
        x = x.mm(self.w)
        return x + self.b.expand_as(x)

class Perceptron(nn.Module):
    def __init__(self, in_features, hidden_features, out_features):
        super(Perceptron, self).__init__()
        self.layer1 = Linear(in_features, hidden_features)
        # 此处的Linear是前面自定义的全连接层
        self.layer2 = Linear(hidden_features, out_features)

    def forward(self, x):
        x = self.layer1(x)
        x = t.sigmoid(x)
        return self.layer2(x)

perceptron = Perceptron(3, 4, 1)
for name, para in perceptron.named_parameters():
    print(name, para.size())

# 首先定义一个LeNet网络
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 6, 5), nn.ReLU(), nn.MaxPool2d(2, 2),
            nn.Conv2d(6, 16, 5), nn.ReLU(), nn.MaxPool2d(2, 2))
        self.classifier = nn.Sequential(
            nn.Linear(16 * 5 * 5, 120), nn.ReLU(), nn.Linear(120, 84),
            nn.ReLU(), nn.Linear(84, 10))

    def forward(self, x):
        x = self.features(x)
        x = x.view(-1, 16 * 5 * 5)
        x = self.classifier(x)
        return x

net = Net()

'''
对于如何调整学习率，主要有两种做法。
一种是修改optimizer.param_groups中对应的学习率，
另一种是更简单也是较为推荐的做法——新建优化器，由于optimizer十分轻量级，构建开销很小，故而可以构建新的optimizer。
但是后者对于使用动量的优化器（如Adam），会丢失动量等状态信息，可能会造成损失函数的收敛出现震荡等情况。
'''

# 方法1: 调整学习率，新建一个optimizer
old_lr = 0.1
optimizer = optim.SGD([{
    'params': net.features.parameters()
}, {
    'params': net.classifier.parameters(),
    'lr': old_lr * 0.1
}],
                       lr=1e-5)
# 方法2: 调整学习率, 手动decay, 保存动量
for param_group in optimizer.param_groups:
    param_group['lr'] *= 0.1  # 学习率为之前的0.1倍


import os

import numpy as np
from numpy.testing import assert_almost_equal, assert_array_equal

import gsw
from gsw._utilities import Bunch

root_path = os.path.abspath(os.path.dirname(__file__))

cv = Bunch(np.load(os.path.join(root_path, 'gsw_cv_v3_0.npz')))
# Override the original with what we calculate using pchip interp
cv.geo_strf_velocity = np.load(os.path.join(root_path,'geo_strf_velocity.npy'))

lon = [1, 2]
lat = [45, 45]
expected = 78626.18767687

# distance tests

def test_list():
    value = gsw.distance(lon, lat, p=0, axis=-1)
    assert_almost_equal(expected, value)

def test_1darray():
    value = gsw.distance(np.array(lon), np.array(lat), p=0, axis=-1)
    assert_almost_equal(expected, value)

def test_1darray_default_p():
    # @match_args_return doesn't see the default p.
    value = gsw.distance(np.array(lon), np.array(lat))
    assert_almost_equal(expected, value)

def test_2dlist():
    value = gsw.distance(np.atleast_2d(lon), np.atleast_2d(lat), p=0, axis=1)
    assert_almost_equal(expected, value)

# geostrophic streamfunction tests

def test_strf_no_good():
    # revised geo_strf_dyn_height requires 2 valid points
    shape = (5,)
    SA = np.ma.masked_all(shape, dtype=float)
    CT = np.ma.masked_all(shape, dtype=float)
    p = np.array([0.0, 10.0, 20.0, 30.0, 40.0])

    # No valid points.
    strf = gsw.geo_strf_dyn_height(SA, CT, p, p_ref=0, axis=0)
    expected = np.zeros(shape, float) + np.nan
    assert_array_equal(strf.filled(np.nan), expected)

    # 1 valid point: not enough.
    SA[:1] = 35
    CT[:1] = 5
    strf = gsw.geo_strf_dyn_height(SA, CT, p, p_ref=0, axis=0)
    expected = np.zeros(shape, float) + np.nan
    assert_array_equal(strf.filled(np.nan), expected)

    # 2 valid points: enough for the calculation to proceed.
    SA[:2] = 35
    CT[:2] = [5, 4]
    strf = gsw.geo_strf_dyn_height(SA, CT, p, p_ref=0, axis=0)
    assert strf.count() == 2

def test_geostrophy():
    lon = cv.long_chck_cast
    lat = cv.lat_chck_cast
    p = cv.p_chck_cast
    CT = cv.CT_chck_cast
    SA = cv.SA_chck_cast
    strf = gsw.geo_strf_dyn_height(SA, CT, p)
    geovel, midlon, midlat = gsw.geostrophic_velocity(strf, lon, lat)
    assert_almost_equal(geovel, cv.geo_strf_velocity)
    assert_almost_equal(midlon, cv.geo_strf_velocity_mid_long[0])
    assert_almost_equal(midlat, cv.geo_strf_velocity_mid_lat[0])

def test_dyn_height_shallower_pref():
    """
    Check that we can handle a p_ref that is shallower than the top of the
    cast.  To make the results from bin 1 on down independent of whether
    bin 0 has been deleted, we need to use linear interpolation.
    """
    p = cv.p_chck_cast
    CT = cv.CT_chck_cast
    SA = cv.SA_chck_cast
    strf0 = gsw.geo_strf_dyn_height(SA, CT, p, p_ref=0, interp_method='linear')
    strf1 = gsw.geo_strf_dyn_height(SA[1:], CT[1:], p[1:], p_ref=0,
                                    interp_method='linear')
    found = strf1 - strf1[0]
    expected = strf0[1:] - strf0[1]
    assert_almost_equal(found, expected)

def test_pz_roundtrip():
    """
    The p_z conversion functions have Matlab-based checks that use
    only the first two arguments.
    Here we verify that the functions are also inverses when the optional
    arguments are used.
    """
    z = np.array([-10, -100, -1000, -5000], dtype=float)
    p = gsw.p_from_z(z, 30, 0.5, 0.25)
    zz = gsw.z_from_p(p, 30, 0.5, 0.25)
    assert_almost_equal(z, zz)


"""
python -m scripts.skill_transl
"""
import re
from dataclasses import dataclass
from pathlib import Path
from typing import Literal, Pattern

from src.utils import dump_json, load_json

Region = Literal["JP", "CN", "TW", "NA", "KR"]

Mapping = dict[str, dict[Region, str | None]]

jp_chars = re.compile(r"[\u3040-\u309f\u30a0-\u30ff]")

_SKILL_NAME_REPLACES: dict[Pattern, dict[Region, str]] = {
    re.compile(r"^(.+)のドロップ獲得数アップ$"): {
        "CN": "{0}的掉落获得数提升",
        "TW": "{0}的掉落獲得數提升",
        "NA": "Increase amount of {0} per drop",
    },
    re.compile(r"^(.+)のドロップ獲得量アップ$"): {
        "CN": "{0}的掉落获得量提升",
        "TW": "{0}的掉落獲得量提升",
        "NA": "Increase amount of {0} per drop",
    },
    re.compile(r"^(.+)獲得量アップ$"): {
        "CN": "{0}获得量提升",
        "TW": "{0}獲得量提升",
        "NA": "Increase amount of {0} per drop",
    },
}

@dataclass
class _SkillDetail:
    pattern: Pattern
    item_counts_event: tuple[int | list[int], int | list[int], int]
    mapping: dict[Region, str]

    def get_items(self) -> list[int]:
        items = self.item_counts_event[0]
        if isinstance(items, int):
            items = [items]
        return [x for x in items if x >= 0]

    def get_counts(self) -> list[int]:
        counts = self.item_counts_event[1]
        if isinstance(counts, int):
            counts = [counts]
        return [x for x in counts if x >= 0]

    def get_event(self) -> int | None:
        event = self.item_counts_event[2]
        return event if event >= 0 else None

_SKILL_DETAIL_REPLACES: list[_SkillDetail] = [
    _SkillDetail(
        pattern=re.compile(r"^(.+)のドロップ獲得数を(\d+)個増やす【『(.+)』イベント期間限定】$"),
        item_counts_event=(0, 1, 2),
        mapping={
            "CN": "{item}的掉落获得数增加{count}个【『{event}』活动限定】",
            "TW": "{item}的掉落獲得數增加{count}個【『{event}』活動限定】",
            "NA": "Increase {item} amount per drop by {count} [Event Only]",
        },
    ),
    _SkillDetail(
        pattern=re.compile(r"^(.+)のドロップ獲得数を(\d+)個増やす\[最大解放\]【『(.+)』イベント期間限定】$"),
        item_counts_event=(0, 1, 2),
        mapping={
            "CN": "{item}的掉落获得数增加{count}个[最大解放]【『{event}』活动限定】",
            "TW": "{item}的掉落獲得數增加{count}個[最大解放]【『{event}』活動限定】",
            "NA": "Increase {item} amount per drop by {count} [MAX] [Event Only]",
        },
    ),
    _SkillDetail(
        pattern=re.compile(r"^(.+)のドロップ獲得量を(\d+)個増やす【『(.+)』イベント期間限定】$"),
        item_counts_event=(0, 1, 2),
        mapping={
            "CN": "{item}的掉落获得量增加{count}个【『{event}』活动限定】",
            "TW": "{item}的掉落獲得量增加{count}個【『{event}』活動限定】",
            "NA": "Increase {item} amount per drop by {count} [Event Only]",
        },
    ),
    _SkillDetail(
        pattern=re.compile(r"^(.+)のドロップ獲得量を(\d+)個増やす\[最大解放\]【『(.+)』イベント期間限定】$"),
        item_counts_event=(0, 1, 2),
        mapping={
            "CN": "{item}的掉落获得量增加{count}个[最大解放]【『{event}』活动限定】",
            "TW": "{item}的掉落獲得量增加{count}個[最大解放]【『{event}』活動限定】",
            "NA": "Increase {item} amount per drop by {count} [MAX] [Event Only]",
        },
    ),
    _SkillDetail(
        pattern=re.compile(r"^(.+)のドロップ獲得量を(\d+)%増やす【『(.+)』イベント期間限定】$"),
        item_counts_event=(0, 1, 2),
        mapping={
            "CN": "{item}的掉落获得量提升{count}%【『{event}』活动限定】",
            "TW": "{item}的掉落獲得量提升{count}%【『{event}』活動限定】",
            "NA": "Increase {item} amount per drop by {count}% [Event Only]",
        },
    ),
    _SkillDetail(
        pattern=re.compile(r"^(.+)のドロップ獲得量を(\d+)%増やす\[最大解放\]【『(.+)』イベント期間限定】$"),
        item_counts_event=(0, 1, 2),
        mapping={
            "CN": "{item}的掉落获得量提升{count}%[最大解放]【『{event}』活动限定】",
            "TW": "{item}的掉落獲得量提升{count}%[最大解放]【『{event}』活動限定】",
            "NA": "Increase {item} amount per drop by {count}% [MAX] [Event Only]",
        },
    ),
    _SkillDetail(
        pattern=re.compile(r"^『(.+?)』において、自身の攻撃の威力を(\d+)%アップ【『(.+)』イベント期間限定】$"),
        item_counts_event=(-1, 1, 2),
        mapping={
            "CN": "自身的攻击威力提升{count}%【『{event}』活动限定】",
            "TW": "自身的攻擊威力提升{count}%【『{event}』活動限定】",
            "NA": 'Increase ATK Strength by {count}% for yourself in "{event}" [Event Only]',
        },
    ),
    _SkillDetail(
        pattern=re.compile(r"^『(.+?)』において、自身の攻撃の威力を(\d+)%アップ\[最大解放\]【『(.+)』イベント期間限定】$"),
        item_counts_event=(-1, 1, 2),
        mapping={
            "CN": "自身的攻击威力提升{count}%[最大解放]【『{event}』活动限定】",
            "TW": "自身的攻擊威力提升{count}%[最大解放]【『{event}』活動限定】",
            "NA": 'Increase ATK Strength by {count}% for yourself in "{event}" [MAX] [Event Only]',
        },
    ),
    _SkillDetail(
        pattern=re.compile(r"^自身の『(.+?)』における攻撃の威力を(\d+)%アップ【『(.+)』イベント期間限定】$"),
        item_counts_event=(-1, 1, 2),
        mapping={
            "CN": "自身的攻击威力提升{count}%[最大解放]【『{event}』活动限定】",
            "TW": "自身的攻擊威力提升{count}%[最大解放]【『{event}』活動限定】",
            "NA": 'Increase ATK Strength by {count}% for yourself in "{event}" [MAX] [Event Only]',
        },
    ),
    _SkillDetail(
        pattern=re.compile(r"^自身の『(.+?)』における攻撃の威力を(\d+)%アップ\[最大解放\]【『(.+)』イベント期間限定】$"),
        item_counts_event=(-1, 1, 2),
        mapping={
            "CN": "自身的攻击威力提升{count}%[最大解放]【『{event}』活动限定】",
            "TW": "自身的攻擊威力提升{count}%[最大解放]【『{event}』活動限定】",
            "NA": 'Increase ATK Strength by {count}% for yourself in "{event}" [MAX] [Event Only]',
        },
    ),
    _SkillDetail(
        pattern=re.compile(r"^自身の『(.*?)』のクエストクリア時に得られる絆を(\d+)%増やす【『(.*?)』イベント期間限定】$"),
        item_counts_event=(-1, 1, 2),
        mapping={
            "CN": "自身在关卡通关时获得的牵绊值提升{count}%【『{event}』活动限定】",
            "TW": "自身在關卡通關時獲得的羈絆值提升{count}%【『{event}』活動限定】",
            "NA": 'Increase Bond gained when completing quests in "{event}" by {count}% for yourself [Event Only]',
        },
    ),
    _SkillDetail(
        pattern=re.compile(
            r"^自身の『(.*?)』における攻撃の威力を(\d+)%アップ＆クエストクリア時に得られる絆を(\d+)%増やす【『(.*?)』イベント期間限定】$"
        ),
        item_counts_event=(-1, [1, 2], 3),
        mapping={
            "CN": "自身的攻击威力提升{count1}%＆关卡通关时获得的牵绊值提升{count2}%【『{event}』活动限定】",
            "TW": "自身的攻擊威力提升{count1}%＆關卡通關時獲得的羈絆值提升{count2}%【『{event}』活動限定】",
            "NA": 'Increase ATK Strength by {count1}% for yourself in "{event}" & increase Bond gained when completing quests by {count2}% [Event Only]',
        },
    ),
    _SkillDetail(
        pattern=re.compile(
            r"^自身の『(.*?)』において、攻撃の威力を(\d+)%アップ ＋ 味方全体＜控え含む＞の『(.*?)』のクエストクリア時に得られる絆を(\d+)%アップ\(サポート時は無効\)【『(.*?)』イベント期間限定】$"
        ),
        item_counts_event=(-1, [1, 3], 4),
        mapping={
            "CN": "自身的攻击威力提升{count1}%＋己方全体<包括替补>在关卡通关时获得的牵绊值提升{count2}%(作为助战时无效)【『{event}』活动限定】",
            "TW": "自身的攻擊威力提升{count1}%＋我方全體<包括替補>在關卡通關時獲得的羈絆值提升{count2}%(作為助戰時無效)【『{event}』活動限定】",
            "NA": 'Increase your ATK Strength by {count1}% & increase Bond gained for all allies <including sub-members> when completing quests in "{event}" by {count2}% (No effect when equipped as Support) [Event Only]',
        },
    ),
    _SkillDetail(
        pattern=re.compile(
            r"^自身の『(.*?)』における攻撃の威力を(\d+)%アップ ＋ 味方全体[＜<]控え含む[＞>]の『(.*?)』のクエストクリア時に得られる絆を(\d+)%(?:アップ|増やす)\(サポート時は無効\)【『(.*?)』イベント期間限定】$"
        ),
        item_counts_event=(-1, [1, 3], 4),
        mapping={
            "CN": "自身的攻击威力提升{count1}%＋己方全体<包括替补>在关卡通关时获得的牵绊值提升{count2}%(作为助战时无效)【『{event}』活动限定】",
            "TW": "自身的攻擊威力提升{count1}%＋我方全體<包括替補>在關卡通關時獲得的羈絆值提升{count2}%(作為助戰時無效)【『{event}』活動限定】",
            "NA": 'Increase your ATK Strength by {count1}% & increase Bond gained for all allies <including sub-members> when completing quests in "{event}" by {count2}% (No effect when equipped as Support) [Event Only]',
        },
    ),
]

def _get_item_transl(
    text_jp: str,
    region: Region,
    items: dict[str, dict[Region, str | None]],
):
    names = []
    items_jp = text_jp.split("、")
    for name in items_jp:
        if name not in items:
            return None
        v = items[name][region]
        if not v:
            return None
        names.append(v)
    if region == "CN" or region == "TW":
        return "、".join(names)
    elif region == "NA":
        return ", ".join(names)
    else:
        raise KeyError(f"Unimplemented: {region}")

def _update_skill_name(
    text_jp: str,
    transl: dict[Region, str | None],
    region: Region,
    items: dict[str, dict[Region, str | None]],
):
    if transl[region] is not None:
        return
    for pattern, mapping in _SKILL_NAME_REPLACES.items():
        repl = mapping.get(region)
        if not repl:
            continue
        matches = pattern.findall(text_jp)
        if not matches:
            continue
        assert isinstance(matches[0], str)
        name = _get_item_transl(matches[0], region, items)
        if not name:
            continue
        transl[region] = repl.format(name)

def _update_skill_detail(
    text_jp: str,
    transl: dict[Region, str | None],
    region: Region,
    items: dict[str, dict[Region, str | None]],
    events: dict[str, dict[Region, str | None]],
):
    if transl[region] is not None:
        return
    if "期間限定" not in text_jp:
        return
    for detail in _SKILL_DETAIL_REPLACES:
        repl = detail.mapping.get(region)
        if not repl:
            continue
        matches = detail.pattern.findall(text_jp)
        if not matches:
            continue
        match = matches[0]
        replaces: dict[str, str] = {}
        for index, item_index in enumerate(detail.get_items()):
            item_jp: str = match[item_index]
            item = _get_item_transl(item_jp, region, items)
            if item:
                replaces[f"{{item{index+1}}}"] = item
                if index == 0:
                    replaces["{item}"] = item

        for index, count_index in enumerate(detail.get_counts()):
            count = match[count_index]
            replaces[f"{{count{index+1}}}"] = count
            if index == 0:
                replaces["{count}"] = count

        event_index = detail.get_event()
        event: str | None = None
        if event_index:
            event_jp: str = match[event_index]
            if event_jp in events:
                event = events[event_jp].get(region)
            event = event or event_jp
            if event:
                replaces["{event}"] = event

        if "{item}" in replaces and "{count}" not in replaces:
            continue

        for k, v in replaces.items():
            if v:
                repl = repl.replace(k, v)
        if "{item" in repl or "{count" in repl or "{event" in repl:
            continue
        transl[region] = repl

def main():
    mapping_dir = Path(__file__).parents[1] / "data" / "mappings"
    item_names: Mapping = load_json(mapping_dir / "item_names.json")
    event_names: Mapping = load_json(mapping_dir / "event_names.json")
    event_names |= load_json(mapping_dir / "war_names.json")
    skill_names: Mapping = load_json(mapping_dir / "skill_names.json")
    skill_details: Mapping = load_json(mapping_dir / "skill_detail.json")
    assert item_names and skill_names and skill_details and event_names

    # short name for some events
    for event_jp in list(event_names.keys()):
        for region in list(event_names[event_jp].keys()):
            value = event_names[event_jp][region]
            if value and event_jp.count("\n") == value.count("\n") == 1:
                jp2, v2 = event_jp.split("\n")[0], value.split("\n")[0]
                event_names.setdefault(jp2, {}).setdefault(region, v2)

    for text_jp, transl in skill_names.items():
        for region in ("JP", "CN", "TW", "NA", "KR"):
            _update_skill_name(text_jp, transl, region, item_names)
    dump_json(skill_names, mapping_dir / "skill_names.json")

    for text_jp, transl in skill_details.items():
        for region in ("JP", "CN", "TW", "NA", "KR"):
            _update_skill_detail(text_jp, transl, region, item_names, event_names)
    dump_json(skill_details, mapping_dir / "skill_detail.json")

if __name__ == "__main__":
    main()


from django.conf.urls import url

from apps.pdf.views import cpanel, guardar_csv, guardar_pdf, mostrar_resultados

urlpatterns = [
    url(r'^cpanel/', cpanel, name='cpanel'),
    url(r'^guardar_csv/', guardar_csv, name='guardar_csv'),
    url(r'^guardar_pdfs/', guardar_pdf, name='guardar_pdfs'),
    url(r'^resultados/', mostrar_resultados, name='resultados'),
]


from HerancaMultiplas.Eletronico import Electronico
from HerancaMultiplas.Log import LogMixing

class SmartPhone(Electronico, LogMixing):

    def __init__(self, nome):
        super().__init__(nome)
        self._conectado = False

    def conectar(self):
        if not self._ligado:
            info = f"{self._nome} nao esta ligado."
            print(info)
            self.log_inf(info)
            return
        if self._conectado:
            error = f"{self._nome} ja esta conectado."
            print(error)
            self.log_error(error)
            return
        info = f"{self._nome} esta conectado."
        self._conectado = True
        self.log_inf(info)
        print(info)

    def desconectar(self):
        if not self._conectado:
            error = f"{self._nome} Esta conectado"
            print(error)
            self.log_error(error)
            return

        info = f"{self._nome} foi desligado com sucesso"
        print(info)
        self._conectado = False
        self.log_inf(info)