import sys
import re
import os
import hashlib
import time
import subprocess
import multiprocessing

# we define the a few global variables for constant values
DEFAULTHOST = 'tp-4b01-@@'
WORKERS_FILE = 'machines.txt'
USERNAME = 'dalbianco-20'
MAXRETRY = 5

# This function launches a sub process
def launch_subprocess(worker, command, hostname=None):
    # the command to be executed, contains two commands: one to create the remote dir and one to copy the files
    if command == 'mkdir':
        # we're using the -q otpion for quiet mode
        commands = ['ssh', '-q', USERNAME+'@'+worker,'mkdir -p /tmp/'+USERNAME+'/shufflesreceived']
    elif command == 'scp':
        commands = ['scp', '-qC', '/tmp/'+USERNAME+'/shuffles/'+worker+'-'+hostname+'.txt', USERNAME+'@'+worker+':/tmp/'+USERNAME+'/shufflesreceived/']

    # simply create a sub process and return it
    #print('{}: starting {} ...'.format(worker, command))
    process = subprocess.Popen(
                    commands,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    stdin=subprocess.PIPE,
                    universal_newlines=True, # to improve the output rendering
                     )
    return process

# Executes a command on a worker and checks that it worked
def execute_command(worker, command, hostname=None):
    # we need a long timeout for the scp of the shuffles
    if command == 'scp':
        timeout = None
    else:
    # we can have a shorter timeout for mkdir commands
        timeout = 15
    try:
        # execute the sub process on a remote machine with a certain timeout
        process = launch_subprocess(worker, command, hostname)
        # try to get the process' outputs
        stdout, stderr = process.communicate(timeout=timeout)
        returncode = process.returncode

        # executed with errors
        if(returncode != 0):
            print('{}: \033[93m{} terminated with code {}\033[0m'.format(worker, command, returncode))
            if(len(stderr) > 0):
                print(' └ Errors: {}'.format(stderr.strip()))
            if(len(stdout) > 0):
                print(' └ Output: {}'.format(stdout.strip()))

        return returncode
    # the command timed out
    except subprocess.TimeoutExpired:
        print('{}: \033[91m{} timed out\033[0m'.format(worker, command))
        process.kill()
        return -1
    # we have another unexpected exception
    except Exception as e:
        print('{}: {} \033[91mthrew an exception {}\033[0m'.format(worker, command, e))
        process.kill()
        return -1

# the words maps function
def get_maps(filename):
    try:
        with open(filename, 'r', encoding='utf-8') as f:
            words_map = []

            # we read the file by line
            for line in f:
                 # we split the line by whitespace
                words = line.split()

                # we map the words list to the correct format
                # and we add it to our words_map list
                words_map.extend(map(lambda w: '{} 1\n'.format(w), words))

    except Exception:
        return None

    return words_map

# the words shuffle function
def get_shuffles(filename, workers, nb_workers, curdir, hostname):
    shuffles = {}
    try:
        # we read the content of the file created during the map
        with open(filename, 'r') as f:
            for line in f:
                # we generate the hash from each lines
                hash = generate_hash(line.split(' ')[0])
                #hashes.append(hash)

                # we perform attribution per machine using the hash
                modulo = int(hash) % nb_workers

                # first version
                # we write the content in a file in shuffles/<worker>/<hash>-<hostname>.txt
                # with open(curdir+'/shuffles/'+workers[modulo]+'/'+hash+'-'+hostname+'.txt', 'a') as f:
                #     f.writelines(line)

                # second version: we write one file per worker
                # we write the content in a file in shuffles/<worker>-<hostname>.txt
                # with open(curdir+'/shuffles/'+workers[modulo]+'-'+hostname+'.txt', 'a') as f:
                #     f.writelines(line)

                # final version: we write everything in RAM first
                if modulo in shuffles:
                    shuffles[modulo].append(line)
                else:
                    shuffles[modulo] = [line]

    except Exception:
        return False

    # final version: we copy the results from RAM to a file per worker in one shot
    for modulo in shuffles:
        # we write the shuffles in a file in shuffles/<worker>-<hostname>.txt
        try:
            with open(curdir+'/shuffles/'+workers[modulo]+'-'+hostname+'.txt', 'a') as f:
                f.writelines(shuffles[modulo])
        except Exception:
            return False
    return True

# Tries to execute commands on workers
def send_shuffle(worker_hostname_curdir):
    worker, (hostname, curdir) = worker_hostname_curdir
    # we check if there is a file for this worker, if not, we do nothing
    if(not os.path.exists(curdir+'/shuffles/'+worker+'-'+hostname+'.txt')):
        return True

    # we execute this 100*MAXRETRY times at most,
    # MAXRETRY times in case of scp error code other than 1
    retry_nb = 0
    for retry_nb in range(MAXRETRY*100):
        mkdir_returncode = execute_command(worker, 'mkdir')
        if mkdir_returncode == 0:
            scp_s_returncode = execute_command(worker, 'scp', hostname)
            if scp_s_returncode == 0:
                print('{}: \033[92mjob done\033[0m'.format(worker))
                #the job is successful
                return True
            # we had an unexpected error code
            if scp_s_returncode != 1 and retry_nb > MAXRETRY:
                break

        # we wait 200ms
        time.sleep(0.2)

    # the job failed
    return False

# the words reduce function
def get_reduces(filename, words_count):
    try:
        # we open the file
        with open(filename, encoding='utf-8') as f:
            # we read each line
            for line in f:
                # we get the word
                word = line.split(' ')[0]
                # we update our dict accordingly
                words_count[word] = words_count.get(word, 0) + 1

    except Exception:
        return False

    # we return our dict
    return True

# a function that generates a unique hash
def generate_hash(s):
    return str(int.from_bytes(hashlib.sha256(str.encode(s)).digest()[:4], 'little'))

def make_dir(dirname):
    try:
        os.makedirs(dirname, exist_ok=True)
    except FileExistsError:
        pass
    except OSError:
        # if we have an error while creating we exit with an error
        print('Not able to create directory maps', file=sys.stderr)
        return False

    return True

def read_workers(filename):
    workers = []
    with open(filename) as f:
        # we read the file by line
        for line in f:
            # we don't read lines that start with a # to allow for comments
            if line.startswith('#'):
                continue
            # we add the worker to the list of workers
            workers.append(line.strip())
    return workers

##
# main function
##
def main():
    # we check that we received the expected number of arguments
    if len(sys.argv) < 2:
        # we exit with an error if we didn't get the expected number of arguments
        print('Expected at least 1 argument, received none', file=sys.stderr)
        sys.exit(1)

    # we parse the option passed in argument
    option = sys.argv[1]

    if option in ['0', '1']:
        if len(sys.argv) < 3:
            # we exit with an error if we didn't get the expected number of arguments
            print('Expected at 2 arguments, received {}'.format(len(sys.argv)), file=sys.stderr)
            sys.exit(1)
        else: # we get the filename passed in arguement
            file = sys.argv[2]

    # we get our current working directory
    curdir = os.path.dirname(sys.argv[0])

    # if the current directory is empty, we replace it by '.' to avoid issues later
    if curdir == '':
        curdir = '.'

    ###
    # 0: get the splits and map
    if option == '0':
        # we extract the file number from the filename
        file_nb = re.search('([0-9]+)\.txt', file, re.IGNORECASE).group(1)

        # we perform the words map
        words_map = get_maps(file)

        # we couldn't open the file
        if words_map == None:
            print('Couldn\'t open file: {}'.format(file), file=sys.stderr)
            sys.exit(1)

        # we create the maps directory
        if not make_dir(curdir+'/maps'):
            # if we have an error while creating we exit with an error
            sys.exit(1)

        # we write the content in a file UM#id.txt
        with open(curdir+'/maps/UM'+file_nb+'.txt', 'w') as f:
            f.writelines(words_map)
    ###
    # option 1: shuffle
    elif option == '1':
        try:
            hostname = os.uname()[1]
        except Exception:
            hostname = DEFAULTHOST

        workers = read_workers(curdir+'/'+WORKERS_FILE)
        nb_workers = len(workers)

        # we create the shuffles directory
        if not make_dir(curdir+'/shuffles'):
            # if we have an error while creating we exit with an error
            sys.exit(1)

        # to create a directory per worker necessary for the previous versions
        # for worker in workers:
        #     if not make_dir(curdir+'/shuffles/'+worker):
        #         # if we have an error while creating we exit with an error
        #         sys.exit(1)

        shuffle_done = get_shuffles(file, workers, nb_workers, curdir, hostname)
        # we couldn't open the file
        if not shuffle_done:
            print('Couldn\'t open file: {}'.format(file), file=sys.stderr)
            sys.exit(2)

        # we generate a list of tuples (worker, filename) that attributes a worker to each filename
        pool = multiprocessing.Pool(nb_workers)
        # we determine which worker we need to send the file to
        workers_status = pool.map(send_shuffle, zip(workers, [(hostname,curdir)]*nb_workers))
        # if we have some failures
        if not all(workers_status):
            # we generate a list of the failed workers
            failed_workers = [w for w, s in zip(workers, workers_status) if not s]

            # we print a message detailing which machines failed
            print('Failed shuffle transfer to {}'.format(failed_workers), file=sys.stderr)
            sys.exit(3)

    ###
    # option 2: reduce
    elif option == '2':
        try:
            hostname = os.uname()[1]
        except Exception:
            hostname = DEFAULTHOST
        # we create the reduces directory
        if not make_dir(curdir+'/reduces'):
            # if we have an error while creating we exit with an error
            sys.exit(1)

        # we loop on each file received in shufflesreceived/
        words_count = {}
        for f in os.listdir(curdir+'/shufflesreceived/'):
            file = curdir+'/shufflesreceived/'+f
            #hash = f.split('-')[0]

            reduce_done = get_reduces(file, words_count)
            # we couldn't open the file
            if not reduce_done:
                print('Couldn\'t open file: {}'.format(file), file=sys.stderr)
                sys.exit(1)

        # Initial code to create one hash.txt per word
        # for (w,h), c in words_count.items():
        #     # we write the content in a file <hash>.txt in reduces/
        #     with open(curdir+'/reduces/'+h+'.txt', 'w') as f:
        #         f.writelines('{} {}\n'.format(w, c))

        # first improvement : we write line by line
        # we write our words count into a file in /reduces
        # for w, c in words_count.items():
        #     with open(curdir+'/reduces/'+hostname+'.txt', 'a') as f:
        #         f.writelines('{} {}\n'.format(w, c))

        # final version : we write the reduce file in one shot
        with open(curdir+'/reduces/'+hostname+'.txt', 'w') as f:
            f.writelines(map(lambda wc: '{} {}\n'.format(wc[0], wc[1]), words_count.items()))

if __name__ == '__main__':
    main()


import string
from random import choice
from algos import bruteForce, doDecreasebyConstant, avl
import sys

class Game():
    maxGuess = 6
    hangman = ['''
  +---+
  |   |
      |
      |
      |
      |
=========''', '''
  +---+
  |   |
  O   |
      |
      |
      |
=========''', '''
  +---+
  |   |
  O   |
  |   |
      |
      |
=========''', '''
  +---+
  |   |
  O   |
 /|   |
      |
      |
=========''', '''
  +---+
  |   |
  O   |
 /|\  |
      |
      |
=========''', '''
  +---+
  |   |
  O   |
 /|\  |
 /    |
      |
=========''', '''
  +---+
  |   |
  O   |
 /|\  |
 / \  |
      |
=========''']

    def __init__(self):
        self.word = self.random_word()
        self.wrongGuess = []
        self.correct = []
        self.progress = self.get_progress()
        self.gameover = False

    def random_word(self):
        dictionary = open('dictionary.txt', 'r').readlines()
        words = [word.strip() for word in dictionary]
        return choice(words)

    def get_progress(self):
        return "".join([let if let in self.correct else "_" for let in self.word])

    def already_guessed(self, guess):
        return guess in self.correct + self.wrongGuess

    def guess_letter(self, guess):
        if guess in self.word:
            self.correct.append(guess)
        else:
            self.wrongGuess.append(guess)

    def status(self):
        if len(self.wrongGuess) >= Game.maxGuess:
            self.gameover = True
            return "\nYou lost. The word was %r." % self.word
        if set(self.correct) == set(self.word):
            self.gameover = True
            return "\nYou won!"
        return ""

    def __str__(self):
        result = "\n" + "-" * 30 + "\n"
        result += Game.hangman[len(self.wrongGuess)]
        result += "\nProgress: %s" % self.get_progress()
        result += "\nIncorrect guesses: %s" % ", ".join(self.wrongGuess)
        result += self.status()
        return result

    def setWord(self,word, tree, root):
        print("Hangman needs to validate your word. ")
        print("Type the following algorithm you'd like to use. \nBrute Force, Decrease and Conqure, Binary tree")
        algo = input("\"brute\", \"decrease\",\"tree\"\n")
        if(algo == "tree"):
            self.word = avl(word, tree, root)
        elif(algo == "decrease"):
            self.word = doDecreasebyConstant(word)
        else:
            self.word = bruteForce(word)

