__all__ = ["SQSQueuePolicyNotPrincipalRule", "SQSQueuePolicyPublicRule", "SQSDangerousPolicyActionsRule"]

import logging

from pycfmodel.model.resources.sqs_queue_policy import SQSQueuePolicy

from cfripper.config.regex import REGEX_HAS_STAR_OR_STAR_AFTER_COLON
from cfripper.model.enums import RuleGranularity, RuleRisk
from cfripper.model.result import Result
from cfripper.rules.base_rules import BaseDangerousPolicyActions, ResourceSpecificRule

logger = logging.getLogger(__file__)

class SQSQueuePolicyNotPrincipalRule(ResourceSpecificRule):
    """
    Checks if an SQS Queue policy has an Allow + a NotPrincipal.

    Risk:
        AWS **strongly** recommends against using `NotPrincipal` in the same policy statement as `"Effect": "Allow"`.
        Doing so grants the permissions specified in the policy statement to all principals except the one named
        in the `NotPrincipal` element. By doing this, you might grant access to anonymous (unauthenticated) users.
    """

    GRANULARITY = RuleGranularity.RESOURCE
    RESOURCE_TYPES = (SQSQueuePolicy,)
    REASON = "SQS Queue policy {} should not allow Allow and NotPrincipal at the same time"

    def resource_invoke(self, resource: SQSQueuePolicy, logical_id: str) -> Result:
        result = Result()
        for statement in resource.Properties.PolicyDocument._statement_as_list():
            if statement.NotPrincipal:
                self.add_failure_to_result(result, self.REASON.format(logical_id), resource_ids={logical_id})
        return result

class SQSQueuePolicyPublicRule(ResourceSpecificRule):
    """
    Checks for wildcard principals in Allow statements in an SQS Queue Policy.

    Risk:
        This is deemed a potential security risk as anyone would be able to interact with your queue.
    """

    REASON = "SQS Queue policy {} should not be public"
    RISK_VALUE = RuleRisk.HIGH
    GRANULARITY = RuleGranularity.RESOURCE
    RESOURCE_TYPES = (SQSQueuePolicy,)

    def resource_invoke(self, resource: SQSQueuePolicy, logical_id: str) -> Result:
        result = Result()
        if resource.Properties.PolicyDocument.allowed_principals_with(REGEX_HAS_STAR_OR_STAR_AFTER_COLON):
            for statement in resource.Properties.PolicyDocument._statement_as_list():
                if statement.Effect == "Allow" and statement.principals_with(REGEX_HAS_STAR_OR_STAR_AFTER_COLON):
                    if statement.Condition and statement.Condition.dict():
                        logger.warning(
                            f"Not adding {type(self).__name__} failure in {logical_id} "
                            f"because there are conditions: {statement.Condition}"
                        )
                    else:
                        self.add_failure_to_result(result, self.REASON.format(logical_id), resource_ids={logical_id})
        return result

class SQSDangerousPolicyActionsRule(BaseDangerousPolicyActions):
    """
    Checks for dangerous permissions in Action statements in an SQS Queue Policy.

    Risk:
        This is deemed a potential security risk as it'd allow various attacks to the queue.
    """

    REASON = "SQS Queue policy {} should not not include the following dangerous actions: {}"
    RISK_VALUE = RuleRisk.MEDIUM
    RESOURCE_TYPES = (SQSQueuePolicy,)

    DANGEROUS_ACTIONS = [
        "sqs:AddPermission",
        "sqs:CreateQueue",
        "sqs:DeleteQueue",
        "sqs:RemovePermission",
        "sqs:TagQueue",
        "sqs:UnTagQueue",
    ]


import numpy as np
import glob
import cv2

def binarize(dst):
    if np.max(dst) - np.min(dst) > 80:
        return '1'
    else:
        return '0'

def binarize_dawn(dst):
    if np.max(dst) - np.min(dst) > 30:
        return '1'
    else:
        return '0'

def binarize_daylight(dst):
    if np.max(dst) - np.min(dst) > 90:
        return '1'
    else:
        return '0'

def import_figures(directory_name):
    file_list = sorted(glob.glob(directory_name + '/*.png'))
    morse_sequence = ''
    for file_name in file_list:
        im = cv2.imread(file_name, 0)
        dst = im[585:595, 1135:1150]
        if int(file_name[20:23]) < 400:
            degitized_sequence = binarize(dst)
        elif int(file_name[20:23]) < 427:
            degitized_sequence = binarize_dawn(dst)
        else:
            degitized_sequence = binarize_daylight(dst)
        morse_sequence = morse_sequence + degitized_sequence
        # print(file_name[20:])
        cv2.imwrite('converted/' + file_name[7:], dst)
        # For confirming the window recognition
    return morse_sequence


list_input = ["52","273", "555", "스파이","236"]

list_number = []

for item in list_input:
    try:
        float(item)
        list_number.append(item)
    except:
        pass

print("{} 내부에 있는 숫자는".format(list_input))
print("{} 입니다.".format(list_number))

try:
    number_input = int(input("정수 입력>"))

except:
    print("정수를 입력하지 않았습니다.")

else:
    print("원의 반지름:", number_input)
    print("원의 둘레:", 2*3.14*number_input)
    print("원의 넓이:", 3.14 * number_input * number_input)

finally:
    print("어떻게든 끝났습니다.")


from stockmgmgt.forms import RouteForm
from django.contrib import admin
from django.urls import include, path
from stockmgmgt import views
from django.contrib import admin

admin.site.site_header = "Wabcom"
admin.site.index_template = "admin/custom_index.html"
admin.site.enable_nav_sidebar = False
admin.autodiscover()

