import time
import random
from math import inf
from itertools import chain

from utils.result_set import ResultSet

class NSGA2:
    def __init__(self, order, heuristics, generations=100, population_size=100,
                 k_parents=2, crossover_chance=0.6, mutation_chance=0.4):
        self.order = order
        self.nodes_count = len(order)
        self.heuristics = heuristics
        self.dimensions = heuristics.dimensions
        self.generations = generations
        self.population_size = population_size
        self.sort_percentage = 0.5
        self.k_parents = min(population_size, k_parents)
        self.crossover_chance = crossover_chance
        self.mutation_chance = mutation_chance / self.nodes_count

        self.generate_strategy = 'random'
        # self.generate_strategy = 'prefix'
        # self.generate_strategy = 'heuristic'

        # self.crossover_strategy = 'partial_parent'
        self.crossover_strategy = 'majority'
        # self.crossover_strategy = 'vertex_cover'

        self.mutation_strategy = 'vertex_cover'
        # self.mutation_strategy = 'heuristic'

        self.this_population, self.next_population = self.generate_population()

    def run(self):
        for generation in range(self.generations):
            print('Generation', generation + 1)

            # crossover
            self.crossover()

            # mutation
            self.mutation()

            # sort population according to domination rank and crowding distance
            self.next_population = self.selection(*self.sort_population())
            self.this_population = self.copy_individuals(self.next_population)

            # self.crossover_chance *= 0.99
            # self.mutation_chance *= 1.1
            # print('Crossover {:.2f} - Mutation {:.3f}'.format(self.crossover_chance, self.mutation_chance))

    def generate_population(self):
        if self.generate_strategy == 'random':
            return self._generate_random_population()
        elif self.generate_strategy == 'prefix':
            return self._generate_prefix_population()
        elif self.generate_strategy == 'heuristic':
            return self._generate_heuristic_population()

    def _generate_random_population(self, zero_chance=0.2):
        populations = []

        # initialise chromosomes for current and next population
        for _ in range(2):
            population = []
            for count in range(self.population_size):
                chromosome = [0 if random.random() < zero_chance else 1 for _ in range(self.nodes_count)]
                new_individual = {
                    'chromosome': chromosome,
                    'cost': self.heuristics.compute_cost(chromosome)[0].pop()
                }
                population.append(new_individual)
            populations.append(population)

        return populations

    def _generate_prefix_population(self):
        populations = []

        viable = 2 * self.population_size
        min_length = len(bin(viable)) - 2
        counter = 0
        while viable:
            # get best assignment starting with this prefix
            partial_assignment = list(map(int, bin(counter)[2:].ljust(min_length, '0')))
            result, next_best = self.heuristics.compute_cost(partial_assignment)
            while not all(all(value == inf for value in cost) for cost in result) and \
                    len(partial_assignment) < self.nodes_count:
                partial_assignment.append(next_best)
                if len(partial_assignment) == self.nodes_count:
                    break
                result, next_best = self.heuristics.compute_cost(partial_assignment)

            # check if full solution and add to population
            if len(partial_assignment) == self.nodes_count:
                populations.append({
                    'chromosome': partial_assignment,
                    'cost': self.heuristics.compute_cost(partial_assignment)[0].pop()
                })
                viable -= 1

            counter += 1

        return populations[:self.population_size], populations[self.population_size:]

    def _generate_heuristic_population(self, heuristic_chance=0.5):
        populations = []

        # initialise chromosomes for current and next population
        for _ in range(2):
            population = []
            for count in range(self.population_size):
                chromosome = []
                for _ in range(self.nodes_count):
                    if random.random() < heuristic_chance:
                        _, next_best = self.heuristics.compute_cost(chromosome)
                        chromosome.append(next_best)
                    else:
                        chromosome.append(1)

                new_individual = {
                    'chromosome': chromosome,
                    'cost': self.heuristics.compute_cost(chromosome)[0].pop()
                }
                population.append(new_individual)
            populations.append(population)

        return populations

    def sort_population(self, combined=None, keep_best=None):
        # combine first and this population then sort and select next population
        combined = combined or (self.this_population + self.next_population)
        keep_best = keep_best or int(self.population_size * self.sort_percentage)

        # clean domination count and dominates for all individuals to be sorted
        for item in combined:
            if 'domination_count' in item:
                del item['domination_count']
            if 'dominates' in item:
                del item['dominates']
            if 'rank' in item:
                del item['rank']

        # compute domination rank for each chromosome
        first_front = []
        for first_count, first_individual in enumerate(combined):
            first_individual.setdefault('domination_count', 0)
            first_individual.setdefault('dominates', [])

            for second_individual in combined[first_count + 1:]:
                second_individual.setdefault('domination_count', 0)
                second_individual.setdefault('dominates', [])

                if first_individual['cost'] < second_individual['cost']:
                    first_individual['dominates'].append(second_individual)
                    second_individual['domination_count'] += 1
                elif first_individual['cost'] > second_individual['cost']:
                    second_individual['dominates'].append(first_individual)
                    first_individual['domination_count'] += 1

            # check if first individual belongs to the first front
            if not first_individual['domination_count']:
                first_individual['rank'] = 0
                first_front.append(first_individual)

        print('First front ({})'.format(len(first_front)), [item['cost'] for item in first_front][:10])

        # build next fronts starting from first front
        counter = 0
        fronts = [first_front]
        already_added = len(first_front)
        while already_added < keep_best:
            next_front = []
            for individual in fronts[counter]:
                for dominated in individual['dominates']:
                    dominated['domination_count'] -= 1
                    if not dominated['domination_count']:
                        dominated['rank'] = counter + 1
                        next_front.append(dominated)
            counter += 1
            already_added += len(next_front)
            fronts.append(next_front)

        # add other as last front in order to assign them a rank and a distance for tournament selection
        last_front = []
        for individual in combined:
            if 'rank' in individual:
                continue
            individual['rank'] = counter + 1
            last_front.append(individual)
        if last_front:
            fronts.append(last_front)

        # compute crowding distance on each front
        self.crowding_distance(fronts)

        # select best individuals according to crowding domination
        if last_front:
            return sorted(chain(*fronts[:-1]), key=lambda x: (x['rank'], -x['distance']))[:keep_best], last_front
        else:
            return sorted(chain(*fronts), key=lambda x: (x['rank'], -x['distance']))[:self.population_size], last_front

    @staticmethod
    def crowding_distance(fronts):
        for front in fronts:
            # initialize distances
            for individual in front:
                individual['distance'] = 0

            # for each objective sort and add distance
            objectives_count = len(front[0]['cost'])
            for dimension in range(objectives_count):
                sorted_front = sorted(front, key=lambda x: x['cost'][dimension])

                # save min and max values of this objective to normalize
                min_value = sorted_front[0]['cost'][dimension]
                max_value = sorted_front[-1]['cost'][dimension]
                factor = (max_value - min_value) or 10 ** -6

                # keep the most extreme solutions of this front
                sorted_front[0]['distance'] = sorted_front[-1]['distance'] = inf

                # update distance for each individual that is not an edge of the front
                for position, individual in enumerate(sorted_front[1:-1], 1):
                    individual['distance'] += (sorted_front[position + 1]['cost'][dimension] -
                                               sorted_front[position - 1]['cost'][dimension]) / factor

    def selection(self, temp_population, remaining):
        # tournament selection using rank and crowding distance
        while len(temp_population) < self.population_size:
            first, second = random.sample(remaining, 2)
            if (first['rank'], -first['distance']) < (second['rank'], -second['distance']):
                chosen = first
            else:
                chosen = second
            new_individual = self.copy_individual(chosen)
            temp_population.append(new_individual)
        return temp_population

    def crossover(self):
        if self.crossover_strategy == 'partial_parent':
            return self._partial_parent_crossover()
        elif self.crossover_strategy == 'majority':
            return self._majority_crossover()
        elif self.crossover_strategy == 'vertex_cover':
            return self._vertex_cover_crossover()

    def _partial_parent_crossover(self):
        for count in range(int(self.population_size * self.crossover_chance)):
            chosen_parents = random.sample(self.next_population, self.k_parents)
            new_individual = {'chromosome': [], 'cost': None}

            # choose each position according to best partial assignment of parent
            for position in range(self.nodes_count):
                # compute all partial assignments of the chosen parents
                parent_costs = []
                result_set = ResultSet()
                for parent in chosen_parents:
                    this_cost = self.heuristics.compute_cost(parent['chromosome'][:position + 1])[0]
                    parent_costs.append(this_cost)
                    result_set |= this_cost
                best_cost, index = max((len(result_set & cost), count) for count, cost in enumerate(parent_costs))
                new_individual['chromosome'].append(chosen_parents[index]['chromosome'][position])

            # compute cost of new individual
            new_individual['cost'] = self.heuristics.compute_cost(new_individual['chromosome'])[0].pop()

            # replace worst parent with new child
            worst_parent = min(chosen_parents, key=lambda k: k['cost'])
            self.next_population.remove(worst_parent)
            self.next_population.append(new_individual)

    def _majority_crossover(self):
        for count in range(int(self.population_size * self.crossover_chance)):
            chosen_parents = random.sample(self.next_population, self.k_parents)
            new_individual = {'chromosome': [], 'cost': None}

            # choose each position either using MBE heuristic or the majority of the parents
            for position in range(self.nodes_count):
                if all(parent['chromosome'][position] == 1 for parent in chosen_parents):
                    new_individual['chromosome'].append(1)
                elif all(parent['chromosome'][position] == 0 for parent in chosen_parents):
                    new_individual['chromosome'].append(0)
                else:
                    partial_cost, next_best = self.heuristics.compute_cost(new_individual['chromosome'])
                    new_individual['chromosome'].append(next_best)

            # compute cost of new individual and add to population
            new_individual['cost'] = self.heuristics.compute_cost(new_individual['chromosome'])[0].pop()
            self.next_population.append(new_individual)

    def _vertex_cover_crossover(self):
        for count in range(int(self.population_size * self.crossover_chance)):
            first_parent, second_parent = random.sample(self.next_population, 2)
            first_child, second_child = self.copy_individual(first_parent), self.copy_individual(second_parent)

            # choose random node to swap hard constraint solution for
            position = random.randrange(0, self.nodes_count)
            chosen_node = self.order[position]

            first_chromosome = first_child['chromosome']
            second_chromosome = second_child['chromosome']
            first_chromosome[position], second_chromosome[position] = \
                second_chromosome[position], first_chromosome[position]
            for neighbor in chosen_node.neighbors:
                position = self.order.index(neighbor)
                first_chromosome[position], second_chromosome[position] = \
                    second_chromosome[position], first_chromosome[position]

            # add new nodes to population
            first_child['cost'] = self.heuristics.compute_cost(first_child['chromosome'])[0].pop()
            second_child['cost'] = self.heuristics.compute_cost(second_child['chromosome'])[0].pop()
            self.next_population.append(first_child)
            self.next_population.append(second_child)

    def mutation(self):
        if self.mutation_strategy == 'vertex_cover':
            return self._vertex_cover_mutation()
        elif self.mutation_strategy == 'heuristic':
            return self._heuristic_mutation()

    def _vertex_cover_mutation(self):
        # vertex cover specific mutation
        for individual in self.next_population:
            changed = False
            for position in range(self.nodes_count):
                random_number = random.random()
                if random_number < self.mutation_chance / 2:
                    # if change from 1 to 0 set neighbors to 1; if change from 0 to 1 set neighbors to 0
                    value = individual['chromosome'][position]
                    individual['chromosome'][position] = 1 - value
                    node = self.order[position]
                    for neighbor in node.neighbors:
                        individual['chromosome'][self.order.index(neighbor)] = value
                    changed = True
                elif random_number < self.mutation_chance:
                    individual['chromosome'][position] = 1 - individual['chromosome'][position]
                    changed = True
            if changed:
                individual['cost'] = self.heuristics.compute_cost(individual['chromosome'])[0].pop()

    def _heuristic_mutation(self):
        # use heuristics to decide new value for a given position
        for individual in self.next_population:
            changed = False
            for position in range(self.nodes_count):
                random_number = random.random()
                if random_number < self.mutation_chance / 2:
                    this_chromosome = individual['chromosome']
                    _, next_best = self.heuristics.compute_cost(this_chromosome[:position])
                    this_chromosome[position] = next_best
                    changed = True
                elif random_number < self.mutation_chance:
                    individual['chromosome'][position] = 1 - individual['chromosome'][position]
                    changed = True
            if changed:
                individual['cost'] = self.heuristics.compute_cost(individual['chromosome'])[0].pop()

    @staticmethod
    def copy_individuals(individuals):
        return [NSGA2.copy_individual(individual) for individual in individuals]

    @staticmethod
    def copy_individual(individual):
        return {
            'chromosome': list(individual['chromosome']),
            'cost': individual['cost'],
            'rank': individual.get('rank'),
            'distance': individual.get('distance'),
        }