#------------------------------------------------------------------------------
def valid_guess(game):
    while True:
        guess = input("Guess a letter: ").lower()
        if len(guess) > 1:
                if guess == 'quit':
                    return 'quit'
                else:
                    print ("Please guess a letter.")
        elif game.already_guessed(guess):
            print ("You've already guessed %r." , guess)
        else:
            return guess


import os
import subprocess
import pathlib
import sys

EXTENSIONS = [
    '.cpp',
    '.h',
]

def main():
    clang_format = pathlib.Path(sys.prefix) / 'bin' / 'clang-format'
    root = pathlib.Path(os.getenv('BUILD_WORKSPACE_DIRECTORY')) / 'risc0'
    for root, _, files in os.walk(root):
        for file in files:
            path = pathlib.Path(root) / file
            if path.suffix in EXTENSIONS:
                print('.', end='', flush=True)
                subprocess.run([clang_format, '-i', path])
    print()

if __name__ == "__main__":
    main()


from Args import parse_args
from daisy.utils.loader import load_rate, get_ur, build_candidates_set, load_attack_data_get_attack_instances
from daisy.utils.map import neaten_id, get_unpopular, find_neighbor_items
from daisy.utils.splitter import split_test
from daisy.utils.sampler import Sampler
from daisy.utils.data import PairData, PointData
from daisy.utils.metrics import precision_at_k, recall_at_k, map_at_k, hr_at_k, ndcg_at_k, mrr_at_k
import random
import torch
import os
import numpy as np
import copy
import json
import pickle
import time
from tqdm import tqdm
import pandas as pd

def set_global_seeds(i):
    np.random.seed(i)
    random.seed(i)
    torch.manual_seed(i)
    torch.cuda.manual_seed(i)

class Env():
    def __init__(self, args):
        # set_global_seeds(28)
        self.args = args
        self.device = torch.device('cuda:{}'.format(self.args.gpu) if torch.cuda.is_available() else "cpu" )
        self._data_path = f'data/ds/{self.args.dataset}'
        self.save_path = f'{self.args.processed_path}_{self.args.dataset}'
        if not os.path.exists(self.save_path):
            os.makedirs(self.save_path)
        # attack parameters
        self.episode_length = self.args.episode_length
        # preprocess dataset
        df, self.user_num, self.item_num = load_rate(self.args.dataset, self.args.prepro, binary=True, level=self.args.level)
        # clean id + KG
        df, self.item_num_in_kg, self.n_entity, self.n_relation, self.kg, self.kg_dict, self.adj_entity, self.adj_relation, self.degree_item = neaten_id(self.args.dataset, df, self.args.kg_neighbor_size)
        self.degree = list(dict(sorted(self.degree_item.items(), key=lambda item: item[1],reverse=True)).keys())
        self.large_degree_items = self.degree[:int(len(self.degree)*0.3)]
        # generate KGE
        KGFILE = {'ml-1m':'ml1m-kg1m','ml-20m':'ml20m-kg500k','bx':'bx-kg150k','lastfm':'lastfm-kg15k'}
        if not os.path.exists(f'data/kg/{KGFILE[args.dataset]}/ent_embedding.pt'):
            print('============KGE============')
            kg_df = pd.DataFrame(self.kg, columns=['from', 'rel', 'to'])
            kg_df = kg_df.reindex(columns = ['from','to','rel'])
            self.train_KGE(kg_df,f'data/kg/{KGFILE[args.dataset]}/ent_embedding.pt')

        # print('len of rating',len(df))
        # Unpopular + popular
        unpopular_items,self.popular_items = get_unpopular(df, self.item_num_in_kg, args.unpop_ratio)
        # item pool
        self.item_pool = set(range(self.item_num))
        # target_item
        self.target_items = random.sample(unpopular_items, self.args.num_target_item)
        print(f'target items = {self.target_items}')
        # adj_item_dict
        self.adj_item_dict = find_neighbor_items(f'{self._data_path}/adj_item_{self.args.prepro}_{self.args.level}_{self.args.kg_hop}.pkl', self.adj_entity, self.item_num_in_kg, self.args.kg_hop)
        # Negative sampler
        self.spler = Sampler(
            self.user_num+self.args.num_max_attacker,
            self.item_num,
            num_ng=self.args.num_ng,
            sample_method=self.args.sample_method,
            sample_ratio=self.args.sample_ratio
        )
        # Train, Val, Test
        # self.processed_path = f'{self.save_path}/'
        # if not os.path.exists(self.processed_path):
        #     os.makedirs(self.processed_path)
        if os.path.exists(f'{self.save_path}/split_{self.args.num_ng}_{self.args.algo_name}_seed{self.args.seed}.pkl'):
            load_time = time.time()
            with open(f'{self.save_path}/split_{self.args.num_ng}_{self.args.algo_name}_seed{self.args.seed}.pkl','rb') as f:
                process_dict = pickle.load(f)
            self.train_set = process_dict['train_set']
            self.test_set = process_dict['test_set']
            self.test_ur = process_dict['test_ur']
            self.total_train_ur = process_dict['total_train_ur']
            self.test_ucands = process_dict['test_ucands']
            self.train_spy = process_dict['train_spy']
            self.eval_spy = process_dict['eval_spy']
            self.train_neg = process_dict['train_neg']
            self.test_neg = process_dict['test_neg']
            print(f'Load time elapsed= {time.time() - load_time}')
        else:
            self.train_set, self.test_set = split_test(df, 'ufo', self.args.test_size)
            # self.train_set, self.val_set = split_test(self.train_set, self.args.test_method, 0.1)
            self.test_ur = get_ur(self.test_set)
            self.total_train_ur = get_ur(self.train_set)
            self.test_ucands, self.train_spy, self.eval_spy = build_candidates_set(self.test_ur, self.total_train_ur, self.item_pool, self.args, self.target_items)
            self.train_neg = self.spler.transform(self.train_set, is_training=True)
            self.test_neg = self.spler.transform(self.test_set, is_training=True)
            # save!!
            save_dict = {
                'train_set':self.train_set,
                'test_set':self.test_set,
                'test_ur':self.test_ur,
                'total_train_ur':self.total_train_ur,
                'test_ucands':self.test_ucands,
                'train_spy':self.train_spy,
                'eval_spy':self.eval_spy,
                'train_neg':self.train_neg,
                'test_neg':self.test_neg
            }
            with open(f'{self.save_path}/split_{self.args.num_ng}_{self.args.algo_name}_seed{self.args.seed}.pkl', 'wb') as f:
                pickle.dump(save_dict,f)

        # model
        self.build_model()

    def build_model(self):
        self.result_save_path = f'{self.save_path}/{self.args.algo_name}'+\
                f'{self.args.prepro}_{self.args.level}_{self.args.test_method}_{self.args.epochs}_{self.args.sample_ratio}_{self.args.sample_method}_{self.args.loss_type}_{self.args.problem_type}'+\
                    f'{self.args.dataset}'
        if self.args.problem_type == 'pair':
            train_dataset = PairData(self.train_neg, is_training=True)
        else:
            train_dataset = PointData(self.train_neg, is_training=True)
        if self.args.problem_type == 'pair':
            if self.args.algo_name == 'NeuMF':
                from daisy.model.pair.NeuMFRecommender import PairNeuMF
                print(f'================tareget_model [{self.args.algo_name}_{self.args.problem_type}]===============')
                self.model = PairNeuMF(
                    self.user_num+self.args.num_max_attacker,
                    self.item_num,
                    factors=self.args.factors,
                    num_layers=self.args.num_layers,
                    q=self.args.dropout,
                    lr=self.args.lr,
                    epochs=self.args.epochs,
                    reg_1=self.args.reg_1,
                    reg_2=self.args.reg_2,
                    loss_type=self.args.loss_type,
                    gpuid=self.device
                )
        elif self.args.problem_type == 'point':
            if self.args.algo_name == 'NeuMF':
                from daisy.model.point.NeuMFRecommender import PointNeuMF
                print(f'================tareget_model [{self.args.algo_name}_{self.args.problem_type}]===============')
                self.model = PointNeuMF(
                    self.user_num+self.args.num_max_attacker,
                    self.item_num,
                    factors=self.args.factors,
                    num_layers=self.args.num_layers,
                    q=self.args.dropout,
                    lr=self.args.lr,
                    epochs=self.args.epochs,
                    reg_1=self.args.reg_1,
                    reg_2=self.args.reg_2,
                    loss_type=self.args.loss_type,
                    gpuid=self.device
                )
        # 如果有模型，就加载模型
        if os.path.exists(self.result_save_path+f'/model_{self.args.factors}_{self.args.num_layers}_{self.args.dropout}_{self.args.epochs}_{self.args.reg_1}_{self.args.reg_2}.pth'):
            self.model.load_state_dict(torch.load(self.result_save_path+f'/model_{self.args.factors}_{self.args.num_layers}_{self.args.dropout}_{self.args.epochs}_{self.args.reg_1}_{self.args.reg_2}.pth',map_location='cuda:0'))
            self.model.to(self.device)
            # 构造test_ucands
            # model.evaluate_model()
        # 否则，走一遍模型的全流程(earlystop, checkpoint)
        else:
            train_loader = torch.utils.data.DataLoader(
                train_dataset,
                batch_size=128,
                shuffle=True,
                num_workers=4
            )
            if not os.path.exists(self.result_save_path):
                os.makedirs(self.result_save_path)
            s_time = time.time()
            self.model.fit(train_loader)
            elapsed_time = time.time() - s_time
            print(f'prepare the black box model elapsed_time= {elapsed_time}')
            torch.save(self.model.state_dict(), self.result_save_path+f'/model_{self.args.factors}_{self.args.num_layers}_{self.args.dropout}_{self.args.epochs}_{self.args.reg_1}_{self.args.reg_2}.pth')

        #res = self.evaluate(self.test_ucands, self.test_ur)
        #print(res)
        # print('===========before attack=========')
        # for i in self.target_items:
        #     res = self.evaluate(self.train_spy, target_item = i)
        #     print(f'target [{i}] , [{res}]')

    def reset_model(self):
        if os.path.exists(self.result_save_path):
            self.model.load_state_dict(torch.load(self.result_save_path+'/model.pth'))
            self.model.to(self.device)
    def get_target_items(self):
        return self.target_items

    def get_meta(self):
        return self.user_num, self.item_num, self.item_num_in_kg, self.target_items, self.kg,\
         self.n_entity, self.n_relation, self.adj_entity, self.adj_relation,self.adj_item_dict,self.popular_items,self.large_degree_items

    def attack(self, attack_data, target_item, eval=False):
        # attack_data to df
        print('====convert attack profiles to attack df====')
        ui, user, item, r, t = {},[],[],[],[]
        for p in attack_data:
            u = p[0]
            for i in p[1:]:
                user.append(u)
                item.append(i)
                r.append(1.0)
                t.append(1)
        ui['user'] = user
        ui['item'] = item
        ui['rating'] = r
        ui['timestamp'] = t
        attack_df = pd.DataFrame(ui)
        # get train set
        attack_neg_set = self.spler.transform(attack_df, is_training=True)
        if self.args.problem_type == 'pair':
            attack_dataset = PairData(attack_neg_set, is_training=True)
        else:
            attack_dataset = PointData(attack_neg_set, is_training=True)

        attack_loader = torch.utils.data.DataLoader(
                attack_dataset,
                batch_size=128,
                shuffle=True,
                num_workers=4
            )
        self.model.set_epoch(self.args.attack_epochs)
        self.model.fit(attack_loader)

        # evaluate

        res_train = self.evaluate(self.train_spy, target_item = target_item)
        #print(f'evaluate train spy hr [{hr_train}] ndcg [{ndcg_train}]')
        res_val = self.evaluate(self.eval_spy, target_item = target_item)
        #print(f'evaluate eval spy hr [{hr_eval}] ndcg [{ndcg_eval}]')
        return res_train, res_val

    def evaluate(self, test_ucands, test_ur = None, target_item=None):
        assert test_ur is not None or target_item is not None
        # print(f'Start Calculating Metrics......each user have [{self.args.candi_num}] candidates')
        preds = {}
        for u in tqdm(test_ucands.keys()):
            # truncate the acutual candidates num
            if target_item is None:
                test_ucands[u] = test_ucands[u][:self.args.candi_num]
            else:
                test_ucands[u] = test_ucands[u][:self.args.candi_num]+[target_item]
            # build a test MF dataset for certain user u to accelerate
            tmp = pd.DataFrame({
                'user': [u for _ in test_ucands[u]],
                'item': test_ucands[u],
                'rating': [0. for _ in test_ucands[u]], # fake label, make nonsense
            })
            tmp_neg_set = self.spler.transform(tmp, is_training=False)
            if self.args.problem_type == 'pair':
                tmp_dataset = PairData(tmp_neg_set, is_training=False)
            else:
                tmp_dataset = PointData(tmp_neg_set, is_training=False)
            tmp_loader = torch.utils.data.DataLoader(
                tmp_dataset,
                batch_size=128,
                shuffle=False,
                num_workers=0
            )
            topk_indices = self.model.evaluate_model(tmp_loader, self.args.topk)
            preds[u] = torch.take(torch.tensor(test_ucands[u]), topk_indices).cpu().numpy()
        for u in preds.keys():
            if target_item is None:
                preds[u] = [1 if i in test_ur[u] else 0 for i in preds[u]]
            else:
                preds[u] = [1 if i==target_item else 0 for i in preds[u]]
            # process topN list and store result for reporting KPI
        print('Save metric@k result to res folder...')
        res = pd.DataFrame({'metric@K': ['hr', 'ndcg']})
        hr, ndcg = 0, 0
        for k in [1, 5, 10, 20, 30, 50]:
            if k > self.args.attack_topk:
                continue
            tmp_preds = preds.copy()
            tmp_preds = {key: rank_list[:k] for key, rank_list in tmp_preds.items()}
            hr_k = hr_at_k(tmp_preds)
            ndcg_k = np.mean([ndcg_at_k(r, k) for r in tmp_preds.values()])
            # if k == 10:
            #     print(f'HR@{k}: {hr_k:.4f}')
            #     print(f'NDCG@{k}: {ndcg_k:.4f}')

            res[k] = np.array([hr_k, ndcg_k])
            # if k == self.args.attack_topk:
            #     hr, ndcg = hr_k, ndcg_k
        # res.to_csv(
        #     f'{self.result_save_path}/kpi_results.csv',
        #     index=False
        # )
        return res

    def candidate(self, agent_pivot = None):
        # generate valid action set
        candis = []
        # mask = np.array(mask).T

        for b_idx in range(len(self.state)):
            # m = mask[b_idx]
            if self.args.candidate_mode == 'nearest_neighbor':
                pivot = self.state[b_idx][self.step_count]
                pivot_neighbor = self.adj_item_dict[pivot]
                if len(pivot_neighbor) >= self.args.action_size:
                    candis.append(random.sample(pivot_neighbor, self.args.action_size))
                else:
                    rr = self.args.action_size - len(pivot_neighbor)
                    candi = random.sample(list(range(self.item_num_in_kg)), rr) + pivot_neighbor
                    candis.append(candi)
            elif self.args.candidate_mode == 'kg_item':
                candi = random.sample(list(range(self.item_num_in_kg)), self.args.action_size)
                candis.append(candi)
            elif self.args.candidate_mode == 'all_item':
                candi = random.sample(list(range(self.item_num)), self.args.action_size)
                candis.append(candi)
            elif self.args.candidate_mode == 'target_neighbor':
                pivot = self.state[b_idx][1]
                pivot_neighbor = self.adj_item_dict[pivot]
                if len(pivot_neighbor) >= self.args.action_size:
                    candis.append(random.sample(pivot_neighbor, self.args.action_size))
                else:
                    rr = self.args.action_size - len(pivot_neighbor)
                    candi = random.sample(list(range(self.item_num_in_kg)), rr) + pivot_neighbor
                    candis.append(candi)
            elif self.args.candidate_mode == 'agent_select':
                assert agent_pivot is not None
                pivot = self.state[b_idx][agent_pivot[b_idx]]
                pivot_neighbor = self.adj_item_dict[pivot]
                if len(pivot_neighbor) >= self.args.action_size:
                    candis.append(random.sample(pivot_neighbor, self.args.action_size))
                else:
                    rr = self.args.action_size - len(pivot_neighbor)
                    candi = random.sample(list(range(self.item_num_in_kg)), rr) + pivot_neighbor
                    candis.append(candi)
            # candi = set(tmp) - set(m)
        return np.array(candis)
    def p_mask(self):
        if random.random() < self.args.bandit_ratio:
            mask = [[True]*(self.step_count+1) + [False]*(self.episode_length-self.step_count-1)]*len(self.attackers_id)
        else:
            mask = [[True] + [False]*(self.episode_length-1)]*len(self.attackers_id)
        return mask
    '''Gym environment API'''
    def reset(self, target_item, episode):
        self.target_item = target_item
        self.attackers_id = [i for i in range(self.user_num+episode*self.args.num_train_attacker, self.user_num+(episode+1)*self.args.num_train_attacker)]
        self.init_item = [target_item for _ in range(len(self.attackers_id))]
        self.state = np.hstack((np.array(self.attackers_id)[:, None], np.array(self.init_item)[:,None])) # (num_train_attacker,2)
        # Pad state to keep dimension consistent
        self.state = np.pad(self.state, ((0,0),(0,self.episode_length - 1)), constant_values = -1)
        self.step_count = 1
        # State dict
        print(f'action candidates mode [{self.args.candidate_mode}], action size = [{self.args.action_size}]')

        if self.args.candidate_mode == 'agent_select':
            agent_pivot = [1 for _ in range(len(self.attackers_id))] # target item as the initial pivot
            self.valid_actions = self.candidate(agent_pivot) # the neighbors of pivot as the valid actions

            self.pivot_mask = self.p_mask() # batch_size * mask. the target_item and the second item could be the pivot
            return {'some_state':torch.LongTensor(copy.deepcopy(self.state)),
                 'valid_actions': torch.LongTensor(copy.deepcopy(self.valid_actions)),
                    'pivot_mask': torch.LongTensor(copy.deepcopy(self.pivot_mask))
                    }
        else:
            self.valid_actions = self.candidate()
            return {'some_state':torch.LongTensor(copy.deepcopy(self.state)),
                 'valid_actions': torch.LongTensor(copy.deepcopy(self.valid_actions))
                    }
    '''Gym environment API'''
    def step(self, item_action, pivot_action):
        '''
        input:
            action_chosen: [B] 每一行都有一个新的action(item id)
        return
            reward: [bs*attack_user_num] 到了episode长度时，attack_user_num个profile共同得到一个reward，一共有bs个reward，并需要normalize处理，然后repeat
            done: 到了episode长度时，返回True，否则返回False
        '''
        self.step_count += 1
        if pivot_action is None:
            action = self.valid_actions[range(self.valid_actions.shape[0]), item_action.cpu().numpy()]
            self.state[:,self.step_count] = action
            self.valid_actions = self.candidate()
        else:
            # print('pivot_action',pivot_action)
            action = self.valid_actions[range(self.valid_actions.shape[0]), item_action.cpu().numpy()]
            self.state[:,self.step_count] = action # update state must before self.candidate(pivot_action)
            self.valid_actions = self.candidate(pivot_action.cpu().numpy()+1)
            # the pivot mask only affect when mode == 'agent_pivot'
            self.pivot_mask = self.p_mask()

        if self.step_count == self.episode_length:
            res_train, res_val = self.attack(self.state, self.target_item)
            if self.args.rl_reward_type == 'hr':
                rew = res_train.loc[0,self.args.reward_topk]
            elif self.args.rl_reward_type == 'ndcg':
                rew = res_train.loc[1,self.args.reward_topk]
            user_rewards = []
            user_rewards.extend([rew for j in range(len(self.attackers_id))])
            reward = np.array(user_rewards)
            done = [True]*len(self.attackers_id)
        else:
            res_train = -1
            res_val = -1
            reward = np.zeros(len(self.attackers_id))
            done = [False]*len(self.attackers_id)

        info = {'res_train':res_train, 'res_val':res_val }
        if pivot_action is None:
            return {'some_state':torch.LongTensor(copy.deepcopy(self.state)),
                    'valid_actions': torch.LongTensor(copy.deepcopy(self.valid_actions))
                    }, reward, done, info
        else:
            return {'some_state':torch.LongTensor(copy.deepcopy(self.state)),
                    'valid_actions': torch.LongTensor(copy.deepcopy(self.valid_actions)),
                    'pivot_mask': torch.LongTensor(copy.deepcopy(self.pivot_mask))
                    }, reward, done, info
