from __future__ import print_function, absolute_import, division
from future.builtins import *
from future import standard_library
standard_library.install_aliases()

# Copyright 2017 Autodesk Inc.
#
# 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.
from . import PrimitiveSum, SHELLS, SPHERICALNAMES

class AtomicBasisFunction(PrimitiveSum):
    """ Stores an atomic basis function.

    Note:
        Either l and m should be passed, or cart, but not both.

    Args:
        atom (moldesign.Atom): The atom this basis function belongs to
        index (int): the index of this basis function (it is stored as
            ``wfn.basis[self.index]``)
        n (int): principal quantum number (``n>=1``) - shell metadata (used for labeling only)
        l (int): total angular momentum quantum number (``l<=n-1``)
        m (int): z-angular momentum quantum number (optional -
             for spherical sets only; ``|m|<=l``)
        cart (str): cartesian component (optional; for cartesian sets only)
        primitives (List[PrimitiveBase]): List of primitives, if available
    """
    def __init__(self, atom, n=None, l=None, m=None, cart=None, primitives=None):
        super().__init__(primitives)
        self._atom = atom
        self.atom_index = atom.index
        self.n = n
        self.l = l
        self.m = m
        if cart is not None:
            assert self.m is None, 'Both cartesian and spherical components passed!'
            assert len(cart) == self.l, \
                'Angular momentum does not match specified component %s' % cart
            for e in cart:
                assert e in 'xyz'
            self.cart = ''.join(sorted(cart))
        else:
            self.cart = None

        # These quantities can't be defined until we assemble the entire basis
        self.coeffs = None
        self.molecule = atom.molecule
        self.basis = None
        self.occupation = None
        self.wfn = None

    @property
    def atom(self):
        """ moldesign.Atom: the atom this basis function belongs to

        We get the atom via an indirect reference, making it easier to copy the wavefunction
        """
        if self.wfn is not None:
            return self.wfn.mol.atoms[self.atom_index]
        else:
            return self._atom

    @property
    def orbtype(self):
        """ A string describing the orbital's angular momentum state.

        Examples:
            >>> AtomicBasisFunction(n=1, l=0).orbtype
            's'
            >>> AtomicBasisFunction(n=2, l=1, cart='y').orbtype
            'py'
            >>> AtomicBasisFunction(n=3, l=2, m=0).orbtype
            'd(z^2)'
        """
        if self.l == 0: t = 's'
        elif self.cart is not None: t = SHELLS[self.l] + self.cart
        else: t = SPHERICALNAMES[self.l, self.m]
        return t

    @property
    def aotype(self):
        """ A string describing the orbital's state.

        Examples:
            >>> AtomicBasisFunction(n=1, l=0).aotype
            '1s'
            >>> AtomicBasisFunction(n=2, l=1, cart='y').aotype
            '2py'
            >>> AtomicBasisFunction(n=3, l=2, m=0).aotype
            '3d(z^2)'
        """
        t = self.orbtype
        if self.n:
            return '%s%s' % (self.n, t)
        else:
            return t

    def __str__(self):
        return 'AO ' + self.name

    @property
    def name(self):
        try:
            return '%s on atom %s' % (self.aotype, self.atom.name)
        except:
            return 'Basis Fn'

    def __repr__(self):
        return '<%s %s>' % (self.__class__.__name__, self.name)


from shogi import Shogi, Rook, Lance, Pawn

class Interface():

    def __init__(self):
        self.game = Shogi()
        self.turn_count = 0

    # Inicia el loop del juego
    def start_playing(self):
        while self.game.is_playing:
            self.turn_count += 1
            self.input_origin_coordinates()
            self.input_destiny_coordinates()
        print(
            f"### Congratulations! {self.game.playerturn} Wins "
            f"in {self.turn_count} turns! ###".title())

    # Loop para el ingreso de coordenadas para seleccionar una pieza
    def input_origin_coordinates(self):
        input_correct = False
        while not input_correct:
            print(self.print_board())
            if self.game.error != "":
                print(f"---{self.game.error}---")
            row = input("Enter the Origin Row value(0-9): ")
            column = input("Enter the Origin Column value: ")
            if row == "exit" or column == "exit":
                self.game.is_playing = False
            if self.game.play_origin(row, column):
                input_correct = True
        return

    # Loop para el ingreso de coordenadas para el destino de una pieza
    # Si es valido, Pregunta si promocionar la pieza o no
    def input_destiny_coordinates(self):
        input_correct = False
        promote = ""
        while not input_correct:
            print(self.print_board())
            if self.game.error != "":
                print(f"---{self.game.error}---")
            row = input("Enter the Destination Row value(0-8): ")
            column = input("Enter the Destination Column value(0-8): ")
            if self.game.play_destination(row, column):
                input_correct = True
                if self.game.board[int(row)][int(column)].set_for_promotion:
                    while promote != "y" and promote != "n":
                        promote = input(
                            "Do you want to promote the piece?(y/n): ").lower()
                        if promote != "y" and promote != "n":
                            print("Enter 'y' or 'n'")
                    if promote == "y":
                        self.game.board[int(row)][int(column)].promote()
        return

    # Imprime el tablero, el turno actual, y el jugador actual en pantalla
    def print_board(self):
        screen = self.game.board_print()
        symbol = ""
        if self.game.playerturn == "white":
            symbol = "(\u039b)"
        elif self.game.playerturn == "black":
            symbol = "(V)"
        turn_indicator = (
            f"\n======== #{self.turn_count} "
            f"{self.game.playerturn}{symbol} Turn ========\n".title())
        screen += turn_indicator
        return screen

if __name__ == "__main__":
    interface = Interface()
    interface.start_playing()


import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
import sklearn.preprocessing
class FocalLoss(nn.Module):
    def __init__(self, gamma=0, alpha=None, size_average=True):
        super(FocalLoss, self).__init__()
        self.gamma = gamma
        self.alpha = alpha
        if isinstance(alpha,(float,int)): self.alpha = torch.Tensor([alpha,1-alpha])
        if isinstance(alpha,list): self.alpha = torch.Tensor(alpha)
        self.size_average = size_average

    def forward(self, input, target):
        if input.dim()>2:
            input = input.view(input.size(0),input.size(1),-1)  # N,C,H,W => N,C,H*W
            input = input.transpose(1,2)    # N,C,H*W => N,H*W,C
            input = input.contiguous().view(-1,input.size(2))   # N,H*W,C => N*H*W,C
        target = target.view(-1,1)

        logpt = F.log_softmax(input)
        logpt = logpt.gather(1,target)
        logpt = logpt.view(-1)
        pt = Variable(logpt.data.exp())

        if self.alpha is not None:
            if self.alpha.type()!=input.data.type():
                self.alpha = self.alpha.type_as(input.data)
            at = self.alpha.gather(0,target.data.view(-1))
            logpt = logpt * Variable(at)

        loss = -1 * (1-pt)**self.gamma * logpt
        if self.size_average: return loss.mean()
        else: return loss.sum()

class LabelSmoothing(nn.Module):
    """NLL loss with label smoothing.
    """
    def __init__(self, smoothing=0.0):
        """Constructor for the LabelSmoothing module.
        :param smoothing: label smoothing factor
        """
        super(LabelSmoothing, self).__init__()
        self.confidence = 1.0 - smoothing
        self.smoothing = smoothing

    def forward(self, x, target):
        logprobs = torch.nn.functional.log_softmax(x, dim=-1)
        nll_loss = -logprobs.gather(dim=-1, index=target.unsqueeze(1))
        nll_loss = nll_loss.squeeze(1)
        smooth_loss = -logprobs.mean(dim=-1)
        loss = self.confidence * nll_loss + self.smoothing * smooth_loss
        return loss.mean()

def binarize(T, nb_classes):
    T = T.cpu().numpy()

    T = sklearn.preprocessing.label_binarize(
        T, classes = range(0, nb_classes)
    )
    T = torch.FloatTensor(T).cuda()
    return T

def l2_norm(input):
    input_size = input.size()
    buffer = torch.pow(input, 2)
    normp = torch.sum(buffer, 1).add_(1e-12)
    norm = torch.sqrt(normp)
    _output = torch.div(input, norm.view(-1, 1).expand_as(input))
    output = _output.view(input_size)
    return output

class Adaptive_Proxy_Anchor(torch.nn.Module):
    def __init__(self, nb_classes, sz_embed, config,  mrg=0.1, alpha=32, scale_margin=1):
        torch.nn.Module.__init__(self)
        # Proxy Anchor Initialization
        self.proxies = torch.nn.Parameter(torch.randn(nb_classes, sz_embed).to(config.device))
        nn.init.kaiming_normal_(self.proxies, mode='fan_out')
        self.mrg = torch.nn.Parameter(torch.tensor([mrg], requires_grad=True, device=config.device,
                                                   dtype=torch.double))
        self.nb_classes = nb_classes
        self.sz_embed = sz_embed
        self.alpha = alpha
        self.scale_margin = scale_margin

    def forward(self, X, T):
        P = self.proxies

        cos = F.linear(l2_norm(X), l2_norm(P))  # Calcluate cosine similarity
        P_one_hot = binarize( T = T, nb_classes = self.nb_classes)
        N_one_hot = 1 - P_one_hot

        pos_exp = torch.exp(-self.alpha * (cos - self.mrg))
        neg_exp = torch.exp(self.alpha * (cos + self.mrg))

        with_pos_proxies = torch.nonzero(P_one_hot.sum(dim = 0) != 0).squeeze(dim = 1)   # The set of positive proxies of data in the batch
        num_valid_proxies = len(with_pos_proxies)   # The number of positive proxies

        P_sim_sum = torch.where(P_one_hot == 1, pos_exp, torch.zeros_like(pos_exp)).sum(dim=0)
        N_sim_sum = torch.where(N_one_hot == 1, neg_exp, torch.zeros_like(neg_exp)).sum(dim=0)

        pos_term = torch.log(1 + P_sim_sum).sum() / num_valid_proxies
        neg_term = torch.log(1 + N_sim_sum).sum() / self.nb_classes
        loss = pos_term + neg_term + self.scale_margin*1 / (torch.mean(self.mrg))
        return loss

class Proxy_NCA(torch.nn.Module):
    def __init__(self, nb_classes, sz_embed, scale=32):
        super(Proxy_NCA, self).__init__()
        self.nb_classes = nb_classes
        self.sz_embed = sz_embed
        self.scale = scale
        self.loss_func = losses.ProxyNCALoss(num_classes = self.nb_classes, embedding_size = self.sz_embed, softmax_scale = self.scale).to(config.device)

    def forward(self, embeddings, labels):
        loss = self.loss_func(embeddings, labels)
        return loss

class MultiSimilarityLoss(torch.nn.Module):
    def __init__(self ):
        super(MultiSimilarityLoss, self).__init__()
        self.thresh = 0.5
        self.epsilon = 0.1
        self.scale_pos = 2
        self.scale_neg = 50

        self.miner = miners.MultiSimilarityMiner(epsilon=self.epsilon)
        self.loss_func = losses.MultiSimilarityLoss(self.scale_pos, self.scale_neg, self.thresh)

    def forward(self, embeddings, labels):
        hard_pairs = self.miner(embeddings, labels)
        loss = self.loss_func(embeddings, labels, hard_pairs)
        return loss