from django.db import models
from django.contrib.auth.models import User

class Meow(models.Model):
    text = models.CharField(max_length=160)
    user = models.ForeignKey(User)
    ts = models.DateTimeField(auto_now_add=True)

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    followers = models.ManyToManyField('self', symmetrical=False, blank=True)


import random
from enum import Enum

class Card:

    def __init__(self, suit, rank, player=False):
        self._suit = suit
        self._rank = rank
        self._player = player
        self._cardFront
        self._cardBack

        for card in CardSVGs:
            if self._suit.name in card:
                if self._rank.name in card:
                    self._cardFront = card
                    break

    def printCardFront(self):
        img = mpimg.imread(self._cardFront)
        imgplot = plt.imshow(img)
        plt.show()

    def setPlayer(self, player):
        self._player = player

    def getPlayer(self):
        return self._player

    def getCardNeat(self):
        return (self._suit.value, self._rank.value)

    def getSuit(self):
        return self._suit

    def getRankStr(self):
        return self._rank

    def isEqual(self, card):
        if self._suit == card._suit and self._rank == card._rank:
            return True
        else:
            return False

    def getSimpleCard(self):
        return self._suit.value + self._rank.value

    def isCounter(self):
        if self._rank == Ranks.ACE or self._rank == Ranks.TEN or self._rank == Ranks.KING:
            return True
        else:
            return False

    def getRankNum(self):
        switcher = {
            Ranks.ACE: 6,
            Ranks.TEN: 5,
            Ranks.KING: 4,
            Ranks.QUEEN: 3,
            Ranks.JACK: 2,
            Ranks.NINE: 1
        }
        return switcher.get(self._rank)

def getRankNum(rank):
    switcher = {
        Ranks.ACE : 6,
        Ranks.TEN : 5,
        Ranks.KING : 4,
        Ranks.QUEEN : 3,
        Ranks.JACK : 2,
        Ranks.NINE : 1
    }
    return switcher.get(rank)

class Ranks(Enum):
    ACE = 'A'
    TEN = '10'
    KING = 'K'
    QUEEN = 'Q'
    JACK = 'J'
    NINE = '9'

class Suits(Enum):
    SPADES = 'S'
    CLUBS = 'C'
    DIAMONDS = 'D'
    HEARTS = 'H'

class CardSVGs(Enum):
    CLUBS_ACE = 'CLUB-1-ACE.svg'
    CLUBS_NINE = 'CLUB-9-NINE.svg'
    CLUBS_TEN = 'CLUB-10-TEN.svg'
    CLUBS_JACK = 'CLUB-11-JACK.svg'
    CLUBS_QUEEN = 'CLUB-12-QUEEN.svg'
    CLUBS_KING = 'CLUB-13-KING.svg'
    DIAMONDS_ACE = 'DIAMOND-1-ACE.svg'
    DIAMONDS_NINE = 'DIAMOND-9-NINE.svg'
    DIAMONDS_TEN = 'DIAMOND-10-TEN.svg'
    DIAMONDS_JACK = 'DIAMOND-11-JACK.svg'
    DIAMONDS_QUEEN = 'DIAMOND-12-QUEEN.svg'
    DIAMONDS_KING = 'DIAMOND-13-KING.svg'
    HEARTS_ACE = 'HEART-1-ACE.svg'
    HEARTS_NINE = 'HEART-9-NINE.svg'
    HEARTS_TEN = 'HEART-10-TEN.svg'
    HEARTS_JACK = 'HEART-11-JACK.svg'
    HEARTS_QUEEN = 'HEART-12-QUEEN.svg'
    HEARTS_KING = 'HEART-13-KING.svg'
    SPADES_ACE = 'SPADES-1-ACE.svg'
    SPADES_NINE = 'SPADES-9-NINE.svg'
    SPADES_TEN = 'SPADES-10-TEN.svg'
    SPADES_JACK = 'SPADES-11-JACK.svg'
    SPADES_QUEEN = 'SPADES-12-QUEEN.svg'
    SPADES_KING = 'SPADES-13-KING.svg'

class NoNumberBid(Enum):
    PASS = 'pass'
    BID_OR_BUNCH = "bid or bunch"

def getSuitEnum(str):
    for suit in Suits:
        if str == suit.value:
            return suit

def getRankEnum(str):
    for rank in Ranks:
        if str == rank.value:
            return rank

class Deck:

    def __init__(self):
        self._deck = []
        for suit in Suits:
            for rank in Ranks:
                self._deck.append(Card(suit, rank))
                self._deck.append(Card(suit, rank))

    def shuffle(self):
        random.shuffle(self._deck)

    def takeTopCard(self):
        top = self._deck[len(self._deck)-1]
        self._deck.remove(top)
        return top