if __name__=='__main__':
    from collections import defaultdict
    target_items_results_hr_5 = defaultdict(list)
    target_items_results_hr_10 = defaultdict(list)
    target_items_results_hr_20 = defaultdict(list)
    target_items_results_ndcg_5 = defaultdict(list)
    target_items_results_ndcg_10 = defaultdict(list)
    target_items_results_ndcg_20 = defaultdict(list)

    args = parse_args()
    set_global_seeds(args.seed)
    env = Env(args)
    target_items = env.get_target_items()
    print('===========target_items==========')
    print(target_items)
    n_users, n_items, _, _, _, _,_,_,_, adj_item_dict, popular_items, large_degree_items= env.get_meta()
    episode_length = args.episode_length # 16:hr0.32, 32:hr0.42, 64:hr0.9
    eval_n_attacker = 3
    sample_times = 50
    alpha = args.action_size    # 1000 ok 500变弱， 1500变弱

    if args.random_method == 'n':
        method = 'target_neighbor_attack'
    elif args.random_method == 'r':
        method = 'target_random_attack'
    elif args.random_method == 'rn':
        method = 'neighbor_random_attack'
    elif args.random_method == 'd':
        method = 'degree_attack'
    for tar in range(len(target_items)):
        set_global_seeds(args.seed)
        env = Env(args)
        # if tar in [0,1,2,3,4,5,6]: continue
        target_item = target_items[tar]
        # print(f'target_item is {target_item}')
        # print('*'*50)
        num_users = n_users
        pivot = target_item
        # env.reset_model()
        final_results_train = {'hr':{5:[],10:[],20:[]}, 'ndcg':{5:[],10:[],20:[]}}
        final_results_val = {'hr':{5:[],10:[],20:[]}, 'ndcg':{5:[],10:[],20:[]}}
        # item_set_random = random.sample(list(range(n_items)),alpha)
        for s in range(sample_times):
            attack_data = []
            for i in tqdm(range(num_users, num_users+eval_n_attacker),desc='num attacker'):
                attack_profile = [i]
                if random.random() < args.target_bandit:
                    attack_profile.append(target_item)
                else:
                    attack_profile.append(random.choice(list(range(n_items))))

                while(len(attack_profile)-1<=episode_length):
                    # item_set = random.sample(list(range(n_items)),alpha)
                    if args.random_method == 'n':
                        pivot_list = adj_item_dict[pivot]
                        # item_set = random.sample(pivot_list,alpha)
                        item_set = pivot_list
                        j2 = random.choice(item_set)
                        # pivot = j2
                    elif args.random_method == 'r':
                        item_set_random = list(range(n_items))
                        j2 = random.choice(item_set_random)
                    elif args.random_method == 'p':
                        item_set = popular_items
                        j2 = random.choice(item_set)
                    elif args.random_method == 'd':
                        if alpha<=len(large_degree_items):
                            print('no plus')
                            item_set = random.sample(large_degree_items,alpha)
                        else:
                            print('no plus')
                            item_set = random.sample(large_degree_items,alpha - len(large_degree_items)) + large_degree_items
                        # item_set = random.sample(list(range(n_items)),alpha) + large_degree_items
                        j2 = random.choice(item_set)
                    else:
                        if alpha<=len(adj_item_dict[pivot]):
                            print('no plus')
                            item_set = random.sample(adj_item_dict[pivot],alpha)
                        else:
                            print('no plus')
                            item_set = random.sample(list(range(n_items)),alpha - len(adj_item_dict[pivot])) + adj_item_dict[pivot]
                        # item_set = random.sample(list(range(n_items)),alpha) + adj_item_dict[pivot]
                        j2 = random.choice(item_set)
                    attack_profile.append(j2)
                    # item_set.remove(j2)
                attack_data.append(attack_profile)
            res_train, res_val = env.attack(attack_data, target_item)
            for k in [5, 10, 20]:
                final_results_train['hr'][k].append(res_train.loc[0,k])
                final_results_train['ndcg'][k].append(res_train.loc[1,k])
                final_results_val['hr'][k].append(res_val.loc[0,k])
                final_results_val['ndcg'][k].append(res_val.loc[1,k])
            num_users = num_users+eval_n_attacker
        # print(result_dict)
        target_items_results_hr_5[target_item] = final_results_val['hr'][5]
        target_items_results_ndcg_5[target_item] = final_results_val['ndcg'][5]
        target_items_results_hr_10[target_item] = final_results_val['hr'][10]
        target_items_results_ndcg_10[target_item] = final_results_val['ndcg'][10]
        target_items_results_hr_20[target_item] = final_results_val['hr'][20]
        target_items_results_ndcg_20[target_item] = final_results_val['ndcg'][20]
        del env
    # HR
    target_items_results_hr5_df = pd.DataFrame(target_items_results_hr_5)
    target_items_results_hr5_df[-1] = target_items_results_hr5_df.mean(1)
    target_items_results_hr10_df = pd.DataFrame(target_items_results_hr_10)
    target_items_results_hr10_df[-1] = target_items_results_hr10_df.mean(1)
    target_items_results_hr20_df = pd.DataFrame(target_items_results_hr_20)
    target_items_results_hr20_df[-1] = target_items_results_hr20_df.mean(1)
    # NDCG
    target_items_results_ndcg_5 = pd.DataFrame(target_items_results_ndcg_5)
    target_items_results_ndcg_5[-1] = target_items_results_ndcg_5.mean(1)
    target_items_results_ndcg_10 = pd.DataFrame(target_items_results_ndcg_10)
    target_items_results_ndcg_10[-1] = target_items_results_ndcg_10.mean(1)
    target_items_results_ndcg_20 = pd.DataFrame(target_items_results_ndcg_20)
    target_items_results_ndcg_20[-1] = target_items_results_ndcg_20.mean(1)
    print(f'============avg of each iteration method {args.random_method} action_size {args.action_size} seed {args.seed}============')
    print('top20')
    print(target_items_results_hr20_df[-1])
    print('top10')
    print(target_items_results_hr10_df[-1])
    print('top5')
    print(target_items_results_hr5_df[-1])
    print('ndcg20')
    print(target_items_results_ndcg_20[-1])
    print('ndcg10')
    print(target_items_results_ndcg_10[-1])
    print('ndcg5')
    print(target_items_results_ndcg_5[-1])

    if args.random_method == 'r':
        target_items_results_df.to_csv(f'result/{method}/seed_{args.seed}_epi{episode_length}_att{eval_n_attacker}_dim{args.init_dim}{args.dim1}{args.dim2}_kghop{args.kg_hop}.csv', index=False)
    else:
        target_items_results_df.to_csv(f'result/{method}/seed_{args.seed}_action_size_{args.action_size}_epi{episode_length}_att{eval_n_attacker}_dim{args.init_dim}{args.dim1}{args.dim2}_kghop{args.kg_hop}.csv', index=False)
    # kg neighbor attack


