from typing import Optional
import logging
import torch
from torch.distributions import Poisson, Gamma, Bernoulli, Normal
from torch.utils.data import DataLoader
import torch.nn.functional as F
from torch import logsumexp
import torch.distributions as distributions
import numpy as np

from scMVP.inference import Posterior
from . import UnsupervisedTrainer

from scMVP.dataset import GeneExpressionDataset
from scMVP.models import multi_vae_attention
from sklearn.utils.linear_assignment_ import linear_assignment

logger = logging.getLogger(__name__)

class MultiPosterior(Posterior):
    r"""The functional data unit for Multivae. A `MultiPosterior` instance is instantiated with a model and
    a gene_dataset, and as well as additional arguments that for Pytorch's `DataLoader`. A subset of indices
    can be specified, for purposes such as splitting the data into train/test/validation. Each trainer instance of the `Trainer` class can therefore have multiple
    `MultiPosterior` instances to train a model. A `MultiPosterior` instance also comes with many methods or
    utilities for its corresponding data.

    :param model: A model instance from class ``Multivae``
    :param gene_dataset: A gene_dataset instance like ``ATACDataset()`` with attribute ``ATAC_expression``
    :param shuffle: Specifies if a `RandomSampler` or a `SequentialSampler` should be used
    :param indices: Specifies how the data should be split with regards to train/test or labelled/unlabelled
    :param use_cuda: Default: ``True``
    :param data_loader_kwarg: Keyword arguments to passed into the `DataLoader`

    Examples:

    Let us instantiate a `trainer`, with a gene_dataset and a model

        >>> gene_dataset = CbmcDataset()
        >>> totalvi = TOTALVI(gene_dataset.nb_genes, len(gene_dataset.protein_names),
        ... n_batch=gene_dataset.n_batches * False, n_labels=gene_dataset.n_labels, use_cuda=True)
        >>> trainer = TotalTrainer(vae, gene_dataset)
        >>> trainer.train(n_epochs=400)
    """

    def __init__(
        self,
        model: multi_vae_attention,
        gene_dataset: GeneExpressionDataset,
        shuffle: bool = False,
        indices: Optional[np.ndarray] = None,
        use_cuda: bool = True,
        data_loader_kwargs=dict(),
    ):

        super().__init__(
            model,
            gene_dataset,
            shuffle=shuffle,
            indices=indices,
            use_cuda=use_cuda,
            data_loader_kwargs=data_loader_kwargs,
        )
        # Add atac tensor as another tensor to be loaded
        self.data_loader_kwargs.update(
            {
                "collate_fn": gene_dataset.collate_fn_builder(
                    {"atac_expression": np.float32}# debug cell index
                )
            }
        )

        self.data_loader = DataLoader(gene_dataset, **self.data_loader_kwargs)

    def corrupted(self):
        return self.update(
            {
                "collate_fn": self.gene_dataset.collate_fn_builder(
                    {"atac_expression": np.float32}, corrupted=True
                )
            }
        )

    def uncorrupted(self):
        return self.update(
            {
                "collate_fn": self.gene_dataset.collate_fn_builder(
                    {"atac_expression": np.float32}
                )
            }
        )

    @torch.no_grad()
    def elbo(self):
        elbo = self.compute_elbo(self.model)
        logger.debug("ELBO : %.4f" % elbo)
        return elbo
    elbo.mode = "min"

    @torch.no_grad()
    def reconstruction_error(self):
        reconstruction_error = self.compute_reconstruction_error(self.model, self)
        logger.debug("Reconstruction Error : %.4f" % reconstruction_error)
        return reconstruction_error

    reconstruction_error.mode = "min"

    @torch.no_grad()
    def marginal_ll(self, n_mc_samples=1000):

        ll = self.compute_marginal_log_likelihood(self.model, self, n_mc_samples)
        logger.debug("True LL : %.4f" % ll)
        return ll

    def compute_elbo(self, vae:multi_vae_attention, **kwargs):
        """ Computes the ELBO.

        The ELBO is the reconstruction error + the KL divergences
        between the variational distributions and the priors.
        It differs from the marginal log likelihood.
        Specifically, it is a lower bound on the marginal log likelihood
        plus a term that is constant with respect to the variational distribution.
        It still gives good insights on the modeling of the data, and is fast to compute.
        """
        # Iterate once over the posterior and compute the elbo
        elbo = 0
        for i_batch, tensors in enumerate(self):
            (
                sample_batch_X,
                local_l_mean,
                local_l_var,
                batch_index,
                label,
                sample_batch_Y,
            ) = tensors

            reconst_loss, kl_divergence_local, kl_divergence_global = vae(
                sample_batch_X, sample_batch_Y, local_l_mean, local_l_var, batch_index, label
            )
            elbo += torch.sum(reconst_loss + kl_divergence_local).item()
        n_samples = len(self.indices)
        elbo += kl_divergence_global
        return elbo / n_samples

    def compute_reconstruction_error(self, vae:multi_vae_attention, **kwargs):
        r""" Computes log p(x/z), which is the reconstruction error .
                    Differs from the marginal log likelihood, but still gives good
                    insights on the modeling of the data, and is fast to compute

                    This is really a helper function to self.ll, self.ll_protein, etc.
                """
        # Iterate once over the posterior and computes the total log_likelihood
        log_lkl = 0
        for i_batch, tensors in enumerate(self):
            sample_batch, local_l_mean, local_l_var, batch_index, labels = tensors[
                                                                           :5
                                                                           ]  # general fish case

            # Distribution parameters
            outputs = vae.inference(sample_batch, batch_index, labels, **kwargs)
            p_rna_r = outputs["p_rna_r"]
            p_rna_rate = outputs["p_rna_rate"]
            p_rna_dropout = outputs["p_rna_dropout"]
            p_atac_mean = outputs["p_atac_mean"]
            p_atac_r = outputs["p_atac_r"]
            p_atac_dropout = outputs["p_atac_dropout"]

            # Reconstruction loss
            reconst_rna_loss = vae.get_reconstruction_loss(
                sample_batch,
                p_rna_rate,
                p_rna_r,
                p_rna_dropout,
#                bernoulli_params=bernoulli_params,
                **kwargs
            )
            reconst_atac_loss = vae.get_reconstruction_atac_loss(
                sample_batch,
                p_atac_mean,
                p_atac_r,
                p_atac_dropout,
                **kwargs
            )

            log_lkl += torch.sum(reconst_rna_loss).item()
            log_lkl += torch.sum(reconst_atac_loss).item()
        n_samples = len(self.indices)
        return log_lkl / n_samples

    def compute_marginal_log_likelihood(self, vae:multi_vae_attention , n_mc_samples):
        """ Computes a biased estimator for log p(x), which is the marginal log likelihood.

            Despite its bias, the estimator still converges to the real value
            of log p(x) when n_samples_mc (for Monte Carlo) goes to infinity
            (a fairly high value like 100 should be enough)
            Due to the Monte Carlo sampling, this method is not as computationally efficient
            as computing only the reconstruction loss
            """
        # Uses MC sampling to compute a tighter lower bound on log p(x)

        log_lkl = 0
        for i_batch, tensors in enumerate(self):
            sample_batch, local_l_mean, local_l_var, batch_index, labels = tensors
            to_sum = torch.zeros(sample_batch.size()[0], n_mc_samples)

            for i in range(n_mc_samples):
                # Distribution parameters and sampled variables
                outputs = vae.inference(sample_batch, batch_index, labels)
                p_rna_r = outputs["p_rna_r"]
                p_rna_rate = outputs["p_rna_rate"]
                p_rna_dropout = outputs["p_rna_dropout"]
                qz_m = outputs["qz_m"]
                qz_v = outputs["qz_v"]
                z = outputs["z"]
                p_atac_mean = outputs["p_atac_mean"]
                p_atac_r = outputs["p_atac_r"]
                p_atac_dropout = outputs["p_atac_dropout"]
                mu_c = outputs["mu_c"]
                var_c = outputs["var_c"]
                gamma = outputs["gamma"]
                mu_c_max = outputs["mu_c_max"],
                var_c_max = outputs["var_c_max"],
                z_c_max = outputs["z_c_max"],

                # Reconstruction Loss
                reconst_rna_loss = vae.get_reconstruction_loss(
                    sample_batch,
                    p_rna_r,
                    p_rna_rate,
                    p_rna_dropout,
                )
                reconst_atac_loss = vae.get_reconstruction_atac_loss(
                    sample_batch,
                    p_atac_r,
                    p_atac_mean,
                    p_atac_dropout,
                )

                # Log-probabilities
                #p_l = Normal(local_l_mean, local_l_var.sqrt()).log_prob(library).sum(dim=-1)
                p_z = 0.0
                for prob, mu, var in mu_c, var_c, gamma:
                    p_z += prob*Normal(mu, var.sqrt()).log_prob(z).sum(dim=-1)

                p_x_zl = -reconst_rna_loss - reconst_atac_loss
                q_z_x = Normal(qz_m, qz_v.sqrt()).log_prob(z).sum(dim=-1)
                #q_z_max = Normal(mu_c_max, var_c_max.sqrt()).log_prob(z_c_max).sum(dim=-1)

                to_sum[:, i] = p_z + p_x_zl - q_z_x  #- q_z_max

            batch_log_lkl = logsumexp(to_sum, dim=-1) - np.log(n_mc_samples)
            log_lkl += torch.sum(batch_log_lkl).item()

        n_samples = len(self.indices)
        # The minus sign is there because we actually look at the negative log likelihood
        return -log_lkl / n_samples

    @torch.no_grad()
    def get_latent(self, sample=False):
        """
        Output posterior z mean or sample, batch index, and label
        :param sample: z mean or z sample
        :return: three np.ndarrays, latent, batch_indices, labels
        """
        latent = []
        latent_rna = [];
        latent_atac = [];
        batch_indices = []
        labels = []
        cluster_gamma = []
        cluster_index = []
        for tensors in self:
            sample_batch_rna, local_l_mean, local_l_var, batch_index, label, sample_batch_atac = tensors
            give_mean = not sample
            latent_temp = self.model.sample_from_posterior_z(
                [sample_batch_rna, sample_batch_atac], y=label, give_mean=give_mean
            )
            latent += [
                latent_temp[0][0].cpu()
            ]
            latent_rna += [
                latent_temp[1][0].cpu()
            ]
            latent_atac += [
                latent_temp[2].cpu()
            ]
            gamma, mu_c, var_c, pi = self.model.get_gamma(latent_temp[0][0])
            cluster_gamma += [gamma.cpu()]
            cluster_index += [torch.argmax(gamma.cpu(),dim=1)]
            batch_indices += [batch_index.cpu()]
            labels += [label.cpu()]
        return (
            np.array(torch.cat(latent)),
            np.array(torch.cat(latent_rna)),
            np.array(torch.cat(latent_atac)),
            np.array(torch.cat(cluster_gamma)),
            np.array(torch.cat(cluster_index)),
            np.array(torch.cat(batch_indices)),
            np.array(torch.cat(labels)).ravel(),
        )

    @torch.no_grad()
    def generate(
        self,
        n_samples: int = 100,
        genes: Optional[np.ndarray] = None,
        batch_size: int = 256,
        #batch_size: int = 128,
    ) :
        """
        Create observation samples from the Posterior Predictive distribution

        :param n_samples: Number of required samples for each cell
        :param genes: Indices of genes of interest
        :param batch_size: Desired Batch size to generate data

        :return: Tuple (x_new, x_old)
            Where x_old has shape (n_cells, n_genes)
            Where x_new has shape (n_cells, n_genes, n_samples)
        """
        assert self.model.reconstruction_loss in ["zinb", "zip"]
        zero_inflated = "zinb"

        rna_old = []
        rna_new = []
        atac_old = []
        atac_new = []
        for tensors in self.update({"batch_size": batch_size}):
            sample_batch, _, _, batch_index, labels = tensors
            outputs = self.model.inference(
                sample_batch, batch_index=batch_index, y=labels, n_samples=n_samples
            )
            p_rna_r = outputs["p_rna_r"]
            p_rna_rate = outputs["p_rna_rate"]
            p_rna_dropout = outputs["p_rna_dropout"]
            p_atac_mean = outputs["p_atac_mean"]
            p_atac_dropout = outputs["p_atac_dropout"]

            # Generating rna-seq data
            p = p_rna_rate / (p_rna_rate + p_rna_r)
            r = p_rna_r
            # Important remark: Gamma is parametrized by the rate = 1/scale!
            l_train_rna = distributions.Gamma(concentration=r, rate=(1 - p) / p).sample()
            # Clamping as distributions objects can have buggy behaviors when
            # their parameters are too high
            l_train_rna = torch.clamp(l_train_rna, max=1e8)
            gene_expressions = distributions.Poisson(
                l_train_rna
            ).sample()  # Shape : (n_samples, n_cells_batch, n_genes)

            #Generating atac-seq data
            l_train_atac = torch.clamp(p_atac_mean, max=1e2)
            atac_expressions = distributions.Poisson(
                l_train_atac
            ).sample()

            # zero-inflate
            if zero_inflated:
                p_zero_rna = (1.0 + torch.exp(-p_rna_dropout)).pow(-1)
                random_prob_rna = torch.rand_like(p_zero_rna)
                gene_expressions[random_prob_rna <= p_zero_rna] = 0

                p_zero_atac = (1.0 + torch.exp(-p_atac_dropout)).pow(-1)
                random_prob_atac = torch.rand_like(p_zero_atac)
                atac_expressions[random_prob_atac <= p_zero_atac] = 0

            gene_expressions = gene_expressions.permute(
                [1, 2, 0]
            )  # Shape : (n_cells_batch, n_genes, n_samples)
            atac_expressions = atac_expressions.permute(
                [1, 2, 0]
            )

            rna_old.append(sample_batch[0].cpu())
            rna_new.append(gene_expressions.cpu())
            atac_old.append(sample_batch[1].cpu())
            atac_new.append(atac_expressions.cpu())

        rna_old = torch.cat(rna_old)  # Shape (n_cells, n_genes)
        rna_new = torch.cat(rna_new)  # Shape (n_cells, n_genes, n_samples)
        if genes is not None:
            gene_ids = self.gene_dataset.genes_to_index(genes)
            rna_new = rna_new[:, gene_ids, :]
            rna_old = rna_old[:, gene_ids]
        return rna_new.numpy(), rna_old.numpy(), atac_new.numpy(), rna_old.numpy()

    @torch.no_grad()
    def imputation(self, n_samples: int = 1):
        """ Gene imputation
        """
        imputed_rna_list = []
        imputed_atac_list = []
        label_list = []  # for the annotated data
        atac_list = []
        for tensors in self:
            x_rna, local_l_mean, local_l_var, batch_index, label, x_atac = tensors
            p_rna_rate, p_atac_rate = self.model.get_sample_rate(
                x=[x_rna,x_atac], batch_index=batch_index, y=label,  n_samples=n_samples, local_l_mean = local_l_mean, local_l_var = local_l_var
            )
            imputed_rna_list += [np.array(p_rna_rate.cpu())]
            imputed_atac_list += [np.array(p_atac_rate.cpu())]
            label_list += [np.array(label.cpu())] # only for annotated data
            atac_list += [np.array(x_atac.cpu())] # for the bins without call peak
        imputed_rna_list = np.concatenate(imputed_rna_list)
        imputed_atac_list = np.concatenate(imputed_atac_list)
        label_list = np.concatenate(label_list) # only for annotated data
        atac_list = np.concatenate(atac_list)# for the bins without call peak
        return imputed_rna_list.squeeze(), imputed_atac_list.squeeze(), label_list.squeeze(), atac_list

    @torch.no_grad()
    def get_sample_scale(self):
        p_rna_scales = []
        p_atac_scales = []
        for tensors in self:
            x_rna, _, _, batch_index, labels, x_atac = tensors
            p_rna_scales += [
                np.array(
                    (
                        self.model.get_sample_scale(
                            x=[x_rna,x_atac], batch_index=batch_index, y=labels, n_samples=1
                        )[0]
                    )
                )
            ]
            p_atac_scales += [
                np.array(
                    (
                        self.model.get_sample_scale(
                            x=[x_rna,x_atac], batch_index=batch_index, y=labels, n_samples=1
                        )[1]
                    )
                )
            ]
        return np.concatenate(p_rna_scales), np.concatenate(p_atac_scales)

    def cluster_acc(Y_pred, Y):
        assert Y_pred.size == Y.size
        D = max(Y_pred.max(), Y.max()) + 1
        w = np.zeros((D, D), dtype=np.int64)
        for i in range(Y_pred.size):
            w[Y_pred[i], Y[i]] += 1
        ind = linear_assignment(w.max() - w)
        return sum([w[i, j] for i, j in ind]) * 1.0 / Y_pred.size, ind

    def get_clustering(self):
        latent, latent_rna, latent_atac, cluster_gamma, batch_indices, labels = self.get_latent()
        cluster_accuarcy, ind = self.cluster_acc(np.argmax(cluster_gamma,axis=1),labels)
        print('cell dataset multi-vae - clustering accuracy: %.2f%%' % (cluster_accuarcy * 100))
        return cluster_accuarcy, ind