class Player:

    def __init__(self, name=""):
        self._name = name
        self._hand = []
        self._bid = ""
        self._meld = 0

    def getName(self):
        return self._name

    def setName(self, name):
        self._name = name

    def getCardFromSimple(self, simpleCard):
        for card in self._hand:
            if card.getSimpleCard() == simpleCard:
                return card

    def resetBid(self):
        self._bid = ""

    def fillHand(self, card):
        self._hand.append(card)
        self.sortHand()

    def isInHand(self, card):
        for c in self._hand:
            if c == card:
                return True
        return False

    def removeCard(self, card):
        self._hand.remove(card)

    def getHand(self):
        return self._hand

    def getSimpleHand(self):
        simpleHand = []
        for card in self._hand:
            simpleHand.append(card.getSimpleCard())
        return simpleHand

    def printHandFront(self):
        for card in self._hand:
            card.printCardFront()

    def sorting(self, card):
        key = card.getSimpleCard()
        return key[0] + str(card.getRankNum())

    def sortHand(self):
        self._hand.sort(key=self.sorting, reverse=True)

    def askBid(self, currentBid, first):
        if self.getBid() == NoNumberBid.PASS:
            return
        bid = input(self.getName() + ", enter bid:")
        bid = bid.lower()
        for b in NoNumberBid:
            if b.value == bid:
                bid = b
        if bid == NoNumberBid.PASS:
            self._bid = bid
        elif bid == NoNumberBid.BID_OR_BUNCH:
            if first is True and currentBid == 240:
                self._bid = bid
            else:
                print(self.getName() + ", enter appropriate bid")
                self.askBid(currentBid, first)
                return
        else:
            try:
                bid = int(bid)
            except ValueError:
                print(self.getName() + ", enter integer bid")
                self.askBid(currentBid, first)
                return
            if bid % 10 != 0:
                print(self.getName() + ", enter appropriate integer bid")
                self.askBid(currentBid, first)
                return
            if bid <= currentBid:
                print(self.getName() + ", enter larger bid")
                self.askBid(currentBid, first)
                return
            self._bid = bid

    def outOfSuit(self, suit):
        for card in self._hand:
            if card.getSuit() == suit:
                return False
        return True

    def canBeat(self, suit, rank):
        for card in self._hand:
            if card.getSuit() == suit:
                if card.getRankNum() > rank:
                    return True
        return False

    def askTrick(self, trickRound, trump):
        leadingTrick = trickRound.isLeadingCard()

        trickSimple = input(self.getName() + ", play trick:").upper()
        trick = Card(getSuitEnum(trickSimple[0]), getRankEnum(trickSimple[1:]), self)
        for card in self._hand:
            if card.isEqual(trick):
                if leadingTrick:
                    return card
                else:
                    firstSuit = trickRound.getFirstCard().getSuit()
                    winner = trickRound.getWinningCard(trump)
                if not self.outOfSuit(firstSuit):
                    winner = trickRound.getWinningCard(trump, True)
                    if trick.getSuit() != firstSuit:
                        print(self.getName() + ", enter card in suit")
                        return
                    elif self.canBeat(firstSuit, winner.getRankNum()):
                        if trick.getRankNum() > winner.getRankNum():
                            return card
                        else:
                            print(self.getName() + ", enter appropriate card. You must win the trick if you can.")
                            return
                    else:
                        return card
                elif not self.outOfSuit(trump):
                    if winner.getSuit() != trump:
                        if trick.getSuit() == trump:
                            return card
                        else:
                            print(self.getName() + ", enter trump card. You must win the trick if you can.")
                            return
                    elif self.canBeat(winner.getSuit(), winner.getRankNum()):
                        if trick.getSuit() == trump and trick.getRankNum() > winner.getRankNum():
                            return card
                        else:
                            print(self.getName() + ", enter trump card. You must win the trick if you can.")
                            return
                    else:
                        return card
                else:
                    return card
        print(self.getName() + ", enter trick card from hand")
        return

    def getBid(self):
        return self._bid

    def getMeld(self):
        return self._meld

    def scoreGroups(self, group, score, doubleScore):
        tempHand = self.getSimpleHand()
        if set(group).issubset(tempHand):
            for card in group:
                tempHand.remove(card)
            if set(group).issubset(tempHand):
                self._meld += doubleScore
            else:
                self._meld += score

    def scoreHand(self, trump):
        fiveNinesNoMeldCheck = False
        if trump is None:
            fiveNinesNoMeldCheck = True

        acesAround = []
        kingsAround = []
        queensAround = []
        jacksAround = []
        for s in Suits:
            acesAround.append(s.value + 'A')
            kingsAround.append(s.value + 'K')
            queensAround.append(s.value + 'Q')
            jacksAround.append(s.value + 'J')

        pinochle = [Suits.SPADES.value + "Q", Suits.DIAMONDS.value + "J"]

        self.scoreGroups(acesAround, 100, 1000)
        self.scoreGroups(kingsAround, 80, 800)
        self.scoreGroups(queensAround, 60, 600)
        self.scoreGroups(jacksAround, 40, 400)

        self.scoreGroups(pinochle, 40, 300)

        for suit in Suits:
            if not fiveNinesNoMeldCheck and suit != trump:
                marriage = [suit.value + "K", suit.value + "Q"]
                self.scoreGroups(marriage, 20, 40)
            else:
                marriage = [suit.value + "K", suit.value + "Q"]
                self.scoreGroups(marriage, 20, 40)

        if not fiveNinesNoMeldCheck:
            run = [trump.value + "A", trump.value + "10", trump.value + "K", trump.value + "Q", trump.value + "J"]
            royalMarriage = [trump.value + "K", trump.value + "Q"]
            royalHalfMarriageA = [trump.value + "A", trump.value + "10", trump.value + "K", trump.value + "K", trump.value + "Q", trump.value + "J"]
            royalHalfMarriageB = [trump.value + "A", trump.value + "10", trump.value + "K", trump.value + "Q", trump.value + "Q", trump.value + "J"]
            nine = [trump.value + "9"]

            if set(run).issubset(self.getSimpleHand()):
                self.scoreGroups(run, 150, 1500)
                if set(royalHalfMarriageA).issubset(self.getSimpleHand()):
                    self._meld += 20
                if set(royalHalfMarriageB).issubset(self.getSimpleHand()):
                    self._meld += 20
            elif set(royalMarriage).issubset(self.getSimpleHand()):
                self.scoreGroups(royalMarriage, 40, 80)

            self.scoreGroups(nine, 10, 20)
            print(self.getName() + "'s meld: " + str(self._meld))

    def loadMeldPoints(self):
        tempMeld = self._meld
        self._meld = 0
        return tempMeld

    def is5NinesNoMeld(self):
        nines = 0
        for card in self._hand:
            if card.getRankNum() == 1:
                nines += 1
        if nines < 5:
            return False
        else:
            self.scoreHand(None)
            if self._meld == 0:
                return True
            else:
                return False

class Team:

    def __init__(self, player1, player2, name):
        self._p1 = player1
        self._p2 = player2
        self._name = name
        self._score = 0
        self._roundScore = 0

    def isOnTeam(self, player):
        if player == self._p1 or player == self._p2:
            return True
        else:
            return False

    def getPartners(self):
        return [self._p1, self._p2]

    def getPartner1(self):
        return self._p1

    def getPartner2(self):
        return self._p2

    def getPartnerOf(self, player):
        if player == self._p1:
            return self._p2
        else:
            return self._p1

    def addScore(self, score, newRound=False):
        if not newRound:
            self._roundScore += score
        else:
            self._score += score

    def getScore(self):
        return self._score

    def getRoundScore(self):
        return self._roundScore

    def getName(self):
        return self._name

    def setName(self, name):
        self._name = name

class Game:

    def __init__(self, players=['', '', '', '']):
        self._p1 = Player(players[0])
        self._p2 = Player(players[1])
        self._p3 = Player(players[2])
        self._p4 = Player(players[3])
        self._allPlayers = [self._p1, self._p2, self._p3, self._p4]
        self._team1 = Team(self._p1, self._p3, "Team 1")
        self._team2 = Team(self._p2, self._p4, "Team 2")
        self._allTeams = [self._team1, self._team2]
        self._gameOver = False

    def askTeamNames(self):
        for team in self._allTeams:
            players = ""
            for player in team.getPartners():
                players += player.getName() + " and "
            players = players.removesuffix(' and ')
            name = input(players + " team name: ")
            team.setName(name)

    def askPlayerNames(self):
        for player in self._allPlayers:
            name = input("Player " + str(self._allPlayers.index(player) + 1) + " name: ")
            player.setName(name)

    def getAllPlayers(self):
        return self._allPlayers

    def getPlayers(self, number): #number is 1-4
        return self._allPlayers[number - 1]

    def getAllTeams(self):
        return self._allTeams

    def getTeams(self, number): # number is 1-2
        return self._allTeams[number-1]

    def showScores(self):
        print("Scores")
        print(self._team1.getName() + ": " + str(self._team1.getScore()))
        print(self._team2.getName() + ": " + str(self._team2.getScore()))

    def gameOver(self):
        self._gameOver = True

    def isGameOver(self):
        return self._gameOver

    def playRound(self):
        round = PinochleRound(self)
        round.deal()
        round.showAllHands()
        round.bidding()
        round.passingCards()
        round.scoreMeld()
        round.trickPlaying()
        round.finishRound()

class Tricks:

    def __init__(self):
        self._cardsPlayed = []
        self._winningcard = None
        self._leadingCard = True

    def playCard(self, card):
        self._cardsPlayed.append(card)
        self._leadingCard = False

    def isLeadingCard(self):
        return self._leadingCard

    def isDone(self):
        if len(self._cardsPlayed) >= 4:
            return True
        else:
            return False

    def getFirstCard(self):
        if not self._leadingCard:
            return self._cardsPlayed[0]
        else:
            return None

    def getWinningCard(self, trump, ignoreTrump=False):
        winRank = 0
        winSuit = self._cardsPlayed[0].getSuit()
        winningCard = None
        for card in self._cardsPlayed:
            if card.getSuit() == winSuit:
                if card.getRankNum() > winRank:
                    winRank = card.getRankNum()
                    winningCard = card
            elif card.getSuit() == trump:
                if not ignoreTrump:
                    winSuit = trump
                    winRank = card.getRankNum()
                    winningCard = card
        return winningCard

    def getCounters(self):
        counters = 0
        for card in self._cardsPlayed:
            if card.isCounter():
                counters += 10
        return counters