import configparser
indicator = [1,3,4,6,7]
def create_config(indicator):
    config = configparser.ConfigParser()
    config.read('./NEAT-Try/XOR-conf')
    print("Loading config!")
    config['DefaultGenome']['num_inputs'] = str(len(indicator))
    config.add_section('Inputs')
    config.set('Inputs','Indicators', str(indicator))
    with open('temp.conf','w') as f:
        config.write(f)
    print("Temp config created!")

create_config(indicator)


"""Использование готовой обученной модели из библиотеки transformers
для оценки тональности высказываний (sentiment analysis)
на массиве отзывов о товарах и услугах Amazon, IMDB, YELP.
"""

import pandas as pd
from sklearn import metrics
from transformers import pipeline

from matplotlib import pyplot as plt
import seaborn as sns

# Параметры отображения графиков:
plt.rcParams['figure.figsize'] = 12, 8
plt.rcParams.update({'font.size': 11})

# Считываем данные из csv-файла:
data = pd.read_csv('reviews_data.csv',
                   header=None,
                   names=['review', 'sentiment', 'source'],
                   dtype={'source': 'category'},
                   delimiter='\t')

# Готовая модель для задачи анализа тональности:
nlp = pipeline('sentiment-analysis')

# Пример обработки одного текстового фрагмента:
prediction = nlp('We are very happy to include pipeline into the transformers repository.')
print(prediction)

# Модель требует значительных объемов памяти и много времени на inference:
# обработка массива из 3,000 отзывов может занимать 5-6 минут и до 7-8 Гб.

# Для тестирования модели на меньших объемах исходных данных
# можно взять случайную выборку таким способом:
# data = data.sample(frac=0.1)  # 300 случайных отзывов

# Оценка тональности набора текстов:
input_texts = data['review'].to_list()
prediction = nlp(input_texts)

# Преобразуем список словарей в pd.DataFrame и соединяем с исходными данными:
prediction = pd.DataFrame(prediction)
data['label'] = prediction['label'].values
data['score'] = prediction['score'].values

# Бинарный столбец с прогнозом модели:
data['pred_sentiment'] = data['label'].apply(lambda x: 1 if x == 'POSITIVE' else 0)

# Показатели точности модели:
accuracy = metrics.accuracy_score(data['sentiment'], data['pred_sentiment'])
print('Accuracy score:', accuracy)

# Столбец с вероятностью положительной оценки
data['pred_prob'] = data['score']
data.loc[data['sentiment'] == 0, 'pred_prob'] = 1 - data.loc[data['sentiment'] == 0, 'score']
roc_score = metrics.roc_auc_score(data['sentiment'], data['pred_prob'])
print('ROC AUC:', roc_score)

clf_report = metrics.classification_report(data['sentiment'], data['pred_sentiment'])
print(clf_report)

conf_matrix = metrics.confusion_matrix(data['sentiment'], data['pred_sentiment'])
conf_matrix = pd.DataFrame(conf_matrix,
                           columns=['pred_negative', 'pred_positive'],
                           index=['actual_negative', 'actual_positive'])

sns.heatmap(conf_matrix, annot=True, fmt='d', cmap=plt.cm.Blues)
plt.yticks(rotation=0)
plt.title('Confusion Matrix')
plt.tight_layout()
plt.savefig('transformer_confusion.png')
plt.show()

# Accuracy score: 0.928
# ROC AUC: 1.0

#               precision    recall  f1-score   support
#
#            0       0.92      0.93      0.93      1500
#            1       0.93      0.92      0.93      1500
#
#     accuracy                           0.93      3000
#    macro avg       0.93      0.93      0.93      3000
# weighted avg       0.93      0.93      0.93      3000


def Insertion_Sort(arr, low, n):
    for i in range(low + 1, n + 1):
        val = arr[i]
        j = i
        while j>low and arr[j-1]>val:
            arr[j]= arr[j-1]
            j-= 1
        arr[j]= val

def Partition(arr, low, high):
    pivot = arr[high]
    i = j = low
    for i in range(low, high):
        if arr[i]<pivot:
            temp= array[i]
            array[i]= array[j]
            array[j]=temp
            j+= 1
    temp= array[j]
    array[j]= array[high]
    array[high]=temp
    return j

def New_Quick_Sort(arr, low, high):
    while low<high:
        if high-low + 1<9:
            Insertion_Sort(arr, low, high)
            break
        else:
            pivot = Partition(arr, low, high)
            if pivot-low<high-pivot:
                New_Quick_Sort(arr, low, pivot-1)
                low = pivot + 1
            else:
                New_Quick_Sort(arr, pivot + 1, high)
                high = pivot-1
    return arr

if __name__ == '__main__':

    array = [ 13, 85, 51, 52, 98, 75, 23,56, 13, 35, 23, 91, 55, 12,39, 30, 72, 33, 7, 11, 94 ]
    New_Quick_Sort(array, 0, len(array)-1)
    print(array)


from django.shortcuts import render

from rest_framework import mixins
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response

from .models import Article, Entry
from. serializers import ArticleSerializer, EntrySerializer

def home(request):
    return render(request, 'home.html')