class ContrastiveLoss(torch.nn.Module):
    def __init__(self, margin=0.5, **kwargs):
        super(ContrastiveLoss, self).__init__()
        self.margin = margin
        self.loss_func = losses.ContrastiveLoss(neg_margin=self.margin)

    def forward(self, embeddings, labels):
        loss = self.loss_func(embeddings, labels)
        return loss

class TripletLoss(torch.nn.Module):
    def __init__(self, margin=0.1, **kwargs):
        super(TripletLoss, self).__init__()
        self.margin = margin
        self.miner = miners.TripletMarginMiner(margin, type_of_triplets = 'semihard')
        self.loss_func = losses.TripletMarginLoss(margin = self.margin)

    def forward(self, embeddings, labels):
        semi_hard_pairs = self.miner(embeddings, labels)
        loss = self.loss_func(embeddings, labels, semi_hard_pairs)
        return loss

class NPairLoss(torch.nn.Module):
    def __init__(self, l2_reg=0):
        super(NPairLoss, self).__init__()
        self.l2_reg = l2_reg
        self.loss_func = losses.NPairLoss(l2_reg_weight=self.l2_reg, normalize_embeddings=False)

    def forward(self, embeddings, labels):
        loss = self.loss_func(embeddings, labels)
        return loss


import base64
import cPickle as pickle
import codecs
import zlib

def create_names():
    with codecs.open("allCountries.txt", encoding="ascii", errors="replace") as f_in:
        with open("names.txt", "w") as f_out:
            for line in f_in:
                elems = line.split(u'\t')
                try:
                    f_out.write("%s\n" % elems[2].strip())
                except:
                    continue

def is_word_not_in_bloom_filter(word, array, k=3):
    m = len(array)
    for i in xrange(1, k + 1):
        key = word * i
        bit = (abs(hash(key))) % m
        if array[bit] is False:
            return True
    return False

def create_bloom_filter(m=12000000, k=2):
    array = [False] * m
    with open("names.txt") as f_in:
        lines = (line.strip() for line in f_in)
        for line in lines:
            for i in xrange(1, k + 1):
                key = line * i
                bit = (abs(hash(key))) % m
                array[bit] = True
    serialized = base64.encodestring(zlib.compress(pickle.dumps(array, -1), 9))
    with open("serialized.txt", "w") as f_out:
        f_out.write(serialized)

if __name__ == "__main__":
    create_bloom_filter()


import flwr as fl
from strategies.FedAvg import FedAvg
from strategies.FedOpt import FedOpt
from typing import Callable, Dict, List, Optional, Tuple
import uploads.model as ICU
import json
import torch
import os.path, requests
from app import contract, job_contract_address
import numpy as np
from collections import OrderedDict
from web3 import Web3
from abi import job_abi
import ipfshttpclient

DEFAULT_SERVER_ADDRESS = "[::]:8080"
DEVICE = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
DATA_ROOT = "uploads/testset.csv"

# Sign in to Ethereum Account
web3 = Web3(Web3.HTTPProvider('https://ropsten.infura.io/v3/ec89decf66584cd984e5f89b6467f34f'))
account = web3.eth.account.from_key('0x6b162e9dbfa762373e98b3944279f67b8fac61dc85f255da0108ebdc408af182')
web3.eth.default_account = account._address

job_abi = json.loads(job_abi)
job_contract_address = '0xD1a210292F6D37098114AFF851D747Ba6ccBAB9B'
contract = web3.eth.contract(address=job_contract_address, abi=job_abi)

def get_eval_fn(
    testset,
) -> Callable[[fl.common.Weights], Optional[Tuple[float, float]]]:
    """Return an evaluation function for centralized evaluation."""

    def evaluate(weights: fl.common.Weights) -> Optional[Tuple[float, float]]:
        model = ICU.Loader(DATA_ROOT).load_model()
        state_dict = OrderedDict(
            {k: torch.Tensor(v) for k, v in zip(model.state_dict().keys(), weights)}
        )
        model.load_state_dict(state_dict, strict=True)

        model.to(DEVICE)
        testloader = torch.utils.data.DataLoader(testset, batch_size=32, shuffle=False)

        return ICU.test(model, testloader, device=DEVICE)

    return evaluate
def get_on_fit_config_fn() -> Callable[[int], Dict[str, str]]:
    """Return a function which returns training configurations."""

    def fit_config(rnd: int) -> Dict[str, str]:
        """Return a configuration with static batch size and (local) epochs."""

        config = {
            "learning_rate": str(data['lr']),
            "batch_size": str(data["batch_size"]),
            "epochs": str(data["epoch"]),
        }
        return config

    return fit_config

def configure_flower_server():

    strategy_type = data["strategy"]
    if (strategy_type == 'datasize' or strategy_type == 'accuracy'):
        strategy = FedAvg(
            fraction_fit=float(data["fraction_fit"]),
            fraction_eval=float(data["fraction_eval"]),
            min_fit_clients=int(data["min_fit_clients"]),
            min_eval_clients=int(data["min_eval_clients"]),
            min_available_clients=int(data["min_clients"]),
            on_fit_config_fn=get_on_fit_config_fn(),
            eval_fn=None,
            on_evaluate_config_fn=None,
            accept_failures=bool(data["failure"]),
            mode=strategy_type,
            model=ICU
            # eval_fn=get_eval_fn(testloader)
            # Minimum number of clients that need to be connected to the server before a training round can start
        )
    else:
        model = ICU.Loader(DATA_ROOT).load_model()
        distribution = data["distr"]
        for name, param in model.named_parameters():
            if distribution == 'normal':
                torch.nn.init.normal_(param, mean=float(data["mean"]), std=float(data["std"]))
            elif distribution == 'uniform':
                torch.nn.init.uniform_(param, a=float(data["lb"]), b=float(data["ub"]))
            else:
                if 'bias' not in name:
                    if distribution == 'xuniform':
                        torch.nn.init.xavier_uniform_(param, gain=float(data["gain"]))
                    if distribution == 'xnormal':
                        torch.nn.init.xavier_normal_(param, gain=float(data["gain"]))
                    if distribution == 'kuniform':
                        torch.nn.init.kaiming_uniform_(param, a=float(0), mode=data["fan"], nonlinearity=data["linear"])
                    if distribution == 'knormal':
                        torch.nn.init.kaiming_normal_(param, a=float(0), mode=data["fan"], nonlinearity=data["linear"])
                else:
                    torch.nn.init.zeros_(param)
        strategy = FedOpt(
            fraction_fit=float(data["fraction_fit"]),
            fraction_eval=float(data["fraction_eval"]),
            min_fit_clients=int(data["min_fit_clients"]),
            min_eval_clients=int(data["min_eval_clients"]),
            min_available_clients=int(data["min_clients"]),
            on_fit_config_fn=get_on_fit_config_fn(),
            eval_fn=None,
            on_evaluate_config_fn=None,
            accept_failures=bool(data["failure"]),
            beta=data["beta"],
            initial_parameters=model.get_weights(),
            eta=data["slr"],
            eta_l=data["clr"],
            tau=data["da"],
            mode=strategy_type,
            model=ICU
        )

    return strategy

def launch_fl_server():
    strategy = configure_flower_server()
    fl.server.start_server("0.0.0.0:8080", config={"num_rounds": data["round"]}, strategy=strategy)

def contrib_cal(rnd):
    if os.path.exists('contrib.json'):
        f = open('contrib.json', )
        data = json.load(f)
        f.close()
        weights = []
        for i in range(rnd):
            weights.append(1/(i+1))
        m = 0
        for k, v in data.items():
            data[k]=np.average(v, weights=weights)
            m += data[k]
        for k, v in data.items():
            data[k] = v/m
        return data

    return 'No such file'

def calculate_compensations(job_id, compensation_weights):
    # Retrieve Job's bounty
    job = contract.functions.jobs(job_id).call()
    bounty = job[10]

    # Calculate compensations
    compensations = {address: int(weight*bounty) for address, weight in compensation_weights.items()}

    # Save compensations in the log ?

    return compensations

def save_weights_and_training_log(num_rounds):
    client = ipfshttpclient.connect('/dns/ipfs.infura.io/tcp/5001/https')

    model_weights_file_name = './round-'+str(num_rounds)+'-model.pt'
    model_weights_hash = client.add(model_weights_file_name)['Hash']

    log_hash = client.add('./contrib.json')['Hash']
    return model_weights_hash, log_hash

def send_compensations(job_id, compensations, model_weights_hash, log_hash):
    addresses = []
    compensation_values = []
    for address, value in compensations.items():
        addresses.append(str(address))
        compensation_values.append(int(value))

    # Create Transaction
    #  compensate(uint _id, uint [] memory _compensation, address payable [] memory _clients, string memory _resultsHash, string memory _weightsHash)
    transaction = contract.functions.compensate(int(job_id), compensation_values, addresses, log_hash, model_weights_hash) \
        .buildTransaction({'chainId': 3, 'gas': 7000000, 'nonce': web3.eth.getTransactionCount(account._address)})

    # Sign transaction with private key
    signed_txn = web3.eth.account.signTransaction(transaction, account._private_key)

    # Send transaction
    txn_hash = web3.eth.sendRawTransaction(signed_txn.rawTransaction)

    # Wait for transaction receipt
    receipt = web3.eth.wait_for_transaction_receipt(txn_hash)

    return receipt

if os.path.exists('uploads/strategy.json'):
    f = open('uploads/strategy.json', )
    data = json.load(f)
    f.close()
    if data['strategy'] != "":
        launch_fl_server()
        with open('uploads/job_id.txt', 'r') as f:
            job_id = int(f.readline())

        compensation_weights = contrib_cal(int(data["round"]))
        compensations = calculate_compensations(job_id, compensation_weights)
        model_weights_hash, log_hash = save_weights_and_training_log(int(data["round"]))
        #print(model_weights_hash)
        #print(log_hash)
        print("compensations")
        print(compensations)
        receipt = send_compensations(job_id, compensations, model_weights_hash, log_hash)
        if receipt['status'] == 0:
            print('transaction failed')
        else:
            print('transaction success')


from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from user.models import MusicUser
from .models import Playlist, Song
from django.forms.models import model_to_dict
from django.http import HttpResponseRedirect, HttpResponse, JsonResponse
from django.shortcuts import render
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt
from mutagen.mp3 import MP3
from django.db.utils import IntegrityError
import json
# Create your views here.

class ComplexEncoder(json.JSONEncoder):
    def default(self, obj):
        """
        自定义JSON编码器，增加对时间的编码方式
        """
        if isinstance(obj, datetime):
            return obj.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(obj, date):
            return obj.strftime('%Y-%m-%d')
        else:
            return json.JSONEncoder.default(self, obj)