class PinochleRound:

    def __init__(self, game):
        self._allPlayers = game.getAllPlayers()
        self._team1 = game.getTeams(1)
        self._team2 = game.getTeams(2)
        self._deck = Deck()
        self._deck.shuffle()
        self._trump = False
        self._finalBid = 0
        self._tookBid = False
        self._shootMoon = False
        self._game = game

    def deal(self):
        for index in range(12):
            for player in self._allPlayers:
                card = self._deck.takeTopCard()
                player.fillHand(card)
                card.setPlayer(player)

    def dealRigged(self):
        for index in range(12):
            for player in self._allPlayers:
                if self._allPlayers.index(player) == 3:
                    card = Card(Suits.SPADES, Ranks.NINE, player)
                else:
                    card = self._deck.takeTopCard()
                player.fillHand(card)
                card.setPlayer(player)

    def reshuffle(self):
        for player in self._allPlayers:
            hand = player.getHand().copy()
            for index in range(len(hand)):
                player.removeCard(hand[index])
        self._deck = Deck()
        self._deck.shuffle()

    def getPlayer(self, playerName):
        for player in self._allPlayers:
            if player.getName() == playerName:
                return player

    def getTeam(self, player):
        if player in self._team1.getPartners():
            return self._team1
        else:
            return self._team2

    def getOtherTeam(self, player):
        if player in self._team1.getPartners():
            return self._team2
        else:
            return self._team1

    def addScore(self, score, player):
        team = self.getTeam(player)
     #   if team == self.getTeam(self._tookBid):
     #       self._biddersScore += score
        team.addScore(score)

    def showHand(self, player):
        print(player.getName() + "'s hand:")
        #for card in player.getHand():
            #print(card.getCardNeat())
        player.printCardFront()

    def showAllHands(self):
        for player in self._allPlayers:
            self.showHand(player)

    def check5NinesNoMeld(self):
        for player in self._allPlayers:
            if player.is5NinesNoMeld():
                while True:
                    answer = input(player.getName() + ", do you want to throw with 5 nines no meld?").upper()
                    if answer == "YES":
                        print(player.getName() + " had 5 nines no meld. Reshuffling and dealing")
                        self.reshuffle()
                        self.deal()
                        self.showAllHands()
                        self.check5NinesNoMeld()
                        break
                    elif answer == "NO":
                        return
                    else:
                        print("Answer with yes or no")

    def bidding(self):
        self.check5NinesNoMeld()
        passed = 0
        currentBid = 240
        for player in self._allPlayers:
            player.resetBid()
        biddingPlayers = self._allPlayers.copy()
        first = True
        while passed < 3:
            for player in biddingPlayers.copy():
                player.askBid(currentBid, first)
                if player.getBid() == NoNumberBid.PASS:
                    passed += 1
                    if passed == 4 and first == True:
                        break
                    biddingPlayers.remove(player)
                    if passed >= 3 and first == False:
                        break
                else:
                    if type(player.getBid()) is int:
                        currentBid = player.getBid()
            else:
                first = False
                continue
            break

        finalBid = biddingPlayers[0].getBid()
        if finalBid == NoNumberBid.PASS:
            print("No bids, reshuffle?")
            self.reshuffle()
            self.deal()
            self.bidding()
            return
        else:
            self._finalBid = finalBid
            self._tookBid = biddingPlayers[0]
            print("Final bid: " + str(finalBid) + ", " + biddingPlayers[0].getName())
            while True:
                trump = input(biddingPlayers[0].getName() + ", enter trump suit:")
                trump = trump.upper()
                for suit in Suits:
                    if trump == suit.name:
                        self._trump = suit
                if self._trump in list(Suits):
                    break

    def pass4Cards(self, playerPassing):
        recieving = self.getTeam(playerPassing).getPartnerOf(playerPassing)
        counter = 1
        self.showHand(playerPassing)
        message = playerPassing.getName() + ", pass card " + str(counter) + ":"
        while counter < 5:
            cardToPassSimple = input(message).upper()
            cardToPass = playerPassing.getCardFromSimple(cardToPassSimple)
            if playerPassing.isInHand(cardToPass):
                recieving.fillHand(cardToPass)
                playerPassing.removeCard(cardToPass)
                counter += 1
                message = playerPassing.getName() + ", pass card " + str(counter) + ":"
            else:
                message = 'Card not in hand. ' + playerPassing.getName() + ", pass card " + str(counter) + ":"

    def passingCards(self):
        player = self._tookBid
        team = self.getTeam(player)
        partner = team.getPartnerOf(player)

        self.pass4Cards(partner)
        self.pass4Cards(player)

    def scoreMeld(self):
        for player in self._allPlayers:
            player.scoreHand(self._trump)

        self.askShootMoon()

        if not self.canMakeBid() and not self._shootMoon:
            self.throwIn()
            return

        for player in self._allPlayers:
            if self._shootMoon:
                if self.getTeam(player) != self.getTeam(self._tookBid):
                    self.addScore(player.loadMeldPoints(), player)
            else:
                self.addScore(player.loadMeldPoints(), player)

    def canMakeBid(self):
        meld = self._tookBid.getMeld() + self.getTeam(self._tookBid).getPartnerOf(self._tookBid).getMeld()
        if meld + 250 < self._finalBid:
            return False
        else:
            return True

    def askShootMoon(self):
        while True:
            answer = input(self._tookBid.getName() + ", do you want to shoot the moon?").upper()
            if answer == "YES":
                print(self._tookBid.getName() + " is shooting the moon")
                self._shootMoon = True
                return
            elif answer == "NO":
                self._shootMoon = False
                return
            else:
                print("Answer with yes or no")

    def getNextPlayer(self, currentPlayer):
        for player in self._allPlayers:
            if player == currentPlayer:
                index = self._allPlayers.index(player)
                return self._allPlayers[(index +  1)%4]

    def trickPlaying(self):
        nextPlayer = self._tookBid
        round = 1
        trickCards = Tricks()
        while round < 13:
            for player in self._allPlayers:
                if trickCards.isDone():
                    counters = trickCards.getCounters()
                    if round == 12:
                        counters += 10
                    winCard = trickCards.getWinningCard(self._trump)
                    self.addScore(counters, winCard.getPlayer())
                    self._game.showScores()
                    trickCards = Tricks()
                    nextPlayer = winCard.getPlayer()
                    round += 1
                    break
                if player == nextPlayer:
                    self.showHand(player)
                    trick = None
                    while trick is None:
                        trick = player.askTrick(trickCards, self._trump)
                    player.removeCard(trick)
                    trickCards.playCard(trick)
                    nextPlayer = self.getNextPlayer(player)

    def madeBid(self):
        if self._shootMoon:
            self._finalBid = 250

        if self.getTeam(self._tookBid).getRoundScore() >= self._finalBid:
            return True
        else:
            if self._shootMoon:
                self._finalBid = 500
            return False

    def finishRound(self):
        biddingTeam = self.getTeam(self._tookBid)
        otherTeam = self.getOtherTeam(self._tookBid)
        print(biddingTeam.getName(), " bid: ", self._finalBid)

        if self.madeBid():
            score = biddingTeam.getRoundScore()
            if self._shootMoon:
                score = 500
            biddingTeam.addScore(score, True)
            print(biddingTeam.getName(), "made bid!")
            print(biddingTeam.getName(), "scored:", score)
        else:
            biddingTeam.addScore(-self._finalBid, True)
            print(biddingTeam.getName(), "did not make the bid! :(")
            print(biddingTeam.getName(), "scored:", -self._finalBid)

        score = otherTeam.getRoundScore()
        otherTeam.addScore(score, True)
        print(otherTeam.getName(), " scored: ", score)

        winner = self.winner()
        if winner is not Null:
            print(winner.getName(), " wins!!")
            self._game.showScores()

    def winner(self): #Null is no winner yet
        t1Score = self._team1.getScore()
        t2Score = self._team2.getScore()

        if t1Score < 1500 and t1Score > -1500 and t2Score < 1500 and t2Score > -1500:
            return Null
        elif t1Score >= 1500 and t2Score < t1Score:
            return self._team1
        elif t2Score >= 1500 and t1Score < t2Score:
            return self._team2
        elif t1Score <= -1500 and t2Score > t1Score:
            return self._team2
        elif t2Score <= -1500 and t1Score > t2Score:
            return self._team1
        else:
            return Null

if __name__ == '__main__':
    players = ["Lizzy", "Micah", "Dad", "Mom"]
    myGame = Game(players)
    myGame.showScores()
  #  myGame.askPlayerNames()
  #  myGame.askTeamNames()
    myGame.playRound()


from kivymd.uix.responsivelayout import MDResponsiveLayout

from View.HomeScreen.components import (
    HomeMobileScreenView,
    TabletScreenView,
    DesktopScreenView,
)
from View.base_screen import BaseScreenView
from kivy.properties import ListProperty

class HomeScreenView(MDResponsiveLayout, BaseScreenView):
    _data = ListProperty()
    def __init__(self, **kw):
        super().__init__(**kw)
        self.mobile_view = HomeMobileScreenView()
        self.tablet_view = TabletScreenView()
        self.desktop_view = DesktopScreenView()
        # print(self.model.data)
        # print(self.mobile_view.name)
        for x in self.model._data:
            x['father'] = self
        self.mobile_view.ids.home_tile.data = self.model.data
        self.mobile_view.ids.home_tile.bind(scroll_y=self.controller.update_scroll)
        # print(self.ids.home_refresh_layout.ids)
        # print(self.mobile_view.ids)

    def model_is_changed(self) -> None:
        """
        Called whenever any change has occurred in the data model.
        The view in this method tracks these changes and updates the UI
        according to these changes.
        """
        print('model is changed home')

    def testing(self) -> None:
        print('home screen testing new model modifiers method')


import requests

def download():
    """Function to download the latest version of the mapping between OMIM and uniprot."""
    url = 'http://www.uniprot.org/docs/mimtosp.txt'
    file_Name = 'data.txt'
    data = requests.get(url)
    file = open(file_Name, 'wb')
    for line in data.iter_content():
        file.write(line)
    file.close()

download()


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

# sxvao.py

import serial

class SXVAO():
    def __init__(self, parent, comport, timeout=10):
        self.parent = parent
        self.comport = comport
        self.timeout = timeout
        # configuration attributes
        self.steps_per_pixel = 6.0
        self.switch_xy = False
        self.reverse_x = False
        self.reverse_y = False
        self.mount_steps_per_pixel = 6.0
        self.mount_switch_xy = False
        self.mount_reverse_x = False
        self.mount_reverse_y = False
        self.max_steps = 10
        self.steps_limit = 1000
        # internal variables
        self.ao = None
        self.count_steps_N = 0
        self.count_steps_W = 0

    def Connect(self):
        if self.ao is None:
            try:
                self.ao = serial.Serial(self.comport, timeout=10)
            except OSError:
                return False
            self.ao.write('X')
            response = self.ao.read(1)
            return response == 'Y'
        else:
            return False

    def Disconnect(self):
        if self.ao is not None:
            self.ao.close()
            self.ao = None

    def MakeCorrection(self, dx, dy):
        if self.reverse_x:
            dx = -dx
        if self.reverse_y:
            dy = -dy
        if self.switch_xy:
            dx, dy = dy, dx
        nx = self.DeltaToSteps(dx)
        dir = 'T' if dx > 0 else 'W'
        while nx > 0:
            n = nx%self.max_steps
            self.MakeSteps(dir, n)
            nx -= n
        ny = self.DeltaToSteps(dy)
        dir = 'N' if dy > 0 else 'S'
        while ny > 0:
            n = ny%self.max_steps
            self.MakeSteps(dir, n)
            ny -= n
        return True

    def MakeMountCorrection(self, dx, dy):
        if self.mount_reverse_x:
            dx = -dx
        if self.mount_reverse_y:
            dy = -dy
        if self.mount_switch_xy:
            dx, dy = dy, dx
        nx = self.DeltaToMountSteps(dx)
        dir = 'T' if dx > 0 else 'W'
        self.MakeMountSteps(dir, nx)
        ny = self.DeltaToMountSteps(dy)
        dir = 'N' if dy > 0 else 'S'
        self.MakeMountSteps(dir, ny)
        return True

    def DeltaToSteps(self, d):
        return int(round(abs(d)/self.steps_per_pixel))

    def DeltaToMountSteps(self, d):
        return int(round(abs(d)/self.mount_steps_per_pixel))

    def MakeSteps(self, dir, n=1):
        # dir must be one of [N, S, T, W]
        if dir == 'N':
            self.count_steps_N += n
        elif dir == 'S':
            self.count_steps_N -= n
        if dir == 'W':
            self.count_steps_W += n
        elif dir == 'T':
            self.count_steps_W -= n
        command = 'G{:1s}{:05d}'.format(dir, n)
        self.ao.write(command)
        response = self.ao.read(1)
        if response == 'G':
            self.parent.Log('AO unit took {:d} steps {:s}'.format(n, dir))
        elif response == 'L':
            self.parent.Log('AO unit hit limit')
        else:
            self.parent.Log('AO unit stepping failed')
        self.RecentreMountIfNeeded(force=(response=='L'))

    def MakeMountSteps(self, dir, n=1):
        # dir must be one of [N, S, T, W]
        command = 'M{:1s}{:05d}'.format(dir, n)
        self.ao.write(command)
        response = self.ao.read(1)
        if response == 'M':
            self.parent.Log('Mount took {:d} steps {:s}'.format(n, dir))
        else:
            self.parent.Log('Mount stepping failed')

    def RecentreMountIfNeeded(self, force=False):
        # Move to approximately recentre AO with
        # opposing move for scope to keep image stationary
        # North-South
        mount_steps_N = (self.count_steps_N * self.mount_steps_per_pixel
                         / self.steps_per_pixel)
        if self.count_steps_N > self.steps_limit or force:
            self.MakeSteps('S', abs(self.count_steps_N))
            self.MakeMountSteps('N', abs(mount_steps_N))
            self.count_steps_N = 0
        elif self.count_steps_N < -self.steps_limit:
            self.MakeSteps('N', abs(self.count_steps_N))
            self.MakeMountSteps('S', abs(mount_steps_N))
            self.count_steps_N = 0
        # West-East
        mount_steps_W = (self.count_steps_W * self.mount_steps_per_pixel
                         / self.steps_per_pixel)
        if self.count_steps_W > self.steps_limit or force:
            self.MakeSteps('T', abs(self.count_steps_W))
            self.MakeMountSteps('W', abs(mount_steps_W))
            self.count_steps_W = 0
        elif self.count_steps_W < -self.steps_limit:
            self.MakeSteps('W', abs(self.count_steps_W))
            self.MakeMountSteps('T', abs(mount_steps_W))
            self.count_steps_W = 0

    def Centre(self):
        self.ao.write('K')
        response = self.ao.read(1)
        return response == 'K'