class ArticleViewSet(mixins.RetrieveModelMixin,
                     mixins.ListModelMixin,
                     viewsets.GenericViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer

    @action(detail=True, methods=['get'])
    def entries(self, request, pk=None):
        article = self.get_object()
        serializer = EntrySerializer(article.entry_set.all(), many=True)
        return Response(serializer.data)

class EntryViewSet(mixins.RetrieveModelMixin,
                   mixins.ListModelMixin,
                   viewsets.GenericViewSet):
    queryset = Entry.objects.all()
    serializer_class = EntrySerializer


from django.conf.urls import url,include
from .views import login_view,register_view,logout_view

app_name = 'hesablar'

urlpatterns = [
    url(r'^giris/$',login_view),
    url(r'^qeydiyyat/$',register_view),
    url(r'^cixis/$',logout_view),
]


#!/usr/bin/env python3

#print('Running' if __name__ == '__main__' else 'Importing', __file__)

import numpy as np
import sys
import os
import argparse
from PIL import Image
import tkinter as tk

from ..api import ZgyReader
from ..test.utils import SDCredentials
from ..tools.viewzgy import savePNG, showFileInTk

def run(filename, *, lods = [0], direction = 0, datarange=None,
        outname = None, iocontext=None):
    """
    Read one trace or slices in the specified direction, save and display.
    """
    allslices = []
    with ZgyReader(filename, iocontext=SDCredentials()) as reader:
        for lod in lods:
            step = 1<<lod
            start = [0, 0, 0]
            size = np.array(reader.size, dtype=np.int64) // (1 << lod)
            start[direction] = size[direction] // 2
            size[direction] = 1
            if direction == 2:
                size[0] = min(size[0], 1024)
                size[1] = min(size[1], 1024)
            section = np.zeros(size, dtype=np.float32)
            reader.read(start, section, lod)
            allslices.append(np.squeeze(section))
    s = allslices[0].shape
    w = np.sum([allslices[i].shape[0] for i in range(3)])
    combined = np.zeros((w, s[1]), dtype=allslices[0].dtype)
    combined[0:s[0],:] = allslices[0]
    ss = allslices[1].shape
    combined[s[0]:s[0]+ss[0], 0:ss[1]] = allslices[1]
    sss = allslices[2].shape
    combined[s[0]+ss[0]:s[0]+ss[0]+sss[0], 0:sss[1]] = allslices[2]
    combined = combined[::-1,::]
    savePNG(combined, outname, datarange=datarange)
    showFileInTk(outname, title=os.path.basename(outname))

def Main(args, *, gain="1", prefix=""):
    """
    Show 3 ZGY files, with the 3 first LODs.
    The files are assumed to be uncompressed original, file after compression,
    and the difference between those two. The value range of the diff is a
    certain percentage of the value range in the first inout. This makes it
    possible to compare the quality from different settings.
    """
    with ZgyReader(args[0], iocontext=None) as reader:
        datarange0 = reader.datarange
        datarange1 = ((reader.datarange[0]/gain, reader.datarange[1]/gain))
    run(args[0], lods=range(3), direction=0, datarange = datarange0,
            outname = prefix + "-showorig.png")
    run(args[1], lods=range(3), direction=0, datarange = datarange0,
            outname = prefix + "-showcomp.png")
    run(args[2], lods=range(3), direction=0, datarange = datarange1,
            outname = prefix + "-showdiff.png")

if __name__ == "__main__":
    np.seterr(all='raise')
    parser = argparse.ArgumentParser(description='Evaluate compression')
    parser.add_argument('orig', help='Original ZGY input file')
    parser.add_argument('comp', help='Data after compression')
    parser.add_argument('diff', help='Compression noise')
    parser.add_argument('--gain', nargs=1, default=[50], type=int,
                        help='Scaling of diff cube relative to orig range.')
    parser.add_argument('--prefix', nargs=1, default=["check"], type=str,
                        help='prefix for output file name.')
    args = parser.parse_args()
    #print(args)
    Main([args.orig, args.comp, args.diff], gain=args.gain[0], prefix=args.prefix[0])
    sys.exit(0)

# Copyright 2017-2020, Schlumberger
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


import csv

# csv file name
filename = "procssing_times_table.csv"
rows = []
array2D = []

# reading csv file
with open(filename, 'r') as csvfile:

    csvreader = csv.reader(csvfile)

    for row in csvreader:
        rows.append(row)
    for row in rows:
        array2D.append(row[0].split(";"))


def make_number_to_window_size(a, hash_map):
    stack = []
    a.append(0)
    for i, value in enumerate(a):
        if not stack or stack[-1][1] < value:
            stack.append((i, value))
        else:
            j = i
            while stack and stack[-1][1] >=  value:
                j, pre_value = stack.pop()
                window_size = i - j
                if pre_value in hash_map:
                    if hash_map[pre_value] < window_size:
                        hash_map[pre_value] = window_size
                else:
                    hash_map[pre_value] = window_size
            stack.append((j, value))
    a.pop()

def inverse_hash_map(hash_map, new_hash_map):
    # exchange keys and value:
    for value, window_size in hash_map.items():
        if window_size in new_hash_map:
            new_hash_map[window_size] = max(new_hash_map[window_size], value)
        else:
            new_hash_map[window_size] = value

def make_max_number_per_window_size(a, hash_map):
    solutions = list()
    for window_size in range(len(a), 0, -1):
        if window_size in hash_map:
            solutions.append(hash_map[window_size])
        else:
            solutions.append(solutions[-1])
    return solutions

def final_part(arr, max_window):
    ans = [0]*(len(arr)-1)
    v_ant = min(max_window.values())
    for i in range(len(arr)-1, 0, -1):
        if i in max_window and max_window[i] > v_ant:
            ans[i-1] = max_window[i]
            v_ant = max_window[i]
        else:
           ans[i-1] = v_ant
    return ans

def riddle(a):
    hash_map = dict()
    new_hash_map = dict()
    make_number_to_window_size(a, hash_map)
    inverse_hash_map(hash_map, new_hash_map)
    return final_part(a, new_hash_map) #make_max_number_per_window_size(a, new_hash_map)

if __name__ == "__main__":
    a = [6, 3, 5, 1, 12]
    a = [2, 6, 1, 12]
    a = [1, 2, 3, 5, 1, 13, 3]
    a = [3, 5, 4, 7, 6, 2]
    a = [6, 5, 4, 3, 2, 1]

    a = [11, 2, 3, 14, 5, 2, 11, 12]

    print(riddle(a))
    #hash_map = dict()
    #make_number_to_window_size(a, hash_map)
    #print(hash_map)

    #a = [1, 2, 3, 4, 5]

    # solutions = riddle(a)
    # print(solutions)

    # solutions = riddle(a)
    # print(solutions)


import time
import smbus
import math
import statistics
import socket
import RPi.GPIO as GPIO
from multiprocessing import Process
import threading

#
#    0     1
#     #   #
#      ###
#      ###
#     #   #
#    3     2
#

emergency_stop = [0]

KP_roll = 0.004
KI_roll = 0.006
KD_roll = 0.005

KP_pitch = 0.004
KI_pitch = 0.006
KD_pitch = 0.005

KP_yaw = 0.004
KI_yaw = 0.006
KD_yaw = 0.005

GyroPrev = [0,0,0]
GamepadPrev = [0,0,0]

motor = [0,0,0,0]
motor_gpio = [38, 35, 13, 18]
motor_control = []

gamepad_output = [0,0,0,0]

Gyro = [0,0,0]
Accel = [0,0,0]

AccelWindowX = []
AccelWindowY = []
AccelWindowZ = []

GyroAngles = [0,0,0]
AccelAngles = [0,0]
Angles = [0,0,0]

#GyroOffset = [-4.43, 20.46 , -0.308]
#AccelOffset = [0.0075, -0.0368, -0.056]
GyroOffset = [0,0,0]
AccelOffset = [0,0,0]

rate_pid_integral = [0,0,0]
angle_pid_integral = [0,0,0]

GyroSensitivity = 32.8
AccelSensitivity = 4096

RAD_TO_DEG = 180 / math.pi
true = 0x01
false = 0x00
I2C_ADD_ICM20948 = 0x68
I2C_ADD_ICM20948_AK09916 = 0x0C
I2C_ADD_ICM20948_AK09916_READ = 0x80
I2C_ADD_ICM20948_AK09916_WRITE = 0x00
REG_ADD_WIA = 0x00
REG_VAL_WIA = 0xEA
REG_ADD_USER_CTRL = 0x03
REG_VAL_BIT_DMP_EN = 0x80
REG_VAL_BIT_FIFO_EN = 0x40
REG_VAL_BIT_I2C_MST_EN = 0x20
REG_VAL_BIT_I2C_IF_DIS = 0x10
REG_VAL_BIT_DMP_RST = 0x08
REG_VAL_BIT_DIAMOND_DMP_RST = 0x04
REG_ADD_PWR_MIGMT_1 = 0x06
REG_VAL_ALL_RGE_RESET = 0x80
REG_VAL_RUN_MODE = 0x01
REG_ADD_LP_CONFIG = 0x05
REG_ADD_PWR_MGMT_1 = 0x06
REG_ADD_PWR_MGMT_2 = 0x07
REG_ADD_ACCEL_XOUT_H = 0x2D
REG_ADD_ACCEL_XOUT_L = 0x2E
REG_ADD_ACCEL_YOUT_H = 0x2F
REG_ADD_ACCEL_YOUT_L = 0x30
REG_ADD_ACCEL_ZOUT_H = 0x31
REG_ADD_ACCEL_ZOUT_L = 0x32
REG_ADD_GYRO_XOUT_H = 0x33
REG_ADD_GYRO_XOUT_L = 0x34
REG_ADD_GYRO_YOUT_H = 0x35
REG_ADD_GYRO_YOUT_L = 0x36
REG_ADD_GYRO_ZOUT_H = 0x37
REG_ADD_GYRO_ZOUT_L = 0x38
REG_ADD_EXT_SENS_DATA_00 = 0x3B
REG_ADD_REG_BANK_SEL = 0x7F
REG_VAL_REG_BANK_0 = 0x00
REG_VAL_REG_BANK_1 = 0x10
REG_VAL_REG_BANK_2 = 0x20
REG_VAL_REG_BANK_3 = 0x30
REG_ADD_GYRO_SMPLRT_DIV = 0x00
REG_ADD_GYRO_CONFIG_1 = 0x01
REG_VAL_BIT_GYRO_DLPCFG_2 = 0x10
REG_VAL_BIT_GYRO_DLPCFG_4 = 0x20
REG_VAL_BIT_GYRO_DLPCFG_6 = 0x30
REG_VAL_BIT_GYRO_FS_250DPS = 0x00
REG_VAL_BIT_GYRO_FS_500DPS = 0x02
REG_VAL_BIT_GYRO_FS_1000DPS = 0x04
REG_VAL_BIT_GYRO_FS_2000DPS = 0x06
REG_VAL_BIT_GYRO_DLPF = 0x01
REG_ADD_ACCEL_SMPLRT_DIV_2 = 0x11
REG_ADD_ACCEL_CONFIG = 0x14
REG_VAL_BIT_ACCEL_DLPCFG_2 = 0x10
REG_VAL_BIT_ACCEL_DLPCFG_4 = 0x20
REG_VAL_BIT_ACCEL_DLPCFG_6 = 0x30
REG_VAL_BIT_ACCEL_FS_2g = 0x00
REG_VAL_BIT_ACCEL_FS_4g = 0x02
REG_VAL_BIT_ACCEL_FS_8g = 0x04
REG_VAL_BIT_ACCEL_FS_16g = 0x06
REG_VAL_BIT_ACCEL_DLPF = 0x01
REG_ADD_I2C_SLV0_ADDR = 0x03
REG_ADD_I2C_SLV0_REG = 0x04
REG_ADD_I2C_SLV0_CTRL = 0x05
REG_VAL_BIT_SLV0_EN = 0x80
REG_VAL_BIT_MASK_LEN = 0x07
REG_ADD_I2C_SLV0_DO = 0x06
REG_ADD_I2C_SLV1_ADDR = 0x07
REG_ADD_I2C_SLV1_REG = 0x08
REG_ADD_I2C_SLV1_CTRL = 0x09
REG_ADD_I2C_SLV1_DO = 0x0A

# ICM20948
class ICM(object):
    def __init__(self,address=I2C_ADD_ICM20948):
        self._address = address
        self._bus = smbus.SMBus(1)
        bRet = self.icm20948Check()
        time.sleep(0.5)
        self._write_byte(REG_ADD_REG_BANK_SEL, REG_VAL_REG_BANK_0)
        self._write_byte(REG_ADD_PWR_MIGMT_1, REG_VAL_ALL_RGE_RESET)
        time.sleep(0.1)
        self._write_byte(REG_ADD_PWR_MIGMT_1, 0x09)
        self._write_byte(REG_ADD_LP_CONFIG, 0x00)
        self._write_byte(REG_ADD_REG_BANK_SEL, REG_VAL_REG_BANK_2)
        self._write_byte(REG_ADD_GYRO_SMPLRT_DIV, 0x00)
        self._write_byte(REG_ADD_GYRO_CONFIG_1, REG_VAL_BIT_GYRO_DLPCFG_2 | REG_VAL_BIT_GYRO_FS_1000DPS | true)
        self._write_byte(REG_ADD_ACCEL_SMPLRT_DIV_2, 0x00)
        self._write_byte(REG_ADD_ACCEL_CONFIG, REG_VAL_BIT_ACCEL_DLPCFG_2 | REG_VAL_BIT_ACCEL_FS_8g | true)
        self._write_byte(REG_ADD_REG_BANK_SEL, REG_VAL_REG_BANK_0)
        time.sleep(0.1)
        self.icm20948Offset()
        time.sleep(2)
        x = threading.Thread(target=self.read_gamepad)
        x.start()
        self.setup_motors()

    def emergency_stop(self):
        emergency_stop[0] = 1
        for i in range(2):
            for i in motor_control:
                i.ChangeDutyCycle(3)

    def read_gamepad(self):
        UDP_IP = "10.42.0.209"
        UDP_PORT = 5005
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.bind((UDP_IP, UDP_PORT))
        while True:
            data, addr = sock.recvfrom(1024)
            if data.decode('utf-8') == "stop":
                self.emergency_stop()
                break
            value = data.decode('utf-8').split()
            gamepad_output[0] = float(value[0])
            gamepad_output[1] = float(value[1])
            gamepad_output[2] = float(value[2])
            gamepad_output[3] = float(value[3])

    def setup_motors(self):
        GPIO.setwarnings(False)
        GPIO.setmode(GPIO.BOARD)
        y = 0
        for i in motor_gpio:
            GPIO.setup(i, GPIO.OUT)
            motor_control.append(GPIO.PWM(i, 50))
            motor_control[y].start(0)
            y += 1
        time.sleep(3)
        for i in motor_control:
            i.ChangeDutyCycle(3)
        i = 4
        while i<4.7:
            for y in motor_control:
                y.ChangeDutyCycle(i)
            print(i)
            time.sleep(0.1)
            i += 0.02

    def icm20948_Gyro_Accel_Read(self):
        data = self._read_block(REG_ADD_ACCEL_XOUT_H, 12)
        Accel[0] = data[0] << 8 | data[1]
        Accel[1] = data[2] << 8 | data[3]
        Accel[2] = data[4] << 8 | data[5]
        Gyro[0] = data[6] << 8 | data[7]
        Gyro[1] = data[8] << 8 | data[9]
        Gyro[2] = data[10] << 8 | data[11]
        if Accel[0] >= 32767:
            Accel[0] = Accel[0] - 65535
        elif Accel[0] <= -32767:
            Accel[0] = Accel[0] + 65535
        if Accel[1] >= 32767:
            Accel[1] = Accel[1] - 65535
        elif Accel[1] <= -32767:
            Accel[1] = Accel[1] + 65535
        if Accel[2] >= 32767:
            Accel[2] = Accel[2] - 65535
        elif Accel[2] <= -32767:
            Accel[2] = Accel[2] + 65535
        if Gyro[0] >= 32767:
            Gyro[0] = Gyro[0] - 65535
        elif Gyro[0] <= -32767:
            Gyro[0] = Gyro[0] + 65535
        if Gyro[1] >= 32767:
            Gyro[1] = Gyro[1] - 65535
        elif Gyro[1] <= -32767:
            Gyro[1] = Gyro[1] + 65535
        if Gyro[2] >= 32767:
            Gyro[2] = Gyro[2] - 65535
        elif Gyro[2] <= -32767:
            Gyro[2] = Gyro[2] + 65535
        AccelWindowX.append(Accel[0] / AccelSensitivity - AccelOffset[0])
        AccelWindowY.append(Accel[1] / AccelSensitivity - AccelOffset[1])
        AccelWindowZ.append(Accel[2] / AccelSensitivity - AccelOffset[2])
        Gyro[0] = Gyro[0] / GyroSensitivity - GyroOffset[0]
        Gyro[1] = Gyro[1] / GyroSensitivity - GyroOffset[1]
        Gyro[2] = Gyro[2] / GyroSensitivity - GyroOffset[2]
        if len(AccelWindowX) > 11:
            AccelWindowX.pop(0)
            AccelWindowY.pop(0)
            AccelWindowZ.pop(0)
        Accel[0] = statistics.median(AccelWindowX)
        Accel[1] = statistics.median(AccelWindowY)
        Accel[2] = statistics.median(AccelWindowZ)

    def icm20948ReadSecondary(self, u8I2CAddr, u8RegAddr, u8Len):
        u8Temp = 0
        self._write_byte(REG_ADD_REG_BANK_SEL, REG_VAL_REG_BANK_3)
        self._write_byte(REG_ADD_I2C_SLV0_ADDR, u8I2CAddr)
        self._write_byte(REG_ADD_I2C_SLV0_REG, u8RegAddr)
        self._write_byte(REG_ADD_I2C_SLV0_CTRL, REG_VAL_BIT_SLV0_EN | u8Len)
        self._write_byte(REG_ADD_REG_BANK_SEL, REG_VAL_REG_BANK_0)
        u8Temp = self._read_byte(REG_ADD_USER_CTRL)
        u8Temp |= REG_VAL_BIT_I2C_MST_EN
        self._write_byte(REG_ADD_USER_CTRL, u8Temp)
        time.sleep(0.01)
        u8Temp &= ~REG_VAL_BIT_I2C_MST_EN
        self._write_byte(REG_ADD_USER_CTRL, u8Temp)
        self._write_byte(REG_ADD_REG_BANK_SEL, REG_VAL_REG_BANK_3)
        u8Temp = self._read_byte(REG_ADD_I2C_SLV0_CTRL)
        u8Temp &= ~(REG_VAL_BIT_I2C_MST_EN & REG_VAL_BIT_MASK_LEN)
        self._write_byte(REG_ADD_I2C_SLV0_CTRL, u8Temp)
        self._write_byte(REG_ADD_REG_BANK_SEL, REG_VAL_REG_BANK_0)

    def icm20948WriteSecondary(self, u8I2CAddr, u8RegAddr, u8data):
        u8Temp = 0
        self._write_byte(REG_ADD_REG_BANK_SEL, REG_VAL_REG_BANK_3)
        self._write_byte(REG_ADD_I2C_SLV1_ADDR, u8I2CAddr)
        self._write_byte(REG_ADD_I2C_SLV1_REG, u8RegAddr)
        self._write_byte(REG_ADD_I2C_SLV1_DO, u8data)
        self._write_byte(REG_ADD_I2C_SLV1_CTRL, REG_VAL_BIT_SLV0_EN | 1)
        self._write_byte(REG_ADD_REG_BANK_SEL, REG_VAL_REG_BANK_0)
        u8Temp = self._read_byte(REG_ADD_USER_CTRL)
        u8Temp |= REG_VAL_BIT_I2C_MST_EN
        self._write_byte(REG_ADD_USER_CTRL, u8Temp)
        time.sleep(0.01)
        u8Temp &= ~REG_VAL_BIT_I2C_MST_EN
        self._write_byte(REG_ADD_USER_CTRL, u8Temp)
        self._write_byte(REG_ADD_REG_BANK_SEL, REG_VAL_REG_BANK_3)
        u8Temp = self._read_byte(REG_ADD_I2C_SLV0_CTRL)
        u8Temp &= ~(REG_VAL_BIT_I2C_MST_EN & REG_VAL_BIT_MASK_LEN)
        self._write_byte(REG_ADD_I2C_SLV0_CTRL, u8Temp)
        self._write_byte(REG_ADD_REG_BANK_SEL, REG_VAL_REG_BANK_0)

    def icm20948Offset(self):
        samples = 1000
        Gx = 0
        Gy = 0
        Gz = 0
        Ax = 0
        Ay = 0
        Az = 0
        for i in range(samples):
            self.icm20948_Gyro_Accel_Read()
            Gx += Gyro[0]
            Gy += Gyro[1]
            Gz += Gyro[2]
            Ax += Accel[0]
            Ay += Accel[1]
            Az += Accel[2]
        GyroOffset[0] = Gx / samples
        GyroOffset[1] = Gy / samples
        GyroOffset[2] = Gz / samples
        AccelOffset[0] = Ax / samples
        AccelOffset[1] = Ay / samples
        AccelOffset[2] = Az / samples - 1
        print("Calibrated")

    def _read_byte(self, cmd):
        return self._bus.read_byte_data(self._address,cmd)

    def _read_block(self, reg, length = 1):
        return self._bus.read_i2c_block_data(self._address, reg, length)

    def _read_u16(self, cmd):
        LSB = self._bus.read_byte_data(self._address, cmd)
        MSB = self._bus.read_byte_data(self._address, cmd + 1)
        return (MSB << 8) + LSB

    def _write_byte(self, cmd, val):
        self._bus.write_byte_data(self._address,cmd,val)
        time.sleep(0.0001)

    def icm20948Check(self):
        bRet = false
        if REG_VAL_WIA == self._read_byte(REG_ADD_WIA):
            bRet = true
        return bRet

    def Get_Gyro_Angles(self, delta_time):
        GyroAngles[0] += Gyro[0] * delta_time
        GyroAngles[1] += Gyro[1] * delta_time
        GyroAngles[2] += Gyro[2] * delta_time

    def Get_Accel_Angles(self):
        x = Accel[0]
        y = Accel[1]
        z = Accel[2]
        AccelAngles[0] = math.atan2(y, z) * RAD_TO_DEG
        AccelAngles[1] = math.atan2(-1 * x, math.sqrt(y * y + z * z)) * RAD_TO_DEG

    def Get_Angles(self, delta_time):
        GYRO_PART = 0.995
        ACCEL_PART = 0.005
        Angles[0] = GYRO_PART * (Angles[0] + Gyro[0] * delta_time) + ACCEL_PART * AccelAngles[0]
        Angles[1] = GYRO_PART * (Angles[1] + Gyro[1] * delta_time) + ACCEL_PART * AccelAngles[1]
        Angles[2] = GyroAngles[2]

    def Calculate(self, delta_time):
        self.icm20948_Gyro_Accel_Read()
        self.Get_Gyro_Angles(delta_time)
        self.Get_Accel_Angles()
        self.Get_Angles(delta_time)

    def Angle_PID(self, delta_time, axis, desired_angle, KP, KI, KD):
        error = desired_angle - Angles[axis]
        error = error * 4
        return self.Rate_PID(delta_time, axis, error, KP, KI, KD)

    def Rate_PID(self, delta_time, axis, desired_pitch, KP, KI, KD):
        error = desired_pitch - Gyro[axis]

        proportional = KP * error
        rate_pid_integral[axis] += KI * error * delta_time
        derivative = KD * (error - GyroPrev[axis] - GamepadPrev[axis])

        GamepadPrev[axis] = desired_pitch
        GyroPrev[axis] = Gyro[axis]

        return proportional + rate_pid_integral[axis] + derivative

if __name__ == '__main__':
    icm = ICM()
    iteration = 0
    delta_t = 0
    last_update = time.perf_counter()
    while True:
        # Stop if emergency stop
        if emergency_stop[0] == 1:
            print("emergency stop")
            break

        # Calculate delta time and set last update time
        delta_t = time.perf_counter() - last_update
        last_update = time.perf_counter()

        # Calculate read data and angles
        icm.Calculate(delta_t)

        # Calculate required thrust, roll, pitch and yaw
        Thrust = gamepad_output[0]
        Roll = icm.Angle_PID(delta_t, 0, gamepad_output[1], KP_roll, KI_roll, KD_roll)
        Pitch = icm.Angle_PID(delta_t, 1, gamepad_output[2], KP_pitch, KI_pitch, KD_pitch)
        Yaw = icm.Rate_PID(delta_t, 0, gamepad_output[3], KP_yaw, KI_yaw, KD_yaw)

        # Calculate thrust for each motor
        motor[0] = Thrust + Roll - Pitch - Yaw
        motor[1] = Thrust - Roll - Pitch + Yaw
        motor[2] = Thrust - Roll + Pitch - Yaw
        motor[3] = Thrust + Roll + Pitch + Yaw

        # Avoid overflow
        for i in range(len(motor)):
            if motor[i] > 10:
                motor[i] = 10
            elif motor[i] < 5:
                motor[i] = 5

        # Set thrust for each motor
        for i in range(len(motor_control)):
            motor_control[i].ChangeDutyCycle(motor[i])

        # Print some data every couple of times
        if iteration%200 == 0:
            print(motor[0], motor[1])
            print(motor[3], motor[2])
            print(Thrust, Roll, Pitch, Yaw)
            print("\n")
        iteration += 1


from mongoengine import *
from models.BtcModels import BtcAddress, BtcTransaction, TxInputAddrInfo, TxOutputAddrInfo
from models.models import AddressTransactionLink
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
from btc_functions import (get_tx, get_out_addrs, get_in_addrs,
    get_raw_tx, coalesce_input_addrs, get_out_addrs_for_inputs)
from btc_crawl import rpc_user, rpc_passwd

'''rpc_connection = AuthServiceProxy("http://%s:%s@127.0.0.1:8332" % (rpc_user, rpc_passwd))'''

def test_addr_neighbors():
    address = "15cE8MYa48tYKdeJg5TEn6VVWuTHeNcZbc"
    addr_obj = BtcAddress.objects(addr=address).first()
    #print("used as input length: ", len(addr_obj.used_as_input))
    #print("used as output length: ", len(addr_obj.used_as_output))
    print("neighbors length: ", len(addr_obj.neighbor_addrs))

def check_otc_conditions(output_tx, change_addr):
    # transaction cannot be a coinbase transaction
    if output_tx.coinbase_tx:
        return False

    tx_input_addrs = set([x.address for x in output_tx.input_addrs])
    tx_output_addrs = set([x.address for x in output_tx.output_addrs])

    # there cannot exist a self-change address (i.e an input address
    # also shows up in the output)
    if tx_input_addrs.intersection(tx_output_addrs):
        return False

    # all other output address have been seen before
    for addr in output_tx.output_addrs:
        if addr.address == change_addr:
            continue

        addr_links_input = AddressTransactionLink.objects(addr_ref_id=addr.addr_ref_id,
            addr_used_as_input=True).count()
        addr_links_output = AddressTransactionLink.objects(addr_ref_id=addr.addr_ref_id,
            addr_used_as_input=False).count()

        if addr_links_input == 0 and addr_links_output <= 1:
            return False

    return True

def compute_otc_stats():
    potential_change_addrs = BtcAddress.objects(neighbor_addrs__size=0).only('addr',
        'ref_id').limit(1000)
    for addr in potential_change_addrs:
        # print("addr: ", addr.addr)
        num_txs_using_addr_as_input = AddressTransactionLink.objects(addr_ref_id=addr.ref_id,
            addr_used_as_input=True).count()
        num_txs_using_addr_as_output = AddressTransactionLink.objects(addr_ref_id=addr.ref_id,
            addr_used_as_input=False).count()

        # print("num input: ", num_txs_using_addr_as_input)
        # print("num output: ", num_txs_using_addr_as_output)

        if num_txs_using_addr_as_input == 0 and num_txs_using_addr_as_output == 1:
            # print("possible OTC")
            output_tx_link = AddressTransactionLink.objects(addr_ref_id=addr.ref_id,
            addr_used_as_input=False).only('tx_ref_id').first()
            output_tx = BtcTransaction.objects(ref_id=output_tx_link.tx_ref_id).first()
            otc_addr = check_otc_conditions(output_tx, addr.addr)
            if otc_addr:
                print("OTC ADDR!!")
                print("========================")

def test():
    num_addrs = BtcAddress.objects().count()
    print(num_addrs)

if __name__ == "__main__":
    # compute_otc_stats()
    test()


from datetime import datetime
import pandas as pd
import numpy as np
#from datetime import timedelta
import time
CITY_DATA = { 'chicago': 'chicago.csv',
              'new york': 'new_york_city.csv',
              'washington': 'washington.csv' }
def get_city():
    """
    Function:
        Asks user to specify a city to analyse.
    Args:
        None
    Returns:
        (str) city - name of the city to analyse.
    """
    # TO DO: get user input for city (chicago, new york city, washington). HINT: Use a while loop to handle invalid inputs
    cities = ['Chicago','New York','Newyork','Washington']
    while True:
        try:
            city = input("\nWould you like to see data for Chicago, New york, or Washington?")
            if city.title() not in cities:
                print("\nPlease enter a valid city.")
                city = input('\nWould you like to see data for Chicago, New york, or Washington?')
            break
        except:
            print("\nLooks like it is not a valid input.")
    if city.title() == 'Newyork':
        city = city[0:3] + ' ' + city[3:]
    return city.lower()
def get_month():
    """
    Function:
        Asks user to specify a month to filter the data.
    Args:
        None
    Returns:
        (str)month - name of the month to filter the data.
    """
    month = ''
    numbers = ['1','2','3','4','5','6','7','8','9','0']
    months = ['January', 'February', 'March', 'April', 'May', 'June']
    if month not in months:
        while True:
             try:
                    month = input("\nWhich month? January, February, March, April, May or June?")
                    if month in numbers:
                        print('\nPlease do not enter the month in numbers')
                    if month.title() not in months:
                        print("\nPlease enter a month between January and June")
                        while True:
                            try:
                                month = input("\nWhich month? January, February, March, April, May or June?")
                                break
                            except:
                                print("\nLooks like it is not a valid input.")
                    break
             except:
                print("\nLooks like it is not a valid input")
    return month
def get_day():
    """
    Function:
        Asks user to specify a day to filter the data
    Args:
        None
    Returns:
        (str)day - name of the day to filter the data.
    """
    while True:
        try:
            day = int(input("\nWhich day? Please type your response as an integer.(e.g.,sunday = 1)"))
            break
        except:
            print("\nLooks like it is not a valid input.")
    return day
def get_filter():
    '''
    Function:
        Asks user to apply a filter
    Args:
        None
    Returns:
        specific filter entered by the user
    '''
    filter = ''
    filters = ['month','day','none']
    if filter not in filters:
        while True:
            try:
                filter = input("\nWould you like to filter the data by month, day, or not at all? Type 'none' for no time filter.")
                if filter.lower() not in filters:
                    print("\nInvalid filter!")
                    filter = input("\nWould you like to filter the data by month, day, or not at all? Type 'none' for no time filter.")
                break
            except:
                print("\nLooks like it is not a valid input.")
    #if filter == 'none':
     #   filter  = filter.title()
    return filter
def get_data():
    """
    Function:
        Asks user to specify a city, month, and day to analyze.
    Args:
        None
    Returns:
        (str) city - name of the city to analyze
        (str) month - name of the month to filter by, or "all" to apply no month filter
        (str) day - name of the day of week to filter by, or "all" to apply no day filter
        (str) filter - filter specified by the user
    """
    print('\nHello! Let\'s explore some US bikeshare data!')
    # TO DO: get user input for city (chicago, new york city, washington). HINT: Use a while loop to handle invalid inputs
    city = get_city()
    filter = get_filter()
    if filter == 'month':
        # TO DO: get user input for month (all, january, february, ... , june)
        month = get_month()
        day = None
    elif filter == 'day':
        # TO DO: get user input for day of week (all, monday, tuesday, ... sunday)
        day = get_day()
        month = None
    else:
        month,day = None,None
    print('-'*40)
    return city,month,day,filter

def load_data(city, month, day,filter):
    """
    Function:
        Loads data for the specified city and filters by month and day if applicable.

    Args:
        (str) city - name of the city to analyze
        (str) month - name of the month to filter by, or "all" to apply no month filter
        (str) day - name of the day of week to filter by, or "all" to apply no day filter
        (str) filter - specific filter that entered by user
    Returns:
        df - Pandas DataFrame containing city data filtered by month and day
    """

    df = pd.read_csv(CITY_DATA[city])
    df.fillna(0)
    if filter == 'none':
        df_filter = df
    elif filter == 'month':
        months = {'january':1,'february':2,'march':3,'april':4,'may':5,'june':6}
        df['Start Time'] = pd.to_datetime(df['Start Time'])
        df['month'] = df['Start Time'].dt.month
        df_filter = df[df['month'] == months[month]]
    else:
        days = {1:'Sunday',2:'Monday',3:'Tuesday',4:'Wednesday',5:'Thursday',6:'Friday',7:'Saturday'}
        df['Start Time'] = pd.to_datetime(df['Start Time'])
        df['day'] = df['Start Time'].dt.weekday_name
        df_filter = df[df['day'] == days[day]]
    return df_filter

def time_stats(df,filter):
    """
    Function:
        Displays statistics on the most frequent times of travel.
    Args:
        df - python data frame
        filter - specific filter that entered by user
    Returns:
        None
    """
    print('Calculating The Most Frequent Times of Travel...\n')
    start_time = time.time()
    # TO DO: display the most common month
    if filter == 'day' or filter == 'none':
        months = ['January', 'February', 'March', 'April', 'May', 'June']
        df['Start Time'] = pd.to_datetime(df['Start Time'])
        index = df['Start Time'].dt.month.mode()[0]
        most_pop_month = months[index - 1]
        print('\nMost popular month: {}'.format(most_pop_month))

    # TO DO: display the most common day of week
    if filter == 'month' or filter == 'none':
        days_of_week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
                    'Saturday', 'Sunday']
        df['Start Time'] = pd.to_datetime(df['Start Time'])
        index = df['Start Time'].dt.dayofweek.mode()[0]
        most_pop_day = days_of_week[index]
        print('\nMost popular day: {}'.format(most_pop_day))
    # TO DO: display the most common start hour
    if filter == 'month' or filter == 'day' or filter == 'none':
        df['Start Time'] = pd.to_datetime(df['Start Time'])
        most_pop_hour = df['Start Time'].dt.hour.mode()[0]
        if most_pop_hour == 0:
            meridiem = 'am'
            most_pop_hour = 12
        elif 1 <= most_pop_hour < 13:
            meridiem = 'am'
        elif 13 <= most_pop_hour < 24:
            meridiem = 'pm'
            most_pop_hour -= 12
        print('\nThe most popular hour of day for start time is {}{}.'.format(most_pop_hour, meridiem))

    print("\nThis took %s seconds." % (time.time() - start_time))
    print('-'*40)