class MultiTrainer(UnsupervisedTrainer):
    r"""The VariationalInference class for the unsupervised training of an autoencoder.

    Args:
        :model: A model instance from class ``TOTALVI``
        :gene_dataset: A gene_dataset instance like ``CbmcDataset()`` with attribute ``protein_expression``
        :train_size: The train size, either a float between 0 and 1 or and integer for the number of training samples
         to use Default: ``0.93``.
        :test_size: The test size, either a float between 0 and 1 or and integer for the number of training samples
         to use Default: ``0.02``. Note that if train and test do not add to 1 the remainder is placed in a validation set
        :\*\*kwargs: Other keywords arguments from the general Trainer class.
    """
    default_metrics_to_monitor = ["elbo"]

    def __init__(
        self,
        model,
        dataset,
        train_size=0.90,
        test_size=0.05,
        pro_recons_weight=1.0,
        n_epochs_back_kl_warmup=50, #200, init
        n_epochs_kl_warmup=200,
        **kwargs
    ):
        self.n_genes = dataset.nb_genes
        self.n_proteins = model.n_input_atac

        self.pro_recons_weight = pro_recons_weight
        self.n_epochs_back_kl_warmup = n_epochs_back_kl_warmup
        super().__init__(
            model, dataset, n_epochs_kl_warmup=n_epochs_kl_warmup, **kwargs
        )
        if type(self) is MultiTrainer:
            (
                self.train_set,
                self.test_set,
                self.validation_set,
            ) = self.train_test_validation(
                model, dataset, train_size, test_size, type_class=MultiPosterior
            )
            self.train_set.to_monitor = []
            self.test_set.to_monitor = ["elbo"]
            self.validation_set.to_monitor = ["elbo"]

    def loss(self, tensors):
        (
            sample_batch_X,
            local_l_mean,
            local_l_var,
            batch_index,
            label,
            sample_batch_Y,
        ) = tensors

        #reconst_loss, kl_divergence_local, kl_divergence_global = self.model(
        #    sample_batch_X, sample_batch_Y, local_l_mean, local_l_var, batch_index, label
        #)
        reconst_loss, kl_divergence_local, kl_divergence_global = self.model(
            sample_batch_X, sample_batch_Y, local_l_mean, local_l_var, batch_index, batch_index
        )
        loss = (
            self.n_samples
            * torch.mean(reconst_loss + self.back_warmup_weight * kl_divergence_local)
            + kl_divergence_global
        )
        print(
            "reconst_loss = %f,kl_divergence_local = %f,kl_weight = %f,loss = %f" %
              (torch.mean(reconst_loss), torch.mean(kl_divergence_local), self.back_warmup_weight, loss)
              )
        # self.KL_divergence = kl_divergence_global
        if self.normalize_loss:
            loss = loss / self.n_samples
        return loss

    def on_epoch_begin(self):
        super().on_epoch_begin()
        if self.n_epochs_back_kl_warmup is not None:
            #self.back_warmup_weight = min(1, self.epoch + self.n_epochs_back_kl_warmup / self.n_epochs_back_kl_warmup)
            self.back_warmup_weight = min(1, self.epoch + self.n_epochs_back_kl_warmup / self.n_epochs_back_kl_warmup)
        else:
            self.back_warmup_weight = 1.0