# None
import random
from random import shuffle
from typing import List

class Solution:
    def mini_median(self, nums):
        nums = sorted(nums)
        n = len(nums)
        mid = n // 2
        return nums[mid] if n & 1 else (nums[mid] + nums[mid - 1]) / 2

    def mom(self, subarrays):
        mom = [self.mini_median(subarray) for subarray in subarrays]
        return self.mini_median(mom)

    def partition(self, nums, l, r, pivot_idx):
        pivot_val = nums[pivot_idx]
        nums[r], nums[pivot_idx] = pivot_val, nums[r]
        store_idx = l
        for i in range(l, r):
            if nums[i] < pivot_val:
                nums[i], nums[store_idx] = nums[store_idx], nums[i]
                store_idx += 1
        nums[store_idx], nums[r] = nums[r], nums[store_idx], nums[r]

    def findMedian(self, nums: List[int]) -> float:
        n = len(nums)
        something = self.mom([nums[i:(i+5)] for i in range(0, n, 5)])
        print(something)

solution = Solution()

def check(input, expected):
    output = solution.findMedian(input)
    assert output == expected

random.seed(5)

a = [1, 2, 3, 4, 5, 6, 7]
b = [1, 2, 3, 4, 5, 6]

shuffle(a)
shuffle(b)

check(a, 4.)
check(b, (3 + 4) / 2)


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

# # Introduction
#

#

#
#
# **What?** Vectorised Backtest of SMA - Simple Moving Average
#
#
#

# # Vectorised vs. event-driven backtesting
#

#

#
#
# - A **vectorised** backtest is the most basic way to evaluate a strategy. It simply multiplies a signal vector that represents the target position size with a vector of returns for the investment horizon to compute the period performance (some used the term equity curve). Vectorised backtesters are for quick research ideas. vectorized backtesting with NumPy and pandas is generally convenient and efficient to implement due to the concise code, and it is fast to execute due to these packages being optimized for such operations.
# - An **event-driven** backtester is a more well thought out simulation. By making use of an event driven backtester we can stop look ahead bias to a large extent by only feeding in the data as it becomes available. This also very closely matches how your trading will take place in real life via an execution system. We also have the advantage of building in transaction costs, liquidity constraints, and market impact. This is not something you can do with the vectorized method. (You could add transaction costs after the fact).
# - There seems to be a bit of a confusion of what what vectorised really means: if behind the scenes, the said vectorised function is simply passing the elements through a loop, just like an event-driven backtester in that sense. Then, there's no correctness reason for preferring one approach over another.
#
#
#

# # Imports
#

# In[26]:

import yfinance as yf
from itertools import product
import datetime
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.style.use("seaborn")
from tqdm import tqdm

# In[2]:

# Getting rid of the warning messages
import warnings
warnings.filterwarnings("ignore")

# Pandas future warning
import warnings
warnings.simplefilter(action='ignore', category=FutureWarning)
import pandas

# # Get the data
#

# In[3]:

# pull historical data
def get_data(pair):

    NUM_DAYS = 10000    # The number of days of historical data to retrieve
    INTERVAL = '1d'
    symbol = str(pair)   # Symbol of the desired stock

    # define start & dates
    start = (datetime.date.today() - datetime.timedelta(NUM_DAYS))
    end = datetime.datetime.today()

    # pull data
    df = yf.download(symbol, start=start, end=end, interval=INTERVAL)
    return df

# In[4]:

pair = "AUDUSD=X"
data = get_data(pair)

# # SMA - Simple Moving Average
#

# In[5]:

# No of day you want to consider
sma_short = 55
sma_long = 200

# Calculate SMA values
data["SMA_S"] = data.Close.rolling(sma_short).mean()
data["SMA_L"] = data.Close.rolling(sma_long).mean()

# Drop missing values
data = data.dropna()
data

# In[6]:

data.plot(figsize=(18, 7), y=["Close", "SMA_S", "SMA_L"],
          title=f"{pair} + SMA{sma_short} & SMA{sma_long}")
# plt.grid()
plt.show()

# # SMA strategy logic
#

#

#
#
# - Where short SMA is greater than the long SMA, the position is +1 (buy)
# - Where short SMA is less than the long SMA, the position is -1 (sell).
#
#
#

# In[7]:

# Define Positions (Long or Short). Where 1 = Buy, -1 = Sell
data["position"] = np.where(data["SMA_S"] > data["SMA_L"], 1, -1)
data

# # Define Buy & Hold Returns
#

#

#
#
# - The daily log returns are calculated by taking the natural logarithm of the division of the present close price by the previous price.
# - Log returns are an important financial metrics for determining the returns of an investment.
# - Strategy returns is the return from the position taken based on the previous close price. i.e the return for the present close price multiplied by the signal position — Buy(+1) or Sell(-1). The logic behind this is simple; if by the end of day 1, the signal says “Buy (+1)” and you take a long position, by day 2, the return of the strategy from the position taken from the signal on day 1 would be the log returns between the price of day 1 and day 2 multiplied by the position itself. E.g. If the position at day 1 is -1 and the log returns at day 2 is -0.00302, the strategy returns = -1 * -0.00302 i.e a profit return of 0.00302
#
#
#

# In[8]:

data.Close/data.Close.shift(1)

# In[9]:

data.Close.div(data.Close.shift(1))

# In[10]:

data["returns"] = np.log(data.Close.div(data.Close.shift(1)))

# daily return of strategy
data["strategy"] = data.position.shift(1) * data["returns"]
data.dropna(inplace=True)

# In[11]:

data.head()

# # Calculate Absolute Performance
#

#

#
#
# - **Absolute performance** — the sum of the log returns of buy & hold and strategy. This gives an overview of the absolute returns after the test period.
# - **Annual returns** — The mean of the log returns of buy & hold and strategy multiplied by the total number of trading days in a year (252).
# - **Annual risk** — The standard deviation of the log returns of buy & hold and strategy multiplied by the square root of total number of trading days in a year (252).
# - **Cumulative Returns** — is calculated by the cumulative sum of exponential of the strategy log returns and the buy & hold returns
#
#
#

# In[12]:

# calculate absolute performance
data[["returns", "strategy"]].sum()

# In[13]:

# CALCULATE ACTUAL VALUE OF ABSOLUTE PERFORMANCE
data[["returns", "strategy"]].sum().apply(np.exp)

# In[14]:

# annual return
data[["returns", "strategy"]].mean() * 252

# In[15]:

# annual risk
data[["returns", "strategy"]].std() * np.sqrt(252)

# In[16]:

data["cum_returns"] = data["returns"].cumsum().apply(np.exp)
data["cum_strategy"] = data["strategy"].cumsum().apply(np.exp)
data

# In[17]:

# Visualize Cummulative returns
data[["cum_returns", "cum_strategy"]].plot(
    figsize=(20, 7), title=f"{pair} Returns + SMA{sma_short} & SMA{sma_long}")
plt.legend(fontsize=12)
plt.show()

#

#
#
# - This shows the strategy using a SMA(sma_short = 55, sma_long = 200) performed worse than a buy & hold investment and would not be profitable to trade.
# - The strategy performance can be calculated by subtracting the last cumulative returns of buy & hold from the last cumulative return of the strategy. T0his shows a -11.0% performance compared to buy & hold
#
#
#

# In[18]:

strat_perf = data.cum_strategy.iloc[-1] - data.cum_returns.iloc[-1]
round(strat_perf, 5)*100

# # Optimise SMA combination
#

# In[20]:

# Create Backtest function
def sma_backtest(data, sma_short, sma_long):
    df = data.copy()
    df["returns"] = np.log(df.Close.div(df.Close.shift(1)))
    df["SMA_S"] = data.Close.rolling(sma_short).mean()
    df["SMA_L"] = data.Close.rolling(sma_long).mean()
    df.dropna(inplace=True)

    df["position"] = np.where(df["SMA_S"] > df["SMA_L"], 1, -1)
    df["strategy"] = df.position.shift(1) * df["returns"]
    df.dropna(inplace=True)

    # returns the absolute performance of strateg
    return round(np.exp(df["strategy"].sum()), 5)

# In[21]:

# range of sma
range_sma_short = range(3, 50, 1)
range_sma_long = range(55, 250, 1)

# In[22]:

# combination of SMAs
smas = list(product(range_sma_short, range_sma_long))
smas

# In[23]:

len(smas)

# In[27]:

# iterate through sma combination and test strategy
abs_perform = []
for pro in tqdm(smas):
    abs_perform.append(sma_backtest(data, pro[0], pro[1]))

# In[28]:

# Get max value
np.max(abs_perform)

# In[32]:

# results to dataframe
results = pd.DataFrame(smas, columns=["SMA_short", "SMA_long"])
results["abs_performance"] = abs_perform
results.sort_values("abs_performance", ascending=False)

# In[34]:

# Get max value combination
best_comb = smas[np.argmax(abs_perform)]
best_comb

# In[35]:

# top 10 best performing combination
best = results.nlargest(10, "abs_performance")
best.head()

# In[36]:

# top 10 least performing combination
least = results.nsmallest(10, "abs_performance")
least.head()

# # Check best performing combination
#

# In[37]:

# define SMA values
sma_short = best_comb[0]
sma_long = best_comb[1]