def station_stats(df):
    """Function:
            Displays statistics on the most popular stations and trip.
       Args:
            df - Pandas data frame filtered by month or day
       Returns:
            None
    """

    print('\nCalculating The Most Popular Stations and Trip...\n')
    start_time = time.time()

    # TO DO: display most commonly used start station
    pop_start_station = df['Start Station'].mode()[0]
    print('\nThe most popular start station is: {}'.format(pop_start_station))
    # TO DO: display most commonly used end station
    pop_end_station = df['End Station'].mode()[0]
    print('\nThe most popular end station is: {}'.format(pop_end_station))

    # TO DO: display most frequent combination of start station and end station trip
    df['trip'] = df['Start Station'] + ' to ' + df['End Station']
    pop_trip = df['trip'].mode()[0]
    print('\nThe most popular trip is: {}'.format(pop_trip))
    print("\nThis took %s seconds." % (time.time() - start_time))
    print('-'*40)

def trip_duration_stats(df):
    """Function:
            Displays statistics on the total and average trip duration.
       Args:
            df - Pandas data frame filtered by month or day
       Returns:
            None
    """

    print('\nCalculating Trip Duration...\n')
    start_time = time.time()

    # TO DO: display total travel time
    total_trip_duration = df['Trip Duration'].sum()
    remain_seconds = total_trip_duration % 60
    minutes = total_trip_duration // 60
    remain_minutes = minutes % 60
    hours = minutes // 60
    print('\nThe total trip duration is {} hours, {} minutes, {} seconds'.format(hours,remain_minutes,remain_seconds))
    # TO DO: display mean travel time
    mean_trip_time = df['Trip Duration'].mean()
    remain_seconds = mean_trip_time % 60
    minutes = mean_trip_time // 60
    remain_minutes = minutes % 60
    hours = minutes // 60
    print('\nThe mean trip duration is {} hours, {} minutes, {} seconds'.format(hours,remain_minutes,remain_seconds))
    print("\nThis took %s seconds." % (time.time() - start_time))
    print('-'*40)