#!/bin/python3

import sys
import re
import statistics as stat
import numpy as np

count = []
step = -1

with open(sys.argv[1],"r") as f:
    for data in f:
        if "TimeStep" in data:
            nextstep = int(re.findall("(?<=\().+?(?=\))", data)[0].split(",")[0][8:])
            if step == nextstep:
                count = count[:-1]
            else:
                step = nextstep
            count.append([])
        elif "optimal relaxation factor = " in data:
            count[-1].append(float(data.split("=")[1][1:-2]))
print(len(count))
# print(count)
numrelax = [np.count_nonzero(np.array(count[i])<1.0) for i in range(len(count))]
print(np.count_nonzero(numrelax))
# print("$"+str(stat.mean(count))+" \pm "+str(stat.stdev(count))+"$(max "+str(max(count))+")")
# print(stat.median(count))
# print(stat.mode(count))


# -*- coding: utf-8 -*-
# author: Jeffz615

import tkinter as tk
import tkinter.messagebox
import win32api
import win32con
import json

def loadreg():
    global regeditKey, regeditJson, regFrame, regWidth, regHeight, regFullscreen
    regeditKey = win32api.RegOpenKey(
        win32con.HKEY_CURRENT_USER, r'Software\miHoYo\崩坏3', 0, win32con.KEY_ALL_ACCESS)
    regeditJson = json.loads(win32api.RegQueryValueEx(
        regeditKey, 'GENERAL_DATA_V2_ScreenSettingData_h1916288658')[0][:-1])
    regFrame = json.loads(win32api.RegQueryValueEx(
        regeditKey, 'GENERAL_DATA_V2_PersonalGraphicsSetting_h906361411')[0][:-1])
    regWidth = win32api.RegQueryValueEx(
        regeditKey, 'Screenmanager Resolution Width_h182942802')[0]
    regHeight = win32api.RegQueryValueEx(
        regeditKey, 'Screenmanager Resolution Height_h2627697771')[0]
    regFullscreen = win32api.RegQueryValueEx(
        regeditKey, 'Screenmanager Is Fullscreen mode_h3981298716')[0]
    if regWidth != regeditJson['width']:
        win32api.RegSetValueEx(
            regeditKey, 'Screenmanager Resolution Width_h182942802', 0, win32con.REG_DWORD, regWidth)
        regWidth = regeditJson['width']
    if regHeight != regeditJson['height']:
        win32api.RegSetValueEx(
            regeditKey, 'Screenmanager Resolution Height_h2627697771', 0, win32con.REG_DWORD, regHeight)
        regHeight = regeditJson['height']
    if regFullscreen != int(regeditJson['isfullScreen']):
        win32api.RegSetValueEx(
            regeditKey, 'Screenmanager Is Fullscreen mode_h3981298716', 0, win32con.REG_DWORD, int(regFullscreen))
        regFullscreen = regeditJson['isfullScreen']