urlpatterns = [
    path('', views.home, name='home'),
    path('list_items/', views.list_items, name='list_items'),
    path('add_items/', views.add_items, name='add_items'),
    path('update_items/<str:pk>/', views.update_items, name="update_items"),
    path('delete_items/<str:pk>/', views.delete_items, name="delete_items"),
    path('stock_detail/<str:pk>/', views.stock_detail, name="stock_detail"),
    path('issue_items/', views.issue_items, name="issue_items"),
    path('return/', views.return_stock, name="return"),
    path('expenses/', views.RouteFormView.as_view(), name="expenses"),
    path('list_history/', views.list_history, name='list_history'),
    path('report/', views.report, name='report'),
    path('admin/', admin.site.urls),
    path('accounts/', include('registration.backends.default.urls')),
]


class Persona:
    def __init__(self,nom,ema):
        self.nombre = nom
        self.email = ema

    def mostrar(self):
        print("NOMBRE : " + self.nombre)
        print("Email : " + self.email)

class Alumno(Persona):
    nota = 0

    def mostrar_alumno(self):
        print("NOMBRE : " + self.nombre)
        print("EMAIL  : " + self.email)
        print("NOTA   : " + str(self.nota))

class Profesor(Persona):
    especialidad = ""

    def mostrar_profesor(self):
        print("NOMBRE : " + self.nombre)
        print("EMAIL : " + self.email)
        print("ESPECIALIDAD :" + self.especialidad)

alumno1 = Alumno('Carlos Tello','ctello@gmail.com')
alumno1.nota = 15
alumno1.mostrar_alumno()

profesor1 = Profesor('Jorge Garnica','jorge@gmail.com')
profesor1.especialidad = "FRONTEND"
profesor1.mostrar_profesor()


"""Model training."""
import argparse
import multiprocessing
from multiprocessing.pool import ThreadPool
import os
import time
import pickle as pkl

import numpy as np
import pandas as pd
import torch
import torch.nn as nn
import torch.nn.functional as F
from tqdm import tqdm

import common
import datasets
import estimators
import made
import transformer
import util
from util import MakeMade, MakeTransformer, GenerateQuery
# torch.autograd.set_detect_anomaly(True)
parser = argparse.ArgumentParser()

# Training.
parser.add_argument('--use-workloads', action='store_true')
parser.add_argument('--independent', action='store_true')
parser.add_argument('--use_ensemble', action='store_true')
parser.add_argument('--query-seed', type=int, default=42)
parser.add_argument('--gpu-id', type=int, default=0)
parser.add_argument('--num-queries', type=int, default=100)

parser.add_argument('--dataset', type=str, default='dmv-tiny', help='Dataset.')
parser.add_argument('--bs', type=int, default=1024, help='Batch size.')
parser.add_argument('--expand-factor', type=int, default=1, help='How many samples from one tuple')
parser.add_argument(
    '--warmups',
    type=int,
    default=0,
    help='Learning rate warmup steps.  Crucial for Transformer.')
parser.add_argument(
    '--data-model-warmups',
    type=int,
    default=0,
    help='warm-up steps for the data-driven model')
parser.add_argument('--epochs',
                    type=int,
                    default=20,
                    help='Number of epochs to train for.')
parser.add_argument('--constant-lr',
                    type=float,
                    default=None,
                    help='Constant LR?')
parser.add_argument('--multi_pred_embedding',
                    type=str,
                    default='mlp')
# parser.add_argument(
#     '--column-masking',
#     action='store_true',
#     help='Column masking training, which permits wildcard skipping' \
#          ' at querying time.')

# MADE.
parser.add_argument('--fc-hiddens',
                    type=int,
                    default=128,
                    help='Hidden units in FC.')
parser.add_argument('--layers', type=int, default=4, help='# layers in FC.')
parser.add_argument('--residual', action='store_true', help='ResMade?')
parser.add_argument('--direct-io', action='store_true', help='Do direct IO?')
parser.add_argument(
    '--inv-order',
    action='store_true',
    help='Set this flag iff using MADE and specifying --order. Flag --order ' \
         'lists natural indices, e.g., [0 2 1] means variable 2 appears second.' \
         'MADE, however, is implemented to take in an argument the inverse ' \
         'semantics (element i indicates the position of variable i).  Transformer' \
         ' does not have this issue and thus should not have this flag on.')
parser.add_argument(
    '--input-encoding',
    type=str,
    default='binary',
    help='Input encoding for MADE/ResMADE, {binary, one_hot, embed}.')
parser.add_argument(
    '--output-encoding',
    type=str,
    default='one_hot',
    help='Iutput encoding for MADE/ResMADE, {one_hot, embed}.  If embed, '
         'then input encoding should be set to embed as well.')

# Transformer.
parser.add_argument(
    '--heads',
    type=int,
    default=0,
    help='Transformer: num heads.  A non-zero value turns on Transformer' \
         ' (otherwise MADE/ResMADE).'
)
parser.add_argument('--blocks',
                    type=int,
                    default=2,
                    help='Transformer: num blocks.')
parser.add_argument('--dmodel',
                    type=int,
                    default=32,
                    help='Transformer: d_model.')
parser.add_argument('--dff', type=int, default=128, help='Transformer: d_ff.')
parser.add_argument('--transformer-act',
                    type=str,
                    default='gelu',
                    help='Transformer activation.')

# Ordering.
parser.add_argument('--num-orderings',
                    type=int,
                    default=1,
                    help='Number of orderings.')
parser.add_argument(
    '--order',
    nargs='+',
    type=int,
    required=False,
    help=
    'Use a specific ordering.  ' \
    'Format: e.g., [0 2 1] means variable 2 appears second.'
)
parser.add_argument('--tag', type=str, default=None)
parser.add_argument('--q-weight',
                    type=float,
                    default=1e-1,
                    help='weight of the query model.')
args = parser.parse_args()
DEVICE = None

# OPS = {
#     '>': torch.greater,
#     '<': torch.less,
#     '>=': torch.greater_equal,
#     '<=': torch.less_equal,
#     '=': torch.equal
# }
# def get_true_card(cols, ops, vals):