@login_required
def mymusic(request, success=4):
    music_user = request.user
    collect = music_user.collect_user.all()
    build = music_user.build_user.all()
    collect_list = list(collect.values())
    build_list = list(build.values())

    # 前后端数据对接
    collect_result = []
    for each in collect_list:
        dict_collect = {}
        dict_collect.update({"id":each["id"]})
        dict_collect.update({"playList_name":each["playlistname"]})
        dict_collect.update({"playlist_createdTime":str(each["build_date"])})
        play = Playlist.objects.filter(id = each["id"])
        song_num = len(play[0].songs.all().values())
        dict_collect.update({"playlist_cnt":song_num})
        collect_result.append(dict_collect)

    build_result = []
    for each in build_list:
        dict_build = {}
        dict_build.update({"id":each["id"]})
        dict_build.update({"playList_name":each["playlistname"]})
        dict_build.update({"playlist_createdTime":str(each["build_date"])})
        play=Playlist.objects.filter (id = each["id"])
        song_num = len(play[0].songs.all().values())
        dict_build.update({"playlist_cnt":song_num})
        build_result.append(dict_build)

    return render(request, 'music/playlist.html', {
        'username': request.user.username,
        'build_result': build_result,
        'collect_result': collect_result,
        'style1': 'nav_hover',
        'success': success,
    })

@login_required
def upload(request):
    """
    上传音乐界面
    """
    error = ['','','','上传音乐文件','上传歌词文件','上传配图文件']
    flag = True
    if request.method == "POST":
        songname = ""
        singer = ""
        words = ""
        song_url = ""
        picture_url = ""
        album_name = ""
        song_time = 0
        songname = request.POST.get("songname",None)  #输入歌曲名
        singer = request.POST.get("singer",None) #输入歌手名
        album_name = request.POST.get("album_name",None) #输入专辑名
        #获取歌曲文件
        song_file = request.FILES.get("song_file",None)
        #获取歌词文件
        song_words_file = request.FILES.get("song_words_file",None)
        #获取图片文件
        picture_file = request.FILES.get("picture_file",None)
        #判断输入是否出错
        if album_name == None or album_name == "":
            error[0] = "专辑名不能为空"
            flag = False
        if songname == None or songname == "":
            error[1] = "歌名不能为空"
            flag = False
        if singer == None or singer == "":
            error[2] = "歌手名不能为空"
            flag = False
        if song_file == None or song_file.name[-4:]!=".mp3":
            error[3] = "歌曲文件未选择或格式不为MP3"
            flag = False
        if song_words_file == None or song_words_file.name[-4:]!=".txt":
            error[4] = "歌词txt文件未选择或格式不为txt"
            flag = False
        if picture_file == None:
            error[5] = "歌曲配图文件未选择"
            flag = False
        #按要求输入相关数据和文件后进行数据处理
        if flag:
            thesong = Song.objects.create(
                    songname = songname,
                    singer = singer,
                    album_name = album_name,
                    words = "words",
                    song_url = "song_url",
                    picture_url = "picture_url",
                    song_time = "song_time",
                    userid = request.user
                )
            id=thesong.id
            #歌曲文件及路径名
            file_name_song = "./static/song_file/" + str(id) + "_" + song_file.name
            #歌词文件及路径名
            file_name_song_words = "./static/song_words_file/" + str(id) + "_" + song_words_file.name
            #图片文件及路径名
            file_name_picture = "./static/picture_file/" + str(id) + "_" + picture_file.name
            picture_url = file_name_picture
            song_url = file_name_song
            #分块写入文件
            with open(file_name_song, mode='wb+') as f:
                for chunk in  song_file.chunks():
                    f.write(chunk)
            with open(file_name_song_words, mode='wb+') as f:
                for chunk in  song_words_file.chunks():
                    f.write(chunk)
            with open(file_name_picture, mode='wb+') as f:
                for chunk in  picture_file.chunks():
                    f.write(chunk)
            #读取歌词存为string
            for line in  open(file_name_song_words, encoding='utf-8'):
                line = line.strip('\n')
                words = words+line+"\n"
            #获取音乐时长
            audio = MP3(song_url)
            song_time = str(audio.info.length)
            #创建model
            thesong = Song.objects.filter(id=id).update(
                    words = words,
                    song_url = song_url[1:],
                    picture_url = picture_url[1:],
                    song_time = song_time
                )
            #插入到默认歌单：我发布的音乐
            thesong = Song.objects.get(id=id)
            playlist = Playlist.objects.get(playlistname=str(request.user.username)+"_发布的音乐")
            playlist.songs.add(thesong)
            return render(request, 'music/upload.html', {
                'alertBool': 1,
                'username': request.user.username,
                })
        else:
            return render(request, 'music/upload.html', {
                    'alertBool': 0,
                    'username': request.user.username,
                })
    else:
        return render(request, 'music/upload.html', {
                    'username': request.user.username,
                    'alertBool': 2,
                    "error": error,
                    "style2":"nav_hover"
                })

def search_playlist(user, value):
    """
    根据关键字搜索歌单
    """
    playlists = Playlist.objects.filter(playlistname__icontains=value)
    playlists_result = []
    tmep_playlists_result = list(playlists.all().values())
    for each_playlist in tmep_playlists_result:
        dict_playlist = {}
        dict_playlist.update({"playlist_id":each_playlist["id"]})
        dict_playlist.update({"songListT_name":each_playlist["playlistname"]})

        play = Playlist.objects.filter (id = each_playlist["id"])
        song_num = len(play[0].songs.all().values())

        dict_playlist.update({"songListT_num":song_num})
        dict_playlist.update({"songList_songauthor":play[0].build_user.username})
        if len(play[0].collectuser.all().filter(username=user.username)) > 0:
            # 已收藏
            dict_playlist.update({"playlist_flag":"1"})
        else:
            # 未收藏
            dict_playlist.update({"playlist_flag":"0"})
        playlists_result.append(dict_playlist)
    return playlists_result

def search_music(value):
    """
    根据关键字搜索歌曲
    """
    songs = Song.objects.filter (songname__icontains=value)
    temp_result = list(songs.values())

    songs_result=[]
    for each_song in temp_result:
        dict_song = {}
        dict_song.update({"song_id":each_song["id"]})
        dict_song.update({"songList_songname":each_song["songname"]})
        dict_song.update({"songList_songauthor":each_song["singer"]})
        dict_song.update({"songList_album":each_song["album_name"]})
        temp = each_song["song_time"]
        time = str(int(float(temp)/60)) + ':' + str(int(float(temp))%60)
        dict_song.update({"songList_songtime":time})
        songs_result.append(dict_song)
    return songs_result

@login_required
def search(request):
    """
    搜索歌曲或歌单
    """

    value = request.GET.get("value",None)
    songs_result = search_music(value)
    user = request.user
    playlists_result = search_playlist(user, value)
    return render(request, 'music/Search.html', {
        'value': value,
        'songs_result': songs_result,
        'playlists_result' : playlists_result,
        'username': user.username
    })

@login_required
def music_player_song(request):
    """
    音乐播放界面
    """
    value = request.GET.get("value")
    songid = request.GET.get("songid")
    songs_result=search_music(value)
    return render(request, 'music/music_player.html', {
        'songid' : songid,
        'songs_result': songs_result,
        'username': request.user.username
    })

@login_required
def music_player_playlist(request):
    """
    获取完整歌单播放
    """
    playlistid = request.GET.get("playlistid")
    songid = request.GET.get("songid")
    p = Playlist.objects.filter (id=playlistid)
    playlist = p.all().values()[0]
    songs = list(p[0].songs.all().values())
    songs_result=[]
    for each_song in songs:
        dict_song = {}
        dict_song.update({"song_id":each_song["id"]})
        dict_song.update({"songList_songname":each_song["songname"]})
        dict_song.update({"songList_songauthor":each_song["singer"]})
        dict_song.update({"songList_album":each_song["album_name"]})
        temp = each_song["song_time"]
        time = str(int(float(temp)/60)) + ':' + str(int(float(temp))%60)
        dict_song.update({"songList_songtime":time})
        songs_result.append(dict_song)

    return render(request, 'music/music_player.html', {
        'songid' : songid,
        'songs_result': songs_result,
        'username': request.user.username
    })

@login_required
def single_playlist_info(request):
    """
    歌单详情页面
    """
    playlistid = request.GET.get("id")
    p = Playlist.objects.filter (id=playlistid)
    playlist = p.all().values()[0]

    # 歌单相关字典
    playlists_result = []
    dict_playlist = {}
    dict_playlist.update({"playlist_id":playlist["id"]})
    dict_playlist.update({"playList_name":playlist["playlistname"]})
    dict_playlist.update({"playList_date":str(playlist["build_date"])})
    dict_playlist.update({"picture_url":playlist["picture_url"]})

    song_num = len(p[0].songs.all().values())
    dict_playlist.update({"playList_num":song_num})
    dict_playlist.update({"playList_build_user":p[0].build_user.username})
    playlists_result.append(dict_playlist)

    # 歌曲相关字典
    songs = list(p[0].songs.all().values())
    songs_result=[]
    for each_song in songs:
        dict_song = {}
        dict_song.update({"song_id":each_song["id"]})
        dict_song.update({"songList_songname":each_song["songname"]})
        dict_song.update({"songList_songauthor":each_song["singer"]})
        dict_song.update({"songList_album":each_song["album_name"]})
        temp = each_song["song_time"]
        time = str(int(float(temp)/60)) + ':' + str(int(float(temp))%60)
        dict_song.update({"songList_songtime":time})
        songs_result.append(dict_song)

    return render(request, 'music/single_playlist_info.html', {
        'playlists_result': playlists_result,
        'songs_result': songs_result,
        'username': request.user.username,
    })

def get_music_detail(request):
    """
    搜索功能：获取歌曲信息
    """
    songid = request.GET.get('id', None)
    result = list(Song.objects.filter(id=songid).values())

    songname = result[0]['songname']
    album_name = result[0]['album_name']
    song_url = result[0]['song_url']
    words = result[0]['words']
    picture_url = result[0]['picture_url']

    jsondata = {
            'songname': songname,
            'album_name': album_name,
            'song_url': song_url,
            'words':words,
            'picture_url': picture_url
            }
    return JsonResponse(jsondata, json_dumps_params={'ensure_ascii':False})

@login_required
def playlist(request):
    """
    搜索功能：获取歌单详情信息
    """
    playlistid = request.GET.get('playlistid', None)
    p = Playlist.objects.filter(id=playlistid)
    playlist = p.all().values()[0]
    songs = list(p[0].songs.all().values())
    playlist['build_user'] = p[0].build_user.username
    playlist['songs_counts'] = len(songs)
    playlist['songs'] = json.dumps(songs, cls=ComplexEncoder)
    playlist['attrs'] = Song.getattr()
    return render(request, 'music/playlist.html', {
        'username': request.user.username,
        'playlist': playlist,
    })

@login_required
def createlist(request):
    """
    创建歌单，前台利用ajax发送请求
    """
    if request.method == 'POST':
        playlistname = request.POST.get('playlistname', None)
        build_user = request.user
        picture_file = request.FILES.get("picture_file",None)
        pl = Playlist.objects.filter(playlistname=playlistname, build_user=build_user)
        if len(pl) != 0:
            message = '歌单名已存在，请重新输入！'
            return render(request, 'music/createlist.html', {
                'alertBool': 0,
                'username': request.user.username,
                'message': message,
            })
        #创建歌单
        thelist = Playlist.objects.create(
            playlistname = playlistname,
            picture_url = "",
            build_user = build_user,
        )
        id = thelist.id
        file_name_picture = "./static/playlist_picture_file/" + str(id) + "_" + picture_file.name
        picture_url = file_name_picture
        #写入文件
        with open(file_name_picture, mode='wb+') as f:
            for chunk in  picture_file.chunks():
                f.write(chunk)
        #更新歌单图片路径
        thelist = Playlist.objects.filter(id=id).update(
            #playlistname = playlistname,
            picture_url = picture_url[1:],
            #build_user = build_user,
        )
        return mymusic(request, 3)
    return render(request, 'music/createlist.html', {
        'alertBool': 2,
        'username': request.user.username,
    })