try:
    endByte = b'\x00'
    screenWidth = win32api.GetSystemMetrics(0)
    screenHeight = win32api.GetSystemMetrics(1)
    loadreg()
except:
    exit(1)

def on_closing():
    win32api.RegCloseKey(regeditKey)
    window.destroy()

window = tk.Tk()
window.title("崩坏3 PC端 分辨率&帧率 修改工具")
window.geometry("400x140")
window.protocol("WM_DELETE_WINDOW", on_closing)
window.resizable(0, 0)

def check(context):
    if context.isdigit() or context == "":
        return True
    else:
        return False

widthLabel = tk.Label(window, text='宽 Width')
widthLabel.place(x=0.5, y=0.5)

width = tk.StringVar()
widthEntry = tk.Entry(window, show=None, textvariable=width)
widthEntry.place(x=75, y=0.5)
width.set(regeditJson['width'])

heightLabel = tk.Label(window, text='高 Height')
heightLabel.place(x=0.5, y=25)

height = tk.StringVar()
heightEntry = tk.Entry(window, show=None, textvariable=height)
heightEntry.place(x=75, y=25)
height.set(regeditJson['height'])

TargetFrameRateForInLevelLabel = tk.Label(
    window, text='关卡内帧率 TargetFrameRateForInLevel')