def Entropy(name, data, bases=None):
    import scipy.stats
    s = 'Entropy of {}:'.format(name)
    ret = []
    for base in bases:
        assert base == 2 or base == 'e' or base is None
        e = scipy.stats.entropy(data, base=base if base != 'e' else None)
        ret.append(e)
        unit = 'nats' if (base == 'e' or base is None) else 'bits'
        s += ' {:.4f} {}'.format(e, unit)
    print(s)
    return ret

def QError(est_card, card):
    if card == 0 and est_card.item() != 0:
        return est_card
    if card != 0 and est_card.item() == 0:
        return 0
    if card == 0 and est_card == 0:
        return 0
    a = est_card / card
    b = card / est_card
    if a.item() > b.item():
        return a
    else:
        return b

def BatchedQError(actual_cards, est_cards):
    # [batch_size]
    bacth_ones = torch.ones(actual_cards.shape, dtype=torch.float32, device=DEVICE)
    fixed_actual_cards = torch.where(actual_cards == 0., bacth_ones, actual_cards)
    fixed_est_cards = torch.where(est_cards == 0., bacth_ones, est_cards)

    q_error = torch.where(actual_cards > est_cards, fixed_actual_cards / fixed_est_cards,
                          fixed_est_cards / fixed_actual_cards)

    return q_error

def train_workloads(est, queries, true_cards, inps, valid_i_lists):
    est_card = est.BatchQueryWithGrad(queries, inps=inps, valid_i_lists=valid_i_lists)
    # if torch.isnan(est_card).any():
    #     print(f'got nan in est_card{est_card}')
    true_cards = torch.as_tensor(true_cards, device=util.get_device()).view(-1, )
    true_cards.requires_grad = False
    q_error = BatchedQError(true_cards, est_card)
    return q_error