@login_required
def remove_playlist(request):
    """
    删除歌单
    """
    flag = 0
    listid = request.GET.get("id",None)
    playlist = Playlist.objects.get(id = listid)
    if playlist.build_user == request.user:  #删除用户自建的歌单
        # 检查是否为系统默认歌单，默认歌单无法删除
        if playlist.playlistname == str(request.user.username)+"_发布的音乐" or playlist.playlistname == str(request.user.username)+"_喜欢的音乐":
            return mymusic(request, 0)
        else:
            playlist.delete()
            return mymusic(request, 1)
    elif request.user in list(playlist.collectuser.all()): #删除用户收藏的歌单
        playlist.collectuser.remove(request.user)
        return mymusic(request, 2)

@login_required
def getsonglist(request):
    """
    获取当前用户所创建的歌单
    """
    theuser = request.user
    build = Playlist.objects.filter(build_user = theuser).exclude(playlistname = "%s_发布的音乐" % theuser.username)
    result = [{"play_listid":x.id,"list_img":x.picture_url,"list_num":len(list(x.songs.all())),"list_name":x.playlistname} for x in build]

    return JsonResponse( result,safe=False,json_dumps_params={'ensure_ascii':False})

@login_required
def remove_song(request):
    """
    删除歌曲
    """
    theuser = request.user
    songid =  request.GET.get('songid', None)
    songlistid =  request.GET.get('songlistid', None)
    if songid == None or  songlistid == None:
        return JsonResponse({"message":"参数错误","status":0} ,json_dumps_params={'ensure_ascii':False})
    song = Song.objects.get(id = songid ) #歌曲
    songlist = Playlist.objects.get(id = songlistid) #歌单
    # 检查是否问当前歌曲的上传者
    if theuser != songlist.build_user:
        return JsonResponse({"message":"这不是您创建的歌单，您没有权限!","status":0},json_dumps_params={'ensure_ascii':False})
    if song  in songlist.songs.all():
        songlist.songs.remove(song)
        return JsonResponse({"message":"您成功将歌曲在歌单 %s 内删除 !"%songlist.playlistname ,"status":1},json_dumps_params={'ensure_ascii':False})
    else:
        return JsonResponse({"message":"该歌曲不在歌单内 %s"%songlist.playlistname ,"status":1},json_dumps_params={'ensure_ascii':False})

@login_required
def add_song(request):
    theuser = request.user
    songid =  request.GET.get('songid', None)
    songlistid =  request.GET.get('songlistid', None)
    if songid == None or  songlistid == None:
        return JsonResponse({"message":"参数错误","status":0} ,json_dumps_params={'ensure_ascii':False})
    song = Song.objects.get(id = songid ) #歌曲
    songlist = Playlist.objects.get(id = songlistid) #歌单
    if theuser != songlist.build_user:
        return JsonResponse({"message":"这不是您创建的歌单，您没有权限!","status":0},json_dumps_params={'ensure_ascii':False})
    if song not in songlist.songs.all():
        songlist.songs.add(song)
        return JsonResponse({"message":"您成功将歌曲添加入歌单：%s !"%songlist.playlistname ,"status":1},json_dumps_params={'ensure_ascii':False})
    else:
        return JsonResponse({"message":"歌单： %s已存在该收藏歌曲"%songlist.playlistname ,"status":1},json_dumps_params={'ensure_ascii':False})

@login_required
def add_songlist(request):
    """
    添加歌曲，前台利用ajax技术
    """
    theuser = request.user
    songlistid = request.GET.get("songlistid",None)
    if songlistid == None:
        return JsonResponse({"message":"parameters errors"})
    songlist = Playlist.objects.get(id = songlistid)
    if theuser in songlist.collectuser.all():
        songlist.collectuser.remove(theuser)
        return JsonResponse({"message":"你已取消收藏该歌单"})
    else:
        songlist.collectuser.add(theuser)
        return JsonResponse({"message":"你成功收藏改该歌单"})

@login_required
def alterSong(request):
    """
    编辑歌曲信息
    """
    song_name = request.GET.get('song_name', None)
    list_name = request.GET.get('list_name', None)
    action = request.GET.get('action', None)

    song = Song.objects.get(songname=song_name)
    playlist = Playlist.objects.get(playlistname=list_name)

    if action == '1':
        # 添加联系
        if song not in playlist.songs.all():
            playlist.songs.add(song)
    else:
        # 删除联系
        if song in playlist.songs.all():
            playlist.songs.remove(song)

    return JsonResponse({'Action': ('Add' if action=='1' else 'Delete'), 'result': 'Success'})

@login_required
def alterPlayList(request):
    """
    收藏歌单
    """
    playlist = request.GET.get('playlist', None)
    action = request.GET.get('action', None)
    user = request.user
    playlist = models.Playlist.objects.get(playlistname=playlist)

    if action == '1':
        # 添加联系
        if user not in playlist.collectuser.all():
            playlist.collectuser.add(user)
    else:
        # 删除联系
        if user in playlist.collectuser.all():
            playlist.collectuser.remove(user)

    return JsonResponse({'Action': ('Add' if action=='1' else 'Delete'), 'result': 'Success'})


# 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.

from openstack.tests.functional.shared_file_system import base

class ShareSnapshotTest(base.BaseSharedFileSystemTest):
    def setUp(self):
        super(ShareSnapshotTest, self).setUp()

        self.SHARE_NAME = self.getUniqueString()
        self.SNAPSHOT_NAME = self.getUniqueString()
        my_share = self.operator_cloud.shared_file_system.create_share(
            name=self.SHARE_NAME,
            size=2,
            share_type="dhss_false",
            share_protocol='NFS',
            description=None,
        )
        self.operator_cloud.shared_file_system.wait_for_status(
            my_share,
            status='available',
            failures=['error'],
            interval=5,
            wait=self._wait_for_timeout,
        )
        self.assertIsNotNone(my_share)
        self.assertIsNotNone(my_share.id)
        self.SHARE_ID = my_share.id

        msp = self.operator_cloud.shared_file_system.create_share_snapshot(
            share_id=self.SHARE_ID, name=self.SNAPSHOT_NAME, force=True
        )
        self.operator_cloud.shared_file_system.wait_for_status(
            msp,
            status='available',
            failures=['error'],
            interval=5,
            wait=self._wait_for_timeout,
        )
        self.assertIsNotNone(msp.id)
        self.SNAPSHOT_ID = msp.id

    def tearDown(self):
        snpt = self.operator_cloud.shared_file_system.get_share_snapshot(
            self.SNAPSHOT_ID
        )
        sot = self.operator_cloud.shared_file_system.delete_share_snapshot(
            snpt, ignore_missing=False
        )
        self.operator_cloud.shared_file_system.wait_for_delete(
            snpt, interval=2, wait=self._wait_for_timeout
        )
        self.assertIsNone(sot)
        sot = self.operator_cloud.shared_file_system.delete_share(
            self.SHARE_ID, ignore_missing=False
        )
        self.assertIsNone(sot)
        super(ShareSnapshotTest, self).tearDown()

    def test_get(self):
        sot = self.operator_cloud.shared_file_system.get_share_snapshot(
            self.SNAPSHOT_ID
        )
        self.assertEqual(self.SNAPSHOT_NAME, sot.name)

    def test_list(self):
        snaps = self.operator_cloud.shared_file_system.share_snapshots(
            details=True
        )
        self.assertGreater(len(list(snaps)), 0)
        for snap in snaps:
            for attribute in (
                'id',
                'name',
                'created_at',
                'updated_at',
                'description',
                'share_id',
                'share_proto',
                'share_size',
                'size',
                'status',
                'user_id',
            ):
                self.assertTrue(hasattr(snap, attribute))

    def test_update(self):
        u_snap = self.operator_cloud.shared_file_system.update_share_snapshot(
            self.SNAPSHOT_ID, display_description='updated share snapshot'
        )
        get_u_snap = self.operator_cloud.shared_file_system.get_share_snapshot(
            u_snap.id
        )
        self.assertEqual('updated share snapshot', get_u_snap.description)


import pickle
import pandas as pd
from bs4 import BeautifulSoup
import requests
import html5lib
import tkinter as tk

# Functions
def load_model():
    model_filename = 'commute_estimator_model.pkl'
    with open(model_filename, 'rb') as file:
        model = pickle.load(file)
    return model

def load_ct():
    ct_filename = 'commute_estimator_ct.pkl'
    with open(ct_filename, 'rb') as file:
        ct = pickle.load(file)
    return ct

def get_current_weather():
    URL = "https://www.timeanddate.com/weather/canada/calgary"
    r = requests.get(URL)

    soup = BeautifulSoup(r.content, 'html5lib')
    qlook = soup.find('div', attrs={'id': 'qlook'})
    text = qlook.find_all('p')[1].text
    weather = text.split()
    hi = weather[4]
    lo = weather[6]
    mean = (int(hi) + int(lo)) / 2
    wind_s = weather[8]

    default_values = {
        'Max Temp (°C)': hi,
        'Min Temp (°C)': lo,
        'Mean Temp (°C)': mean,
        'Wind Speed (km/h)': wind_s,
    }

    return default_values

def get_current_weather_and_set_defaults():
    default_values = get_current_weather()
    max_temp_entry.delete(0, tk.END)
    max_temp_entry.insert(0, default_values['Max Temp (°C)'])
    min_temp_entry.delete(0, tk.END)
    min_temp_entry.insert(0, default_values['Min Temp (°C)'])
    mean_temp_entry.delete(0, tk.END)
    mean_temp_entry.insert(0, default_values['Mean Temp (°C)'])
    wind_spd_entry.delete(0, tk.END)
    wind_spd_entry.insert(0, default_values['Wind Speed (km/h)'])

def run_model():
    model = load_model()
    ct = load_ct()

    wind_dir_dict = {'N':0, 'NE': 4.5, 'E':9, 'SE':14.5, 'S':18, 'SW':22.5, 'W':27, 'NW':31.5}
    commute_dir = 'northbound' if commute_dir_var.get() else 'southbound'
    max_temp = max_temp_entry.get()
    min_temp = min_temp_entry.get()
    mean_temp = mean_temp_entry.get()
    rain = rain_entry.get()
    snow = snow_entry.get()
    precip = precip_entry.get()
    snowg = snow_on_gnd_entry.get()
    wind_dir = selected_wind_direction.get()
    wind_spd = wind_spd_entry.get()

    new_data = pd.DataFrame({
        'direction': [commute_dir],
        'Max Temp (°C)': [float(max_temp)],
        'Min Temp (°C)': [float(min_temp)],
        'Mean Temp (°C)': [float(mean_temp)],
        'Total Rain (mm)': [float(rain)],
        'Total Snow (cm)': [float(snow)],
        'Total Precip (mm)': [float(precip)],
        'Snow on Grnd (cm)': [float(snowg)],
        'Dir of Max Gust (10s deg)': [wind_dir_dict[wind_dir]],
        'Spd of Max Gust (km/h)': [float(wind_spd)]
    })

    transformed_new_data = ct.transform(new_data)
    prediction = model.predict(transformed_new_data)

    if new_data['direction'].values[0] == 'northbound':
        text = f"It will take {int(prediction//60)}min, {int(prediction%60)}sec to get to school."
    else:
        text = f"It will take {int(prediction//60)}min, {int(prediction%60)}sec to get home."

    output = tk.Label(root, text=text)
    global grid_depth
    output.grid(row=16, column=0, columnspan=3, pady=10)