TargetFrameRateForInLevelLabel.place(x=0.5, y=49.5)

TargetFrameRateForInLevel = tk.StringVar()
TargetFrameRateForInLevelEntry = tk.Entry(
    window, show=None, textvariable=TargetFrameRateForInLevel)
TargetFrameRateForInLevelEntry.place(x=240, y=49.5)
TargetFrameRateForInLevel.set(regFrame['TargetFrameRateForInLevel'])

TargetFrameRateForOthersLabel = tk.Label(
    window, text='关卡外帧率 TargetFrameRateForOthers')
TargetFrameRateForOthersLabel.place(x=0.5, y=74)

TargetFrameRateForOthers = tk.StringVar()
TargetFrameRateForOthersEntry = tk.Entry(
    window, show=None, textvariable=TargetFrameRateForOthers)
TargetFrameRateForOthersEntry.place(x=240, y=74)
TargetFrameRateForOthers.set(regFrame['TargetFrameRateForOthers'])

flag = tk.IntVar()
fullscreenCheckbutton = tk.Checkbutton(
    window, text='全屏显示 FullScreen', variable=flag, onvalue=1, offvalue=0)
fullscreenCheckbutton.place(x=250, y=0.5)
flag.set(regeditJson['isfullScreen'])

def main():
    global regeditJson, regFrame, regWidth, regHeight, regFullscreen
    widthNum = width.get()
    heightNum = height.get()
    isfullScreen = bool(flag.get())
    frame1 = TargetFrameRateForInLevel.get()
    frame2 = TargetFrameRateForOthers.get()
    if check(widthNum) and check(heightNum) and check(frame1) and check(frame2):
        widthNum = int(widthNum)
        heightNum = int(heightNum)
        frame1 = int(frame1)
        frame2 = int(frame2)
        if not (int(widthNum) <= screenWidth and int(heightNum) <= screenHeight):
            tkinter.messagebox.showerror(
                title='Error', message='Width/Height 超出屏幕尺寸.')
            return
    else:
        tkinter.messagebox.showerror(
            title='Error', message='Width/Height Error.')
        return
    if widthNum != regeditJson['width'] or heightNum != regeditJson['height'] or isfullScreen != regeditJson['isfullScreen'] or frame1 != regFrame['TargetFrameRateForInLevel'] or frame2 != regFrame['TargetFrameRateForOthers']:
        value = bytes(json.dumps({'width': widthNum, 'height': heightNum,
                                  'isfullScreen': isfullScreen}), encoding='utf-8') + endByte
        regFrame['TargetFrameRateForInLevel'] = frame1
        regFrame['TargetFrameRateForOthers'] = frame2
        frameJson = bytes(json.dumps(regFrame), encoding='utf-8') + endByte
        try:
            win32api.RegSetValueEx(
                regeditKey, 'GENERAL_DATA_V2_ScreenSettingData_h1916288658', 0, win32con.REG_BINARY, value)
            win32api.RegSetValueEx(
                regeditKey, 'Screenmanager Resolution Width_h182942802', 0, win32con.REG_DWORD, widthNum)
            win32api.RegSetValueEx(
                regeditKey, 'Screenmanager Resolution Height_h2627697771', 0, win32con.REG_DWORD, heightNum)
            win32api.RegSetValueEx(
                regeditKey, 'Screenmanager Is Fullscreen mode_h3981298716', 0, win32con.REG_DWORD, int(isfullScreen))
            win32api.RegSetValueEx(
                regeditKey, 'GENERAL_DATA_V2_PersonalGraphicsSetting_h906361411', 0, win32con.REG_BINARY, frameJson)
            loadreg()
            tkinter.messagebox.showinfo(title='Info', message='Success!')
        except:
            tkinter.messagebox.showerror(
                title='Error', message='Regedit I/O Error.')
            exit(1)