def user_stats(df,city):
    """Function:
            Displays statistics on bikeshare users.
       Args:
            df - Pandas data frame filtered by month or day
            city - specific city that entered by user
    """

    print('\nCalculating User Stats...\n')
    start_time = time.time()

    # TO DO: Display counts of user types
    df['User'] = df['User Type']
    subscribers = df.query('User == "Subscriber" ').User.count()
    customers = df.query('User == "Customer" ').User.count()
    print('\nThere are {} subscribers and {} customers'.format(subscribers,customers))
    # TO DO: Display counts of gender
    if city == 'chicago' or city == 'new york':
        male = df.query('Gender == "Male" ').Gender.count()
        female = df.query('Gender == "Female" ').Gender.count()
    # TO DO: Display earliest, most recent, and most common year of birth
        earliest_birth = df['Birth Year'].min()
        most_recent_birth = df['Birth Year'].max()
        most_common_birth = df['Birth Year'].mode()[0]
        print('\nOldest user was born in: {}'.format(earliest_birth))
        print('\nYoungest user was born in: {}'.format(most_recent_birth))
        print('\nMost popular birth year is: {}'.format(most_common_birth) )
        print("\nThis took %s seconds." % (time.time() - start_time))
        print('-'*40)

def more_data(df,filter):
    '''
    Function:
        Calculates individual trip data
    Args:
        df - Pandas data frame filtered by month or day
        filter - specific filter entered by user
    Returns:
        None
    '''
    if filter == 'month':
        df = df.drop(['trip','User','month'], axis = 1)
        print(df.head(1))
        print('-'*40)
    elif filter == 'day':
        df = df.drop(['trip','User','day'], axis = 1)
        print(df.head(1))
        print('-'*40)
    else:
        df = df.drop(['trip','User'], axis = 1)
        print(df.head(1))
        print('-'*40)
def individual_trip_stats(df,filter):
    '''
    Function:
        Asks if user wants to see individual trip data
    Args:
        df - Pandas data frame filtered by month or day
        filter - specific filter that entered by user
    Returns:
        None
    '''
    start_time = time.time()
    key = True
    while key == True:
        opt_more_data = input('Would you like to see individual trip data?(yes or no)')
        if opt_more_data.lower() == 'yes':
            more_data(df,filter)
        elif opt_more_data.lower() == 'no':
            break
        else:
            print("Looks like it is not a valid input.")
    print('\nThis took %s seconds.'%(time.time() - start_time))
    print('-'*40)

def main():
    while True:
        city, month, day,filter = get_data()
        df = load_data(city, month, day, filter)
        time_stats(df,filter)
        station_stats(df)
        trip_duration_stats(df)
        user_stats(df,city)
        individual_trip_stats(df,filter)
        restart = input('\nWould you like to restart? Enter yes or no.\n')
        if restart.lower() != 'yes':
            break

if __name__ == "__main__":
	main()


from __future__ import print_function

def main():
    bt = [4, 6, 3, 5, 7]
    prio=[2,3,1,4,5]
    TurnAT = 0
    wt = 0
    avwt=0
    print("Enter total number of processes in range 1-5:")
    n=int(raw_input())
    print("\n  Process no.    Waiting Time   Turnaround Time")
    i = 0
    while i < n:
        j = 0
        while j < n:
            if (prio[i] < prio[j]):
                swap = bt[i]
                bt[i] = bt[j]
                bt[j] = swap
            j += 1
        i += 1
    i = 0
    while i < n:
        TurnAT = bt[i] + wt
        avwt += wt
        print(i + 1,  "\t\t\t\t ", wt, "\t\t\t\t ", TurnAT)
        wt += bt[i]
        i += 1
    avwt /= i
    print("\n  Average Waiting Time", avwt)

    return 0;

main()


from odoo import models, fields, api

class SubstituirOrientador(models.TransientModel):
    _name = 'ud.biblioteca.substituir_orientador.wizard'

    novo_orientador = fields.Char('Nome', required=True)
    ultimo_nome = fields.Char('Último nome', required=True)
    titulacao_id = fields.Many2one('ud.biblioteca.orientador.titulacao', 'Titulação', required=True)

    def substituir_orientador(self):
        """
        Cria um novo orientador, busca as publicações afetadas pelo orientador selecionada,
        remove as selecionadas, subistitui pela novo orientador
        :return:
        """
        orientador_sel_ids = self._context.get('active_ids')
        orientador_model = self.env[self._context.get('active_model')]

        # localiza todas as publicações afetadas e remove a palavra antiga
        pub_afetadas_orientador = set()
        pub_afetadas_coorientador = set()
        for orientador in orientador_model.browse(orientador_sel_ids):
            for pub in orientador.publicacao_orientador_ids:
                pub_afetadas_orientador.add(pub.id)
            for pub in orientador.publicacao_coorientador_ids:
                pub_afetadas_coorientador.add(pub.id)
            orientador.unlink()

        # Cria o novo orientador
        orientador_model.create({
            'name': self.novo_orientador,
            'ultimo_nome': self.ultimo_nome,
            'titulacao_id': self.titulacao_id.id,
            'publicacao_orientador_ids': [(4, p) for p in pub_afetadas_orientador],
            'publicacao_coorientador_ids': [(4, p) for p in pub_afetadas_coorientador],
        })
        return {}