# Initializing window
root = tk.Tk()
root.title("Commute Predictor")

# Checkbox variables
commute_dir_var = tk.IntVar()
selected_wind_direction = tk.StringVar()

# Setting up grid in GUI
commute_dir_label = tk.Label(root, text='Commute Direction').grid(row=0, column=0, padx=5, pady=5)
northbound_checkbox = tk.Checkbutton(root, text='Northbound', variable=commute_dir_var, onvalue=1, offvalue=0)
southbound_checkbox = tk.Checkbutton(root, text='Southbound', variable=commute_dir_var, onvalue=0, offvalue=1)
northbound_checkbox.grid(row=0, column=1, padx=5, pady=5, sticky="w")
southbound_checkbox.grid(row=1, column=1, padx=5, pady=5, sticky="w")

get_weather_button = tk.Button(root, text="Get Current Weather", command=get_current_weather_and_set_defaults)
get_weather_button.grid(row=2, column=0, columnspan=3, pady=10)

max_temp_label = tk.Label(root, text='Max Temp (°C)').grid(row=3, column=0, padx=5, pady=5)
max_temp_entry = tk.Entry(root)
max_temp_entry.grid(row=3, column=1, columnspan=2, padx=5, pady=5, sticky="w")

min_temp_label = tk.Label(root, text='Min Temp (°C)').grid(row=4, column=0, padx=5, pady=5)
min_temp_entry = tk.Entry(root)
min_temp_entry.grid(row=4, column=1, columnspan=2, padx=5, pady=5, sticky="w")

mean_temp_label = tk.Label(root, text='Mean Temp (°C)').grid(row=5, column=0, padx=5, pady=5)
mean_temp_entry = tk.Entry(root)
mean_temp_entry.grid(row=5, column=1, columnspan=2, padx=5, pady=5, sticky="w")

rain_label = tk.Label(root, text='Total Rain (mm)').grid(row=6, column=0, padx=5, pady=5)
rain_entry = tk.Entry(root)
rain_entry.grid(row=6, column=1, columnspan=2, padx=5, pady=5, sticky="w")

snow_label = tk.Label(root, text='Total Snow (cm)').grid(row=7, column=0, padx=5, pady=5)
snow_entry = tk.Entry(root)
snow_entry.grid(row=7, column=1, columnspan=2, padx=5, pady=5, sticky="w")

precip_label = tk.Label(root, text='Total Precip (mm)').grid(row=8, column=0, padx=5, pady=5)
precip_entry = tk.Entry(root)
precip_entry.grid(row=8, column=1, columnspan=2, padx=5, pady=5, sticky="w")

snow_on_gnd_label = tk.Label(root, text='Snow on Ground (cm)').grid(row=9, column=0, padx=5, pady=5)
snow_on_gnd_entry = tk.Entry(root)
snow_on_gnd_entry.grid(row=9, column=1, columnspan=2, padx=5, pady=5, sticky="w")

wind_spd_label = tk.Label(root, text='Wind Speed (km/h)').grid(row=10, column=0, padx=5, pady=5)
wind_spd_entry = tk.Entry(root)
wind_spd_entry.grid(row=10, column=1, columnspan=2, padx=5, pady=5, sticky="w")

wind_dir_label = tk.Label(root, text='Wind Direction').grid(row=11, column=0, padx=5, pady=5)

N_button = tk.Radiobutton(root, text='N', variable=selected_wind_direction, value='N')
N_button.grid(row=11, column=1, padx=1, pady=5, sticky="w")
NE_button = tk.Radiobutton(root, text='NE', variable=selected_wind_direction, value='NE')
NE_button.grid(row=11, column=2, padx=1, pady=5, sticky="w")

E_button = tk.Radiobutton(root, text='E', variable=selected_wind_direction, value='E')
E_button.grid(row=12, column=1, padx=1, pady=5, sticky="w")
SE_button = tk.Radiobutton(root, text='SE', variable=selected_wind_direction, value='SE')
SE_button.grid(row=12, column=2, padx=1, pady=5, sticky="w")

S_button = tk.Radiobutton(root, text='S', variable=selected_wind_direction, value='S')
S_button.grid(row=13, column=1, padx=1, pady=5, sticky="w")
SW_button = tk.Radiobutton(root, text='SW', variable=selected_wind_direction, value='SW')
SW_button.grid(row=13, column=2, padx=1, pady=5, sticky="w")

W_button = tk.Radiobutton(root, text='W', variable=selected_wind_direction, value='W')
W_button.grid(row=14, column=1, padx=1, pady=5, sticky="w")
NW_button = tk.Radiobutton(root, text='NW', variable=selected_wind_direction, value='NW')
NW_button.grid(row=14, column=2, padx=1, pady=5, sticky="w")

# Button which calls run_model()
calc_button = tk.Button(root, text="Calculate Commute", command=lambda: run_model())
calc_button.grid(row=15, column=0, columnspan=3, pady=10)

# fit window to contents
root.update_idletasks()

root.mainloop()


#!/usr/bin/env python3

import io
import os
import sys

# Currently the rd page is not copied into the trace. If you want to change
# the contents of the rd page, think carefully about trace compatibility.
# One option would be to save the (replay) rd page into the trace and have
# replay default to the old rd page if the saved page is not present.

def write_rd_page(f, is_64, is_replay):
    # The length of each code sequence must be RD_PAGE_SYSCALL_STUB_SIZE.
    # The end of each syscall instruction must be at offset
    # RD_PAGE_SYSCALL_INSTRUCTION_END.
    if is_64:
        bytes = bytearray([
            0x0f, 0x05, # syscall
            0xc3, # ret
        ])
    else:
        bytes = bytearray([
            0xcd, 0x80, # int 0x80
            0xc3, # ret
        ])
    nocall_bytes = bytearray([
        0x31, 0xc0, # xor %eax,%eax
        0xc3, # ret
    ])

    # traced
    f.write(bytes)
    # privileged traced
    f.write(bytes)

    # untraced
    f.write(bytes)
    # untraced replay-only
    if is_replay:
        f.write(bytes)
    else:
        f.write(nocall_bytes)
    # untraced record-only
    if is_replay:
        f.write(nocall_bytes)
    else:
        f.write(bytes)

    # privileged untraced
    f.write(bytes)
    # privileged untraced replay-only
    if is_replay:
        f.write(bytes)
    else:
        f.write(nocall_bytes)
    # privileged untraced record-only
    if is_replay:
        f.write(nocall_bytes)
    else:
        f.write(bytes)

    ff_bytes = bytearray([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])
    f.write(ff_bytes)

generators_for = {
    'rd_page_32': lambda stream: write_rd_page(stream, False, False),
    'rd_page_64': lambda stream: write_rd_page(stream, True, False),
    'rd_page_32_replay': lambda stream: write_rd_page(stream, False, True),
    'rd_page_64_replay': lambda stream: write_rd_page(stream, True, True),
}

def main(argv):
    filename = argv[0]
    base = os.path.basename(filename)

    if os.access(filename, os.F_OK):
        with open(filename, 'rb') as f:
            before = f.read()
    else:
        before = ""

    stream = io.BytesIO()
    generators_for[base](stream)
    after = stream.getvalue()
    stream.close()

    if before != after:
        with open(filename, 'wb') as f:
            f.write(after)

if __name__ == '__main__':
    main(sys.argv[1:])


import logging

from aiogram import types
from aiogram.dispatcher import FSMContext

from keyboards.inline import dynamic_keyboards
from loader import dp
from states.states import *
from utils.db_api.python_mysql import mysql_connection

@dp.message_handler(content_types="any", state=AddInformation.all_states)
async def add_money(message: types.Message, state: FSMContext):
    user_id = message.from_user.id
    msg_text = message.text
    conn = mysql_connection()
    c = conn.cursor(buffered=True)
    state_name = await state.get_state()
    state_data = await state.get_data()
    logging.info(f'{user_id} {msg_text}')
    info_type = state_data.get('info_type')
    param_id = state_data.get('param_id')
    brand_id = state_data.get('brand_id')
    if info_type == 'params':
        for one_param in msg_text.split("\n"):
            one_param = one_param.strip()
            if one_param:
                c.execute("select count(*) from options where option_name = %s and param_id = %s",
                          (one_param, param_id))
                if not c.fetchone()[0]:
                    c.execute("insert into options (param_id, option_name) values (%s, %s)",
                              (param_id, one_param))
                    conn.commit()
    elif info_type == 'options':
        for one_param in msg_text.split("\n"):
            one_param = one_param.strip()
            c.execute("select option_id from options where param_id = %s and option_name = %s",
                      (param_id, one_param,))
            option_id = c.fetchone()[0]
            c.execute("select category_id from brands where brand_id = %s",
                      (brand_id,))
            category_id = c.fetchone()[0]
            if one_param:
                c.execute("select count(*) from brand_params "
                          "where brand_id = %s and param_id = %s and option_id = %s",
                          (brand_id, param_id, option_id))
                if not c.fetchone()[0]:
                    c.execute("insert into brand_params (param_id, brand_id, option_id, category_id) "
                              "values (%s, %s, %s, %s)",
                              (param_id, brand_id, option_id, category_id))
                    conn.commit()
    elif info_type == 'brands':
        c.execute("select category_id, is_serial, is_model, parent_id from brands where brand_id = %s", (brand_id,))
        category_id, parent_is_serial, parent_is_model, parent_parent_id = c.fetchone()
        if parent_is_serial:
            is_serial = 0
            is_model = 1
        elif parent_is_model:
            raise
        else:
            is_serial = 1
            is_model = 0
        for one_param in msg_text.split("\n"):
            one_param = one_param.strip()
            if one_param:
                c.execute("select count(*) from brands where brand_name = %s and parent_id = %s",
                          (one_param, brand_id))
                if not c.fetchone()[0]:
                    c.execute("insert into brands (category_id, parent_id, brand_name, is_serial, is_model) "
                              "values (%s, %s, %s, %s, %s)",
                              (category_id, brand_id, one_param, is_serial, is_model))
                    conn.commit()
    elif info_type == 'brands_params':
        for one_model in msg_text.split("\n"):
            one_model = one_model.strip()
            param_params = one_model.split('  ')

            model_name = param_params[0].strip()
            model_params = param_params[1:]

            c.execute("select count(*) from brands where brand_name = %s and parent_id = %s", (model_name, brand_id))
            if not c.fetchone()[0]:
                c.execute("insert into brands (brand_name, parent_id) values (%s, %s)",
                          (model_name, brand_id))
                conn.commit()
            c.execute("select brand_id, category_id "
                      "from brands where brand_name = %s and parent_id = %s", (model_name, brand_id))
            model_id, category_id = c.fetchone()
            for one_param in model_params:
                one_param = one_param.strip()
                c.execute("select param_id, option_id from options where option_name = %s",
                          (one_param,))
                try:
                    param_id, option_id = c.fetchone()
                    c.execute("select count(*) from brand_params "
                              "where param_id = %s and option_id = %s and brand_id = %s",
                              (param_id, option_id, model_id))

                    # assert 1 == 0
                    if not c.fetchone()[0]:
                        c.execute("insert into brand_params (category_id, brand_id, param_id, "
                                  "option_id, param_position) "
                                  "values (%s, %s, %s, %s, %s)",
                                  (category_id, model_id, param_id, option_id,
                                   1 if param_id == 1 else (3 if param_id == 2 else 0)))
                    conn.commit()
                except Exception as e:
                    logging.info(f'{e, model_name, one_param}')
                    pass
    await message.answer("Успех ✅")
    if info_type == 'params':
        await message.answer(f'Выберите параметр',
                             reply_markup=await dynamic_keyboards.params_for_admin(c))
    elif info_type in ('brands', 'brands_params'):
        await message.answer(f'Выберите бренд',
                             reply_markup=await dynamic_keyboards.brands_for_admin(c))
    c.close()
    conn.close()