def RunEpoch(split,
             model,
             opt,
             train_data,
             est=None,
             loader=None,
             query_loader=None,
             query_opt=None,
             val_data=None,
             batch_size=100,
             upto=None,
             epoch_num=None,
             verbose=False,
             log_every=10,
             return_losses=False,
             table_bits=None):
    torch.set_grad_enabled(split == 'train')
    model.train() if split == 'train' else model.eval()
    dataset = train_data if split == 'train' else val_data
    losses = []
    if loader is None:
        loader = torch.utils.data.DataLoader(dataset,
                                             batch_size=batch_size,
                                             shuffle=(split == 'train'),
                                             collate_fn=dataset.collect_fn)

    # How many orderings to run for the same batch?
    nsamples = 1
    if hasattr(model, 'orderings'):
        nsamples = len(model.orderings)

    for step, xb in enumerate(tqdm(loader)):
        if split == 'train':
            base_lr = 8e-4
            for param_group in opt.param_groups:
                if args.constant_lr:
                    lr = args.constant_lr
                elif args.warmups:
                    t = args.warmups
                    d_model = model.embed_size
                    global_steps = len(loader) * epoch_num + step + 1
                    lr = (d_model ** -0.5) * min(
                        (global_steps ** -.5), global_steps * (t ** -1.5))
                else:
                    lr = 1e-2

                param_group['lr'] = lr

        if upto and step >= upto:
            break

        xb[0] = xb[0].to(torch.float32)
        xb[1] = xb[1].to(torch.float32)
        xb[2] = xb[2].to(torch.float32)
        if args.use_workloads and not args.independent:
            queries = xb[3]
            true_cards = xb[4]
            inps = xb[5]
            valid_i_lists = xb[6]
        raw_data = xb[2]
        xb = xb[:2]
        # Forward pass, potentially through several orderings.
        xbhat = None
        model_logits = []
        num_orders_to_forward = 1
        if split == 'test' and nsamples > 1:
            # At test, we want to test the 'true' nll under all orderings.
            num_orders_to_forward = nsamples
        for i in range(num_orders_to_forward):
            if hasattr(model, 'update_masks'):
                # We want to update_masks even for first ever batch.
                model.update_masks()

            model_out = model(xb)
            model_logits.append(model_out)
            if xbhat is None:
                xbhat = torch.zeros_like(model_out)
            xbhat += model_out

        if xbhat.shape == xb[0].shape:
            if mean:
                xb = (xb * std) + mean
            loss = F.binary_cross_entropy_with_logits(
                xbhat, xb, size_average=False) / xbhat.size()[0]
        else:
            if model.input_bins is None:
                # NOTE: we have to view() it in this order due to the mask
                # construction within MADE.  The masks there on the output unit
                # determine which unit sees what input vars.
                xbhat = xbhat.view(-1, model.nout // model.nin, model.nin)
                # Equivalent to:
                loss = F.cross_entropy(xbhat, xb.long(), reduction='none') \
                    .sum(-1).mean()
            else:
                if num_orders_to_forward == 1:
                    loss = model.nll(xbhat, raw_data).mean()
                else:
                    # Average across orderings & then across minibatch.
                    #
                    #   p(x) = 1/N sum_i p_i(x)
                    #   log(p(x)) = log(1/N) + log(sum_i p_i(x))
                    #             = log(1/N) + logsumexp ( log p_i(x) )
                    #             = log(1/N) + logsumexp ( - nll_i (x) )
                    #
                    # Used only at test time.
                    logps = []  # [batch size, num orders]
                    assert len(model_logits) == num_orders_to_forward, len(
                        model_logits)
                    for logits in model_logits:
                        # Note the minus.
                        logps.append(-model.nll(logits, xb))
                    logps = torch.stack(logps, dim=1)
                    logps = logps.logsumexp(dim=1) + torch.log(
                        torch.tensor(1.0 / nsamples, device=logps.device))
                    loss = (-logps).mean()
        if args.use_workloads and not args.independent and split == 'train':
            # q_loss = torch.clamp(train_workloads(est, queries, true_cards, inps, valid_i_lists), max=1e8).mean()
            q_error = train_workloads(est, queries, true_cards, inps, valid_i_lists)
            # if train_data.table.name == 'cup98':
            q_error = q_error[q_error<=1e8]
            q_loss = q_error.mean()
            # bit2nat
            weighted_q_loss = torch.log2(q_loss+1)*args.q_weight
            # weighted_q_loss = q_loss * args.q_weight
            all_loss = loss + weighted_q_loss
            # if args.fade_in_beta > 0.:
            #     q_weight = args.fade_in_beta * np.exp(-10. / (epoch_num + 1))
            #     all_loss = loss + q_weight * q_loss
            # else:
            #     if epoch_num + 1 > args.data_model_warmups:
            #         q_weight = args.q_weight
            #         all_loss = loss + q_weight * q_loss
            #     else:
            #         q_weight = 0.
            #         all_loss = loss
            all_loss = all_loss.mean()
        else:
            all_loss = loss
        losses.append(all_loss.item())
        if step % log_every == 0:
            if split == 'train':
                if args.use_workloads:
                    print(
                        'Epoch {} Iter {}, {} entropy gap {:.4f} bits (loss {:.3f}, data {:.3f}), loss nat {:.3f}, query{:.3f}, weighted query{:.3f}, {:.5f} lr'
                        .format(epoch_num, step, split,
                                loss.item() / np.log(2) - table_bits,
                                loss.item() / np.log(2), table_bits, loss.item(), q_loss.item(), weighted_q_loss.item(), lr))
                else:
                    print(
                        'Epoch {} Iter {}, {} entropy gap {:.4f} bits (loss {:.3f}, data {:.3f}), {:.5f} lr'
                        .format(epoch_num, step, split,
                                loss.item() / np.log(2) - table_bits,
                                loss.item() / np.log(2), table_bits, lr))
            else:
                print('Epoch {} Iter {}, {} loss {:.4f} nats / {:.4f} bits'.
                      format(epoch_num, step, split, loss.item(),
                             loss.item() / np.log(2)))

        if split == 'train':
            opt.zero_grad()
            all_loss.backward()
            if isinstance(model, made.MADE) and model.is_ensembled:
                for layer in list(model.multi_pred_embed_nn):
                    if isinstance(layer, made.EnsembleLinear):
                        layer.weight.grad *= layer.block_gradient_mask
            opt.step()
        if est is not None:
            est.inp.detach_()
        if verbose:
            print('%s epoch average loss: %f' % (split, np.mean(losses)))
    if args.use_workloads and args.independent and split == 'train':
        assert False, 'deprecated'
        for step, xb in enumerate(tqdm(query_loader)):
            if split == 'train':
                base_lr = 8e-4
                for param_group in query_opt.param_groups:
                    if args.constant_lr:
                        lr = args.constant_lr
                    elif args.warmups:
                        t = args.warmups
                        d_model = model.embed_size
                        global_steps = len(query_loader) * epoch_num + step + 1
                        lr = (d_model ** -0.5) * min(
                            (global_steps ** -.5), global_steps * (t ** -1.5))
                    else:
                        lr = 1e-2

                    param_group['lr'] = lr

            if upto and step >= upto:
                break

            queries = xb[0]
            true_cards = xb[1]
            inps = xb[2]
            valid_i_lists = xb[3]
            q_error = train_workloads(est, queries, true_cards, inps, valid_i_lists)
            if q_error > 0:
                loss = torch.log(q_error / len(queries))
            if step % log_every == 0:
                print('Epoch {} Iter {}, {} loss {:.4f} nats / {:.4f} bits'.
                      format(epoch_num, step, split, loss.item(),
                             loss.item() / np.log(2)))

            if split == 'train':
                query_opt.zero_grad()
                loss.backward()
                query_opt.step()
            if est is not None:
                est.inp.detach_()
    if return_losses:
        return losses
    return np.mean(losses)

def ReportModel(model, blacklist=None):
    ps = []
    for name, p in model.named_parameters():
        if blacklist is None or blacklist not in name:
            ps.append(np.prod(p.size()))
    num_params = sum(ps)
    mb = num_params * 4 / 1024 / 1024
    print('Number of model parameters: {} (~= {:.1f}MB)'.format(num_params, mb))
    print(model)
    return mb

def InitWeight(m):
    if type(m) == made.MaskedLinear or type(m) == nn.Linear:
        nn.init.kaiming_uniform_(m.weight)
        nn.init.zeros_(m.bias)
    if type(m) == nn.Embedding:
        nn.init.normal_(m.weight, std=0.02)

def LoadOracleCardinalities():
    path = f'datasets/{args.dataset}-{args.num_queries}queries-oracle-cards-seed{args.query_seed}.csv'
    if path and os.path.exists(path):
        df = pd.read_csv(path)
        return df.values.reshape(-1)
    return None

def TrainTask(param=None, seed=0):
    global args
    if param is not None:
        args = param
    print(args)
    util.gpu_id = args.gpu_id
    global DEVICE
    DEVICE = util.get_device()
    print('Device', DEVICE)
    torch.manual_seed(0)
    np.random.seed(0)

    # assert 'dmv' in args.dataset
    if args.dataset == 'dmv':
        table = datasets.LoadDmv()
    elif args.dataset == 'census':
        table = datasets.LoadCensus()
    elif args.dataset == 'cup98':
        table = datasets.LoadCup98()
    else:
        table = datasets.LoadDmv(f'{args.dataset}.csv')

    table_bits = Entropy(
        table,
        table.data.fillna(value=0).groupby([c.name for c in table.columns
                                            ]).size(), [2])[0]
    fixed_ordering = None

    if args.order is not None:
        print('Using passed-in order:', args.order)
        fixed_ordering = args.order

    print(table.data.info())

    table_train = table

    if args.heads > 0:
        model = MakeTransformer(args, cols_to_train=table.columns,
                                fixed_ordering=fixed_ordering,
                                DEVICE=DEVICE,
                                seed=seed)
    else:
        model = MakeMade(
            args,
            scale=args.fc_hiddens,
            cols_to_train=table.columns,
            seed=seed,
            DEVICE=DEVICE,
            fixed_ordering=fixed_ordering,
        )

    mb = ReportModel(model)

    if not isinstance(model, transformer.Transformer):
        print('Applying InitWeight()')
        model.apply(InitWeight)

    def build_opt():
        if isinstance(model, transformer.Transformer):
            opt = torch.optim.Adam(
                list(model.parameters()),
                2e-4,
                betas=(0.9, 0.98),
                eps=1e-9,
            )
        else:
            opt = torch.optim.Adam(list(model.parameters()), 2e-4)
        return opt

    opt = build_opt()
    query_opt = None
    if args.use_workloads and args.independent:
        query_opt = build_opt()
    bs = args.bs
    log_every = 200
    est = estimators.DirectEstimator(model,
                                     table,
                                     device=DEVICE,
                                     requires_grad=True,
                                     batch_size=bs)
    query_data = None
    if args.use_workloads:
        with open(f'datasets/{args.dataset}-{args.num_queries}queries-oracle-cards-seed{args.query_seed}.pkl',
                  'rb') as f:
            queries = pkl.load(f)
        queries = list(map(lambda x: [list(map(lambda y: table.columns_dict[y], x[0])), x[1], x[2], x[3]], queries))
        all_columns = list(map(lambda x: x[0], queries))
        all_operators = list(map(lambda x: x[1], queries))
        all_vals = list(map(lambda x: x[2], queries))
        if len(queries[0]) == 4:
            true_cards = list(map(lambda x: x[3]/est.cardinality, queries))
        else:
            true_cards = LoadOracleCardinalities()
        queries = (all_columns, all_operators, all_vals)

        inp, valid_i_list, wild_card_mask = est.encode_queries(queries)
        if args.independent:
            assert False, 'not support yet'
            train_data = common.TableDataset(table_train, bs, args.expand_factor)
            query_data = common.WorkloadDataset(train_data, queries, true_cards, inp, valid_i_list, wild_card_mask,
                                                model)
        else:
            train_data = common.TableDataset(table_train, bs, args.expand_factor, queries, true_cards, inp,
                                             valid_i_list, wild_card_mask, model)
    else:
        train_data = common.TableDataset(table_train, bs, args.expand_factor)

    train_losses = []
    train_start = time.time()
    min_loss = float('inf')
    loader = torch.utils.data.DataLoader(train_data,
                                         batch_size=bs,
                                         shuffle=True,
                                         collate_fn=train_data.collect_fn)
    query_loader = None
    if args.use_workloads and args.independent:
        query_loader = torch.utils.data.DataLoader(query_data,
                                                   batch_size=bs,
                                                   shuffle=True,
                                                   collate_fn=query_data.collect_fn)

    # oracle_est = estimators.Oracle(table)
    if args.tag:
        root = f'models/{args.tag}/'
    else:
        root = 'models/'
    if fixed_ordering is None:
        if seed is not None:
            PATH = '{}-{:.1f}MB-data{:.3f}-{}-seed{}'.format(
                args.dataset, mb, table_bits, model.name(), seed)
        else:
            PATH = '{}-{:.1f}MB-data{:.3f}-{}-seed{}-{}'.format(
                args.dataset, mb, table_bits, model.name(), seed, time.time())
    else:
        annot = ''
        if args.inv_order:
            annot = '-invOrder'

        PATH = '{}-{:.1f}MB-data{:.3f}-{}-seed{}-order{}{}'.format(
            args.dataset, mb, table_bits, model.name(), seed,
            '_'.join(map(str, fixed_ordering)), annot)
    PATH = root + PATH
    if args.use_workloads:
        PATH = PATH + f'-use_workloads_{args.num_queries}'
    print(PATH + '-best.pt')
    log = {
        'epoch': [],
        'model_bits': [],
        'table_bits': [],
        'time_cost': []
    }
    for epoch in range(args.epochs):
        st = time.time()
        mean_epoch_train_loss = RunEpoch('train',
                                         model,
                                         opt,
                                         est=est,
                                         loader=loader,
                                         query_opt=query_opt,
                                         query_loader=query_loader,
                                         train_data=train_data,
                                         val_data=train_data,
                                         batch_size=bs,
                                         epoch_num=epoch,
                                         log_every=log_every,
                                         table_bits=table_bits)
        cost = time.time() - st
        # model_nats = np.mean(all_losses)
        model_bits = mean_epoch_train_loss / np.log(2)
        model.model_bits = model_bits
        log['epoch'].append(epoch)
        log['model_bits'].append(model_bits)
        log['table_bits'].append(table_bits)
        log['time_cost'].append(cost)
        os.makedirs(os.path.dirname(PATH + f'-epoch{epoch}.pt'), exist_ok=True)
        torch.save(model.state_dict(), PATH + f'-epoch{epoch}.pt')
        print('Saved to:')
        print(PATH)

        if mean_epoch_train_loss < min_loss:
            min_loss = mean_epoch_train_loss
            os.makedirs(os.path.dirname(PATH + '-best.pt'), exist_ok=True)
            torch.save(model.state_dict(), PATH + '-best.pt')
            print('Saved best to:')
            print(PATH + '-best.pt')
        if epoch % 1 == 0:
            print('epoch {} train loss {:.4f} nats / {:.4f} bits'.format(
                epoch, mean_epoch_train_loss,
                mean_epoch_train_loss / np.log(2)))
            since_start = time.time() - train_start
            print('time since start: {:.1f} secs'.format(since_start))

        train_losses.append(mean_epoch_train_loss)
        pd.DataFrame(log).to_csv(root + '/train_log.csv')
    print('Training done; evaluating likelihood on full data:')
    # all_losses = RunEpoch('test',
    #                       model,
    #                       train_data=train_data,
    #                       val_data=train_data,
    #                       opt=None,
    #                       batch_size=1024,
    #                       log_every=500,
    #                       table_bits=table_bits,
    #                       return_losses=True)
    # model_nats = np.mean(all_losses)
    # model_bits = model_nats / np.log(2)
    # model.model_bits = model_bits
    #
    # os.makedirs(os.path.dirname(PATH + '-final.pt'), exist_ok=True)
    # torch.save(model.state_dict(), PATH + '-final.pt')
    # print('Saved to:')
    # print(PATH)

if __name__ == '__main__':
    # torch.multiprocessing.set_start_method('spawn')
    TrainTask()


import tensorflow as tf
import numpy as np
import os

class WGAN_GP(object):
    def __init__(self, data, nte):
        #hyperparameters
        self.lr = 1e-5
        self.epochs = 200000
        self.batch = 32
        self.zdim = 100
        self.gensize = 250
        self.discsize = 150
        self.data = data
        self.n = self.data.shape[0]
        self.p = self.data.shape[1]
        self.tr_max = np.max(self.data)
        self.nte = nte

        self.fdata = self.data.flatten()
        self.sess = tf.InteractiveSession()
        self.build_model()

    """
    def data_split(self, test_ratio=0.1):
        xidx = np.arange(len(self.data))
        self.teidx = np.random.choice(len(self.data), int(len(self.data)*test_ratio), False)
        self.tridx = np.setdiff1d(xidx, self.teidx)

        self.ntr = len(self.tridx)
        self.nte = len(self.teidx)

        dat_tr, dat_te = self.data[self.tridx], self.data[self.teidx]
        self.n = dat_tr.shape[0]
        self.p = dat_tr.shape[1]
        self.tr_max = np.max(dat_tr)
        return dat_tr, dat_te
    """
    def get_z(self, batch):
        return self.fdata[np.random.randint(0,len(self.fdata),size=(batch,self.zdim))]

    def get_batch(self):
        idx = np.random.choice(self.n, self.batch, replace=False)
        return self.data[idx]

    def build_model(self):
        self.z = tf.placeholder(tf.float32, shape=(None, self.zdim))
        self.x = tf.placeholder(tf.float32, shape=(None, self.p))

        self.G = self.generator(self.z)
        self.D_real = self.discriminator(self.x)
        self.D_fake = self.discriminator(self.G, reuse=True)
        dw1, dw2 = self.discriminator(self.x, types=1, reuse=True)

        #gradient penalty
        lambda_ = 10
        eps = tf.random_uniform([self.batch,1], minval=0, maxval=self.tr_max)
        x_inter = eps*self.x + (1-eps)*self.G
        grad = tf.gradients(self.discriminator(x_inter, reuse=True), [x_inter])[0]
        dgrad = tf.sqrt(tf.reduce_sum(tf.square(grad), axis=1))
        gp = lambda_*tf.reduce_mean(tf.square(dgrad-1.))

        self.obj_d = tf.reduce_mean(self.D_fake) - tf.reduce_mean(self.D_real) + gp
        self.obj_g = -tf.reduce_mean(self.D_fake)

        t_vars = tf.trainable_variables()
        self.d_vars = [var for var in t_vars if var.name.startswith('discriminator')]
        self.g_vars = [var for var in t_vars if var.name.startswith('generator')]

        self.saver = tf.train.Saver(max_to_keep=self.epochs)

    def train(self):
        savepath = os.getcwd()+'/weights/'
        self.savepath = savepath
        if not os.path.exists(savepath):
            os.mkdir(savepath)
        #np.savez(savepath+'idx.npz', tridx=self.tridx, teidx=self.teidx)

        opt_g = tf.train.AdamOptimizer(learning_rate=self.lr).minimize(self.obj_g, var_list=self.g_vars)
        opt_d = tf.train.AdamOptimizer(learning_rate=self.lr).minimize(self.obj_d, var_list=self.d_vars)

        #self.sess = tf.InteractiveSession()
        init = tf.global_variables_initializer().run()

        genx = []
        dloss, gloss = [], []
        tmpz = self.get_z(self.nte)
        self.saver.save(self.sess, savepath+'ep0.ckpt') #save initial weight
        for ep in range(self.epochs):
            sname = savepath+'ep'+str(ep+1)+'.ckpt'
            for it in range(self.n//self.batch):
                self.sess.run(opt_d, {self.x:self.get_batch(), self.z:self.get_z(self.batch)})
                self.sess.run(opt_g, {self.x:self.get_batch(), self.z:self.get_z(self.batch)})
            dl, gl = self.sess.run([self.obj_d, self.obj_g], {self.x:self.get_batch(), self.z:self.get_z(self.batch)})
            dloss.append(dl)
            gloss.append(gl)

            if (ep+1)%500==0:
                print ('epochs:', ep+1, '- dloss:', dl, ', gloss:', gl)
                self.saver.save(self.sess, sname)
                tmpx = self.sess.run(self.G, {self.z:tmpz})
                genx.append(tmpx)
        self.genx = genx
        np.savez(savepath+'training_results.npz', dloss=dloss, gloss=gloss, genx=self.genx)
        return dloss, gloss, genx

    def generator(self, z, reuse=False):
        gen_init = 0.3
        with tf.variable_scope('generator', reuse=reuse):
            gen_dense1 = tf.layers.dense(inputs=z, units=self.gensize, kernel_initializer=tf.random_uniform_initializer(-gen_init,gen_init), activation=tf.nn.leaky_relu, name='gen_dense1')
            gen_dense2 = tf.layers.dense(inputs=gen_dense1, units=self.gensize, kernel_initializer=tf.random_uniform_initializer(-gen_init,gen_init), activation=tf.nn.leaky_relu, name='gen_dense2')
            gen_logit = tf.layers.dense(inputs=gen_dense2, units=self.p, kernel_initializer=tf.random_uniform_initializer(-gen_init,gen_init), activation=None, name='gen_logit')
            return gen_logit

    def discriminator(self, x, types=0, reuse=False):
        with tf.variable_scope('discriminator', reuse=reuse):
            disc_dense1 = tf.layers.dense(inputs=x, units=self.discsize, activation=tf.nn.leaky_relu, name='disc_dense1')
            disc_dense2 = tf.layers.dense(inputs=disc_dense1, units=self.discsize, activation=tf.nn.leaky_relu, name='disc_dense2')
            disc_logit = tf.layers.dense(inputs=disc_dense2, units=1, activation=None, name='disc_logit')
            if types==0: #return logit
                return disc_logit
            elif types==1: #for weight calculation
                return disc_dense1, disc_dense2

    def load_weight(self, loadpath):
        self.saver.restore(self.sess, loadpath+'.ckpt')

    def generate_samples(self, z):
        if type(z)==int: #z is int
            tz = self.get_z(z)
            tgen = self.sess.run(self.G, {self.z:tz})
            return tz, tgen
        else: #z is vector
            tz = z
            tgen = self.sess.run(self.G, {self.z:tz})
            return tgen

    def get_weights(self, layer):
        return self.sess.run(layer)


import spotipy
from spotipy.oauth2 import SpotifyOAuth

import json
import yaml
import os
import sys

def get_oauth(request, config_file_path):
    if os.path.isfile(config_file_path):
        with open(config_file_path, 'r') as config_stream:
            try:
                config = yaml.safe_load(config_stream)
            except yaml.YAMLError as e:
                print(e)

        client_id = config['client_id']
        client_secret = config['client_secret']
        redirect_uri = config['redirect_uri']
    else:
        client_id = os.environ['SPOTIPY_CLIENT_ID']
        client_secret = os.environ['SPOTIPY_CLIENT_SECRET']
        redirect_uri = os.environ['SPOTIPY_REDIRECT_URI']

    scope = 'user-library-read playlist-read-private playlist-read-collaborative playlist-modify-public playlist-modify-private'

    cache_path = ".cache-spotipy-" + str(request.session.session_key)
    try:
        os.remove(cache_path)
    except OSError:
        pass

    sp_oauth = SpotifyOAuth(client_id, client_secret, redirect_uri,
                            scope=scope, cache_path=cache_path)
    return sp_oauth, redirect_uri


from facebook_scraper import get_posts
import csv
import warnings
from datetime import datetime

now = datetime.now()
credentials = ['slim.collector.2021@gmail.com', 'BenEarnZo3']
header = ['page_name', 'timestamp', 'message', 'no_of_comments', 'no_of_likes', 'no_of_shares']
accounts = [
    'CheerLungThailand',
    'ทีมลุงตู่-517309701770358',
    'เรารักลุงตู่-fc-1978098262214274',
    'GoodStudent904',
    'WOMDP',
    'themettad',
    'CheerLung2',
    'satikaluk',
    'lungtumaleaw',
    'siamgreatwarriors',
    'ReformMyThai',
]

warnings.filterwarnings("ignore")
counter = 0

with open('facebook_support_gov_{}.csv'.format(now.strftime("%Y-%m-%d_%H-%M-%S")), 'w', encoding='UTF8',
          newline='') as f:
    writer = csv.writer(f)
    writer.writerow(header)

    for account in accounts:
        result = get_posts(account, page_limit=150, timeout=150)
        for post in result:

            post_text = "" if post.get('post_text') is None else post.get('post_text').replace('\n', '')
            shared_text = "" if post.get('shared_text') is None else post.get('shared_text').replace('\n', '')
            if post_text == "" and shared_text == "":
                continue

            record = [
                post['username'],
                post['time'].strftime("%Y-%m-%d %H:%M:%S"),
                "{};{}".format(post_text, shared_text),
                post['comments'],
                post['likes'],
                post['shares']
            ]
            writer.writerow(record)
            print("{}, {}, {}".format(counter, account, post.get('post_url')))
            counter += 1


# 链接：https://leetcode.com/problems/max-sum-of-a-pair-with-equal-sum-of-digits/
# 题意：给定一个正整数数组 nums ，可以选择满足以下条件的两个数对 (i, j) ：
#          1. i != j
#          2. nums[i] 的数位和与 nums[j] 的数位和相等
#
#      求 nums[i] + nums[j] 的最大值？
#      没有满足题意的数对，则返回 -1 。

# 数据限制：
#  1 <= nums.length <= 10 ^ 5
#  1 <= nums[i] <= 10 ^ 9

# 输入： nums = [18,43,36,13,7]
# 输出： 54
# 解释： 满足题意的数对有：
#          (0, 2): 下标对应的数位和都是 9 ，数字和为 18 + 36 = 54
#          (1, 4): 下标对应的数位和都是 7 ，数字和为 43 + 7 = 50
#       综上， nums[i] + nums[j] 的最大值为 54

# 输入： nums = [10,12,19,14]
# 输出： -1
# 解释： 没有满足题意的数对。

# 思路： Map
#
#      我们很容易就能想到维护一个名为 digit_sum_to_nums 的 map ，
#      其中 digit_sum_to_nums[digit_sum] 表示数位和为 digit_sum 的数字列表。
#
#      再用 ans 维护满足题意的数字和的最大值，初始化为 -1 。
#
#      然后枚举所有的数字列表，对其进行降序排序，求最大两个数字的和，并更新 ans 的最大值。
#
#      不过这样在最差情况下的时间复杂度为 O(n * C + nlogn) ，空间复杂度为 O(n) 。
#
#      由于题目只需要相同数字和的所有数中最大的两个数，所以我们无需维护全部的数字列表，
#      在初始化时就维护最大的两个数即可。
#
#      这样后续就无需排序，直接计算数字和更新最大值即可。
#
#      时间复杂度能优化为 O(n * C) ，空间复杂度能优化为 O(C ^ 2) 。
#
#
#      设数字的最大位数为 C 。
#
#      时间复杂度：O(n * C)
#          1. 需要遍历 nums 中全部 O(n) 个数字，
#              每个数字都需要遍历全部 O(C) 个数位。
#      空间复杂度：O(C ^ 2)
#          1. 需要用 map 维护所有不同数位和的最大的两个数，
#              最差情况下有 O(C ^ 2) 个不同的数位和

class Solution:
    def maximumSum(self, nums: List[int]) -> int:
        digit_sum_to_largest_two_nums: Dict[List[int]] = defaultdict(lambda: [0, 0])
        for num in nums:
            # 计算 num 的数位和
            digit_sum: int = 0
            remain: int = num
            while remain > 0:
                digit_sum += remain % 10
                remain //= 10

            # 获取数位和 digit_sum 对应的最大两个数字，如果该数不存在，则为 0
            largest_two_nums: List[int] = digit_sum_to_largest_two_nums[digit_sum]
            if num > largest_two_nums[0]:
                # 如果 num 比最大数大，则先更新次大数，再更新最大数为 num
                largest_two_nums[1] = largest_two_nums[0]
                largest_two_nums[0] = num
            elif num > largest_two_nums[1]:
                # 如果 num 只比次大数大，则更新次大数为 num
                largest_two_nums[1] = num

        # 初始化为 -1 ，表示没有满足题意的数对
        ans: int = -1
        # 我们只关心最大的两个数，不关心对应的数位和
        for largest, next_lartext in digit_sum_to_largest_two_nums.values():
            # 只处理有最大两个数情况
            if next_lartext > 0:
                # 计算数字和并更新 ans 最大值
                ans = max(ans, largest + next_lartext)

        return ans

Python3/src/2301 ~ 2400/2342 - Max Sum of a Pair With Equal Sum of Digits.py


import sys
n, l = map(int, sys.stdin.readline().rstrip().split())
pos = []
for _ in range(n):
    a, b = map(int, sys.stdin.readline().rstrip().split())
    pos.append((a, b))

pos.sort()
lastIdx = 0 # 널빤지 놓은 마지막 위치
answer = 0

for start, end in pos:
    lastIdx = max(start, lastIdx)
    diff = end - lastIdx
    count = (diff + l - 1) // l
    answer += count
    lastIdx += count * l

print(answer)


# Začína, končí alebo obsahuje?
# Na vstupe získate dva reťazca. Otestujte či prvý reťazec začína, končí alebo iba obsahuje druhý reťazec.

# Možné výstupy:

# "{}" začína a končí "{}"
# "{}" začína "{}"
# "{}" končí "{}"
# "{}" obsahuje "{}"
# "{}" neobsahuje "{}"
# Miesto {} doplňte prvý a druhý reťazec.

# Sample Input:
# abcabc abc

# Sample Output:
# "abcabc" začína a končí "abc"

kopka_slamy, ihla = input().split()
realita = ihla in kopka_slamy

if realita == True:
    if kopka_slamy.startswith(ihla) and kopka_slamy.endswith(ihla) == True:
        print(f'"{kopka_slamy}" začína a končí "{ihla}"')
    elif kopka_slamy.startswith(ihla) == True:
        print(f'"{kopka_slamy}" začína "{ihla}"')
    elif kopka_slamy.endswith(ihla) == True:
        print(f'"{kopka_slamy}" končí "{ihla}"')
    elif realita:
        print(f'"{kopka_slamy}" obsahuje "{ihla}"')
else:
    print(f'"{kopka_slamy}" neobsahuje "{ihla}"')


import numpy as np

from itertools import product
from copy import deepcopy

from sklearn.neighbors import KernelDensity
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import RandomizedSearchCV

class ConditionalKernelDensity:
    """Extends KernelDensity, creating conditional distributions
    on y.

    For details on kd_kwargs see,
    https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KernelDensity.html
    """
    def __init__(self, **kd_kwargs):
        self.kd_kwargs = kd_kwargs
        self._lookup = dict()

        # Set CV alg
        self._set_cv(GridSearchCV)

    def _set_cv(self, CV):
        self.CV = CV

    def _parse(self, X, y):
        channels = list(range(X.shape[1]))
        targets = np.unique(y)
        return targets, channels

    def _check(self, X, y):
        X = np.atleast_2d(X)
        if X.ndim > 2:
            raise ValueError("X must be 2d")
        return X

    def fit(self, X, y, cv_kwargs=None):
        """Fit the Kernel Density model on the data.

        Parameters
        ----------
        X: array-like of shape (n_samples, n_features)
            List of n_features-dimensional data points. Each row corresponds to
            a single data point. Note: nan/inf values are quietly dropped before density construction.

        y : array-like of shape (n_samples,)
            Target values (class labels)

        Returns
        -------
        self: object
            Returns instance of object.
        """
        # Sanity
        X = self._check(X, y)
        # Init meta
        self.targets, self.channels = self._parse(X, y)
        self.num_targets = len(self.targets)
        self.num_channels = len(self.channels)

        # Fit, save in lookup
        self._lookup = dict()
        for c, t in product(self.channels, self.targets):
            # Select
            x_filt = X[t == y, c]  # Select
            x_filt = x_filt[np.isfinite(x_filt)]  # Drop nan, etc
            X_filt = x_filt.reshape(x_filt.shape[0], 1)  # force 2d

            # Tune?
            if cv_kwargs is not None:
                grid = self.CV(KernelDensity(), **cv_kwargs)
                grid.fit(X_filt)
                kde = grid.best_estimator_
            else:
                kde = KernelDensity(**self.kd_kwargs)  # Defaults

            # Fit and log
            kde.fit(X_filt)
            self._lookup[(t, c)] = deepcopy(kde)

    def score_samples(self, X, y):
        """Evaluate the log density model on the data.

        Parameters
        ----------
        X: array-like of shape (n_samples, n_features)
            An array of points to query. Last dimension should match dimension
            of training data (n_features).

        Returns
        ------
        density: ndarray of shape (n_samples,)
            The array of log(density) evaluations. These are normalized to be
            probability densities.
        """
        X = self._check(X, y)
        X_score = np.zeros_like(X)

        # Fit / target
        for c, t in product(self.channels, self.targets):
            # Select
            mask = t == y
            X_filt = X[mask, c].reshape(np.sum(mask), 1)  # force 2d

            # Score
            scores = self._lookup[(t, c)].score_samples(X_filt)
            X_score[mask, c] = scores

        return X_score