submit = tk.Button(window, text='完成 Submit', command=main)
submit.place(x=250, y=100)

window.mainloop()

bh3/崩坏3 PC端 分辨率&帧率修改工具.py

崩坏3 PC端 分辨率&帧率修改工具.py


from django.shortcuts import render
from django.template import RequestContext
from gallery.models import Album, Photo
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView
from infinite_pagination import InfinitePaginator
from django.http import HttpResponse
import json
from pages.models import Settings

def home(request):
    context = RequestContext(request)
    context['photos'] = Album.objects.all()
    return render(request, 'index.html', context)

def photo(request):
    context = RequestContext(request)
    return render(request, 'detail.html', context)

class AlbumDetailView(DetailView):
    model = Album
    paginate_by = 1
    def get_context_data(self, **kwargs):

        autoload = Settings.objects.filter(autoload_photos=True)
        context = super(AlbumDetailView, self).get_context_data(**kwargs)
        print(context)
        ss = Album()
        if autoload:
            photos = Photo.objects.filter(album=self.object.id)[:3]
        else:
            photos = Photo.objects.filter(album=self.object.id)
        context['photos'] = photos
        return context

def json_album_detail(request):
    album = Album
    data = request.GET.get('album_id')
    count = request.GET.get('count')
    load_count = request.GET.get('load_count')
    if request.method == "GET":
        photos_all = Photo.objects.filter(album=data).count()
        photos = Photo.objects.filter(album=data)[load_count:count]
        if photos:
            if int(count) >= photos_all:
                json_data = {'photos': 'none'}
            else:
                i=0
                json_data = {}
                for item in photos:
                    i=i+1

                    json_data[i] = {}
                    json_data[i]['url'] = item.image.url
        else:
            json_data = {'photos': 'none'}

        return HttpResponse(json.dumps(json_data), content_type = "application/json")

class AlbumListView(ListView):

    model = Album
    paginate_by = 3
    paginator_class = InfinitePaginator

    def get_context_data(self, **kwargs):

        context = super(AlbumListView, self).get_context_data(**kwargs)

        return context


from collections import Counter
def solution(nums,k):
    d = set()
    for i in range(len(nums)):
        r = k - i
        for j in range(i+1,len(nums)):
            if(r - nums[j]) in d:
                return True
            d.add(r - nums[j])
    return False
print(solution([20, 303, 3, 4, 25],49))


from flask import Flask, render_template, request
import jsonify
import requests
import joblib
from tensorflow.keras.models import load_model
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
app = Flask(__name__)
# load model and transformer
model = load_model('best_model.h5')
sc = joblib.load('scaler.pkl')

@app.route('/',methods=['GET'])
def Home():
    return render_template('index.html')

@app.route("/predict", methods=['POST'])
def predict():
    if request.method == 'POST':
        gender = request.form['gender']
        if (gender=='male'):
            gender=0
        else:
            gender=1
        senior = request.form['senior']
        if (senior == 'yes'):
            senior = 1
        else:
            senior = 0
        partner = request.form['partner']
        if (partner == 'yes'):
            partner = 1
        else:
            partner = 0
        dependents = request.form['dependents']
        if (dependents == 'yes'):
            dependents = 1
        else:
            dependents = 0
        tenure=int(request.form['tenure'])
        phoneserv = request.form['phoneserv']
        if (phoneserv == 'yes'):
            phoneserv = 1
        else:
            phoneserv = 0
        multilines = request.form['multilines']
        if (multilines == 'yes'):
            multilines = 1
        else:
            multilines = 0
        onlinesec = request.form['onlinesec']
        if (onlinesec == 'yes'):
            onlinesec = 1
        else:
            onlinesec = 0
        onlinebac = request.form['onlinebac']
        if (onlinebac == 'yes'):
            onlinebac = 1
        else:
            onlinebac = 0
        devicepro = request.form['devicepro']
        if (devicepro == 'yes'):
            devicepro = 1
        else:
            devicepro = 0
        techsup = request.form['techsup']
        if (techsup == 'yes'):
            techsup = 1
        else:
            techsup = 0
        strtv = request.form['strtv']
        if (strtv == 'yes'):
            strtv = 1
        else:
            strtv = 0
        strmvs = request.form['strmvs']
        if (strmvs == 'yes'):
            strmvs = 1
        else:
            strmvs = 0
        paperless = request.form['paperless']
        if (paperless == 'yes'):
            paperless = 1
        else:
            paperless = 0
        mb=float(request.form['mb'])
        tb=float(request.form['tb'])
        intserv_dsl=0
        intserv_fiber=0
        intserv_no=0
        intserv=request.form['intserv']
        if (intserv == 'dsl'):
            intserv_dsl = 1
        elif (intserv == 'fiber'):
            intserv_fiber=1
        else:
            intserv_no=1
        contract_mtom=0
        contract_oy=0
        contract_ty=0
        contract = request.form['contract']
        if (contract == 'mtom'):
            contract_mtom = 1
        elif (contract == 'oy'):
            contract_oy=1
        else:
            contract_ty=1
        pm_bt=0
        pm_cc=0
        pm_ec=0
        pm_mc=0
        pm=request.form['pm']
        if (pm == 'bt'):
            pm_bt=1
        elif (pm == 'cc'):
            pm_cc=1
        elif (pm == 'ec'):
            pm_ec=1
        else:
            pm_mc=1

        prediction=model.predict(sc.transform([[gender,senior,partner,dependents,tenure,phoneserv,multilines,onlinesec,
                                                        onlinebac,devicepro,techsup,strtv,strmvs,paperless,mb,tb,
                                                        intserv_dsl,intserv_fiber,intserv_no,
                                                        contract_mtom,contract_oy,contract_ty,
                                                        pm_bt,pm_cc,pm_ec,pm_mc]])) > 0.5
        output=prediction.tolist()

        if output==[[True]]:
            return render_template('index.html',prediction_text="Customer is unlikely to remain loyal")
        else:
            return render_template('index.html',prediction_text="Customer is likely to remain loyal")
    else:
        return render_template('index.html')