import discord, logging, json
import asyncio
import datetime
import pytz
import schedule
import toks
from tinydb import TinyDB, Query

db = TinyDB('data.json')
client = discord.Client()
Users = Query()

BIRTHDAY_ROLE = toks.BIRTHDAY_ROLE
BIRTHDAY_CHANNEL = toks.BIRTHDAY_CHANNEL
RESPONSE_CHANNEL = toks.RESPONSE_CHANNEL
LEMON_SERVER = toks.LEMON_SERVER
TESTING_CHANNEL = toks.TESTING_CHANNEL
TEST_ROLE = toks.TEST_ROLE
HOME_SERVER = toks.HOME_SERVER
OWNER_ID = toks.OWNER_ID
CLIENT_TOKEN = toks.CLIENT_TOKEN
KAIT_ID = toks.KAIT_ID
# Print the starting text
print('---------------')
print('lemonbot')
print('---------------')
print('Starting lemonbot...')

logging.basicConfig(level=logging.WARNING)

def getDate():
    now = datetime.datetime.now(pytz.timezone('US/Pacific'))
    date = {
        'year': now.year,
        'month': now.month,
        'day': now.day,
        'hour': now.hour,
        'minute': now.minute,
        'second': now.second,
    }
    return date
@client.event
async def on_ready():
    print(client.user.name + ' Launched!')

@client.event
async def on_message(message):
    if message.author == client.user:
        return
    elif message.content.startswith('!purge'):
        await client.delete_message(message)
        if message.author.id == OWNER_ID: #dats me
            db.purge()
            await client.send_message(message.author, 'Birthday database purged!')
        else:
            await client.send_message(message.author, 'no')
            await client.send_file(message.channel, './res/img/unacceptable.png')
            msg = '{0.author.mention} has attempted to purge the db.'.format(message)
            await client.send_message(message.channel, msg)
            await client.send_message(message.channel, "Ahh! Atatatatat-No! That is why I'm royal, and *you* are servile!")
            await client.send_file(message.channel, './res/img/unacceptable.png')

    elif message.content.startswith("!status"):
        await client.send_message(message.channel, "Stop screaming! Why are you screaming?!")
    elif message.content.startswith('!purpose'):
        await client.send_file(message.channel, './res/img/purpose.png')
    elif message.content.startswith('!today'):
        date = getDate()
        msg = "Today's date is: {}/{}/{}".format(str(date['month']), str(date['day']), str(date['year']))
        await client.send_message(message.channel, msg)
    elif message.content.startswith('!code'):
        await client.send_message(message.channel, 'https://github.com/AndrewYW/lemonbot')
    elif message.content.startswith('!bday'):
        if message.channel.id == BIRTHDAY_CHANNEL:
            if message.content == "!bday":
                await client.send_message(message.channel, "{0.author.mention}: Need to include month and day.".format(message))
            else:
                await client.delete_message(message)
                await bday_command(message)
    elif message.content.startswith('!list'):
        if message.author.id == OWNER_ID or message.author.id == KAIT_ID:
            doc = db.all()
            for item in doc:
                string = item['user'] + ', birthday: ' + str(item['month']) + ' ' + str(item['day'])
                await client.send_message(client.get_channel(RESPONSE_CHANNEL), string)

    elif message.content.startswith('!lemonbot'):
        await client.send_message(message.channel, """
            Lemonbot, the bot for lemons.
            Commands list and formatting:
            [!status]: Checks status of bot.
            [!purpose]: Just try it.
            [!today]: Returns today's date in mm/dd/yyyy format.
            [!bday mm dd]: Adds your birthday to the database.
            [!code]: Links the Github repo of Lemonbot.
            """)

async def bday_command(message):
    auth = message.author
    temp = message.content.split(" ")
    if len(temp) == 3 and temp[1].isdigit() and temp[2].isdigit():
        month = int(temp[1])
        date = int(temp[2])
        if not db.contains(Users.id == auth.id):
            db.insert({
                'user': auth.name,
                'id': auth.id,
                'text': message.content,
                'month': month,
                'day': date,
                'birthday': False,
                'changed': False
            })
            await client.send_message(client.get_channel(RESPONSE_CHANNEL), 'Inserted into database: {0.author}'.format(message))
            await client.send_message(message.channel, '{0.author.mention}: Add success!'.format(message))
        else:
            if not Users.changed and Users.birthday:
                db.update({
                    'month': month,
                    'day': date,
                    'changed': True
                }, Users.id == auth.id)
                await client.send_message(message.channel, 'Updating birthday entry for: {0.author.mention}'.format(message))
                await client.send_message(client.get_channel(RESPONSE_CHANNEL), 'Updated entry for {0.author}'.format(message))
    else:
        await client.send_message(message.channel, "'They didn't understand my lemon styles. I like this way better.'")
        await client.send_message(message.channel, 'Proper format: "!bday mm dd"')

async def scrub_bdays(month, day):
    """
    Get all members of Lemon Fam
    Clear given role role from every member
    I really hope this works lmao
    """
    lemonServer = client.get_server(LEMON_SERVER)
    role = discord.utils.get(lemonServer.roles, id = BIRTHDAY_ROLE)
    birthdayLemons = db.search(Users.day != day)
    amount = "Removing: " + str(len(birthdayLemons)) + " members today"
    await client.send_message(client.get_channel(RESPONSE_CHANNEL), amount)
    if len(birthdayLemons) > 0:
        for doc in birthdayLemons:
            lemon = lemonServer.get_member(doc['id'])
            if lemon:
                if len(lemon.roles) > 0:
                    if role in lemon.roles:
                        await client.remove_roles(lemon, role)
                        await client.send_message(client.get_channel(RESPONSE_CHANNEL), "Removed role")

async def add_bdays(month, day):
    """
    Scan through database
    If doc birthday value matches today's date, add role to that member
    """
    lemonServer = client.get_server(LEMON_SERVER) #LEMON_SERVER
    birthdayLemons = db.search((Users.month == month) & (Users.day == day) & (Users.birthday==False))
    if len(birthdayLemons) > 0:
        amount = "Adding " + str(len(birthdayLemons)) + " members today"
        await client.send_message(client.get_channel(RESPONSE_CHANNEL), amount)
        for doc in birthdayLemons:
            lemon = lemonServer.get_member(doc['id'])
            db.update({'birthday': True}, Users.id == lemon.id)
            update = "Birthday today: " + str(lemon.name)
            await client.send_message(client.get_channel(RESPONSE_CHANNEL), update)
            role = discord.utils.get(lemonServer.roles, id=BIRTHDAY_ROLE)
            await client.add_roles(lemon, role) #BIRTHDAY_ROLE
            await client.send_message(client.get_channel(RESPONSE_CHANNEL), "Added role to a user")

async def daily_check():
    """
    Scan through database
    Return list of docs where birthday matches current date
    if birthday in members.roles
    For each document:
    """
    await client.wait_until_ready()
    while not client.is_closed:
        date = getDate()
        current = 'Current day: ' + str(date['month']) + "/" + str(date['day']) + "/" + str(date['year'])
        await client.send_message(client.get_channel(RESPONSE_CHANNEL), current ) #Private testing channel
        await scrub_bdays(date['month'], date['day'])
        await asyncio.sleep(10)
        await add_bdays(date['month'], date['day'])

        await asyncio.sleep(86400) #repeat daily -- 86400 seconds in a day

if __name__ == '__main__':
    client.loop.create_task(daily_check())
    client.run(CLIENT_TOKEN)


#!/usr/bin/env python3

import argparse
import os
import sys
from typing import Iterable, Iterator, List, Optional, Text, Tuple

from rich.console import Console  # type: ignore

from . import __version__
from .color import color_unified_diff_line
from .diff import external_diff, u_diff
from .textiter import head, tail
from .utils import file_exists, get_tables_argument_list

def main() -> None:  # pragma: no cover
    # try/except block rationale:
    # handles "premature" socket closure exception that is
    # raised by Python when stdout is piped to tools like
    # the `head` executable and socket is closed early
    # see: https://docs.python.org/3/library/signal.html#note-on-sigpipe
    try:
        run(sys.argv[1:])
    except BrokenPipeError:
        # Python flushes standard streams on exit; redirect remaining output
        # to devnull to avoid another BrokenPipeError at shutdown
        devnull = os.open(os.devnull, os.O_WRONLY)
        os.dup2(devnull, sys.stdout.fileno())
        sys.exit(0)