# calculate SMA values
new_data = data.Close.to_frame()
new_data["SMA_s"] = data.Close.rolling(sma_short).mean()
new_data["SMA_l"] = data.Close.rolling(sma_long).mean()

# drop missing values
new_data = new_data.dropna()
new_data

# In[38]:

new_data["2021"].plot(
    figsize=(18, 7), title=f"{pair} + SMA{sma_short} & SMA{sma_long}")
plt.show()

# In[39]:

# Define Positions (Long or Short). Where 1 = Buy, -1 = Sell
new_data["position"] = np.where(new_data["SMA_s"] > new_data["SMA_l"], 1, -1)
new_data

# In[40]:

new_data["returns"] = np.log(new_data.Close.div(new_data.Close.shift(1)))

# daily return of strategy
new_data["strategy"] = new_data.position.shift(1) * new_data["returns"]
new_data.dropna(inplace=True)
new_data

# In[41]:

# calculate absolute performance
new_data[["returns", "strategy"]].sum()

# In[42]:

# CALCULATE ACTUAL VALUE OF ABSOLUTE PERFORMANCE
new_data[["returns", "strategy"]].sum().apply(np.exp)

# In[43]:

# annual return
new_data[["returns", "strategy"]].mean() * 252

# In[44]:

# annual risk
new_data[["returns", "strategy"]].std() * np.sqrt(252)

# In[45]:

new_data["cum_returns"] = new_data["returns"].cumsum().apply(np.exp)
new_data["cum_strategy"] = new_data["strategy"].cumsum().apply(np.exp)
new_data

# In[46]:

# Visualize Cummulative returns
new_data[["cum_returns", "cum_strategy"]].plot(
    figsize=(20, 7), title=f"{pair} Returns + SMA{sma_short} & SMA{sma_long}")
plt.legend(fontsize=12)
plt.show()

# # References
#

#

#
#
# - [YAHOO AUD/USD](https://finance.yahoo.com/quote/AUDUSD=X/?guccounter=1&guce_referrer=aHR0cHM6Ly93d3cuZ29vZ2xlLmNvLnVrLw&guce_referrer_sig=AQAAALNbKvdnnyycC3agGxv2fNzx__G73WarjVfBU63B7R9XGoqbvxhA3w9GcR3L9FLa8dLwc66QMCF26cabsJGtchOasiKqmt8cQaoNpVmRM6nZyYSu0yh96F93qHmzud_O1HgswybhoZM4CTiX9kybecUul4nmAlvBODyHEXBmyJ5t)
# - [Blog article](https://wire.insiderfinance.io/vectorized-backtest-of-sma-cross-strategy-991cb13ffcd0)
# - [Why do we need event-driven backtesters?](https://quant.stackexchange.com/questions/46791/why-do-we-need-event-driven-backtesters)
# - [Why log return?](https://quantivity.wordpress.com/2011/02/21/why-log-returns/)
#
#
#

# In[ ]:

tutorials/testing/From_notebook_to_python/Vectorised Backtest of SMA - Simple Moving Average.py


from PIL import Image
import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import os

actual_path = os.getcwd()
data_path = os.path.join(actual_path, 'data', 'estadio_guillermon_moncada.jpg')

image = Image.open(data_path)

# Convert the image to a matrix of RGB values
image = np.array(image.convert('RGB'))

height, width, _ = image.shape

features = np.zeros((height * width, 5))

# Fill the features with the RGB values and XY coordinates of the pixels of the image
for i in range(height):
    for j in range(width):
        index = i * width + j
        features[index, 0] = image[i, j, 0]
        features[index, 1] = image[i, j, 1]
        features[index, 2] = image[i, j, 2]
        features[index, 3] = i
        features[index, 4] = j

n_clusters = 10

kmeans = KMeans(n_clusters=n_clusters, random_state=42, n_init='auto').fit(features)

# Get the cluster labels assigned to each pixel
labels = kmeans.labels_

# Create a new image with the colors of the centroids of each cluster
new_image = np.zeros_like(image)
for i in range(height):
    for j in range(width):
        index = i * width + j
        label = labels[index]
        new_image[i, j, 0] = kmeans.cluster_centers_[label, 0]
        new_image[i, j, 1] = kmeans.cluster_centers_[label, 1]
        new_image[i, j, 2] = kmeans.cluster_centers_[label, 2]

plt.imshow(new_image)
plt.show()


#from keras.models import  Sequential
import pandas as pd
from keras.layers import Activation,Dense
from keras import optimizers
from keras.models import Sequential
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

housing_data=pd.read_csv('Housing.csv')
#print(housing_data.isnull().sum())
# We do not have any null data

for column in ['mainroad','guestroom','basement','hotwaterheating','airconditioning','prefarea']:
    housing_data[column] = housing_data[column].map(
        {'yes': 1, 'no': 0})

y=housing_data['price'].values
X=housing_data.drop(['price','furnishingstatus'],axis=1).values

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=101)

s_scaler = StandardScaler()
X_train = s_scaler.fit_transform(X_train.astype(np.float32))
X_test = s_scaler.transform(X_test.astype(np.float32))

model = Sequential()
model.add(Dense(10, input_shape = (11,)))
model.add(Activation('sigmoid'))
model.add(Dense(10))                         # Hidden layer => only output dimension should be designated
model.add(Activation('sigmoid'))
model.add(Dense(1))

sgd = optimizers.SGD(lr = 0.01)    # stochastic gradient descent optimizer

model.compile(optimizer = sgd, loss = 'mean_squared_error', metrics = ['mse'])
model.fit(X_train, y_train, batch_size = 50, epochs = 50, verbose = 1)
model.summary()

results = model.evaluate(X_test, y_test)

print('loss: ', results[0])
print('mse: ', results[1])


#!/usr/bin/env python3
# vim: textwidth=0 wrapmargin=0 tabstop=2 shiftwidth=2 softtabstop=2 smartindent smarttab

import os
import yaml, logging, argparse

import random, base64, hashlib
import json
import cgi
#import cgitb
#cgitb.enable(display=0, logdir="/var/www/user-rw/athan.fysh.org/fd-api-logs")

import urllib.request
import requests
import pprint
pp = pprint.PrettyPrinter(indent=2)

import org.miggy.edcapi

###########################################################################
"""
 "  Configuration
"""
###########################################################################
__configfile_fd = os.open("fd-api-config.yaml", os.O_RDONLY)
__configfile = os.fdopen(__configfile_fd)
__config = yaml.load(__configfile, Loader=yaml.CLoader)
###########################################################################

###########################################################################
# Logging
###########################################################################
os.environ['TZ'] = 'UTC'
__default_loglevel = logging.INFO
__logger = logging.getLogger('fd-api')
__logger.setLevel(__default_loglevel)
__logger_ch = logging.StreamHandler()
__logger_ch.setLevel(__default_loglevel)
__logger_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(module)s.%(funcName)s:\n%(message)s')
__logger_formatter.default_time_format = '%Y-%m-%d %H:%M:%S';
__logger_formatter.default_msec_format = '%s.%03d'
__logger_ch.setFormatter(__logger_formatter)
__logger.addHandler(__logger_ch)
###########################################################################

###########################################################################
# MAIN
###########################################################################
def main():
  __logger.debug('Start-Up')

  if not os.getenv('GATEWAY_INTERFACE'):
    handleCLI()
  else:
    handleCGI()

###########################################################################
# Being called from command-line
###########################################################################
def handleCLI():
  #########################################
  # Command-Line Arguments
  #########################################
  __parser = argparse.ArgumentParser()
  __parser.add_argument("--loglevel", help="set the log level to one of: DEBUG, INFO (default), WARNING, ERROR, CRITICAL")
  __parser.add_argument("cmdrname", nargs=1, help="Specify the Cmdr Name for this Authorization")
  __args = __parser.parse_args()
  cmdrName = __args.cmdrname[0]
  if __args.loglevel:
    __level = getattr(logging, __args.loglevel.upper())
    __logger.setLevel(__level)
    __logger_ch.setLevel(__level)

  #########################################

  ########################################
  # Retrieve and test state
  ########################################
  db = org.miggy.edcapi.database.database(__logger, __config)
  __logger.debug("cmdrName: '{}'".format(cmdrName))
  auth_state = db.getActiveTokenState(cmdrName)
  if auth_state:
    ## Do we have an access_token, and does it work?
    if auth_state['access_token']:
      print("Found un-expired access_token, assuming it's good.")
      return(0)
    else:
      print("Un-expired access_token, but no access_token? WTF!")
      return(-1)
  else:
    print("No auth state with un-expired access_token found, continuing...")
  ########################################

  ########################################
  # Generate Code Verifier
  ########################################
  verifier = random.SystemRandom().getrandbits(8 * 32)
  __logger.debug('raw verifier: {}'.format(verifier))
  # We need a Base64, URL safe, version of this. NB: the '=' on the end is
  # OK in this instance.
  verifier_b64 = base64.urlsafe_b64encode(verifier.to_bytes(32, byteorder='big'))
  __logger.debug('b64 verifier: {}'.format(verifier_b64))
  ########################################

  ########################################
  # Generate Code Challenge
  ########################################
  # Using the URL-safe Base64 version of verifier, with the '=' still on the
  # end
  challenge = hashlib.sha256(verifier_b64).digest()
  __logger.debug('raw challenge: {}'.format(challenge))
  challenge_b64 = base64.urlsafe_b64encode(challenge)
  __logger.debug('b64 challenge: {}'.format(challenge_b64))
  challenge_b64_str = challenge_b64.decode().replace('=','')
  __logger.debug('str challenge: {}'.format(challenge_b64_str))
  ########################################

  ########################################
  # Generate 'State'
  ########################################
  state = random.SystemRandom().getrandbits(8 * 32)
  __logger.debug('raw state: {}'.format(state))
  #state_b64 = base64.b64encode(state.to_bytes(32, byteorder='big'))
  state_b64 = base64.urlsafe_b64encode(state.to_bytes(32, byteorder='big'))
  __logger.debug('b64 state: {}'.format(state_b64))
  state_b64_str = state_b64.decode().replace('=','')