if __name__=="__main__":
    app.run(debug=True)


#!/usr/bin/env python3
""" precision calculation """
import numpy as np

def precision(confusion):
    """ that calculates the precision for each class in a confusion matrix:
        confusion: np.ndarray confusion matrix (classes, classes)
        Returns: np.ndarray(classes,) of sensitivities
    """
    classes = confusion.shape[0]
    sens = np.zeros(classes)
    for i in range(classes):
        sens[i] = confusion[i][i] / np.sum(confusion.T[i])
    return sens


# This class represents an instance of the data.
class DataInstance:
  def __init__(self, line, has_label):
    fields = line.split("|")
    offset = 0

    if has_label:
      # whether clicked: 0 or 1
      self.clicked = int(fields[0])
      offset = 1
    else:
      self.clicked = -1

    # depth of the session
    self.depth = int(fields[offset])
    # position of the ad
    self.position = int(fields[offset + 1])
    self.userid = int(fields[offset + 2])
    # user gender indicator (-1 for male, 1 for female)
    self.gender = int(fields[offset+3])
    if self.gender != 0:
      self.gender = int((self.gender - 1.5) * 2)
    # user age indicator:
    #   '1' for (0, 12],
    #   '2' for (12, 18],
    #   '3' for (18, 24],
    #   '4' for (24, 30],
    #   '5' for (30, 40], and
    #   '6' for greater than 40.
    self.age = int(fields[offset + 4])
    # list of token ids
    self.tokens = [int(xx) for xx in fields[offset + 5].split(",")]

  def __str__(self):
    string = ""
    if self.clicked >= 0:
      string += str(self.clicked) + "|"
    string += str(self.depth) + "|"
    string += str(self.position) + "|"
    string += str(self.userid) + "|"
    string += str(self.gender) + "|"
    string += str(self.age) + "|"
    string += ",".join([str(tok) for tok in self.tokens])
    return string


from kivy.graphics import Color
from kivy.lang import Builder
from kivy.properties import ObjectProperty, NumericProperty, Clock, StringProperty, ListProperty
from kivy.uix.screenmanager import Screen
from kivy.logger import Logger

from util.PhotoStore import PhotoStore

class ShowImageScreen(Screen):
    obj_lbl_print_copies = ObjectProperty()

    str_image1 = StringProperty()

    r = NumericProperty(0.0)
    g = NumericProperty(0.0)
    b = NumericProperty(0.0)

    int_screen_width = NumericProperty()
    obj_print_layout = ObjectProperty()
    int_pos_x = NumericProperty()

    event = None

    def __init__(self, controller):
        super(ShowImageScreen, self).__init__()
        self.controller = controller

    def switch_mode(self):
        self.r = float(self.controller.get_conf("app.video_background_color_r")) / 255.0
        self.g = float(self.controller.get_conf("app.video_background_color_g")) / 255.0
        self.b = float(self.controller.get_conf("app.video_background_color_b")) / 255.0

    def set_image(self, image):
        Logger.debug("ShowImageScreen.set_image() with {0}".format(image))
        self.str_image1 = image

        if self.controller.get_conf("app.printing_enabled"):
            # show print dialog after x seconds if printing enabled
            self.event = Clock.schedule_once(self._show_print_dialog, self.controller.get_conf("app.show_image_duration"))

    def on_touch_up(self, touch):
        Logger.debug("Touch UP: x: {0}, y: {1}".format(touch.px, touch.py))

        # show print dialog when screen pressed
        if self.controller.get_conf("app.printing_enabled"):
            self.event.cancel()
            self._show_print_dialog()

    def print_image(self):
        """ called from kv file """
        nb_copies = int(self.obj_lbl_print_copies.text)
        self.controller.print_image(nb_copies)

        self._hide_print_dialog()

    def abort_print_dialog(self):
        """ called from kv file """
        self.controller.show_loop_screen()

        # cancel Clock if present
        if self.event:
            self.event.cancel()

        self._hide_print_dialog()

    def _show_print_dialog(self, *args):
        Logger.debug('ShowImageScreen.show_print_dialog()')

        self.int_pos_x = self.int_screen_width / 2 - self.obj_print_layout.width / 2

    def _hide_print_dialog(self, *args):
        Logger.debug('ShowImageScreen.hide_print_dialog()')

        self.int_pos_x = 5000
        self.obj_lbl_print_copies.text = '1'