def run(argv: List[Text]) -> None:
    # ------------------------------------------
    # argparse command line argument definitions
    # ------------------------------------------
    parser = argparse.ArgumentParser(description="An OpenType table diff tool for fonts.")
    parser.add_argument("--version", action="version", version=f"fdiff v{__version__}")
    parser.add_argument(
        "-l", "--lines", type=int, default=3, help="Number of context lines (default: 3)"
    )
    parser.add_argument(
        "--include",
        type=str,
        default=None,
        help="Comma separated list of tables to include",
    )
    parser.add_argument(
        "--exclude",
        type=str,
        default=None,
        help="Comma separated list of tables to exclude",
    )
    parser.add_argument("--head", type=int, help="Display first n lines of output")
    parser.add_argument("--tail", type=int, help="Display last n lines of output")
    parser.add_argument("--external", type=str, help="Run external diff tool command")
    parser.add_argument(
        "-c",
        "--color",
        action="store_true",
        default=False,
        help="Force ANSI escape code color formatting in all environments",
    )
    parser.add_argument(
        "--nomp",
        action="store_true",
        help="Do not use multi process optimizations (default: on)",
    )
    parser.add_argument(
        "--nocolor",
        action="store_true",
        default=False,
        help="Do not use ANSI escape code colored diff (default: on)",
    )
    parser.add_argument("PREFILE", help="Font file path/URL 1")
    parser.add_argument("POSTFILE", help="Font file path/URL 2")

    args: argparse.Namespace = parser.parse_args(argv)

    # /////////////////////////////////////////////////////////
    #
    #  Validations
    #
    # /////////////////////////////////////////////////////////

    # ----------------------------------
    #  Incompatible argument validations
    # ----------------------------------
    #   --include and --exclude are mutually exclusive options
    if args.include and args.exclude:
        sys.stderr.write(
            f"[*] Error: --include and --exclude are mutually exclusive options. "
            f"Please use ONLY one of these options in your command.{os.linesep}"
        )
        sys.exit(1)

    # -------------------------------
    #  File path argument validations
    # -------------------------------

    if not args.PREFILE.startswith("http") and not file_exists(args.PREFILE):
        sys.stderr.write(
            f"[*] ERROR: The file path '{args.PREFILE}' can not be found.{os.linesep}"
        )
        sys.exit(1)
    if not args.PREFILE.startswith("http") and not file_exists(args.POSTFILE):
        sys.stderr.write(
            f"[*] ERROR: The file path '{args.POSTFILE}' can not be found.{os.linesep}"
        )
        sys.exit(1)

    # /////////////////////////////////////////////////////////
    #
    #  Command line logic
    #
    # /////////////////////////////////////////////////////////

    # instantiate a rich Console
    console = Console()

    # parse explicitly included or excluded tables in
    # the command line arguments
    # set as a Python list if it was defined on the command line
    # or as None if it was not set on the command line
    include_list: Optional[List[Text]] = get_tables_argument_list(args.include)
    exclude_list: Optional[List[Text]] = get_tables_argument_list(args.exclude)

    # flip logic of the command line flag for multi process
    # optimization use
    use_mp: bool = not args.nomp

    if args.external:
        # ------------------------------
        #  External executable tool diff
        # ------------------------------
        # head and tail are not supported when external diff tool is called
        if args.head or args.tail:
            sys.stderr.write(
                f"[ERROR] The head and tail options are not supported with external "
                f"diff executable calls.{os.linesep}"
            )
            sys.exit(1)

        # lines of context filter is not supported when external diff tool is called
        if args.lines != 3:
            sys.stderr.write(
                f"[ERROR] The lines option is not supported with external diff "
                f"executable calls.{os.linesep}"
            )
            sys.exit(1)

        try:
            with console.status("Processing...", spinner="dots10"):
                ext_diff: Iterable[Tuple[Text, Optional[int]]] = external_diff(
                    args.external,
                    args.PREFILE,
                    args.POSTFILE,
                    include_tables=include_list,
                    exclude_tables=exclude_list,
                    use_multiprocess=use_mp,
                )

                # write stdout from external tool
                for line, exit_code in ext_diff:
                    # format with color by default unless:
                    #   (1) user entered the --nocolor option
                    #   (2) we are not piping std output to a terminal
                    # Force formatting with color in all environments if the user includes
                    # the `-c` / `--color` option
                    if (not args.nocolor and console.is_terminal) or args.color:
                        sys.stdout.write(color_unified_diff_line(line))
                    else:
                        sys.stdout.write(line)
                    if exit_code is not None:
                        sys.exit(exit_code)
        except Exception as e:
            sys.stderr.write(f"[*] ERROR: {e}{os.linesep}")
            sys.exit(1)
    else:
        # ---------------
        #  Unified diff
        # ---------------
        # perform the unified diff analysis
        with console.status("Processing...", spinner="dots10"):
            try:
                uni_diff: Iterator[Text] = u_diff(
                    args.PREFILE,
                    args.POSTFILE,
                    context_lines=args.lines,
                    include_tables=include_list,
                    exclude_tables=exclude_list,
                    use_multiprocess=use_mp,
                )
            except Exception as e:
                sys.stderr.write(f"[*] ERROR: {e}{os.linesep}")
                sys.exit(1)

            # re-define the line contents of the diff iterable
            # if head or tail is requested
            if args.head:
                iterable = head(uni_diff, args.head)
            elif args.tail:
                iterable = tail(uni_diff, args.tail)
            else:
                iterable = uni_diff

            # print unified diff results to standard output stream
            has_diff = False
            # format with color by default unless:
            #   (1) user entered the --nocolor option
            #   (2) we are not piping std output to a terminal
            # Force formatting with color in all environments if the user includes
            # the `-c` / `--color` option
            if (not args.nocolor and console.is_terminal) or args.color:
                for line in iterable:
                    has_diff = True
                    sys.stdout.write(color_unified_diff_line(line))
            else:
                for line in iterable:
                    has_diff = True
                    sys.stdout.write(line)

        # if no difference was found, tell the user in addition to the
        # the zero exit status code.
        if not has_diff:
            print("[*] There is no difference in the tested OpenType tables.")


import unittest
import glob
import os.path as op

def BOLD_FIR_files(     analysis_info,
                        experiment,
                        fir_file_reward_list = '',
                        glm_file_mapper_list = '',
                        behavior_file_list = '',
                        mapper_contrast = 'stim',
                        h5_file = '',
                        roi_list = ['V1','V2','V3']
                        ):
    """Performs a per-slice FIR deconvolution on nifti-files in_files,
    with per-slice regressors from slice_regressor_list of nifti files,
    and per-TR regressors from vol_regressors text file.
    Uses standard HRF and its time-derivative.
    Assumes slices to be the last spatial dimension of nifti files,
    and time to be the last.

    Parameters
    ----------
    in_file : str
        Absolute path to nifti-file.
    slice_regressor_list : list
        list of absolute paths to per-slice regressor nifti files
    vol_regressor_list : str
        absolute path to per-TR regressor text file

    Returns
    -------
    res_file : str
        Absolute path to nifti-file containing residuals after regression.
    rsq_file : str
        Absolute path to nifti-file containing rsq of regression.
    beta_file : str
        Absolute path to nifti-file containing betas from regression.

    """

    import nibabel as nib
    import numpy as np
    import numpy.linalg as LA
    import scipy as sp
    import os
    import os.path as op
    import pandas as pd
    from spynoza.nodes.utils import get_scaninfo
    from fir import FIRDeconvolution
    from hedfpy import HDFEyeOperator
    import tempfile
    import bottleneck as bn
    # from behavior import behavior_timing
    from utils import roi_data_from_hdf

    threshold = 1.67
    zero_interval = [-2.5,-0.5]

    # roi data
    mapper_alias = op.split(glm_file_mapper_list[0])[-1][:-7] + '_logp'

    # the first file is longer in one or two subjects, so we take the scaninfo of the second file
    TR, dims, dyns, voxsize, affine = get_scaninfo(fir_file_reward_list[1])

    # behavior
    event_names, all_behav_event_times, rename_dict, which_event_name_rewarded = behavior_timing(experiment, behavior_file_list, dyns, TR)
    fir_aliases = [op.split(fir_file_reward_list[0])[-1][:-7] + '_%s'%en for en in event_names]

    out_figures = []
    for roi in roi_list:
        contrast_data = roi_data_from_hdf(data_types_wildcards = [mapper_alias], roi_name_wildcard = roi, hdf5_file = h5_file, folder_alias = 'GLM')
        fir_data = [roi_data_from_hdf(data_types_wildcards = [fa], roi_name_wildcard = roi, hdf5_file = h5_file, folder_alias = 'GLM') for fa in fir_aliases]
        deconvolution_interval_timepoints = np.linspace(analysis_info['fir_interval'][0], analysis_info['fir_interval'][1], fir_data[0].shape[-1], endpoint = False)

        # for experiment 'unpredictable' and 'variable' the masking contrast is the initial mapper
        if experiment in ['unpredictable', 'variable', 'stream-up']:
            if mapper_contrast == 'stim':
                fir_time_course_dict = {en: fd[contrast_data[:,1]>threshold].mean(axis = 0) for en,fd in zip(event_names, fir_data)}
            elif mapper == 'surround':
                fir_time_course_dict = {en: fd[contrast_data[:,4]>threshold].mean(axis = 0) for en,fd in zip(event_names, fir_data)}
        elif experiment == 'predictable':
            rewarded_location, rewarded_orientation = which_event_name_rewarded.split('_')
            # check which stimulus was rewarded and implement correct contrast values
            if rewarded_location == 'left':
                rsci,nrsci = [1,4], [7,10]
            elif rewarded_location == 'right':
                rsci,nrsci = [7,10], [1,4]
            # create joined contrast values (not averaged just yet - T values should sort-of sum.)
            if mapper_contrast == 'rewarded_stim':
                contrast_data_joined = contrast_data[:,rsci[0]] + contrast_data[:,rsci[1]]
            elif mapper_contrast == 'nonrewarded_stim':
                contrast_data_joined = contrast_data[:,nrsci[0]] + contrast_data[:,nrsci[1]]
            else:
                print('unknown mask type for experiment predictable')
            # create ROIs with these contrasts
            fir_time_course_dict = {en: fd[contrast_data_joined>threshold].mean(axis = 0) for en,fd in zip(event_names, fir_data)}

        if experiment == 'unpredictable':
            out_figures.append(
                            plot_fir_results_unpredictable(deconvolution_interval_timepoints,
                                                        event_names,
                                                        fir_time_course_dict,
                                                        zero_interval = zero_interval,
                                                        use_zero_interval = False,
                                                        suffix = roi
                                                        ))
        elif experiment == 'predictable':
            out_figures.append(
                            plot_fir_results_predictable(deconvolution_interval_timepoints,
                                                        rename_dict,
                                                        event_names,
                                                        fir_time_course_dict,
                                                        zero_interval = zero_interval,
                                                        use_zero_interval = False,
                                                        suffix = roi
                                                        ))
        elif experiment == 'variable':
            out_figures.append(
                            plot_fir_results_variable(deconvolution_interval_timepoints,
                                                        event_names,
                                                        fir_time_course_dict,
                                                        zero_interval = zero_interval,
                                                        use_zero_interval = False,
                                                        suffix = roi
                                                        ))

        # the derived data types are added in the plot functions, and overwritten such that the no-zero'd data are saved
        out_values = np.array([np.squeeze(fir_time_course_dict[key]) for key in fir_time_course_dict.iterkeys()]).T
        out_columns = [key for key in fir_time_course_dict.iterkeys()]

        out_df = pd.DataFrame(out_values, columns = out_columns, index = deconvolution_interval_timepoints)

        store = pd.HDFStore(h5_file)
        store['/fir/'+experiment+'/'+roi+'_'+mapper_contrast] = out_df
        store.close()

    return out_figures