#.replace('+','-').replace('/','_').replace('=','')
  __logger.debug('str state: {}'.format(state_b64_str))
  ########################################

  ########################################
  # Store state and the codes for when redirect_uri is called
  ########################################
  db.storeNewState(state_b64_str, challenge_b64.decode(), verifier_b64.decode(), cmdrName)
  ########################################

  ########################################
  # Get the User's Authorization
  ########################################
  __logger.debug("auth_api_url: '{}'".format(__config.get('auth_api_url')))
  request_uri = (__config.get('auth_api_url') +
      '/auth?'
      'response_type=code'
      '&audience=frontier,steam,epic'
      '&scope=capi'
      '&client_id=' + __config.get('clientid') +
      '&code_challenge=' + challenge_b64_str +
      '&code_challenge_method=S256'
      '&state=' + state_b64_str +
      '&redirect_uri=' + __config.get('redirect_uri')
  )
  print('Go to the following URL and Authorize the Application:\n\n{}\n'.format(request_uri))
  return(0)
  ########################################
###########################################################################

###########################################################################
# Being called as CGI
###########################################################################
def handleCGI():
  print('Content-Type: text/plain')
  print()
  ########################################
  # Check the received code
  ########################################
  getparams = cgi.FieldStorage()
  #cgi.test()
  #print("getparams:\n{}\n".format(getparams))
  if 'code' not in getparams:
    __logger.error("No 'code' received")
    return(-1)
  auth_code = getparams['code'].value
  if 'state' not in getparams:
    __logger.error("No 'state' received")
    return(-1)
  state_recv = getparams['state'].value
  ####
  # Retrieve state
  ####
  db = org.miggy.edcapi.database.database(__logger, __config)
  if not db:
    __logger.error('Failed to open auth state database')
  auth_state = db.getAuthState(state_recv)
  ####

  if auth_state and state_recv != auth_state['state']:
    __logger.error("Received state doesn't match the stored one")
    return(-2)
  __logger.debug("Auth Code: '{}'".format(auth_code))
  __logger.debug("Received State: '{}'".format(state_recv))
  ########################################

  ########################################
  # Make a Token Request
  ########################################
  uri = __config.get('auth_api_url') + '/token'
  data = {
    'grant_type': 'authorization_code',
    'code': auth_code,
    'redirect_uri': __config.get('redirect_uri'),
    'client_id': __config.get('clientid'),
    'code_verifier': auth_state['verifier']
  }
  req_data = ""
  for d in data.keys():
    if d == 'redirect_uri':
      req_data = req_data + urllib.parse.urlencode({d:data[d]}) + "&"
    else:
      req_data = req_data + d + "=" + data.get(d) + "&"
  req_data = req_data[0:-1]
  req_data = req_data.encode('ascii')
  #print("req_data:\n{}\n".format(req_data))
  #return(0)
  ### import http.client as http_client
  ### http_client.HTTPConnection.debuglevel = 1
  ### requests_log = logging.getLogger("requests.packages.urllib3")
  ### requests_log.setLevel(logging.DEBUG)
  ### requests_log.propagate = True

  response = requests.post(uri, data=req_data,
    headers={
      'Content-Type': 'application/x-www-form-urlencoded',
      'User-Agent': __config.get('user_agent')
    }
  )
  tokens = json.loads(response.text)
  print(response.text)
  ########################################

  ########################################
  # Update stored data with the access_token, refresh_token and expires
  ########################################
  db.updateWithAccessToken(
    state_recv,
    tokens['token_type'],
    tokens['access_token'],
    tokens['refresh_token'],
    tokens['expires_in']
  )
  ########################################

  ########################################
  # Retrieve /decode so we know who this Access Token is for
  ########################################
  uri = __config.get('auth_api_url') + '/decode'
  session = requests.Session()
  session.headers.update(
    {
      'User-Agent': __config.get('user_agent'),
      "Authorization": "Bearer " + tokens["access_token"],
      "Content-Type": "application/json"
    }
  )
  response = session.get(uri)
  decode = json.loads(response.text)
  print(response.text)
  db.updateWithCustomerID(tokens['access_token'], decode['usr']['customer_id'])
  ########################################
###########################################################################

if __name__ == '__main__':
      main()


import os
from collections import OrderedDict

os.environ['OPENBLAS_NUM_THREADS'] = '1'
os.environ['OMP_NUM_THREADS'] = '1'
os.environ['MKL_NUM_THREADS'] = '1'
os.environ['TF_XLA_FLAGS'] = '--tf_xla_enable_xla_devices'

import tensorflow as tf

tf.config.threading.set_inter_op_parallelism_threads(1)
tf.config.threading.set_intra_op_parallelism_threads(1)

import numpy as np
np.random.seed(0)

import sys
sys.path.append('./precompiler')

import graph
from graph import convert_keras_to_graph

from benchmarks import benchmark, get_benchmarks

import argparse

import logging
logging.basicConfig(filename='logger.out', filemode='w', level=logging.INFO)

import json

def split_mat(x_size, w_size, array_size, tile_first_dim=None):
    no_row, no_col = array_size

    if tile_first_dim is None:
        partition_size = (no_row, no_row, no_col)
    else:
        partition_size = (tile_first_dim, no_row, no_col)

    dim1 = int(x_size[0])
    dim2 = int(w_size[0])
    dim3 = int(w_size[1])

    no_row_tile = int( np.ceil (dim2 / partition_size[1]) )
    no_col_tile = int( np.ceil (dim3 / partition_size[2]) )

    w_tile_dim = {i:{} for i in range(no_row_tile)}
    for j in range(no_col_tile):
        for i in range(no_row_tile):
            tile_dim1 = min((i+1)*partition_size[1], dim2) - i*partition_size[1]
            tile_dim2 = min((j+1)*partition_size[2], dim3) - j*partition_size[2]
            w_tile_dim[i][j] = [tile_dim1,tile_dim2]

    no_batch_tile = int( np.ceil (dim1 / partition_size[0]) )
    x_tile_dim = {i:{} for i in range(no_batch_tile)}

    for j in range(no_row_tile):
        for i in range(no_batch_tile):
            tile_dim1 = min((i+1)*partition_size[0], dim1) - i*partition_size[0]
            tile_dim2 = min((j+1)*partition_size[1], dim2) - j*partition_size[1]
            x_tile_dim[i][j] = [tile_dim1, tile_dim2]

    return x_tile_dim, w_tile_dim, no_batch_tile, no_row_tile, no_col_tile

def partition_layer(layer_node, array_size, partition_size):
    if layer_node.layer_type == 'Conv2D' or layer_node.layer_type == 'Dense':
        gemm_info = {}

        input_size = layer_node.layer_attr["input_size"]
        weight_size = layer_node.layer_attr["weight_size"]

        if layer_node.layer_type == 'Conv2D':
            gemm_info["kernel_size"] = layer_node.layer_attr["kernel_size"]

        gemm_info["input_size"] = input_size
        gemm_info["weight_size"] = weight_size

        x_tile_dim, w_tile_dim, no_batch_tile, no_row_tile, no_col_tile = split_mat(input_size, weight_size, array_size, partition_size)
        no_tiles = (no_batch_tile, no_row_tile, no_col_tile)

        gemm_info["x_tile_dim"] = x_tile_dim
        gemm_info["w_tile_dim"] = w_tile_dim
        gemm_info["no_tiles"] = no_tiles

        return gemm_info
    else:
        logging.info("No GEMM operation found at layer {} of type {}.".format(layer_node.layer_name, layer_node.layer_type))
        return None

def all_dependencies_scheduled(layer_name, graph, layer_schedules):
    node = graph.get_node(layer_name)

    for s in node.src:
        if s.layer_name not in layer_schedules:
            return False

    return True

def precompile_model(model, array_size, partition_size=None):
    graph = convert_keras_to_graph(model)

    raw_input = 1

    layers = OrderedDict()
    for layer_name in graph.get_layer_names():
        layer_node = graph.get_node(layer_name)
        gemm_op = partition_layer(layer_node, array_size, partition_size)

        dependencies = [s.layer_name for s in layer_node.src]

        layers[layer_name] = {"gemm_op": gemm_op, "deps": dependencies, "raw_input":raw_input, "layer_type": layer_node.layer_type}

        if gemm_op is not None:
            raw_input = 0 #toggle raw_input after the first layer with gemm ops

    return layers

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--model', type=str, required=False, default='bert_medium')
    parser.add_argument('--extra_models', type=str, nargs='+', required=False, default=[])
    parser.add_argument('--batch_size', type=int, required=False, default=1, help='Batch size')
    parser.add_argument('--sentence_len', type=int, required=False, default=100, help='Sentence length for transformer model')
    parser.add_argument('--imsize', type=int, required=False, default=299)
    parser.add_argument('--array_size', type=int, nargs='+', required=False, default=[32,32], help='Array size')
    parser.add_argument('--out_dir', type=str, required=False, default="experiments/tmp")
    parser.add_argument('--partition_size', type=int, required=False, default=None)
    parser.add_argument('--read_only', type=int, required=False, default=1)
    parser.add_argument('--enable_schedule_duplication', type=int, required=False, default=1)

    args = parser.parse_args()

    batch_size = args.batch_size
    sentence_len = args.sentence_len

    array_size = args.array_size

    imsize = args.imsize
    partition_size = args.partition_size
    out_dir = args.out_dir
    extra_models = args.extra_models
    extra_models = [m for m in extra_models if m != "None"]

    if len(extra_models) > 0:
        assert args.enable_schedule_duplication == False, "Schedule duplication is supported only for a single BERT model"

    json_out = {"args":args.__dict__}
    for m in [args.model] + extra_models:
        bm = get_benchmarks(m, batch_size, imsize, sentence_len, args.read_only)
        if bm.model_type == "BERT" and args.enable_schedule_duplication:
            keras_model = bm.get_keras_model(no_layers=1)
            no_repeat = bm.no_layers
        else:
            keras_model = bm.get_keras_model()
            no_repeat = 1

        layers = precompile_model(keras_model, array_size=array_size, partition_size=partition_size)
        json_out[m] = {"order":list(layers.keys()), "layers":layers, "no_repeat":no_repeat, "no_ops":bm.no_ops}

    os.makedirs(out_dir, exist_ok=True)
    with open(out_dir+"/precompiled_model.json", "w") as outfile:
        json.dump(json_out, outfile)

    print("precompiled model is saved at: {}".format(out_dir))

if __name__ == "__main__":
    main()


import requests
from dotenv import load_dotenv
import json
import os
from datetime import datetime
from collections import defaultdict
load_dotenv()

API_ME = "https://scrapbox.io/api/users/me"
API_IMPORT = "https://scrapbox.io/api/page-data/import/{project}.json"
API_PAGE_LIST = "https://scrapbox.io/api/pages/{project}"
API_PAGE = "https://scrapbox.io/api/pages/{project}/{title}"
API_QUERY = "https://scrapbox.io/api/pages/{project}/search/query"