#Builder.load_file("screens/ShowImagePrintDialog.kv")
Builder.load_file("screens/ShowImageScreen.kv")


# 프로그래머스 - [1차] 뉴스 클러스터링(17667)
# https://school.programmers.co.kr/learn/courses/30/lessons/17677

def solution(str1, str2):
    str1 = [str1[i:i+2].lower() for i in range(len(str1) - 1) if str1[i:i+2].isalpha()]
    str2 = [str2[i:i+2].lower() for i in range(len(str2) - 1) if str2[i:i+2].isalpha()]

    intxn = sum([min(str1.count(c), str2.count(c)) for c in set(str1) & set(str2)])
    un = sum([max(str1.count(c), str2.count(c)) for c in set(str1) | set(str2)])

    if un:
        return int(intxn / un * 65536)
    return 65536

programmers/17677-[1차]-뉴스-클러스터링/17677_[1차]_뉴스_클러스터링.py


from typing import List, Union

from aiogram import types
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters import Text
from aiogram.types import CallbackQuery

from handlers.users.main_menu import get_and_save_category, get_category
from handlers.users.start import reset_state_saving_user_id
from keyboards.default import back_menu, main_menu
from keyboards.inline.callback_data import confirmation_callback
from keyboards.inline.categories import get_categories_buttons
from keyboards.inline.categories_actions import categories_actions, confirmation_buttons
from loader import dp, db
from states.categories import DeleteCategory, AddCategory

@dp.message_handler(Text(equals="Категории"))
async def show_all_categories(message: Union[types.Message, CallbackQuery], state: FSMContext, show_info=True):
    message_text = "Ваши категории:"
    if isinstance(message, types.Message):
        user_tg_id = message.from_user.id
        await state.update_data(user_tg_id=user_tg_id)
    else:
        user_tg_id = (await state.get_data()).get("user_tg_id")

    user_categories_lst: List[str] = await db.get_user_categories(user_tg_id)
    for index, category in enumerate(user_categories_lst):
        notes_in_category: List[str] = await db.get_user_notes_in_category(user_tg_id, category)
        count_of_notes_in_category = len(notes_in_category)
        message_text += f"\n{index + 1}. {category} (кол-во заметок: {count_of_notes_in_category})"

    if isinstance(message, CallbackQuery):
        message = message.message
    if show_info:
        await message.answer("Чтобы вернуться в главное меню, нажмите Главное меню",
                             reply_markup=back_menu)
    await message.answer(message_text, reply_markup=categories_actions)

@dp.callback_query_handler(confirmation_callback.filter(action_name="delete"))
async def choose_category_to_delete(call: types.CallbackQuery, state: FSMContext):
    await call.message.delete()
    message_text = "Выберите категорию, которую хотите удалить:"
    user_tg_id = (await state.get_data()).get("user_tg_id")

    user_categories_lst: List[str] = await db.get_user_categories(user_tg_id)

    await call.message.answer(message_text,
                              reply_markup=get_categories_buttons(categories=user_categories_lst))
    await DeleteCategory.choose_category.set()

@dp.callback_query_handler(state=DeleteCategory.choose_category)
async def delete_category_confirmation(call: types.CallbackQuery, state: FSMContext):
    category = await get_and_save_category(call, state)
    message_text = f"Вы уверены, что хотите удалить категорию {category}?"

    await call.message.answer(message_text, reply_markup=confirmation_buttons)
    await DeleteCategory.delete_confirmation.set()

@dp.callback_query_handler(confirmation_callback.filter(action_name="yes"),
                           state=DeleteCategory.delete_confirmation)
async def delete_category(call: types.CallbackQuery, state: FSMContext):
    await call.message.delete()
    category = await get_category(state)
    user_tg_id = (await state.get_data()).get("user_tg_id")

    await db.delete_user_category(user_tg_id, category)

    await call.message.answer(f"Категория {category} успешно удалена", reply_markup=main_menu)
    await reset_state_saving_user_id(state)

@dp.callback_query_handler(confirmation_callback.filter(action_name="no"),
                           state=DeleteCategory.delete_confirmation)
async def deny_delete_category(call: types.CallbackQuery, state: FSMContext):
    await call.message.delete()
    await reset_state_saving_user_id(state)
    await show_all_categories(call, state, False)

@dp.callback_query_handler(confirmation_callback.filter(action_name="add"))
async def add_category(call: types.CallbackQuery):
    await call.message.delete()
    message_text = "Введите название категории, которую вы хотите добавить"
    await call.message.answer(message_text)
    await AddCategory.write_new_category_name.set()

@dp.message_handler(state=AddCategory.write_new_category_name)
async def category_added(message: types.Message, state: FSMContext):
    new_category_name = message.text
    user_tg_id = message.from_user.id
    await state.update_data(user_tg_id=user_tg_id)

    if await db.add_user_category(user_tg_id, new_category_name):
        await message.answer(f"Категория {new_category_name} успешно создана")
    else:
        await message.answer(f"Категория {new_category_name} уже создана")

    await reset_state_saving_user_id(state)
    await show_all_categories(message, state, False)