from socketserver import ForkingTCPServer
from socketserver import StreamRequestHandler

class Handler(StreamRequestHandler):

    def handle(self):
       	request = self.rfile.read(1024)
        print(request.decode())
        http_response = b"""\
HTTP/1.1 200 OK

Hello, World!
"""
        self.wfile.write(http_response)

server = ForkingTCPServer(("127.0.0.1", 8888), Handler)
server.serve_forever()


file=open("Kate/26_7855.txt")
NumRol=int(file.readline()[:-1])
NumGuests=int(file.readline()[:-1])
Time=[]
Rol=[0]*NumRol
for i in range(NumGuests):
    TimeIn,TimeOut=map(int,file.readline().split())
    Time.append([TimeIn,TimeOut+30])
Time.sort()
last=0
timeDelay=0
for i in range(NumGuests):
    flag=False
    for j in range(NumRol-1,0,-1):
        if (Time[i][0]>Rol[j]):
            Rol[j]=Time[i][1]
            last=j+1
            flag=True
            break
    if not flag:
        timeDelay=max(min(Rol)-Time[i][0],timeDelay)
        Rol[Rol.index(min(Rol))]=Time[i][1]
        last=Rol.index(min(Rol))+1
print(timeDelay,last)


# Paulean Marguerette F. Parrish
# Bscpe 1-4
# Problem no. 2
# Write a Python program that read a file containing the name of 20 students together with their GWA.
# The program will outputs the name of the student who got the highest GWA (including the GWA).

# Header design
import pyfiglet

print(" \033[95mHello! I hope you're having a great day!!! ".center(70, "="))
print("")

# Ask for the name of the user
user_name = input("\033[92mMay I know your name? \033[0m")
print("\n\033[94mThank you", user_name,  "you may now proceed to the program!")
print("")

# Open the Name_and_GWA.txt and read the file
with open('Name_and_GWA.txt', 'r') as input_file:

    # Initialize the highest GWA and student name
    highest_gwa = 5.00

    # Iterate over each line
    for line in input_file:

        # Split the line into the student name and GWA
        name, gwa = line.strip().split(',')

        # Convert the GWA to a float
        gwa = float(gwa)

        # Compare the GWA to the current highest GWA
        if gwa < highest_gwa:

            # Update the highest GWA and student name
            highest_gwa = gwa
            highest_student = name

# Print the name of the student who got the highest GWA
    print("\033[95mThe student with the highest GWA is", highest_student, "with a GWA of ", highest_gwa)

# Column for the names and GWA
print("\n\033[93mAmong the list of students:")
with open("Name_and_GWA.txt") as column_file:
  print("{:<25}{:<25}".format("\nStudent Name:", "  GWA:\n"))
  for line in column_file:
    name, gwa = line.split(",")
    column_name = name
    column_gwa = gwa
    print("{:<25}{:<25}".format(column_name, column_gwa))

# Program is completed
from termcolor import colored
from pyfiglet import Figlet
f = Figlet(font = "banner3-d")
print(colored(f.renderText('Thank you!'), 'red'))


import sys

n = int(input())

paper = []
blue = 0
white = 0

for _ in range(n):
    paper.append(list(map(int, list(sys.stdin.readline().split()))))

def dividePaper(rs, cs, l):
    compare = paper[rs][cs]
    global blue, white
    for i in range(rs, rs + l):
        for j in range(cs, cs + l):
            if paper[i][j] != compare:
                next = l // 2
                dividePaper(rs, cs, next)
                dividePaper(rs, cs + next, next)
                dividePaper(rs + next, cs, next)
                dividePaper(rs + next, cs + next, next)
                return
    if compare == 1:
        blue += 1
    else:
        white += 1
    return

dividePaper(0, 0, n)
print(white)
print(blue)


import tensorflow as tf

class InputEmbeddingLayer(tf.keras.layers.Layer):

    def __init__(self, seq_len, vocab_size, embed_dim):
        super(InputEmbeddingLayer, self).__init__()
        self.seq_len = seq_len

        self.pos_embed = tf.keras.layers.Embedding(input_dim=seq_len, output_dim=embed_dim)

        self.token_embed = tf.keras.layers.Embedding(input_dim=vocab_size, output_dim=embed_dim)

    @tf.function
    def call(self, input):
        pos_code_indices = tf.range(0, self.seq_len)

        # call both embedding-layers
        input_e = self.token_embed(input)
        pos_e = self.pos_embed(pos_code_indices)
        # return the sum of both
        # return tf.keras.layers.Add()([input_e, pos_e])
        return tf.add(input_e, pos_e)


def solution(my_string):
  answer = ''
  my_dict = dict()

  for s in my_string:
    my_dict[s] = True

  for d in my_dict:
    answer += d

  return answer

print(solution("people"))
print(solution("We are the world"))


import numpy as np
import gym
from stable_baselines3 import PPO
# from stable_baselines.common import make_vec_env
from openDSSenv34 import openDSSenv34
# import json
# import datetime as dt
import torch
# from stable_baselines3.common.utils import set_random_seed
from feedforwardPolicy import *
from stable_baselines3 import A2C, PPO
from CustomPolicies import ActorCriticGCAPSPolicy
from DSS_Initialize import   *

class CustomGNN(BaseFeaturesExtractor):
    """
    :param observation_space: (gym.Space)
    :param features_dim: (int) Number of features extracted.
        This corresponds to the number of unit for the last layer.
    """

    def __init__(self,
                observation_space: gym.spaces.Box,
                 features_dim: int = 256,
                 n_layers=2,
                 n_dim=256,
                 n_p=1,
                 node_dim=3,
                 n_K=1,
                 ):
        super(CustomGNN, self).__init__(observation_space, features_dim)
        self.n_layers = n_layers
        self.n_dim = n_dim
        self.n_p = n_p
        self.n_K = n_K
        self.node_dim = node_dim
        self.init_embed = torch.nn.Linear(node_dim, n_dim * n_p)
        self.init_embed_depot = torch.nn.Linear(2, n_dim)

        self.W_L_1_G1 = torch.nn.Linear(n_dim * (n_K + 1) * n_p, n_dim)

        self.normalization_1 = torch.nn.BatchNorm1d(n_dim * n_p)

        self.W_F = torch.nn.Linear(n_dim * n_p, features_dim)
        self.full_context_nn = th.nn.Linear(41, features_dim)
        self.switch_encoder = torch.nn.Linear(2 * features_dim, features_dim)

        self.activ = torch.nn.Tanh()

    def forward(self, data):
        X = data['NodeFeat(BusVoltage)']
        # X = torch.cat((data['loc'], data['deadline']), -1)
        num_samples, num_locations, _ = X.size()
        # A = ((1 / distance_matrix) * (torch.eye(num_locations, device=distance_matrix.device).expand(
        #    (num_samples, num_locations, num_locations)) - 1).to(torch.bool).to(torch.float))
        # A[A != A] = 0
        A = data["Adjacency"]
        # print(A.shape)
        D = torch.mul(torch.eye(num_locations).expand((num_samples, num_locations, num_locations)),
                      (A.sum(-1))[:, None].expand((num_samples, num_locations, num_locations)))

        # Layer 1

        F0 = self.init_embed(X)

        L = D - A

        g_L1_1 = self.W_L_1_G1(torch.cat((F0[:, :, :],
                                          torch.matmul(L, F0)[:, :, :]
                                          ),
                                         -1))

        F1 = g_L1_1  # torch.cat((g_L1_1), -1)
        # F1 = self.activ(F1)

        F_final = self.W_F(F1)

        h = F_final  # torch.cat((init_depot_embed, F_final), 1)

        switch_embeddings = self.switch_encoder(
            torch.cat((h[:, switch_bus_map[:, 0], :], h[:, switch_bus_map[:, 1], :]), -1))
        context = self.full_context_nn(th.cat((data["loss"], data["EdgeFeat(branchflow)"]), -1))
        return self.activ(switch_embeddings.mean(dim=1)) + context

def learning_rate_schedule(initial_value: float) -> Callable[[float], float]:

    def func(progress_remaining: float) -> float:

        # return max((progress_remaining**2) * initial_value, 0.0002)

        return  initial_value
    return func

env = openDSSenv34()
rms_prop_eps = 1e-5
policy_kwargs = dict(
    features_extractor_class=CustomGNN,
    features_extractor_kwargs=dict(features_dim=128),
    activation_fn=torch.nn.Tanh,
    net_arch=[dict(vf=[128,128])]
)

observations = env.test_func()

log_dir = "."
# model.save(log_dir + "r1_34_bus")
model = PPO.load(log_dir + "r1_34_bus_gcaps_with_entropy_05_multi_env_2", env=env)

for i in range(10):
    observations['loss'] = np.float32(np.reshape(observations['loss'], (1,)))
    observations['TopologicalConstr'] = np.reshape(observations['TopologicalConstr'], (1,))
    observations['VoltageViolation'] = np.reshape(observations['VoltageViolation'], (1,))
    observations['FlowViolation'] = np.reshape(observations['FlowViolation'], (1,))
    observations['Convergence'] = np.reshape(observations['Convergence'], (1,))
    observations['EdgeFeat(branchflow)'] = np.float32(observations["EdgeFeat(branchflow)"])
    action, _states = model.predict(observations, deterministic=True)
    observations, rewards, dones, info = env.step(action)
    observations = env.test_func()


from .framework import *

class PedidoDomesticoEspecificacion(BaseEspecificacion):
    """
    Define la especificacion que el pedido
    debe ser local
    """
    def es_satisfecho_por(self, pedido):
        return pedido.direccion_destino.pais == 'ARG'

class MaterialPeligrosoEspecificacion(BaseEspecificacion):
    '''
    Define la especificacion para evaluar si tiene material
    peligroso
    '''

    def es_satisfecho_por(self, pedido):
        items = pedido.obtener_items_pedido()
        hay_peligro = 0
        for i in items:
            if i.tiene_material_peligroso:
                hay_peligro += 1
        return hay_peligro > 0

class PedidoValorElevadoEspecificacion(BaseEspecificacion):
    '''
    Evalua si el pedido tiene un valor alto
    '''

    def es_satisfecho_por(self, pedido):
        items = pedido.obtener_items_pedido()
        valor_pedido = 0
        for i in items:
            valor_pedido += i.precio
        return valor_pedido > 20

class HayStockEspecificacion(BaseEspecificacion):
    '''
    Evalua si hay stock para el pedido
    '''
    def es_satisfecho_por(self, pedido):
        items = pedido.obtener_items_pedido()
        hay_stock = True
        for i in items:
            if not i.hay_stock:
                hay_stock = False
        return hay_stock

class PedidoRapidoEspecificacion(BaseEspecificacion):
    '''
    Evalua se en un pedido de salida rapida
    '''
    def __init__(self):
        self._pedido_local_espec = PedidoDomesticoEspecificacion()
        self._valor_alto_espec = PedidoValorElevadoEspecificacion()
        self._material_peligroso_espec = MaterialPeligrosoEspecificacion()
        self._hay_stock_espec = HayStockEspecificacion()

    def es_satisfecho_por(self, candidata):
        return self._pedido_local_espec\
            .y(self._material_peligroso_espec)\
            .y(self._hay_stock_espec)\
            .y(self._valor_alto_espec)\
            .es_satisfecho_por(candidata)


from scrapy import Item,Field

class DmozItem(Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = Field()
    link = Field()
    description = Field()

#follow person information
class InformationItem(Item):
    _id = Field()
    Info = Field()
    Num_Tweets = Field()
    Num_Follows = Field()
    Num_Fans = Field()
    Home_Page = Field()

#tweets info
class TweetsItem(Item):
    _id = Field()
    Content = Field()
    Time_Location = Field()
    Pic_Url = Field()
    Num_Comment = Field()
    Num_Like = Field()
    NUm_Transfer = Field()