class FIRTestCase(unittest.TestCase):

    def setUp(self):
        import glob
        import os.path as op
        from utils.plotting import *
        from utils.behavior import behavior_timing

        # standard test path and subject
        test_path = '/home/shared/-2014/reward/new/'
        test_sj = 'sub-004'
        h5_file= glob.glob(op.join(test_path, test_sj, 'h5/*roi.h5'))[0]
        fir_frequency = 10
        fir_interval = [-2.0,7.0]
        data_type = '_pupil_bp_zscore'
        lost_signal_rate_threshold = 0.15
        method = 'fir'

        experiment = 'unpredictable'
        # input files
        fir_file_reward_list = glob.glob(op.join(test_path, test_sj, 'psc/*-unpredictable_reward*.nii.gz'))
        fir_file_reward_list.sort()
        glm_file_mapper_list = glob.glob(op.join(test_path, test_sj, 'psc/*-unpredictable_mapper*.nii.gz'))
        glm_file_mapper_list.sort()
        # behavior files
        behavior_file_list = glob.glob(op.join(test_path, test_sj, 'events/tsv/*-unpredictable_reward*.tsv'))
        behavior_file_list.sort()

        experiment = 'predictable'
        # input files
        fir_file_reward_list = glob.glob(op.join(test_path, test_sj, 'psc/*-predictable_reward*.nii.gz'))
        fir_file_reward_list.sort()
        glm_file_mapper_list = glob.glob(op.join(test_path, test_sj, 'psc/*-predictable_mapper*.nii.gz'))
        glm_file_mapper_list.sort()
        # behavior files
        behavior_file_list = glob.glob(op.join(test_path, test_sj, 'events/tsv/*-predictable_reward*.tsv'))
        behavior_file_list.sort()

        experiment = 'variable'
        # # input files
        fir_file_reward_list = glob.glob(op.join(test_path, test_sj, 'psc/*-variable_*_reward*.nii.gz'))
        fir_file_reward_list.sort()
        glm_file_mapper_list = glob.glob(op.join(test_path, test_sj, 'psc/*-unpredictable_mapper*.nii.gz'))
        glm_file_mapper_list.sort()
        # behavior files
        behavior_file_list = glob.glob(op.join(test_path, test_sj, 'events/tsv/*-variable_*_reward*.tsv'))
        behavior_file_list.sort()

    def runTest(self):
        fit_FIR_nuisances_all_files(
            example_func = self.example_func,
            in_files = self.in_files,
            slice_regressor_lists = self.slice_regressor_lists,
            vol_regressor_list = self.vol_regressor_list,
            behavior_file_list = self.behavior_file_list,
            fir_frequency = 4,
            fir_interval = [-3.0,15.0]
            )


from collections import defaultdict
class Solution(object):
    def distinctNames(self, ideas):
        """
        :type ideas: List[str]
        :rtype: int
        """
        dic = defaultdict(set)
        for idea in ideas:
            dic[idea[1:]].add(idea[0])

        cs = 'abcdefghijklmnopqrstuvwxyz'
        cts = {a:{b:0 for b in cs} for a in cs}
        sm =0
        for key in dic:
            values = dic[key]
            for a in values:
                for b in cs:
                    if b in values: continue
                    sm += cts[a][b]
            for a in values:
                for b in cs:
                    if b in values: continue
                    cts[b][a] +=1

        return sm*2

re =Solution().distinctNames(["aaa","baa","caa","bbb","cbb","dbb"])
print(re)


#!/usr/bin/env python3
###############################################################################
# Includes
###############################################################################

import struct
from xml.sax.handler import property_xml_string
import rclpy
from rclpy.node import Node
from std_msgs.msg import Int32
from sensor_msgs.msg import Image, PointCloud2, PointField
from geometry_msgs.msg import PoseStamped
from iii_interfaces.msg import Powerline, PowerlineDirection
#import ros2_numpy

import cv2 as cv
from cv_bridge import CvBridge

import numpy as np

import time
import copy
import sys
import os
import math
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import matplotlib.lines as mlines

from threading import Thread, Lock

from sshkeyboard import listen_keyboard

###############################################################################
#  Defines
###############################################################################
global image_width
image_width  = 640 #1920
global image_height
image_height  = 480 #1080
global img_dims
img_dims = (image_width, image_height)

###############################################################################
# Class
###############################################################################

class IdDrawer(Node):

    key_thread = None

    def __init__(self):
        self.pl_ = None
        self.pl_buff_ = []

        self.pl_dir_ = None
        self.pl_dir_buff_ = []

        self.buff_size_ = 2

        self.pl_lock_ = Lock()
        self.dir_lock_ = Lock()

        self.key_thread = Thread(target=self.keylistener, args=())

        self.pressed_keys = []
        self.typed_ID = -1

        super().__init__("image_drawer")
        self.pl_sub_ = self.create_subscription(
            Powerline,
            "/pl_mapper/powerline",
            self.on_pl_msg,
            10
        )

        self.pl_direction_sub_ = self.create_subscription(
            PoseStamped,
            "/pl_dir_computer/powerline_direction",
            self.on_pl_direction,
            10
        )

        self.drawn_img_pub_ = self.create_publisher(
            Image,
            "/ID_image",
            10
        )

        self.ID_pub_ = self.create_publisher(
            Int32,
            "/typed_ID",
            10
        )

        timer_period = 0.1  # seconds
        self.timer = self.create_timer(timer_period, self.draw_image)

    def on_pl_msg(self, msg):
        if self.pl_lock_.acquire(blocking=True):
            self.pl_ = msg
            self.pl_buff_.append(self.pl_)
            if len(self.pl_buff_) == self.buff_size_+1:
                self.pl_buff_.pop(0)
            self.pl_lock_.release()

    def on_pl_direction(self, msg):
        if self.dir_lock_.acquire(blocking=True):
            self.pl_dir_ = msg
            self.pl_dir_buff_.append(self.pl_dir_)
            if len(self.pl_dir_buff_) == self.buff_size_+1:
                self.pl_dir_buff_.pop(0)
            self.dir_lock_.release()

    def rotate_xy(self, x, y, angle):

        rot_mat = np.matrix([[math.cos(angle), -math.sin(angle)], [math.sin(angle), math.cos(angle)]])

        xy = np.matrix([[x],[y]])

        rot_xy = np.matmul(rot_mat, xy)

        return rot_xy[0][0], rot_xy[1][0]

    def draw_image(self):

        if len(self.pl_buff_) < self.buff_size_-1 or len(self.pl_dir_buff_) < self.buff_size_-1:
            return

        pl = []
        if self.pl_lock_.acquire(blocking=True):
            if len(self.pl_buff_) == self.buff_size_-1:
                pl_temp = self.pl_
                for i in range(pl_temp.count):
                    pl.append([pl_temp.poses[i].position.x, pl_temp.poses[i].position.y, pl_temp.poses[i].position.z])
                pl = np.asarray(pl)
            else:
                pl_temp = self.pl_buff_.pop(0)
                for i in range(pl_temp.count):
                    pl.append([pl_temp.poses[i].position.x, pl_temp.poses[i].position.y, pl_temp.poses[i].position.z])
                pl = np.asarray(pl)
            self.pl_lock_.release()

        if self.dir_lock_.acquire(blocking=True):
            temp_dir = self.pl_dir_buff_.pop(0)

            pl_dir = math.atan2(
                2*(temp_dir.pose.orientation.w*temp_dir.pose.orientation.z+temp_dir.pose.orientation.x*temp_dir.pose.orientation.y),
                1-2*(temp_dir.pose.orientation.y*temp_dir.pose.orientation.y+temp_dir.pose.orientation.z*temp_dir.pose.orientation.z)
            )

            self.dir_lock_.release()

        # something wrong with rotation ?

        rotated_points_x = []
        points_z = []

        p_x = []
        p_y = []

        for i in range(len(pl)):
            to_rot_x = pl[i][0]
            to_rot_y = pl[i][1]
            # print("X,Y: ", to_rot_x, to_rot_y)
            rot_x, rot_y = self.rotate_xy(to_rot_x, to_rot_y, -pl_dir+1.57)
            # print("rot X,Y: ", rot_x, rot_y)
            rotated_points_x.append(rot_x)
            points_z.append(pl[i][2])

            p_x.append(pl[i][0])
            p_y.append(pl[i][2])

        fig, ax = plt.subplots()
        ax.scatter(rotated_points_x, points_z, linewidth=0.000001, color='green', label='Powerlines (#ID)')
        ax.scatter(0, 0, linewidth=0.000001, color='red', label='Ego', marker='X')

        n = []

        for i in range(pl_temp.count):
            n.append(pl_temp.ids[i])

        for i, txt in enumerate(n):
            ax.annotate(txt, (rotated_points_x[i], points_z[i]))

        ax.legend()

        plt.axis('square')

        # plt.show()

        fig.canvas.draw()

        img = np.frombuffer(fig.canvas.tostring_rgb(), dtype=np.uint8)
        # img = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='')
        img  = img.reshape(fig.canvas.get_width_height()[::-1] + (3,))

        # img is rgb, convert to opencv's default bgr
        img = cv.cvtColor(img,cv.COLOR_RGB2BGR)

        cvb = CvBridge()
        msg = cvb.cv2_to_imgmsg(img, encoding="bgr8")

        self.drawn_img_pub_.publish(msg)

        plt.cla()
        plt.clf()
        plt.close('all')

    ## Key press handling

    def press(self, key):
        numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

        if key == 'e' or key == 'enter':

            if len(self.pressed_keys) < 1:
                print("Key sequence has length 0, no ID submitted")

            else:
                key_string = ""

                for i in range(len(self.pressed_keys)):
                    key_string = key_string + str(self.pressed_keys[i])
                    self.typed_ID = int(key_string)

                if len(self.pressed_keys) > 10 or self.typed_ID > 2147483647:
                    print("Entered ID outside range [0, 2147483648], clearing sequence")
                    self.pressed_keys.clear()
                    print("Type ID - current key sequence: [ ]")
                    print("Press 'del' to clear or 'enter' to submit sequence\n")
                    return

                print("ID", self.typed_ID, "submitted, clearing sequence")
                self.pressed_keys.clear()

                msg = Int32()
                msg.data = self.typed_ID
                self.ID_pub_.publish(msg)

        elif key == 'x' or key == 'delete':
                print("Clearing typed sequence")
                self.pressed_keys.clear()

        elif key == 'backspace':
            print("Deleted latest entry")

            if len(self.pressed_keys) > 0:
                self.pressed_keys.pop()

        elif key in numbers:
            self.pressed_keys.append(key)

        else:
            print("Unsupported command:", key)

        key_string = ""
        for i in range(len(self.pressed_keys)):
            key_string = key_string + str(self.pressed_keys[i])
        print("Type ID - current key sequence: [", key_string, "]")
        print("Press 'del' to clear or 'enter' to submit sequence\n")

    def keylistener(self):

        print("\nEnter powerline ID")
        print("Press 'del' to clear or 'enter' to submit sequence\n")

        listen_keyboard(
            on_press=self.press,
        )

###############################################################################
# Main
###############################################################################

if __name__ == "__main__":
    rclpy.init()

    print("Starting IdDrawer node")

    minimal_publisher = IdDrawer()

    minimal_publisher.key_thread.start()

    rclpy.spin(minimal_publisher)

    # Destroy the node explicitly
    # (optional - otherwise it will be done automatically
    # when the garbage collector destroys the node object)
    minimal_publisher.destroy_node()
    rclpy.shutdown()


import matplotlib.pyplot as plt
from PIL import Image

plt.rcParams['font.sans-serif'] ="SimHei"
img=Image.open("lena512color.tiff")

plt.figure(figsize=(10,10))
plt.subplot(221)
plt.axis("off")
plt.imshow(img)
plt.title("原图",fontsize=20)

plt.subplot(222)
plt.axis("off")
img_flr=img.transpose(Image.FLIP_LEFT_RIGHT)
plt.imshow(img_flr)
plt.title("左右翻转",fontsize=20)

plt.subplot(223)
plt.axis("off")
img_r90=img.transpose(Image.ROTATE_90)
plt.imshow(img_r90)
plt.title("逆时针翻转90度",fontsize=20)

plt.subplot(224)
plt.axis("off")
img_tp=img.transpose(Image.TRANSPOSE)
plt.imshow(img_tp)
plt.title("转置",fontsize=20)

plt.show()