# init
sid = os.getenv("SID")
cookie = "connect.sid=" + sid
r = requests.get(API_ME, headers={"Cookie": cookie})
r.raise_for_status()
csrfToken = r.json()["csrfToken"]

def import_to(project, data):
    """
    data: string
    """

    url = API_IMPORT.format(project=project)
    r = requests.post(
        url,
        files={"import-file": data},
        headers={
            "Cookie": cookie,
            "Accept": "application/json, text/plain, */*",
            "X-CSRF-TOKEN": csrfToken,
        }
    )
    r.raise_for_status()

def get_page_list(project):
    url = API_PAGE_LIST.format(project=project)
    r = requests.get(
        url,
        headers={
            "Cookie": cookie,
            "Accept": "application/json, text/plain, */*",
            "X-CSRF-TOKEN": csrfToken,
        }
    )
    r.raise_for_status()
    return r

def get_page(project, title):
    url = API_PAGE.format(project=project, title=title)
    r = requests.get(
        url,
        headers={
            "Cookie": cookie,
            "Accept": "application/json, text/plain, */*",
            "X-CSRF-TOKEN": csrfToken,
        }
    )
    r.raise_for_status()
    return r

def query(project, q, skip=0, sort="pageRank", limit=100):
    url = API_QUERY.format(project=project)
    r = requests.get(
        url,
        params=dict(q=q, skip=skip, sort=sort, limit=limit),
        headers={
            "Cookie": cookie,
            "Accept": "application/json, text/plain, */*",
            "X-CSRF-TOKEN": csrfToken,
        }
    )
    r.raise_for_status()
    return r

def write_pages(project, pages):
    data = json.dumps({"pages": pages})
    import_to(project, data)

def get_recent_pages(project):
    r = get_page_list("nishio")
    data = r.json()
    pages = data["pages"]
    now = datetime.now()
    for p in pages:
        updated = datetime.fromtimestamp(p["updated"])
        if (now - updated).days < 1:
            yield p

def get_recent_keyword(project):
    link_to = defaultdict(list)
    for page in get_recent_pages(project):
        title = page["title"]
        print(title)
        page = get_page(project, title).json()
        links = page["links"]
        for k in links:
            link_to[k].append(title)

    return link_to

def ex1():
    active_project = os.getenv("ACTIVE_PROJECT")
    target_projects = os.getenv("TARGET_PROJECTS").split(",")
    target_project = target_projects[0]
    output_project = os.getenv("OUTPUT_PROJECT")

    link_to = get_recent_keyword(active_project)
    lines = []
    print("-----\n\n")
    for keyword in link_to:
        data = query(target_project, keyword).json()
        query_link = f"[query https://scrapbox.io/{target_project}/search/page?q={keyword}]"
        if data["count"] > 0:
            lines.append(
                f"[{keyword}]:"
            )
            lines.append(
                f" [/{target_project}/{keyword}]({query_link}: {data['count']} hits)"
            )
            if data["count"] > 7:
                # too many
                pass
            else:
                for page in data["pages"]:
                    title = page['title']
                    lines.append(f" [/{target_project}/{title}]:")
                    for line in page["lines"]:
                        lines.append(f"  `{line}`")
    print("\n".join(lines))

    # write_pages(output_project, dict(title="tmp", lines=lines))

def _test():
    pages = [
        {
            "title": "Scbot Home",
            "lines": ["Scbot Home", "Hello world!"]
        }
    ]
    write_pages("nishio", pages)


import numpy as np
import matplotlib.pyplot as plt
import scipy.signal as ss

folds = np.loadtxt("files.dat", dtype=bytes, delimiter='\t').astype(str)

order_str = "_008.norm.dat"

specs=[]
corrs=[]
phases=[]
for i in range(0, len(folds[:,0])):
    specs.append(np.loadtxt("../EXTRACTED/"+folds[i,0]+"/"+folds[i,1]+"/"+folds[i,1]+order_str))
    corrs.append(float(folds[i,3]))
    phases.append(float(folds[i,2]))

xx=[]
yy=[]
v0=-11.8
lam0=6562.8
wing=4 # wing in angstrems
for k in range(0, len(folds)):
    xx1=[]
    yy1=[]
    x0=lam0*(1.0+(v0-corrs[k])/300000.0)
    xlim1=x0-wing; xlim2=x0+wing
    for i in range(0, len(specs[k][:,0])):
        if((specs[k][i,0]>=xlim1) & (specs[k][i,0]<=xlim2)):
            xx1.append(specs[k][i,0])
            yy1.append(specs[k][i,1])
    yyf = ss.savgol_filter(yy1, 5, 2)
    xx.append(xx1)
    yy.append(yyf)

for i in range(0, len(xx)):
    x0=lam0*(1.0+(v0-corrs[i])/300000.0)
    for j in range(0, len(xx[i])):
        xx[i][j] = (xx[i][j] - x0)*300000/x0

period = 1.76159 #days
expos = (30/60)/24/period
pp =  np.linspace(0,1,100)
vv = np.linspace(-100, 100, 200)
xxm, yym = np.meshgrid(vv, pp)
zz=np.zeros((len(pp),len(vv)))

for i in range(0,len(pp)):
    filled = False
    for p in range(0, len(phases)):
        if (phases[p]<=(pp[i]+expos/2)) & (phases[p]>(pp[i]-expos/2)):
            for k in range(0, len(vv)):
                zz[i,k]=np.interp(vv[k], xx[p], yy[p])
            filled = True
    if filled==False:
        for k in range(0, len(vv)):
                zz[i,k]=1

plt.imshow(zz, interpolation="nearest", cmap=plt.get_cmap("seismic"), extent=[vv[0],vv[len(vv)-1],1,0], aspect=300)
plt.xlabel("Velosity, km/s")
plt.ylabel("Phase")
plt.colorbar()
plt.show()


import yaml
import os
from common import do_contants

class DoYaml:
    def __init__(self, yamlfilepath):
        if os.path.exists(yamlfilepath):
            self.yamlfilepath = yamlfilepath
        else:
            raise FileNotFoundError('文件不存在！')

    def read_yaml(self):
        with open(self.yamlfilepath, 'rb') as f:
            y = yaml.load(f, Loader=yaml.FullLoader)
        return y

    def write_yaml(self, num, key, value):
        with open(self.yamlfilepath, 'rb') as f:
            y = yaml.load(f, Loader=yaml.FullLoader)
            y[int(num - 1)][key] = value

        with open(self.yamlfilepath, 'w', encoding='utf-8') as w_f:
            # 覆盖原先的配置文件
            yaml.dump(y, w_f, allow_unicode=True)
            # y = yaml.load(f, Loader=yaml.FullLoader)
        return y

if __name__ == '__main__':
    a = DoYaml(do_contants.case_file + '\\wap_day.yaml')
    b = a.read_yaml()
    print(b)
    # print(
    # a.write_yaml(b,'result','false'))


import os
import sys
import cv2
import random
import numpy as np
import pandas as pd
from tqdm import tqdm

output = "dataset"
num_classes = 5
line_width = 2
num_imgs_per_class = int(sys.argv[1]) if len(sys.argv)>1 else 1000
img_size = int(sys.argv[2]) if len(sys.argv)>2 else 64
shape_names = ["circle", "square", "rectangle", "triangle", "polygon"]
df = pd.DataFrame(columns=["path", "label"])
if not os.path.exists(output):
    os.makedirs(output)

def generate_(shape_name):
    img = np.zeros((img_size, img_size), dtype=np.uint8)
    center = (random.randint(img_size // 4, 3 * img_size // 4), random.randint(img_size // 4, 3 * img_size // 4))
    if shape_name == 'circle':
        radius = img_size // 4 - line_width // 2
        cv2.circle(img, center, radius, 255, line_width)
    elif shape_name == 'square':
        side = img_size // 2 - line_width // 2
        side = min(center[0], center[1], img_size - center[0], img_size - center[1])  - line_width // 2
        pt1 = (center[0] - side // 2, center[1] - side // 2)
        pt2 = (center[0] + side // 2, center[1] + side // 2)
        cv2.rectangle(img, pt1, pt2, 255, line_width)
    elif shape_name == 'rectangle':
        width = img_size // 4 - line_width // 2
        height = img_size // 4 - line_width // 2
        width = min(center[0], img_size - center[0]) - line_width // 2
        height = min(center[1], img_size - center[1]) - line_width // 2
        pt1 = (center[0] - width // 2, center[1] - height // 2)
        pt2 = (center[0] + width // 2, center[1] + height // 2)
        cv2.rectangle(img, pt1, pt2, 255, line_width)
    elif shape_name == 'triangle':
        side = img_size // 4 - line_width // 2
        side = min(center[0], center[1], img_size - center[0], img_size - center[1]) * 2 - line_width // 2
        pt1 = (center[0], center[1] - side // 2)
        pt2 = (center[0] - side // 2, center[1] + side // 2)
        pt3 = (center[0] + side // 2, center[1] + side // 2)
        pts = np.array([pt1, pt2, pt3], dtype=np.int32)
        cv2.polylines(img, [pts], True, 255, line_width)
    elif shape_name == 'polygon':
        pts = []
        poly_side = 5
        r = min(center[0], center[1], img_size - center[0], img_size - center[1]) - line_width // 2
        for i in range(poly_side):
            theta = i * (360 // poly_side)
            #r = random.randint(img_size // 4 - line_width, img_size // 2)
            x = center[0] + int(r * np.cos(np.deg2rad(theta)))
            y = center[1] + int(r * np.sin(np.deg2rad(theta)))
            pts.append([x, y])
        pts = np.array(pts, dtype=np.int32)
        cv2.polylines(img, [pts], True, 255, line_width)
    return img

count = 0
print("----- Generating Dataset -----")
for i in tqdm(range(num_classes), total=num_classes):
    shape_name = shape_names[i]
    for j in range(num_imgs_per_class):
        img = generate_(shape_name)
        label = i
        filename = f'{shape_name}_{j}.png'
        df.loc[count, 'path'] = filename.split(".")[0]
        df.loc[count, 'label'] = i
        cv2.imwrite(f"{output}/{filename}", img)
        count += 1
print(f'{num_classes*num_imgs_per_class} images generated')
print("Distribution of the data:")
print(df.label.value_counts())
df.to_csv("./dataset.csv", index=False)