# coding=utf-8
from utils.metrics import *
from sklearn.metrics import *
from sklearn.preprocessing import LabelBinarizer
from utils.generic import *
from utils.constants import *
import itertools as it
from tqdm import tqdm
from collections import defaultdict
from torch.utils.data import DataLoader
from time import time
import numpy as np
import pandas as pd
import gc
import os

class RecRunner:
    @staticmethod
    def parse_runner_args(parser):
        """
        跑模型的命令行参数
        :param parser:
        :return:
        """
        parser.add_argument('--load', type=int, default=0,
                            help='Whether load model and continue to train')
        parser.add_argument('--load_attack', action='store_true',
                            help='Whether load attacker model and continue to train')
        parser.add_argument('--epoch', type=int, default=100,
                            help='Number of epochs.')
        parser.add_argument('--disc_epoch', type=int, default=500,
                            help='Number of epochs for training extra discriminator.')
        parser.add_argument('--check_epoch', type=int, default=1,
                            help='Check every epochs.')
        parser.add_argument('--early_stop', type=int, default=1,
                            help='whether to early-stop.')
        parser.add_argument('--lr', type=float, default=0.001,
                            help='Learning rate.')
        parser.add_argument('--lr_attack', type=float, default=0.001,
                            help='attacker learning rate.')
        parser.add_argument('--batch_size', type=int, default=128,
                            help='Batch size during training.')
        parser.add_argument('--vt_batch_size', type=int, default=512,
                            help='Batch size during testing.')
        parser.add_argument('--dropout', type=float, default=0.2,
                            help='Dropout probability for each deep layer')
        parser.add_argument('--l2', type=float, default=1e-4,
                            help='Weight of l2_regularize in loss.')
        parser.add_argument('--l2_attack', type=float, default=1e-4,
                            help='Weight of attacker l2_regularize in loss.')
        parser.add_argument('--no_filter', action='store_true',
                            help='if or not use filters')
        parser.add_argument('--reg_weight', type=float,
                            default=1,
                            help='Trade off for adversarial penalty')
        parser.add_argument('--d_steps', type=int,
                            default=10,
                            help='the number of steps of updating discriminator')
        parser.add_argument('--optimizer', type=str, default='GD',
                            help='optimizer: GD, Adam, Adagrad')
        parser.add_argument('--metric', type=str, default="RMSE",
                            help='metrics: RMSE, MAE, AUC, F1, Accuracy, Precision, Recall')
        parser.add_argument('--skip_eval', type=int, default=0,
                            help='number of epochs without evaluation')
        parser.add_argument('--num_worker', type=int, default=1,
                            help='number of processes for multi-processing data loading.')
        parser.add_argument('--fix_one', action='store_true',
                            help='fix one feature for evaluation.')
        parser.add_argument('--eval_disc', action='store_true',
                            help='train extra discriminator for evaluation.')
        return parser

    def __init__(self, optimizer='GD', learning_rate=0.01, epoch=100, batch_size=128, eval_batch_size=128 * 128,
                 dropout=0.2, l2=1e-5, metrics='RMSE', check_epoch=10, early_stop=1, num_worker=1, no_filter=False,
                 reg_weight=0.1, d_steps=100, disc_epoch=1000):
        """
        初始化
        :param optimizer: optimizer name
        :param learning_rate: learning rate
        :param epoch: total training epochs
        :param batch_size: batch size for training
        :param eval_batch_size: batch size for evaluation
        :param dropout: dropout rate
        :param l2: l2 weight
        :param metrics: evaluation metrics list
        :param check_epoch: check intermediate results in every n epochs
        :param early_stop: 1 for early stop, 0 for not.
        :param no_filter: if or not use filters
        :param reg_weight: adversarial penalty weight
        :param d_steps: the number of steps to optimize discriminator
        :param disc_epoch: number of epoch for training extra discriminator
        """
        self.optimizer_name = optimizer
        self.learning_rate = learning_rate
        self.epoch = epoch
        self.batch_size = batch_size
        self.eval_batch_size = eval_batch_size
        self.dropout = dropout
        self.no_dropout = 0.0
        self.l2_weight = l2
        self.reg_weight = reg_weight
        self.d_steps = d_steps
        self.no_filter = no_filter
        self.disc_epoch = disc_epoch

        # convert metrics to list of str
        self.metrics = metrics.lower().split(',')
        self.check_epoch = check_epoch
        self.early_stop = early_stop
        self.time = None

        # record train, validation, test results
        self.train_results, self.valid_results, self.test_results = [], [], []
        self.disc_results = []
        self.num_worker = num_worker

    def _build_optimizer(self, model, lr=None, l2_weight=None):
        optimizer_name = self.optimizer_name.lower()
        if lr is None:
            lr = self.learning_rate
        if l2_weight is None:
            l2_weight = self.l2_weight

        if optimizer_name == 'gd':
            logging.info("Optimizer: GD")
            optimizer = torch.optim.SGD(model.parameters(), lr=lr, weight_decay=l2_weight)
        elif optimizer_name == 'adagrad':
            logging.info("Optimizer: Adagrad")
            optimizer = torch.optim.Adagrad(model.parameters(), lr=lr, weight_decay=l2_weight)
        elif optimizer_name == 'adam':
            logging.info("Optimizer: Adam")
            optimizer = torch.optim.Adam(model.parameters(), lr=lr, weight_decay=l2_weight)
        else:
            logging.error("Unknown Optimizer: " + self.optimizer_name)
            assert self.optimizer_name in ['GD', 'Adagrad', 'Adam']
            optimizer = torch.optim.SGD(model.parameters(), lr=lr, weight_decay=l2_weight)
        return optimizer

    def _check_time(self, start=False):
        if self.time is None or start:
            self.time = [time()] * 2
            return self.time[0]
        tmp_time = self.time[1]
        self.time[1] = time()
        return self.time[1] - tmp_time

    @staticmethod
    def get_filter_mask(filter_num):
        return np.random.choice([0, 1], size=(filter_num,))

    @staticmethod
    def _get_masked_disc(disc_dict, labels, mask):
        if np.sum(mask) == 0:
            return []
        masked_disc_label = [(disc_dict[i + 1], labels[:, i]) for i, val in enumerate(mask) if val != 0]
        return masked_disc_label

    def fit(self, model, batches, fair_disc_dict, epoch=-1):  # fit the results for an input set
        """
        Train the model
        :param model: model instance
        :param batches: train data in batches
        :param fair_disc_dict: fairness discriminator dictionary
        :param epoch: epoch number
        :return: return the output of the last round
        """
        gc.collect()
        torch.cuda.empty_cache()

        if model.optimizer is None:
            model.optimizer = self._build_optimizer(model)
        model.train()

        for idx in fair_disc_dict:
            discriminator = fair_disc_dict[idx]
            if discriminator.optimizer is None:
                discriminator.optimizer = self._build_optimizer(discriminator)
            discriminator.train()

        loss_list = list()
        output_dict = dict()
        eval_dict = None
        for batch in tqdm(batches, leave=False, desc='Epoch %5d' % (epoch + 1),
                          ncols=100, mininterval=1):
            # step1: use filter mask select filters
            # step2: use selected filter filter out the embeddings
            # step3: use the filtered embeddings for recommendation task and get rec loss rec_loss
            # step4: apply the discriminator with the filtered embeddings and get discriminator loss d_loss
            #  (use filter_mask to decide use which discriminator)
            # step5: combine rec_loss and d_loss and do optimization (use filter and rec model optimizer)
            # step6: use discriminator optimizer to optimize discriminator K times
            if self.no_filter:
                mask = [0] * model.num_features
                mask = np.asarray(mask)
            else:
                mask = self.get_filter_mask(model.num_features)

            batch = batch_to_gpu(batch)
            model.optimizer.zero_grad()

            labels = batch['features'][:len(batch['features'])//2, :]
            if not self.no_filter:
                masked_disc_label = \
                    self._get_masked_disc(fair_disc_dict, labels, mask)
            else:
                masked_disc_label = \
                    self._get_masked_disc(fair_disc_dict, labels, mask + 1)

            # calculate recommendation loss + fair discriminator penalty
            result_dict = model(batch, mask)
            rec_loss = result_dict['loss']
            vectors = result_dict['u_vectors']
            vectors = vectors[:len(vectors) // 2, :]

            fair_d_penalty = 0
            if not self.no_filter:
                for fair_disc, label in masked_disc_label:
                    fair_d_penalty += fair_disc(vectors, label)
                fair_d_penalty *= -1
                loss = rec_loss + self.reg_weight * fair_d_penalty
            else:
                loss = rec_loss
            loss.backward()
            model.optimizer.step()

            loss_list.append(result_dict['loss'].detach().cpu().data.numpy())
            output_dict['check'] = result_dict['check']

            # update discriminator
            if not self.no_filter:
                if len(masked_disc_label) != 0:
                    for _ in range(self.d_steps):
                        for discriminator, label in masked_disc_label:
                            discriminator.optimizer.zero_grad()
                            disc_loss = discriminator(vectors.detach(), label)
                            disc_loss.backward(retain_graph=False)
                            discriminator.optimizer.step()

            # collect discriminator evaluation results
            if eval_dict is None:
                eval_dict = self._eval_discriminator(model, labels, vectors.detach(), fair_disc_dict, len(mask))
            else:
                batch_eval_dict = self._eval_discriminator(model, labels, vectors.detach(), fair_disc_dict, len(mask))
                for f_name in eval_dict:
                    new_label = batch_eval_dict[f_name]['label']
                    current_label = eval_dict[f_name]['label']
                    eval_dict[f_name]['label'] = torch.cat((current_label, new_label), dim=0)

                    new_prediction = batch_eval_dict[f_name]['prediction']
                    current_prediction = eval_dict[f_name]['prediction']
                    eval_dict[f_name]['prediction'] = torch.cat((current_prediction, new_prediction), dim=0)

        # generate discriminator evaluation scores
        d_score_dict = {}
        if eval_dict is not None:
            for f_name in eval_dict:
                l = eval_dict[f_name]['label']
                pred = eval_dict[f_name]['prediction']
                n_class = eval_dict[f_name]['num_class']
                d_score_dict[f_name] = self._disc_eval_method(l, pred, n_class)

        output_dict['d_score'] = d_score_dict
        output_dict['loss'] = np.mean(loss_list)
        return output_dict

    def train(self, model, dp_dict, fair_disc_dict, skip_eval=0, fix_one=False):
        """
        Train model
        :param model: model obj
        :param dp_dict: Data processors for train valid and test
        :param skip_eval: number of epochs to skip for evaluations
        :param fair_disc_dict: fairness discriminator dictionary
        :return:
        """
        train_data = DataLoader(dp_dict['train'], batch_size=self.batch_size, num_workers=self.num_worker,
                                shuffle=True, collate_fn=dp_dict['train'].collate_fn)
        validation_data = DataLoader(dp_dict['valid'], batch_size=None, num_workers=self.num_worker,
                                     pin_memory=True, collate_fn=dp_dict['test'].collate_fn)
        test_data = DataLoader(dp_dict['test'], batch_size=None, num_workers=self.num_worker,
                               pin_memory=True, collate_fn=dp_dict['test'].collate_fn)

        self._check_time(start=True)  # start time
        try:
            for epoch in range(self.epoch):
                self._check_time()
                output_dict = \
                    self.fit(model, train_data, fair_disc_dict, epoch=epoch)
                if self.check_epoch > 0 and (epoch == 1 or epoch % self.check_epoch == 0):
                    self.check(model, output_dict)
                training_time = self._check_time()

                if epoch >= skip_eval:
                    valid_result_dict, test_result_dict = None, None
                    if self.no_filter:
                        valid_result = self.evaluate(model, validation_data) if \
                            validation_data is not None else [-1.0] * len(self.metrics)
                        test_result = self.evaluate(model, test_data) \
                            if test_data is not None else [-1.0] * len(self.metrics)
                    else:
                        valid_result, valid_result_dict = \
                            self.eval_multi_combination(model, validation_data, fix_one) \
                            if validation_data is not None else [-1.0] * len(self.metrics)
                        test_result, test_result_dict = self.eval_multi_combination(model, test_data, fix_one) \
                            if test_data is not None else [-1.0] * len(self.metrics)

                    testing_time = self._check_time()

                    # self.train_results.append(train_result)
                    self.valid_results.append(valid_result)
                    self.test_results.append(test_result)
                    self.disc_results.append(output_dict['d_score'])

                    if self.no_filter:
                        logging.info("Epoch %5d [%.1f s]\n validation= %s test= %s [%.1f s] "
                                     % (epoch + 1, training_time,
                                        format_metric(valid_result), format_metric(test_result),
                                        testing_time) + ','.join(self.metrics))
                    else:
                        logging.info("Epoch %5d [%.1f s]\t Average: validation= %s test= %s [%.1f s] "
                                     % (epoch + 1, training_time,
                                        format_metric(valid_result), format_metric(test_result),
                                        testing_time) + ','.join(self.metrics))
                        for key in valid_result_dict:
                            logging.info("validation= %s test= %s "
                                         % (format_metric(valid_result_dict[key]),
                                            format_metric(test_result_dict[key])) + ','.join(self.metrics) +
                                         ' (' + key + ') ')

                    if best_result(self.metrics[0], self.valid_results) == self.valid_results[-1]:
                        model.save_model()
                        for idx in fair_disc_dict:
                            fair_disc_dict[idx].save_model()

                    if self.eva_termination() and self.early_stop == 1:
                        logging.info("Early stop at %d based on validation result." % (epoch + 1))
                        break
                if epoch < skip_eval:
                    logging.info("Epoch %5d [%.1f s]" % (epoch + 1, training_time))
        except KeyboardInterrupt:
            logging.info("Early stop manually")
            save_here = input("Save here? (1/0) (default 0):")
            if str(save_here).lower().startswith('1'):
                model.save_model()
                for idx in fair_disc_dict:
                    fair_disc_dict[idx].save_model()

        # Find the best validation result across iterations
        best_valid_score = best_result(self.metrics[0], self.valid_results)
        best_epoch = self.valid_results.index(best_valid_score)
        # prepare disc result string
        disc_info = self.disc_results[best_epoch]
        disc_info_str = ['{}={:.4f}'.format(key, disc_info[key]) for key in disc_info]
        disc_info_str = ','.join(disc_info_str)
        logging.info("Best Iter(validation)= %5d\t valid= %s test= %s [%.1f s] "
                     % (best_epoch + 1,
                        format_metric(self.valid_results[best_epoch]),
                        format_metric(self.test_results[best_epoch]),
                        self.time[1] - self.time[0]) + ','.join(self.metrics) + ' ' + disc_info_str +
                     ' AUC')
        best_test_score = best_result(self.metrics[0], self.test_results)
        best_epoch = self.test_results.index(best_test_score)
        disc_info = self.disc_results[best_epoch]
        disc_info_str = ['{}={:.4f}'.format(key, disc_info[key]) for key in disc_info]
        disc_info_str = ','.join(disc_info_str)
        logging.info("Best Iter(test)= %5d\t valid= %s test= %s [%.1f s] "
                     % (best_epoch + 1,
                        format_metric(self.valid_results[best_epoch]),
                        format_metric(self.test_results[best_epoch]),
                        self.time[1] - self.time[0]) + ','.join(self.metrics) + ' ' + disc_info_str +
                     ' AUC')
        model.load_model()
        for idx in fair_disc_dict:
            fair_disc_dict[idx].load_model()

    def eval_multi_combination(self, model, data, fix_one=False):
        """
        Evaluate model on validation/test dataset under different filter combinations.
        The output is the averaged result over all the possible combinations.
        :param model: trained model
        :param data: validation or test data (not train data)
        :param fix_one: if true, only evaluate on one feature instead of all the combinations (save running time)
        :return: averaged evaluated result on given dataset
        """
        n_features = model.num_features
        feature_info = model.data_processor_dict['train'].data_reader.feature_info

        if not fix_one:
            mask_list = [list(i) for i in it.product([0, 1], repeat=n_features)]
            mask_list.pop(0)
            # mask_list = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
        else:
            feature_range = np.arange(n_features)
            shape = (feature_range.size, feature_range.max() + 1)
            one_hot = np.zeros(shape).astype(int)
            one_hot[feature_range, feature_range] = 1
            mask_list = one_hot.tolist()
            mask_list = [mask_list[1]]
        result_dict = {}
        acc_result = None
        for mask in mask_list:
            mask = np.asarray(mask)
            feature_idx = np.where(mask == 1)[0]
            f_name_list = [feature_info[i + 1].name for i in feature_idx]
            f_name = ' '.join(f_name_list)

            cur_result = self.evaluate(model, data, mask) if data is not None else [-1.0] * len(self.metrics)
            acc_result = np.array(cur_result) if acc_result is None else acc_result + np.asarray(cur_result)

            result_dict[f_name] = cur_result

        if acc_result is not None:
            acc_result /= len(mask_list)

        return list(acc_result), result_dict

    @torch.no_grad()
    def evaluate(self, model, batches, mask=None, metrics=None):
        """
        evaluate recommendation performance
        :param model:
        :param batches: data batches, each batch is a dict.
        :param mask: filter mask
        :param metrics: list of str
        :return: list of float number for each metric
        """
        if metrics is None:
            metrics = self.metrics
        model.eval()

        if mask is None:
            mask = [0] * model.filter_num
            mask = np.asarray(mask)

        result_dict = defaultdict(list)
        for batch in tqdm(batches, leave=False, ncols=100, mininterval=1, desc='Predict'):
            batch = batch_to_gpu(batch)
            out_dict = model.predict(batch, mask)
            prediction = out_dict['prediction']
            labels = batch[LABEL].cpu()
            sample_ids = batch['X'][:, 2].cpu()
            assert len(labels) == len(prediction)
            assert len(sample_ids == len(prediction))
            prediction = prediction.cpu().numpy()
            data_dict = {LABEL: labels, SAMPLE_ID: sample_ids}
            results = self.evaluate_method(prediction, data_dict, metrics=metrics)
            for key in results:
                result_dict[key].extend(results[key])

        evaluations = []
        for metric in metrics:
            evaluations.append(np.average(result_dict[metric]))

        return evaluations

    @staticmethod
    def evaluate_method(p, data, metrics):
        """
        Evaluate model predictions.
        :param p: predicted values, np.array
        :param data: data dictionary which include ground truth labels
        :param metrics: metrics list
        :return: a list of results. The order is consistent to metric list.
        """
        label = data[LABEL]
        evaluations = {}
        for metric in metrics:
            if metric == 'rmse':
                evaluations[metric] = [np.sqrt(mean_squared_error(label, p))]
            elif metric == 'mae':
                evaluations[metric] = [mean_absolute_error(label, p)]
            elif metric == 'auc':
                evaluations[metric] = [roc_auc_score(label, p)]
            else:
                k = int(metric.split('@')[-1])
                df = pd.DataFrame()
                df[SAMPLE_ID] = data[SAMPLE_ID]
                df['p'] = p
                df['l'] = label
                df = df.sort_values(by='p', ascending=False)
                df_group = df.groupby(SAMPLE_ID)
                if metric.startswith('ndcg@'):
                    ndcgs = []
                    for uid, group in df_group:
                        ndcgs.append(ndcg_at_k(group['l'].tolist()[:k], k=k, method=1))
                    evaluations[metric] = ndcgs
                elif metric.startswith('hit@'):
                    hits = []
                    for uid, group in df_group:
                        hits.append(int(np.sum(group['l'][:k]) > 0))
                    evaluations[metric] = hits
                elif metric.startswith('precision@'):
                    precisions = []
                    for uid, group in df_group:
                        precisions.append(precision_at_k(group['l'].tolist()[:k], k=k))
                    evaluations[metric] = precisions
                elif metric.startswith('recall@'):
                    recalls = []
                    for uid, group in df_group:
                        recalls.append(1.0 * np.sum(group['l'][:k]) / np.sum(group['l']))
                    evaluations[metric] = recalls
                elif metric.startswith('f1@'):
                    f1 = []
                    for uid, group in df_group:
                        num_overlap = 1.0 * np.sum(group['l'][:k])
                        f1.append(2 * num_overlap / (k + 1.0 * np.sum(group['l'])))
                    evaluations[metric] = f1
        return evaluations

    def eva_termination(self):
        """
        Early stopper
        :return:
        """
        metric = self.metrics[0]
        valid = self.valid_results
        if len(valid) > 20 and metric in LOWER_METRIC_LIST and strictly_increasing(valid[-5:]):
            return True
        elif len(valid) > 20 and metric not in LOWER_METRIC_LIST and strictly_decreasing(valid[-5:]):
            return True
        elif len(valid) - valid.index(best_result(metric, valid)) > 20:
            return True
        return False

    @torch.no_grad()
    def _eval_discriminator(self, model, labels, u_vectors, fair_disc_dict, num_disc):
        feature_info = model.data_processor_dict['train'].data_reader.feature_info
        feature_eval_dict = {}
        for i in range(num_disc):
            discriminator = fair_disc_dict[i + 1]
            label = labels[:, i]
            # metric = 'auc' if feature_info[i + 1].num_class == 2 else 'f1'
            feature_name = feature_info[i + 1].name
            discriminator.eval()
            if feature_info[i + 1].num_class == 2:
                prediction = discriminator.predict(u_vectors)['prediction'].squeeze()
            else:
                prediction = discriminator.predict(u_vectors)['output']
            feature_eval_dict[feature_name] = {'label': label.cpu(), 'prediction': prediction.detach().cpu(),
                                               'num_class': feature_info[i + 1].num_class}
            discriminator.train()
        return feature_eval_dict

    @staticmethod
    def _disc_eval_method(label, prediction, num_class, metric='auc'):
        if metric == 'auc':
            if num_class == 2:
                score = roc_auc_score(label, prediction, average='micro')
                # score = roc_auc_score(label, prediction)
                score = max(score, 1 - score)
                return score
            else:
                lb = LabelBinarizer()
                classes = [i for i in range(num_class)]
                lb.fit(classes)
                label = lb.transform(label)
                # label = lb.fit_transform(label)
                score = roc_auc_score(label, prediction, multi_class='ovo', average='macro')
                score = max(score, 1 - score)
                return score
        else:
            raise ValueError('Unknown evaluation metric in _disc_eval_method().')

    def check(self, model, out_dict):
        """
        Check intermediate results
        :param model: model obj
        :param out_dict: output dictionary
        :return:
        """
        check = out_dict
        logging.info(os.linesep)
        for i, t in enumerate(check['check']):
            d = np.array(t[1].detach().cpu())
            logging.info(os.linesep.join([t[0] + '\t' + str(d.shape), np.array2string(d, threshold=20)]) + os.linesep)

        loss, l2 = check['loss'], model.l2()
        l2 = l2 * self.l2_weight
        l2 = l2.detach()
        logging.info('loss = %.4f, l2 = %.4f' % (loss, l2))
        if not (np.absolute(loss) * 0.005 < l2 < np.absolute(loss) * 0.1):
            logging.warning('l2 inappropriate: loss = %.4f, l2 = %.4f' % (loss, l2))

        # for discriminator
        disc_score_dict = out_dict['d_score']
        for feature in disc_score_dict:
            logging.info('{} AUC = {:.4f}'.format(feature, disc_score_dict[feature]))

    def train_discriminator(self, model, dp_dict, fair_disc_dict, lr_attack=None, l2_attack=None):
        """
        Train discriminator to evaluate the quality of learned embeddings
        :param model: trained model
        :param dp_dict: Data processors for train valid and test
        :param fair_disc_dict: fairness discriminator dictionary
        :return:
        """
        train_data = DataLoader(dp_dict['train'], batch_size=dp_dict['train'].batch_size, num_workers=self.num_worker,
                                shuffle=True, collate_fn=dp_dict['train'].collate_fn)
        test_data = DataLoader(dp_dict['test'], batch_size=dp_dict['test'].batch_size, num_workers=self.num_worker,
                               pin_memory=True, collate_fn=dp_dict['test'].collate_fn)
        self._check_time(start=True)  # 记录初始时间s

        feature_results = defaultdict(list)
        best_results = dict()
        try:
            for epoch in range(self.disc_epoch):
                self._check_time()
                output_dict = \
                    self.fit_disc(model, train_data, fair_disc_dict, epoch=epoch,
                                  lr_attack=lr_attack, l2_attack=l2_attack)

                if self.check_epoch > 0 and (epoch == 1 or epoch % (self.disc_epoch // 4) == 0):
                    self.check_disc(output_dict)
                training_time = self._check_time()

                test_result_dict = \
                    self.evaluation_disc(model, fair_disc_dict, test_data, dp_dict['train'])
                d_score_dict = test_result_dict['d_score']
                # testing_time = self._check_time()
                if epoch % (self.disc_epoch // 4) == 0:
                    logging.info("Epoch %5d [%.1f s]" % (epoch + 1, training_time))
                for f_name in d_score_dict:
                    if epoch % (self.disc_epoch // 4) == 0:
                        logging.info("{} AUC= {:.4f}".format(f_name, d_score_dict[f_name]))
                    feature_results[f_name].append(d_score_dict[f_name])
                    if d_score_dict[f_name] == max(feature_results[f_name]):
                        best_results[f_name] = d_score_dict[f_name]
                        idx = dp_dict['train'].data_reader.f_name_2_idx[f_name]
                        fair_disc_dict[idx].save_model()

        except KeyboardInterrupt:
            logging.info("Early stop manually")
            save_here = input("Save here? (1/0) (default 0):")
            if str(save_here).lower().startswith('1'):
                for idx in fair_disc_dict:
                    fair_disc_dict[idx].save_model()

        for f_name in best_results:
            logging.info("{} best AUC: {:.4f}".format(f_name, best_results[f_name]))

        for idx in fair_disc_dict:
            fair_disc_dict[idx].load_model()

    def fit_disc(self, model, batches, fair_disc_dict, epoch=-1, lr_attack=None, l2_attack=None):
        """
        Train the discriminator
        :param model: model instance
        :param batches: train data in batches
        :param fair_disc_dict: fairness discriminator dictionary
        :param epoch: epoch number
        :param lr_attack: attacker learning rate
        :param l2_attack: l2 regularization weight for attacker
        :return: return the output of the last round
        """
        gc.collect()
        torch.cuda.empty_cache()

        for idx in fair_disc_dict:
            discriminator = fair_disc_dict[idx]
            if discriminator.optimizer is None:
                discriminator.optimizer = self._build_optimizer(discriminator, lr=lr_attack, l2_weight=l2_attack)
            discriminator.train()

        output_dict = dict()
        loss_acc = defaultdict(list)

        eval_dict = None
        for batch in tqdm(batches, leave=False, desc='Epoch %5d' % (epoch + 1),
                          ncols=100, mininterval=1):
            if self.no_filter:
                mask = [0] * model.num_features
                mask = np.asarray(mask)
            else:
                mask = self.get_filter_mask(model.num_features)

            batch = batch_to_gpu(batch)

            labels = batch['features']
            if not self.no_filter:
                masked_disc_label = \
                    self._get_masked_disc(fair_disc_dict, labels, mask)
            else:
                masked_disc_label = \
                    self._get_masked_disc(fair_disc_dict, labels, mask + 1)

            # calculate recommendation loss + fair discriminator penalty
            uids = batch['X'] - 1
            vectors = model.apply_filter(model.uid_embeddings(uids), mask)
            output_dict['check'] = []

            # update discriminator
            if len(masked_disc_label) != 0:
                for idx, (discriminator, label) in enumerate(masked_disc_label):
                    discriminator.optimizer.zero_grad()
                    disc_loss = discriminator(vectors.detach(), label)
                    disc_loss.backward()
                    discriminator.optimizer.step()
                    loss_acc[discriminator.name].append(disc_loss.detach().cpu())

        for key in loss_acc:
            loss_acc[key] = np.mean(loss_acc[key])

        output_dict['loss'] = loss_acc
        return output_dict

    @torch.no_grad()
    def evaluation_disc(self, model, fair_disc_dict, test_data, dp):
        num_features = dp.data_reader.num_features

        def eval_disc(labels, u_vectors, fair_disc_dict, mask):
            feature_info = dp.data_reader.feature_info
            feature_eval_dict = {}
            for i, val in enumerate(mask):
                if val == 0:
                    continue
                discriminator = fair_disc_dict[i + 1]
                label = labels[:, i]
                # metric = 'auc' if feature_info[i + 1].num_class == 2 else 'f1'
                feature_name = feature_info[i + 1].name
                discriminator.eval()
                if feature_info[i + 1].num_class == 2:
                    prediction = discriminator.predict(u_vectors)['prediction'].squeeze()
                else:
                    prediction = discriminator.predict(u_vectors)['output']
                feature_eval_dict[feature_name] = {'label': label.cpu(), 'prediction': prediction.detach().cpu(),
                                                   'num_class': feature_info[i + 1].num_class}
                discriminator.train()
            return feature_eval_dict

        eval_dict = {}
        for batch in test_data:
            # VERSION 1
            # if self.no_filter:
            #     # mask = [0] * model.num_features
            #     feature_range = np.arange(num_features)
            #     shape = (feature_range.size, feature_range.max() + 1)
            #     one_hot = np.zeros(shape).astype(int)
            #     one_hot[feature_range, feature_range] = 1
            #     mask_list = one_hot.tolist()
            #     # if num_features == 3:
            #     #     mask_list = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
            #     # elif num_features == 4:
            #     #     mask_list = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
            # else:
            #     mask_list = [list(i) for i in it.product([0, 1], repeat=num_features)]
            #     mask_list.pop(0)

            # VERSION 2
            mask_list = [list(i) for i in it.product([0, 1], repeat=num_features)]
            mask_list.pop(0)

            batch = batch_to_gpu(batch)

            labels = batch['features']
            uids = batch['X'] - 1

            for mask in mask_list:
                if self.no_filter:
                    vectors = model.uid_embeddings(uids)
                else:
                    vectors = model.apply_filter(model.uid_embeddings(uids), mask)
                batch_eval_dict = eval_disc(labels, vectors.detach(), fair_disc_dict, mask)

                for f_name in batch_eval_dict:
                    if f_name not in eval_dict:
                        eval_dict[f_name] = batch_eval_dict[f_name]
                    else:
                        new_label = batch_eval_dict[f_name]['label']
                        current_label = eval_dict[f_name]['label']
                        eval_dict[f_name]['label'] = torch.cat((current_label, new_label), dim=0)

                        new_prediction = batch_eval_dict[f_name]['prediction']
                        current_prediction = eval_dict[f_name]['prediction']
                        eval_dict[f_name]['prediction'] = torch.cat((current_prediction, new_prediction), dim=0)

        # generate discriminator evaluation scores
        d_score_dict = {}
        if eval_dict is not None:
            for f_name in eval_dict:
                l = eval_dict[f_name]['label']
                pred = eval_dict[f_name]['prediction']
                n_class = eval_dict[f_name]['num_class']
                d_score_dict[f_name] = self._disc_eval_method(l, pred, n_class)

        output_dict = dict()
        output_dict['d_score'] = d_score_dict
        return output_dict

    @staticmethod
    def check_disc(out_dict):
        check = out_dict
        logging.info(os.linesep)
        for i, t in enumerate(check['check']):
            d = np.array(t[1].detach().cpu())
            logging.info(os.linesep.join([t[0] + '\t' + str(d.shape), np.array2string(d, threshold=20)]) + os.linesep)

        loss_dict = check['loss']
        for disc_name, disc_loss in loss_dict.items():
            logging.info('%s loss = %.4f' % (disc_name, disc_loss))

        # for discriminator
        if 'd_score' in out_dict:
            disc_score_dict = out_dict['d_score']
            for feature in disc_score_dict:
                logging.info('{} AUC = {:.4f}'.format(feature, disc_score_dict[feature]))


import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import linprog
from pulp import *
import requests
import re
import sys
import cvxopt

recLim = 3500
sys.setrecursionlimit(recLim)

headers = {
    'User-Agent': 'market-tool'
    }
# api url paths
latest_url = 'https://prices.runescape.wiki/api/v1/osrs/latest'
hour_url = 'https://prices.runescape.wiki/api/v1/osrs/1h'

# pull most recent data
getlatest = requests.get(latest_url, headers = headers)
# csv formatting
getlatest = getlatest.text
getlatest = re.sub('":{"high', ',', getlatest)
getlatest = re.sub('},', ',\n', getlatest)
getlatest = re.sub('[^0-9,\n]', '', getlatest)

# pull latest 1 hour average data
gethour = requests.get(hour_url, headers = headers)
# csv formatting
gethour = gethour.text
gethour = re.sub('":{"avgHigh', ',', gethour)
gethour = re.sub('},', ',\n', gethour)
gethour = re.sub('[^0-9,\n]', '', gethour)

store_out = sys.stdout

# write formatted data to files
with open('latest_prices.txt', 'w') as f:
    sys.stdout = f
    print(getlatest)
    sys.stdout = store_out

with open('one_hour_market_data.txt', 'w') as f:
    sys.stdout = f
    print(gethour)
    sys.stdout = store_out

# make pandas dataframes
hour_df = pd.read_csv('one_hour_market_data.txt', names =
                     ['id', 'avg_high', 'high_vol', 'avg_low', 'low_vol', 'delete'])
hour_df = hour_df.drop(columns = ['delete'])
latest_df = pd.read_csv('latest_prices.txt', names =
                        ['id', 'high', 'high_time', 'low', 'low_time', 'delete'])
latest_df = latest_df.drop(columns = ['high_time', 'low_time', 'delete'])

latest_df = latest_df.merge(hour_df, on = ['id'])
latest_id = latest_df['id']

latest_df['Spread'] = latest_df['high'] - latest_df['low']
latest_df['ROI'] = latest_df['Spread'] / latest_df['low']

# read in (mostly) static buy limit data to dataframe
buylim_df = pd.read_json('items-buylimits.json', typ = 'series')
buylim_df.name = 'buy_limit'
itemname_df = pd.read_json('items-summary.json')
itemname_df = itemname_df.transpose()
namemerge = itemname_df.set_index('name')
item_df = namemerge.merge(buylim_df, left_index = True, right_index = True)
item_df = item_df.set_index('id')
item_df = itemname_df.merge(item_df, left_on = ['id'], right_index = True)

latest_df = latest_df.merge(item_df, on = ['id'])
latest_df = latest_df.fillna(0)

temp_array = latest_df.to_numpy()

# calculate important price info
hour_high = temp_array[0:, 3]
hour_low = temp_array[0:, 5]
hour_spread = np.subtract(hour_high, hour_low)

temp_id = temp_array[0:, 0]
temp_low = temp_array[0:, 2]
temp_high_vol = temp_array[0:, 4]
temp_low_vol = temp_array[0:, 6]
temp_spread = temp_array[0:, 1] - temp_low
temp_bl = temp_array[0:, 10]

temp_id = np.int64(temp_id)
temp_bl = np.int64(temp_bl)
temp_low = np.int64(temp_low)
temp_high_vol = np.int64(temp_high_vol)
temp_low_vol = np.int64(temp_low_vol)

# create linear programming model
model = LpProblem(name = 'profit-maximization', sense = LpMaximize)
DV_variablesX = LpVariable.matrix('X', temp_id, cat = 'Integer', lowBound = 0)
DV_variablesY = LpVariable.matrix('Y', temp_id, cat = 'Binary', lowBound = 0)

# maximize for quantity * spread
obj_func = lpSum(DV_variablesX * hour_spread)
model += obj_func

# parameter input
# avalcap: amount of gp available
# maxTrades: number of trade windows available
print("Enter gp available to trade (0-2147483647): ")
capital = int(input())
print("Enter number of windows available (0-8): ")
windows = int(input())
avalcap = np.array([capital])
maxTrades = np.array([windows])

# add constraints to model
model += lpSum((DV_variablesX[i] * hour_low[i]) for i in range(temp_bl.size)) <= avalcap, 'Capital Constraint'
model += lpSum((DV_variablesY[i]) for i in range(temp_bl.size)) <= maxTrades, 'Trade Number Constraint'

# set quantity contraints equal to min(recently traded quantity, buy limit)
for i in range(temp_bl.size):
    model += DV_variablesX[i] <= (temp_bl[i] * DV_variablesY[i]), str(i) + ' Quantity Constraint'

for i in range(temp_bl.size):
    model += DV_variablesX[i] <= (np.minimum(temp_low_vol[i], temp_high_vol[i]) * DV_variablesY[i]), str(i) + ' Hourly Available Quantity'

# run solution
model.writeMPS("model.mps")
model.solve()

status = LpStatus[model.status]

# output result overview
print(status)

solution = np.empty((1, 2))

# output model results into solution array
for v in model.variables():
    if(v.value() > 0):
        v.name = re.sub('X_', '', v.name)
        v.name = re.sub('Y_', '', v.name)
        solution = np.vstack((solution, [int(v.name), v.value()]))

# format solution data
solution = np.delete(solution, 0, axis = 0)
solution = np.delete(solution, np.s_[maxTrades[0] : (maxTrades[0] * 2)], axis = 0)
solution_df = pd.DataFrame(solution, columns = ['id', 'Quantity'])
solution_df = pd.merge(solution_df, latest_df, on = ['id'])
solution_df['Average Spread (1H)'] = (solution_df['avg_high'] - solution_df['avg_low'])
solution_df['Average Profit (1H)'] = solution_df['Average Spread (1H)'] * solution_df['Quantity']
solution_df['Current Profit'] = solution_df['Spread'] * solution_df['Quantity']
solution_df['Volume (1H)'] = solution_df[['high_vol', 'low_vol']].min(axis = 1)
solution_df = solution_df.drop(columns = ['id', 'high', 'avg_high', 'avg_low', 'high_vol', 'low_vol', 'buy_limit'])
solution_df = solution_df.rename(columns = {'low': 'Unit Cost', 'name': 'Name', 'Spread': 'Current Spread', 'ROI': 'Current ROI'})

temp_4h_profit = np.minimum(temp_high_vol, temp_low_vol) * temp_spread * 4
temp_max_profit = temp_spread * temp_bl
temp_bl_profit = np.minimum(temp_4h_profit, temp_max_profit)

# write solution data to csv
solution_df.to_csv('solution.csv')
print(solution_df)


# Definition for a binary tree node.
from typing import Optional

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        self.recurse(root)
        return root

    def recurse(self, node):
        if node == None:
            return
        temp = node.left
        node.left = node.right
        node.right = temp
        self.recurse(node.left)
        self.recurse(node.right)


import cv2
import numpy as np

net = cv2.dnn.readNet("dnn_model/yolov4-tiny.weights", "dnn_model/yolov4-tiny.cfg")

model = cv2.dnn_DetectionModel(net)

model.setInputParams(size = (320, 320), scale = 1/255)

classNamesList = []

with open("dnn_model/classes.txt", "r") as fileObject:
    for className in fileObject.readlines():
        className = className.strip()
        classNamesList.append(className)

# print(classNamesList)
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)

buttonPerson = False
buttonCell = False
buttonRemote = False

color = (200,0,200)
color1 = (200,0,200)
color2 = (200,0,200)

def clickButton(event, x, y, flags, params):
    global buttonPerson, buttonCell, buttonRemote, color, color1, color2
    if event == cv2.EVENT_LBUTTONDOWN:
        print(x,y)

        polygon = np.array([[(20, 20), (210, 20), (210, 70), (20, 70)]])
        polygon1 = np.array([[(20, 80), (220, 80), (210, 130), (20, 130)]])
        polygon2 = np.array([[(20, 140), (220, 140), (210, 190), (20, 190)]])

        isInside = cv2.pointPolygonTest(polygon, (x, y), False)
        isInside1 = cv2.pointPolygonTest(polygon1, (x, y), False)
        isInside2 = cv2.pointPolygonTest(polygon2, (x, y), False)

        if isInside > 0:
            print("inside")

            if buttonPerson is False:
                buttonPerson = True
                color = (0,255,0)
            else:
                buttonPerson = False
                color = (200,0,200)

            print("Person Button: ", buttonPerson)

        if isInside1 > 0:
            print("inside")

            if buttonCell is False:
                buttonCell = True
                color1 = (0,255,0)
            else:
                buttonCell = False
                color1 = (200,0,200)

            print("Cell Button: ", buttonCell)

        if isInside2 > 0:
            print("inside")

            if buttonRemote is False:
                buttonRemote = True
                color2 = (0,255,0)
            else:
                buttonRemote = False
                color2 = (200,0,200)

            print("Remote Button: ", buttonRemote)

# create window
cv2.namedWindow("Frame")
cv2.setMouseCallback("Frame", clickButton)

while True:

    _, frame = cap.read()

    (clasIds, scores, bboxes) = model.detect(frame)

    for classId, score, bbox in zip(clasIds, scores, bboxes):

        score = round(score, 2)
        x, y, w, h = bbox
        objectName = classNamesList[classId]

        if objectName == "person" and buttonPerson is True:
            cv2.putText(frame, f"{objectName}",
                        (x-5, y-20), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)
            cv2.rectangle(frame, (x,y), (x+w, y+h), (0,255,255), 2)

        if objectName == "cell phone" and buttonCell is True:
            cv2.putText(frame, f"{objectName}",
                        (x-5, y-20), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)
            cv2.rectangle(frame, (x,y), (x+w, y+h), (0,255,255), 2)

        if objectName == "remote" and buttonRemote is True:
            cv2.putText(frame, f"{objectName}",
                        (x-5, y-20), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)
            cv2.rectangle(frame, (x,y), (x+w, y+h), (0,255,255), 2)

    # print(f"Class Id: {clasIds}\nSocres: {scores}\nBoundbox: {bboxes}")
    # Create BUtton
    # cv2.rectangle(frame, (20, 20),(210, 70), (200,0,200), -1)
    polygon = np.array([[(20, 20), (220, 20), (210, 70), (20, 70)]])
    cv2.fillPoly(frame, polygon, color)
    cv2.putText(frame, "Person", (30, 60), cv2.FONT_HERSHEY_PLAIN, 3, (255, 255, 255), 3)

    polygon1 = np.array([[(20, 80), (220, 80), (210, 130), (20, 130)]])
    cv2.fillPoly(frame, polygon1, color1)
    cv2.putText(frame, "Phone", (30, 120), cv2.FONT_HERSHEY_PLAIN, 3, (255, 255, 255), 3)

    polygon2 = np.array([[(20, 140), (220, 140), (210, 190), (20, 190)]])
    cv2.fillPoly(frame, polygon2, color2)
    cv2.putText(frame, "Remote", (30, 180), cv2.FONT_HERSHEY_PLAIN, 3, (255, 255, 255), 3)

    cv2.imshow("Frame",frame)

    key = cv2.waitKey(1)

    if key == ord("q"):
        break

cap.release()
cv2.destroyAllWindows()


# Задача 5. Одна семья

family_db = {
    ('Иванов', 'Иван'): 15,
    ('Иванова', 'Елена'): 12,
    ('Иванова', 'Татьяна'): 38,
    ('Иванов', 'Илья'): 45,
    ('Петров', 'Александр'): 46,
    ('Петров', 'Евгений'): 24,
    ('Петрова', 'Алла'): 26,
    ('Петрушина', 'Инга'): 22,
    ('Петрушин', 'Антон'): 24,
    ('Петряков', 'Семен'): 64,
    ('Осокин', 'Владимир'): 65,
    ('Осокина', 'Анастасия'): 47,
    ('Осокин', 'Анатолий'): 36,
    ('Лазарева', 'Елена'): 35,
    ('Лазарев', 'Руслан'): 38,
    ('Лазарева', 'Ольга'): 18,
    ('Федотов', 'Геннадий'): 48,
    ('Федотова', 'Ирина'): 44,
    ('Федотов', 'Иван'): 28
}

def enter_string():
    while True:
        user_string = input('Введите Фамилию Имя и возраст человека для добавления через пробел:').strip().split(' ')
        if len(user_string) != 3:
            print('Ошибка ввода. Проверьте вводимые данные. Количество элементов в строке не равно 3-м.')
        elif user_string[0].isdigit() or user_string[1].isdigit():
            print('Ошибка ввода. В фамилии и имени не должно быть цифр')
        elif user_string[2].isalpha():
            print('Ошибка ввода. Возраст не может содержать буквы.')
        else:
            return tuple(user_string[:2]), int(user_string[2])

def enter_iteration():
    while True:
        user_number = input('Введите количество добавляемых людей: ')
        if not user_number.isdigit():
            print('Ошибка ввода. Ожидается ввод только числового значения.')
        else:
            return int(user_number)

def enter_variant():
    print('В программе предустановленная база данных.\nВы можете использовать ее или создать новую. ')
    print('Чтобы создать новую базу данных - введите \'Y\' и нажмите \'Enter\'.')
    print('Чтобы продолжить использовать имеющуюся базу - нажмите \'Enter\'.')
    number = input('Ваш выбор: ')
    if number.lower() == 'y':
        return True
    else:
        return False

def check_name_surname(data_tuple, db_dict):
    if data_tuple in db_dict.keys():
        return True
    else:
        return False

def check_enter():
    while True:
        user_string = input('Введите фамилию: ')
        if user_string.isdigit():
            print('Ошибка ввода. Имя не должно содержать цифр.')
        else:
            return user_string

if enter_variant():
    family_db.clear()
    for _ in range(enter_iteration()):
        data_name_surname, age = enter_string()
        check_name_surname(data_name_surname, family_db)

surname = check_enter().capitalize()
keys_found = [surname_in_db for surname_in_db in family_db.keys() if surname_in_db[0].startswith(surname)]
if len(keys_found) > 0:
    print()
    for key in keys_found:
        print(f'{key[0]} {key[1]} {family_db[key]}')
else:
    print('Ничего не найдено.')


from typing import List

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def findFrequentTreeSum(root: TreeNode) -> List[int]:
    res, count = [], {}

    def dfs(node):
        nonlocal res
        if not node:
            return 0
        left_num = dfs(node.left)
        right_num = dfs(node.right)
        total = node.val + left_num + right_num
        if not res or count.get(total, 0) + 1 == count[res[0]]:
            res.append(total)
        elif count.get(total, 0) + 1 > count[res[0]]:
            res = [total]
        count[total] = count.get(total, 0) + 1

        return total

    dfs(root)
    return res


favorite_languages = {
'jen': ['python','ruby'],
'sarah': ['c'],
'edward': ['ruby', 'go'],
'phil': ['python','haskell'],
}

for name, langauges in favorite_languages.items():
	print(f"\n{name.title()}'s favorite langauges are:")
	for langauge in langauges:
		print(f"\t{langauge.title()}")

Python crach course October/Chap06/favorite_languages2.py


n=int(input())
m={}
for i in range(n):
    x=list(input().split())
    x1=x[0]
    x2=x[1::]
    y1=0
    for j in range(len(x2)):
        y1=y1+float(x2[j])
    average=(y1/len(x2))
    m[x1]=average

name=input()
for k in m:
    if name == k:
        print("{0:.2f}".format(m[k]))


# Needed
from docker import from_env
from unittest import TestCase

# Not Needed  (Example Only)
from typing import Iterable
from docker import DockerClient
from docker.models.containers import Container
from docker.models.images import Image
from pathlib import Path

class ExplainedExampleTest(TestCase):
	"""
	This class is an testing of a generated test class.
	This serves as a demonstration of the template.
	This class is not actually used.

	The type hints are not necessary, and do not need to be included in the generated test files;
	they are simply here to help explain this testing.
	"""
	# Class Attributes
	client:	DockerClient
	image:	Image
	logs:	Iterable

	# Instance Attributes
	container: Container

	@classmethod
	def setUpClass(cls):
		dockerfile = Path()									# variable
		dockerfile_dir = repr(str(dockerfile.parent))  		# inferred variable
		dockerfile_sub_path = repr(dockerfile.name)  		# inferred variable
		cls.client = from_env()								# Generated Line
		cls.image, cls.logs = cls.client.images.build(path=dockerfile_dir, dockerfile=dockerfile_sub_path, rm=True, forcerm=True)  # Generated Line

	@classmethod
	def tearDownClass(cls):
		cls.client.images.remove(image=cls.image.id, force=True)  # Generated Line

	def setUp(self):
		cls = type(self)  # could also have a class_name variable (instead of this line)  ;  Generated Line
		self.container = cls.client.containers.run(cls.image, detach=True, tty=True)  # Generated Line
		# use the line below instead of the line above if a mount point
		# self.container = cls.client.containers.create(cls.image, detach=True, volumes={'<path_in_main_container>': {'bind': '<path_inside_container>', 'mode': 'rw'}})
		# self.container.put_archive()  # insert files into the container

	def tearDown(self):
		# self.container.get_archive(...)	# extract a specific folder from the container
		# self.container.export(...)		# extract all files from the container
		self.container.remove(force=True)  	# Kill and Remove the container  ;  Generated Line

	def test_dont_verify(self):
		cmd = ...  					# variable ; line not generated
		self.container.exec_run(cmd, stdout=False, stderr=False)  # Generated Line

	def test_verify_no_output(self):
		cmd = ...  					# variable ; line not generated
		exit_code, output = self.container.exec_run(cmd, stdout=True, stderr=True)  # Generated Line
		self.assertFalse(output)  	# allows none or empty string (assertIsNone only allows none)  ;  Generated Line

	def test_verify_with_regex(self):
		cmd = ...  					# variable ; line not generated
		output_regex: str = ...  	# variable ; line not generated
		exit_code, output = self.container.exec_run(cmd, stdout=True, stderr=True)  # Generated Line
		self.assertRegex(output.decode(), output_regex)  # Generated Line


def nextMove(n,r,c,grid):
    p = []
    m = [r, c]
    for index, val in enumerate(grid):
        for i in range(n):
            if val[i] == 'p':
                p.append(index)
                p.append(i)

    if abs(m[1] - p[1]) > abs(m[0] - p[0]) or m[1] == p[1]:
        return "RIGHT" if m[1] - p[1] < 0 else "LEFT"
    else:
        return "DOWN" if m[0] < p[0] else "UP"

n = int(input())
r,c = [int(i) for i in input().strip().split()]
grid = []
for i in range(0, n):
    grid.append(input())

print(nextMove(n,r,c,grid))

Artificial Intelligence/Bot saves princess - 2.py


from aiogram.types import ReplyKeyboardMarkup, KeyboardButton, InlineKeyboardMarkup, InlineKeyboardButton
from ..languages import get_json_name

# --- Language setup ---
b_rus = KeyboardButton('ЪЄиЪЄ║ russian')
b_eng = KeyboardButton('ЪЈ┤заЂДзаЂбзаЂЦзаЂ«заЂДзаЂ┐ english')
kb_language = ReplyKeyboardMarkup(resize_keyboard=True, ).row(b_rus, b_eng)

# --- Main display ---
def kb_menu(user_lang):
    b_menu = KeyboardButton(get_json_name(user_lang, 'menu'))
    b_setting_lang = KeyboardButton(get_json_name(user_lang, 'languages'))
    b_statistic = KeyboardButton(get_json_name(user_lang, 'statistic'))
    return ReplyKeyboardMarkup(resize_keyboard=True, )\
        .row(b_menu, b_setting_lang).row(b_statistic)

# --- Menu buttons ---

def kb_menu_details(user_lang):
    b_settings = KeyboardButton(get_json_name(user_lang, 'settings'))
    menu_buttons = get_json_name(user_lang, 'year_goals',
                                 'month_goals', 'week_goals',
                                 'tomorrow_goals', 'today_goals')
    menu_buttons = [KeyboardButton(i) for i in menu_buttons]
    return ReplyKeyboardMarkup(resize_keyboard=True, ).row(
        menu_buttons[1], menu_buttons[0])\
        .row(menu_buttons[3], menu_buttons[2])\
        .row(menu_buttons[4], b_settings)

def kb_cancel(user_lang):
    b_cancel = KeyboardButton(get_json_name(user_lang, 'cancel'))
    return ReplyKeyboardMarkup(resize_keyboard=True, ).row(b_cancel)

# --- Nav_menu_but ---add, delete goals

def kb_nav(user_lang):
    b_back = KeyboardButton(get_json_name(user_lang, 'back'))
    b_add = KeyboardButton(get_json_name(user_lang, 'add_goal'))
    b_get_goals = KeyboardButton(get_json_name(user_lang, 'get_goals'))
    return ReplyKeyboardMarkup(resize_keyboard=True, )\
        .row(b_add).row(b_back, b_get_goals)


import allure
import jsonschema
from allure_commons._allure import step
from allure_commons.types import Severity

from tests.conftest import post_new_user_params, reqres_api
from utils import load_schema

@allure.title('POST user: Status code is 201')
@allure.label('owner', 'AngPawl')
@allure.tag('smoke tests')
@allure.severity(Severity.CRITICAL)
def test_status_code_is_ok():
    response = reqres_api(url='/users', method='post', json=post_new_user_params)

    with step('Status code is 201'):
        assert (
            response.status_code == 201
        ), f"Status code {response.status_code} is incorrect"

@allure.title('POST user: Response schema is valid')
@allure.label('owner', 'AngPawl')
@allure.tag('smoke tests')
@allure.severity(Severity.CRITICAL)
def test_schema_is_valid():
    schema = load_schema('reqres', 'post_user.json')

    response = reqres_api(url='/users', method='post', json=post_new_user_params)

    with step('Response schema is valid'):
        jsonschema.validate(response.json(), schema)

@allure.title('POST user: Response data contains correct values')
@allure.label('owner', 'AngPawl')
@allure.tag('smoke tests')
@allure.severity(Severity.CRITICAL)
def test_response_data_is_valid():
    response = reqres_api(url='/users', method='post', json=post_new_user_params)

    with step('Response data contains correct values'):
        assert (
            response.json()['name'] == post_new_user_params['name']
        ), f"Response data contains incorrect value: {response.json()['name']}"
        assert (
            response.json()['job'] == post_new_user_params['job']
        ), f"Response data contains incorrect value: {response.json()['job']}"


import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.cuda.amp as amp
from math import exp

# Dice and focal losses taken from (and slightly modified):
# https://github.com/CoinCheung/pytorch-loss/blob/master/focal_loss.py

# Focal-Tversky loss taken from:
# https://github.com/Mr-TalhaIlyas/Loss-Functions-Package-Tensorflow-Keras-PyTorch

# Focal-Tversky loss
class FocalTverskyLoss(nn.Module):
    def __init__(self, weight=None, size_average=True):
        super(FocalTverskyLoss, self).__init__()

    def forward(self, inputs, targets, smooth=1, alpha=0.5, beta=0.5, gamma=1.0):

        #comment out if your model contains a sigmoid or equivalent activation layer
        inputs = torch.sigmoid(inputs)

        #flatten label and prediction tensors
        inputs = inputs.view(-1)
        targets = targets.view(-1)

        #True Positives, False Positives & False Negatives
        TP = (inputs * targets).sum()
        FP = ((1 - targets) * inputs).sum()
        FN = (targets * (1 - inputs)).sum()

        tversky = (TP + smooth) / (TP + alpha * FP + beta * FN + smooth)
        focal_tversky = (1 - tversky) ** gamma

        return focal_tversky

# Generalized soft dice loss
class DiceLoss(nn.Module):
    def __init__(self, p=1, smooth=1, reduction='mean', weight=None):
        super(DiceLoss, self).__init__()
        self.p = p
        self.smooth = smooth
        self.reduction = reduction
        self.weight = None if weight is None else torch.tensor(weight).cuda()

    def forward(self, probs, label):
        '''
        args: probs: tensor of shape (N, C, H, W)
        args: label: tensor of shape(N, C, H, W)
        '''
        numer = torch.sum((probs * label), dim=(2, 3))
        denom = torch.sum(probs.pow(self.p) + label.pow(self.p), dim=(2, 3))
        if not self.weight is None:
            numer = numer * self.weight.view(1, -1)
            denom = denom * self.weight.view(1, -1)
        # numer = torch.sum(numer, dim=1)
        # denom = torch.sum(denom, dim=1)
        loss = 1 - (2 * numer + self.smooth)/(denom + self.smooth)
        if self.reduction == 'mean':
            loss = loss.mean()
        return loss

class FocalSigmoidLossFuncV2(torch.autograd.Function):
    '''
    compute backward directly for better numeric stability
    '''
    @staticmethod
    @amp.custom_fwd(cast_inputs=torch.float32)
    def forward(ctx, logits, label, alpha, gamma):

        probs = torch.sigmoid(logits)
        coeff = (label - probs).abs_().pow_(gamma).neg_()
        log_probs = torch.where(logits >= 0,
                F.softplus(logits, -1, 50),
                logits - F.softplus(logits, 1, 50))
        log_1_probs = torch.where(logits >= 0,
                -logits + F.softplus(logits, -1, 50),
                -F.softplus(logits, 1, 50))
        ce_term1 = log_probs.mul_(label).mul_(alpha)
        ce_term2 = log_1_probs.mul_(1. - label).mul_(1. - alpha)
        ce = ce_term1.add_(ce_term2)
        loss = ce * coeff

        ctx.vars = (coeff, probs, ce, label, gamma, alpha)

        return loss

    @staticmethod
    @amp.custom_bwd
    def backward(ctx, grad_output):
        '''
        compute gradient of focal loss
        '''
        (coeff, probs, ce, label, gamma, alpha) = ctx.vars

        d_coeff = (label - probs).abs_().pow_(gamma - 1.).mul_(gamma)
        d_coeff.mul_(probs).mul_(1. - probs)
        d_coeff = torch.where(label < probs, d_coeff.neg(), d_coeff)
        term1 = d_coeff.mul_(ce)

        d_ce = label * alpha
        d_ce.sub_(probs.mul_((label * alpha).mul_(2).add_(1).sub_(label).sub_(alpha)))
        term2 = d_ce.mul(coeff)

        grads = term1.add_(term2)
        grads.mul_(grad_output)

        return grads, None, None, None

class FocalLoss(nn.Module):

    def __init__(self,
                 alpha=0.25,
                 gamma=2,
                 reduction='mean'):
        super(FocalLoss, self).__init__()
        self.alpha = alpha
        self.gamma = gamma
        self.reduction = reduction

    def forward(self, logits, label):
        '''
        Usage is same as nn.BCEWithLogits:
            >>> criteria = FocalLoss()
            >>> logits = torch.randn(8, 19, 384, 384)
            >>> lbs = torch.randint(0, 2, (8, 19, 384, 384)).float()
            >>> loss = criteria(logits, lbs)
        '''
        loss = FocalSigmoidLossFuncV2.apply(logits, label, self.alpha, self.gamma)
        if self.reduction == 'mean':
            loss = loss.mean()
        if self.reduction == 'sum':
            loss = loss.sum()
        return loss

bce_loss_fn = nn.BCEWithLogitsLoss()
mse_loss_fn = nn.MSELoss()
mae_loss_fn = nn.L1Loss()
foc_loss_fn = FocalLoss(alpha=0.5, gamma=2.0, reduction='mean')  # FocalTverskyLoss()
dic_loss_fn = DiceLoss()

def loss_fn(E_seq, S_seq, S_seq_true, pred_flag=True, split_flag='train'):
    ''' Compute loss for a batch of sequences

    Args:
    -----
    '''

    n_frames = S_seq_true.shape[-1]
    device = S_seq_true.device
    S_seq_true = [S_seq_true[..., t] for t in range(n_frames)]
    time_weight = [1.0 if t > 0 else 0.0 for t in range(n_frames)]
    total_loss = torch.tensor(0.0, device=device)
    for t, (E, S, S_true) in enumerate(zip(E_seq, S_seq, S_seq_true)):

        # Sum of prediction error signals (self-supervised)
        # E[0] is next frame prediction error
        pred_loss = 0.0 if E is None else sum([torch.mean(e) for e in E])

        # Segmentation prediction loss (supervised)
        seg_loss = dic_loss_fn(S, S_true)  # + foc_loss_fn(S, S_true)

        # Account for prediction error only in training mode
        if pred_flag and not split_flag == 'train':
            frame_loss = seg_loss + pred_loss
        else:
            frame_loss = seg_loss  # (seg_loss if seg_loss > 0 else 0.0)

        # Weight loss differently for each frame
        if (split_flag == 'test' and t > 20) \
        or (split_flag == 'val' and t > 5) \
        or (split_flag == 'train' and t > 0):
            total_loss = total_loss + frame_loss * time_weight[t]

    return total_loss / n_frames


import pygame
import gui
import constructor
import recursos
import player
import enemigos
import ataques
import elements

def main():

	#inicio basico del juego
	pygame.init()
	xpan=1200
	ypan=700
	pantalla=pygame.display.set_mode((xpan,ypan))
	salir=False
	reloj1=pygame.time.Clock()
	player1=player.player(ypan/2,xpan/2)#llamo a la clase player,hereda self e imagen y metodos
	cursor1=elements.cursor()
	ataquecuerpo=ataques.ataque_melee()

	tiendacomida=gui.tienda_comidas()
	tiendahechizos=gui.tienda_hechizos()
	tiendaarmas1=gui.tienda_armas1()

	menucirular=gui.menu_circulo()

	menuabro=False

	lobo1=enemigos.lobo_enemigo(450,2200,-170,-170)
	oso1=enemigos.oso_enemigo(800,3000,-100,-100)
	#asset_url18=resource_path("C:/Users/T-800/Desktop/Proyectos Python/Pygame/testexe/imagenes/7.mp3")

	#pygame.mixer.music.load(asset_url18)
	#pygame.mixer.music.play(-1)
	fondo1=elements.fondo()

	global tiempo
	global intervalo

	ataquemelee=False
	clickizquierdo=False
	tiendaactiva1,tiendaactiva2,tiendaactiva3=False,False,False
	hechizosactivo,inventarioactivo=False,False
	Dopreta,Rapreta,Lapreta,Upreta=False,False,False,False
	tiempo=0
	intervalo=0

	def reloj_tiempo():
		global tiempo
		cont=6
		if cont==tiempo:
			tiempo=0

	def reloj_intervalo():
		global intervalo
		cont=100
		if cont==intervalo:
			intervalo=0

	#--------variables que suavizan movimiento

	vx=0
	vy=0#aca defino los vectores de la velocidad
	rect_update=pygame.Rect(0,0,1200,700)

	#------------------------------defino la GUI
	imagen_hechizos=recursos.ventanahechizos.convert()
	hechizos_menu=gui.menu_hechizos(imagen_hechizos,800,448)

	usuariointerfaz=gui.interfaz_usuario(0,0)
	equipamento_cuadro=gui.equipamento(120,120)
	inventario_cuadro=gui.inventario(140,180)

	vida_barra=recursos.barravida.convert()
	barra_vida=gui.barras_estado(vida_barra,127,38)

	mana_barra=recursos.barramana.convert()
	barra_mana=gui.barras_estado(mana_barra,127,63)

	exp_barra=recursos.barraexp.convert()
	barra_exp=gui.barras_exp(exp_barra,141,101)

	#-------------------grupos de sprites y lista de la interfaz
	lista_anclado=[]
	lista_techos=pygame.sprite.Group()
	lista_puertas=pygame.sprite.Group()
	lista_pisos_puertas_techos=pygame.sprite.Group()
	lista_pisos=pygame.sprite.Group()
	lista_paredatras=pygame.sprite.Group()
	lista_paredescostado=pygame.sprite.Group()
	lista_paredfrente=pygame.sprite.Group()
	lista_bloqueofrente=pygame.sprite.Group()
	lista_sprites_fijos=pygame.sprite.Group()
	lista_enemigos=[]

	#------------------llamo al constructor de cosas
	#----------------------casas
	casa1_techo=constructor.obrero(630,295,recursos.techocasa2,0,0)
	casa1_puerta=constructor.obrero(648,446,recursos.puertascasa2,0,0)
	casa1_piso=constructor.obrero(635,350,recursos.pisocasa2,0,0)
	casa1_paredatras=constructor.obrero(634,352,recursos.paredatrascasa2,0,-40)
	casa1_paredcostadoiz=constructor.obrero(634,352,recursos.paredcostadocasa2,0,-50)
	casa1_paredcostadoder=constructor.obrero(806,352,recursos.paredcostadocasa2,0,-50)
	casa1_paredfrente=constructor.obrero(633,446,recursos.paredcasa2,0,-50)
	casa1_bloqueofrente=constructor.obrero(650,500,recursos.bloqueofrentecasa2,0,-5)

	casa2_techo=constructor.obrero(600,695,recursos.techocasa2,0,0)
	casa2_puerta=constructor.obrero(618,846,recursos.puertascasa2,0,0)
	casa2_piso=constructor.obrero(605,750,recursos.pisocasa2,0,0)
	casa2_paredatras=constructor.obrero(604,752,recursos.paredatrascasa2,0,-40)
	casa2_paredcostadoiz=constructor.obrero(604,752,recursos.paredcostadocasa2,0,-50)
	casa2_paredcostadoder=constructor.obrero(776,752,recursos.paredcostadocasa2,0,-50)
	casa2_paredfrente=constructor.obrero(603,846,recursos.paredcasa2,0,-50)
	casa2_bloqueofrente=constructor.obrero(620,900,recursos.bloqueofrentecasa2,0,-5)

	casa3_techo=constructor.obrero(1050,600,recursos.techocasa3,0,0)
	casa3_puerta=constructor.obrero(1050,834,recursos.puertascasa3,0,0)
	casa3_piso=constructor.obrero(1050,670,recursos.pisocasa3,0,0)
	casa3_paredatras=constructor.obrero(1050,670,recursos.paredatrascasa3,0,-40)
	casa3_paredcostadoiz=constructor.obrero(1050,670,recursos.paredcostadocasa3,0,-30)
	casa3_paredcostadoder=constructor.obrero(1350,670,recursos.paredcostadocasa3,0,-30)
	casa3_paredfrente=constructor.obrero(1050,834,recursos.paredcasa3,0,-50)
	casa3_bloqueofrente=constructor.obrero(0,0,recursos.bloqueofrentecasa3,0,-5)

	#--------------fences

	fence_costado1=constructor.obrero(380,180,recursos.fencecostado,0,-30)
	fence_frente1=constructor.obrero(381,235,recursos.fencefrente,0,0)
	fence_costado2=constructor.obrero(380,650,recursos.fencecostado2,0,-30)
	fence_frente2=constructor.obrero(381,1640,recursos.fencefrente,0,0)
	fence_costado3=constructor.obrero(1398,180,recursos.fencecostado,0,-30)
	fence_costado4=constructor.obrero(1398,650,recursos.fencecostado2,0,-30)

	#------------------decoracion

	pino1=constructor.obrero(850,350,recursos.pino,-30,-30)
	pajeral1=constructor.obrero(800,800,recursos.pajeral1,-30,-30)
	cajoncomi1=constructor.obrero(520,880,recursos.cajoncomi,0,-50)
	cajonagua1=constructor.obrero(430,880,recursos.cajonagua,0,-50)
	carretilla1=constructor.obrero(450,780,recursos.carretilla,-30,-30)
	cama1=constructor.obrero(650,390,recursos.cama1,-5,-20)
	biblio1=constructor.obrero(770,360,recursos.biblio1,-5,-15)
	sofa1=constructor.obrero(730,380,recursos.sofa1,-5,-30)
	mesaluz1=constructor.obrero(690,400,recursos.mesa_luz1,-5,-30)
	cuadro1=constructor.obrero(690,360,recursos.cuadro1,-5,-30)
	cama2=constructor.obrero(620,790,recursos.cama1,-5,-20)
	biblio2=constructor.obrero(740,760,recursos.biblio1,-5,-15)
	sofa2=constructor.obrero(700,780,recursos.sofa1,-5,-30)
	mesaluz2=constructor.obrero(660,800,recursos.mesa_luz1,-5,-30)
	cuadro2=constructor.obrero(660,760,recursos.cuadro1,-5,-30)
	cajagrande1=constructor.obrero(550,1048,recursos.caja3,0,-40)
	caja1=constructor.obrero(435,1220,recursos.caja1,0,-40)
	bolsas1=constructor.obrero(530,1220,recursos.bolsas2,0,-40)
	bolsas2=constructor.obrero(675,1220,recursos.bolsas2,0,-40)
	caja2=constructor.obrero(770,1220,recursos.caja2,0,-40)
	caja3=constructor.obrero(675,1070,recursos.caja2,0,-40)
	caja4=constructor.obrero(770,1070,recursos.caja1,0,-40)
	pino2=constructor.obrero(460,650,recursos.pino,-30,-30)
	pino3=constructor.obrero(1000,1000,recursos.pino,-30,-30)
	pino4=constructor.obrero(1250,1100,recursos.pino,-30,-30)
	ropas1=constructor.obrero(1000,450,recursos.ropas,0,-40)
	ropas2=constructor.obrero(1050,1400,recursos.ropas,0,-40)
	excusado1=constructor.obrero(1320,350,recursos.excusado1,0,-40)
	excusado2=constructor.obrero(1050,1500,recursos.excusado1,0,-40)
	hacha1=constructor.obrero(1300,500,recursos.hacha,0,-20)
	pozoagua1=constructor.obrero(1170,1120,recursos.pozoagua,-20,-20)

	#------------puestos y casas fijas

	casafija1=constructor.obrero(1100,300,recursos.casa1,0,-40)
	casafija2=constructor.obrero(670,1400,recursos.casa2,0,-40)
	casafija1b=constructor.obrero(450,1400,recursos.casa1,0,-40)
	casafija1c=constructor.obrero(1150,1400,recursos.casa1,0,-40)
	puestoarmas1=constructor.obrero(450,1000,recursos.puestoarmas,0,-40)
	puestovacio1=constructor.obrero(700,1050,recursos.puestovacio,0,-40)
	puestomagia1=constructor.obrero(460,1200,recursos.puestomagia,0,-40)
	puestocomidas1=constructor.obrero(700,1200,recursos.puestocomidas,0,-40)
	puestotecho1=constructor.obrero(700,1000,recursos.puestotecho,0,0)
	puestotecho2=constructor.obrero(460,1150,recursos.puestotecho,0,0)
	puestotecho3=constructor.obrero(700,1150,recursos.puestotecho,0,0)

	#-----------------------agrego a la lista de la interfaz y a los grupos los sprites

	lis_pisos_puertas_techos=(casa1_techo,casa1_puerta,casa1_piso,casa2_techo,casa2_puerta,casa2_piso,
		casa3_techo,casa3_puerta,casa3_piso,puestotecho1,puestotecho2,puestotecho3)
	for i in lis_pisos_puertas_techos:
		lista_pisos_puertas_techos.add(i)

	lis_sprites_fijos=(fence_costado1,fence_frente1,pino1,pajeral1,cajoncomi1,cajonagua1,
	carretilla1,cama1,biblio1,sofa1,mesaluz1,cuadro1,cama2,biblio2,sofa2,mesaluz2,cuadro2,fence_costado2,
	fence_frente2,fence_costado3,fence_costado4,casafija1,casafija2,casafija1b,puestoarmas1,puestovacio1,puestomagia1,
	puestocomidas1,cajagrande1,caja1,bolsas1,bolsas2,caja2,caja3,caja4,pino2,pino3,pino4,ropas1,ropas2,casafija1c,
	excusado1,excusado2,hacha1,pozoagua1)
	for i in lis_sprites_fijos:
		lista_sprites_fijos.add(i)

	lis_enemigos=(lobo1,oso1)
	for i in lis_enemigos:
		lista_enemigos.append(i)

	lis_techos=(casa1_techo,casa2_techo,casa3_techo,puestotecho1,puestotecho2,puestotecho3)
	lis_puertas=(casa1_puerta,casa2_puerta,casa3_puerta)
	lis_pisos=(casa1_piso,casa2_piso,casa3_piso)
	lis_paredatras=(casa1_paredatras,casa2_paredatras,casa3_paredatras)
	lis_paredescostado=(casa1_paredcostadoder,casa1_paredcostadoiz,casa2_paredcostadoder,casa2_paredcostadoiz,casa3_paredcostadoder,casa3_paredcostadoiz)
	lis_paredfrente=(casa1_paredfrente,casa2_paredfrente,casa3_paredfrente)
	lis_bloqueofrente=(casa1_bloqueofrente,casa2_bloqueofrente,casa3_bloqueofrente)

	for i in lis_techos:
 		lista_techos.add(i)
	for i in lis_puertas:
 		lista_puertas.add(i)
	for i in lis_pisos:
 		lista_pisos.add(i)
	for i in lis_paredatras:
 		lista_paredatras.add(i)
	for i in lis_paredescostado:
 		lista_paredescostado.add(i)
	for i in lis_paredfrente:
 		lista_paredfrente.add(i)
	for i in lis_bloqueofrente:
 		lista_bloqueofrente.add(i)

#---------------------------listas actualizan el movimiento en el lugar sin colision
	lista_todos_sprites=pygame.sprite.Group()
	lista_todos_sprites.add(lista_sprites_fijos)
	lista_todos_sprites.add(lista_paredatras)
	lista_todos_sprites.add(lista_paredescostado)
	lista_todos_sprites.add(lista_paredfrente)
	lista_todos_sprites.add(lista_bloqueofrente)
	lista_todos_sprites.add(lista_pisos_puertas_techos)

	global velocidad
	velocidad=10#---------------------aca defino el valor de la velocidad

	#-----------------------sonido del click
	#sonido_click1=pygame.mixer.Sound(recursos.clickson)

	#------------------------bucle while todo los eventos y animaciones aca adentro
	while salir!=True:
		for event in pygame.event.get():
			if event.type==pygame.QUIT:
				salir=True
			if event.type==pygame.KEYDOWN:#----------------movimiento suavizado con teclas
				if event.key==pygame.K_a:
					Lapreta=True#---------------avisa que esta apretada
				if event.key==pygame.K_d:
					Rapreta=True
				if event.key==pygame.K_w:
					Upreta=True
				if event.key==pygame.K_s:
					Dopreta=True
				if event.key==pygame.K_f:
					menuabro=True
				if event.key==pygame.K_LCTRL:
					ataquemelee=True

			if event.type==pygame.KEYUP:
				if event.key==pygame.K_a:
					Lapreta=False
					#------------------avisa que no esta apretada
				if event.key==pygame.K_d:
					Rapreta=False
				if event.key==pygame.K_w:
					Upreta=False
				if event.key==pygame.K_s:
					Dopreta=False
				if event.key==pygame.K_f:
					menuabro=False
				if event.key==pygame.K_LCTRL:
					ataquemelee=False

			if event.type==pygame.KEYDOWN:
				if event.key==pygame.K_ESCAPE:
					tiendaactiva1=False
					tiendacomida.listacompra=[0,0,0,0,0,0,0,0,0]
					tiendacomida.itemscant=[0,0,0,0,0,0,0,0,0]
					tiendacomida.cantitems=0

					tiendaactiva2=False
					tiendahechizos.listacompra=[0,0,0,0,0,0,0,0,0]
					tiendahechizos.itemscant=[0,0,0,0,0,0,0,0,0]
					tiendahechizos.cantitems=0

					tiendaactiva3=False
					tiendaarmas1.listacompra=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
					tiendaarmas1.itemscant=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
					tiendaarmas1.cantitems=0

			if event.type==pygame.MOUSEBUTTONDOWN:
				if event.button==1:
					clickizquierdo=True

		tiempo+=1
		intervalo+=1
		reloj_intervalo()
		reloj_tiempo()
		reloj1.tick(60)

		#-----------------rellena el display con un color negro
		pantalla.fill((0,0,0))
		#-----------------dibuja el fondo del mapa
		fondo1.update(pantalla,vx,vy)

		#-------------------mueve todas las listas
		for i in lista_todos_sprites:
			i.rect.move_ip(-vx,-vy)

		#--------------------orden de dibujado sobre la pantalla y condiciones de colision/dibujo
		lista_pisos.draw(pantalla)
		lista_paredatras.draw(pantalla)
		lista_sprites_fijos.draw(pantalla)
		lista_paredescostado.draw(pantalla)
		if not pygame.sprite.spritecollide(player1,lista_paredfrente,False):
			lista_paredfrente.draw(pantalla)
		player1.update(pantalla,tiempo,fondo1.rect.left,fondo1.rect.top,Dopreta,Upreta,Rapreta,Lapreta)
		lista_puertas.draw(pantalla)

		if not pygame.sprite.spritecollide(player1,lista_techos,False):
			lista_techos.draw(pantalla)

		if pygame.sprite.spritecollide(player1,lista_techos,False) and pygame.sprite.spritecollide(player1,lista_paredfrente,False):
			lista_bloqueofrente.draw(pantalla)

		#--------------------update enemigos
		for i in lista_enemigos:
			i.update(pantalla,player1,player1.rect.left,player1.rect.top,tiempo)
			i.rect.move_ip(-vx,-vy)

			if i.murio==True:
				player1.oro=player1.oro+i.oro
				player1.exp=player1.exp+i.exp
				print(player1.oro)
				lista_enemigos.remove(i)

		#-----------------------------------------------------------
		#-------------------si ataca melee dibuja el aura
		if ataquemelee==True:
			ataquecuerpo.update(pantalla,vx,vy,clickizquierdo,lista_enemigos,player1,intervalo)

		cursor1.update()
		if menuabro==True and menucirular.boton3.boton_actual==menucirular.boton3.boton1 and pygame.mouse.get_pressed()[0]:
			hechizosactivo=True

		if menuabro==True and menucirular.boton1.boton_actual==menucirular.boton1.boton1 and pygame.mouse.get_pressed()[0]:
			inventarioactivo=True

		if hechizosactivo==True:
			hechizos_menu.update(pantalla,cursor1,True)
		if inventarioactivo==True:
			inventario_cuadro.update(pantalla,cursor1)
		if hechizos_menu.bot_cer.T==1:
			hechizosactivo=False
		if inventario_cuadro.bot_cer.T==1:
			inventarioactivo=False
		usuariointerfaz.update(pantalla)
		barra_vida.update(pantalla,player1.hpmax,player1.salud)
		barra_mana.update(pantalla,300,300)
		barra_exp.update(pantalla,player1.expmax,player1.exp)
		equipamento_cuadro.update(pantalla)
		pantalla.blit(player1.textosalud,(220,43))
		pantalla.blit(player1.textooro,(800,8))
		pantalla.blit(player1.textoexp,(230,100))
		pantalla.blit(player1.textolvl,(120,97))
		pantalla.blit(player1.textomana,(220,68))

		if menuabro==True:
			menucirular.update(pantalla,cursor1)

		if puestocomidas1.rect.colliderect(cursor1) and pygame.mouse.get_pressed()[0]:
			tiendaactiva1=True

		if puestomagia1.rect.colliderect(cursor1) and pygame.mouse.get_pressed()[0]:
			tiendaactiva2=True

		if puestoarmas1.rect.colliderect(cursor1) and pygame.mouse.get_pressed()[0]:
			tiendaactiva3=True

		if tiendaactiva1==True:
			tiendacomida.update(pantalla,cursor1,intervalo)

		if tiendaactiva2==True:
			tiendahechizos.update(pantalla,cursor1,intervalo)
		if tiendaactiva3==True:
			tiendaarmas1.update(pantalla,cursor1,intervalo)

		for i in lista_enemigos:
			pantalla.blit(i.textosalud,(i.rect.left,i.rect.top))

		#-------------------------detecta colisiones y guarda en una lista grande
		colisiones_pared1=pygame.sprite.spritecollide(player1,lista_paredatras,False)
		colisiones_pared2=pygame.sprite.spritecollide(player1,lista_paredescostado,False)
		colisiones_pared3=pygame.sprite.spritecollide(player1,lista_bloqueofrente,False)
		colisiones_pared4=pygame.sprite.spritecollide(player1,lista_sprites_fijos,False)
		colisiones_paredes=colisiones_pared1+colisiones_pared2+colisiones_pared3+colisiones_pared4

		#define que hacer en caso de que haya colisiones para cada elemento de las listas fondo aparte va
		for i in colisiones_paredes:
			for e in lista_todos_sprites:
				e.rect.move_ip(vx,vy)
			lobo1.rect.move_ip(vx,vy)

			for b in lista_anclado:
				b.rect.move_ip(0,0)
			fondo1.rect.move_ip(vx,vy)

		if intervalo==50:
			for i in lista_enemigos:
				if i.rect.colliderect(player1.rect):
					player1.salud=player1.salud-i.danio
					player1.text1=str(player1.salud)
					player1.text2="/"
					player1.text3=str(player1.hpmax)
					player1.fuente=pygame.font.Font(None,15)
					player1.textosalud=player1.fuente.render(player1.text1+player1.text2+player1.text3,0,(255,255,255))

		#ingresar las ordenes que dibujan en la pantalla
		pygame.display.update(rect_update)

	pygame.quit()

main()


from django.http import HttpResponse
from django.views import View
from django.shortcuts import render
from cvolve.main import models

class OffersView(View):

    def get(self, request):
        user = models.User.objects.get(pk=request.user.id)
        offers = user.get_offers_sorted_by_distance(return_distances=True)
        first_offer = offers[0]
        other_offers = [o for o in offers if o.id != first_offer.id]

        return render(request, 'offers.html', {
            'first_offer': first_offer,
            'offers': other_offers
        })


from mock import patch

from .util import V1TestCase, writeable_settings_stub

class TestTakeCommand(V1TestCase):
    get_workitem = patch('helga_versionone.get_workitem')
    get_user = patch('helga_versionone.get_user')

    def test_in_owners(self):
        self.get_workitem().Owners = [self.nick, 'fhqwhgads']
        self.get_user.return_value = self.nick

        return self._test_command(
            'take whatever',
            'Dude {0}, you already own it!'.format(self.nick),
        )

    def test_not_in_owners_write_fail(self):
        self.get_workitem().Owners = ['fhqwhgads']
        self.get_user.return_value = self.nick

        return self._test_command(
            'take whatever',
            'I would, but I\'m not allowed to write :('
        )

class TestTakeCommandWithWrite(V1TestCase):
    settings = patch('helga_versionone.settings', writeable_settings_stub)
    get_workitem = patch('helga_versionone.get_workitem')
    get_user = patch('helga_versionone.get_user')

    def test_not_in_owners_write_ok(self):
        w = self.get_workitem()
        w.Owners = ['fhqwhgads']
        self.get_user.return_value = self.nick

        d = self._test_command(
            'take whatever',
        )

        def check(res):
            # Check data and commit called
            self.assertEquals(
                w.Owners,
                [self.nick],
            )
            self.v1.commit.assert_called_once_with()
            self.assertAck()

        d.addCallback(check)
        return d


import matplotlib
matplotlib.use('TKAgg')
import matplotlib.pyplot as plt

from basic_funcs import load_results, load_dataset, delete_row_csr
import numpy as np
import pickle, random
from sklearn import linear_model
from sklearn.metrics import confusion_matrix
from baseline_model.class_imbalance import imba_tech
import recipe, config

def choose_query(distance, query_strategy):
  """
  This function implements the "query" step in the active learning cycle.
  Note that the batch size is 2.
  :param distance: a list or numpy array, including the distance of all documents to the SVM hyperplane
  :param query_strategy: string, describing which query strategy to be used. Options are:
  1. 'least_confidence'
  2. 'certainty_positive'
  3. 'certainty_positive_negative'
  :return: a list or numpy array with indices for the "selected" documents
  """

  # 'least_confidence' stands for the query strategy - uncertainty sampling
  if query_strategy == 'least_confidence':
    # Get absolute distance to the hyperplane
    abs_distance = np.absolute(distance)
    # Get indices of two documents whose "absolute" distance are the two smallest
    query_indices = np.argsort(abs_distance)[0:2]

  elif query_strategy == 'certainty_positive':
    # Get indices of two documents whose distance to the hyperplane are the two largest (i.e., the first and the second)
    query_indices = np.argsort(distance)[0:2]

  elif query_strategy == 'certainty_positive_negative':
    # Get indices of one documents whose distance to the hyperplane (distance can be negatives) is the smallest
    # and one documents whose distance is the largest (i.e., the first and last one in the order)
    query_indices = np.argsort(distance)[[0, -1]]

  else:
    # if no query strategy is applied, indices of two random documents are assigned
    query_indices = random.sample(range(1, len(distance)), 2)

  return query_indices

def run_query_strategy(partial_set, query_strategy, optimal_alpha, optimal_tol, imba_type, random_seed=None):
  """
  This function implements the active learning process for one dataset.
  :param partial_set: int, index of dataset, ranging from 1 to 5. Each dataset consists of five reviews
  :param query_strategy: string, 'least_confidence', 'certainty_positive' or 'certainty_positive_negative'
  :param optimal_alpha: float, the optimal value of alpha
  :param optimal_tol: float, the optimal value of tolerance
  :param imba_type: string, indicating class imbalance technique
  :param random_seed: int, the number used for the randomization
  :return:
  """

  # Initiate variables
  tp_r = 0
  num_of_iter = 0

  # Indices of documents that were queried and read by the reviewer
  reviewer_list = []
  tp_reviewer_list = []

  # Metrics to be recorded for each iteration in active learning
  number_query_docs = []
  yield_list = []
  burden_list = []

  X_train, y_train, X_u_pool, y_u_pool = load_dataset('partial', partial_set, recipe.STANDARD_TYPE)

  if imba_type == 'weighting':
    # Initiate SVM Model which enables setting class weight
    weight = int((len(y_train) - y_train.sum()) / y_train.sum())
    clf = linear_model.SGDClassifier(loss="hinge", penalty="l2", tol=optimal_tol, alpha=optimal_alpha,
                                     shuffle=True, random_state=1, max_iter=5000, class_weight={1: weight})

  else:
    # Initiate SVM Model
    clf = linear_model.SGDClassifier(loss="hinge", penalty="l2", tol=optimal_tol, alpha=optimal_alpha,
                                     shuffle=True, random_state=1, max_iter=5000)
    # Re-sample the training data due to the undersampling or oversampling - handle class imbalance
    X_train, y_train = imba_tech(X_train, y_train, imba_type, random_seed)

  # Train the model with the seed
  clf.fit(X_train, y_train)

  # Start Active Learning Loop!
  while len(y_u_pool) != 0:

    predictions = clf.predict(X_u_pool)

    ####################################################################################
    # Get confusion matrix for the test data
    cm = confusion_matrix(y_u_pool, predictions)

    # If only one element left in the confusion matrix, then ravel() cannot be used, so here divide it into two paths
    if len(cm) > 1:
      tn_u, fp_u, fn_u, tp_u = cm.ravel()

    else:
      fp_u = 0
      fn_u = 0
      tp_u = 0

    # Calculate Yield and Burden
    yield_al = (tp_r + tp_u)/(tp_r + tp_u + fn_u)
    burden_al = (len(reviewer_list) + tp_u + fp_u)/(len(reviewer_list) + len(y_u_pool))
    ###################################################################################

    # Obtain (or update) the distance (including both positive values and negative values) to the hyperplane
    distance = clf.decision_function(X_u_pool)

    # Record measurements, respectively meaning the number of selected samples, yield, and burden for each iteration
    number_query_docs.append(num_of_iter * 2)
    yield_list.append(yield_al)
    burden_list.append(burden_al)

    # Get indices of selected documents (numpy.array type) following query strategies
    query_indices = choose_query(distance, query_strategy)

    # The X and Y of the queried document
    X_update = X_u_pool[query_indices]  # scipy.sparse.csc.csc_matrix
    y_update = y_u_pool.iloc[query_indices]

    # List of Documents that are to be reviewed by the oracle (reviewer)
    reviewer_list = reviewer_list + list(query_indices)

    # list of "Relevant" Documents that are screened by the oracle (reviewer)
    for query_index in query_indices:
      if y_u_pool.iloc[query_index] == 1:
        tp_reviewer_list.append(query_index)

    # Remove X and y of query documents from Unlabelled pool
    X_u_pool = delete_row_csr(X_u_pool, query_indices)
    y_u_pool = y_u_pool.drop(y_u_pool.index[query_indices])

    # Update the Classifier by partial fit
    clf = clf.partial_fit(X_update, y_update, classes=[0, 1])

    # When the unlabelled pool is empty, stop the loop
    if len(y_u_pool) == 0:
      break

    tp_r = len(tp_reviewer_list)

    num_of_iter += 1

  # Create a dictionary to store the results
  result_obj = {
    'query_strategy': query_strategy,
    'query': number_query_docs,
    'yield': yield_list,
    'burden': burden_list,
  }

  # Store the result dictionary
  with open('../Consolidation/query_strategy/{}_{}_seed_{}_undersamp.pickle'.format(partial_set, query_strategy,
                                                                                random_seed), 'wb') as handle:
    pickle.dump(result_obj, handle, protocol=pickle.HIGHEST_PROTOCOL)

  return result_obj

def test_query_strategy(partial_sets, optimal_alpha, optimal_tol):
  """
  Implement the run_query_strategy() function for different datasets with different query strategies.
  Tested strategies includes 'least_confidence', 'certainty_positive', and 'certainty_positive_negative'.
  Each model repeats five times using different random seeds for random undersampling technique.
  :param partial_sets: a list of integers, indicating different datasets;
  :param optimal_alpha: float, the optimal value of alpha
  :param optimal_tol: float, the optimal value of tolerance
  :return: List of results are stored.
  """

  # List of query strategies to be tested
  query_strategies = ['least_confidence', 'certainty_positive', 'certainty_positive_negative']

  # Seed list
  seeds = list(range(1, 6))

  for query_strategy in query_strategies:

    for partial_set in partial_sets:

      for seed in seeds:

        run_query_strategy(partial_set, query_strategy, optimal_alpha, optimal_tol,
                           imba_type=recipe.CLASS_IMBALANCE, random_seed=seed)

def plot_query_strategy():
  """
  This function makes a boxplot to represent the results of WSS@95 for different query strategies
  :return:
  """
  query_strategies = ['least_confidence', 'certainty_positive', 'certainty_positive_negative']

  partial_sets = [1, 2, 3, 4, 5]

  seeds = list(range(1, 6))

  # This list will be used for making a boxplot
  compare_query_strategy = []

  for query_strategy in query_strategies:

    ilist = []

    for partial_set in partial_sets:

      for seed in seeds:
        query_al, yield_al, burden_al = load_results(partial_set, query_strategy, random_seed=seed)

        # Get 1-burden when yield first stay at 100%
        yield_al = np.array(yield_al)
        index = np.where(yield_al == 1)[0]

        # Add (1-burden) to the list
        ilist.append(1 - burden_al[index[0]])

    compare_query_strategy.append(ilist)

  plt.figure()
  axes = plt.gca()
  axes.set_ylim([-0.1, 1])

  plt.boxplot(compare_query_strategy)

  plt.xticks((1, 2, 3), ('uncertainty', 'certainty \n(positive)', 'certainty \n (positive and negative)'))
  plt.ylabel('(1-Burden) at 100% Yield')

  color = ['r', 'g', 'b', 'k', 'c']

  # Plot each model as a point in the same graph
  for i in range(len(compare_query_strategy)):
    y = compare_query_strategy[i]

    x = list(np.random.normal(i + 1, 0.04, size=len(y)))

    for j in range(5):
      plt.scatter(x[5 * j: 5 * j + 5], y[5 * j: 5 * j + 5], c=color[j], alpha=0.6, s=16)

  # plt.show()
  plt.savefig(config.QUERY_STRATEGY_FIGURE)


"""
Script to move title box around for different pages during export.
This specific script was for a series of maps of city quadrants that
required 4 unique positions, but it could be easily modified to simply
work with left or right pages (use modulus to find even/odd page numbers),
or to move inset maps around.
"""

#specify output pdf base name
outPDF = r"X:\GIS_BASE_MAP\Map Database\manhattan_fire\Maps\Driver Maps\NEW\unlabeled.pdf"

#specify the current map as the working document
thisMap = arcpy.mapping.MapDocument("CURRENT")

#create an object referencing the title box
#previously named "TitleGroup" to aid in python location)
titleBox = arcpy.mapping.ListLayoutElements(thisMap,'',"TitleGroup")[0]

#create data driven pages object
ddPages = thisMap.dataDrivenPages

#create dictionary to set position of the title box based on page #
#title box is set to anchor to top left corner
#positions are inches from bottom left of page
titlePos = {1:(1,18.07),
            2:(22.26,18.07),
            3:(1,1),
            4:(22.26,1)}

#iterate through data driven pages and export to PDF
for pageNum in range(1, ddPages.pageCount + 1):
    ddPages.currentPageID = pageNum

    #set X and Y positions of the title box
    titleBox.elementPositionX = titlePos[pageNum][0]
    titleBox.elementPositionY = titlePos[pageNum][1]

    arcpy.refreshActiveView()
    #export current page to pdf
    ddPages.exportToPDF(outPDF,"CURRENT","","PDF_MULTIPLE_FILES_PAGE_NAME",
                        300,"BEST","RGB",True,"ADAPTIVE","RASTERIZE_BITMAP",
                        False,True,"LAYERS_ONLY",False,100)


import sys
import os
from typing import List, Optional
from ..utils import read_file_as_int

def part_one(inputFile: str):
  lines = read_file_as_int(inputFile)
  prev : Optional[int] = None
  inc = 0
  dec = 0
  for i in lines:
    if prev != None:
      if i < prev:
        dec += 1
      elif i > prev:
        inc += 1
    prev = i
  return prev

def part_two(inputFile: str):
  lines = read_file_as_int(inputFile)
  idx = 0
  inc = 0
  for _ in lines:
    idx += 1
    if idx >= 4:
      a1 = lines[idx-4:idx-1]
      a2 = lines[idx-3:idx]
      if sum(a2) > sum(a1):
        inc += 1

  return inc


import os
import cv2
import tensorflow as tf
try:
    from PIL import Image
except ImportError:
    import Image

import matplotlib.pyplot as plt
import numpy as np
UPLOAD_FOLDER = '/static/uploads/'
# import pytesseract
# pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"

CATEGORIES = ["Black-grass","Charlock","Cleavers","Common Chickweed","Common wheat","Fat Hen","Loose Silky-bent","Maize","Scentless Mayweed","Shepherds Purse","Small-flowered Cranesbill","Sugar beet"]

def prepare(file):
    try:
        IMG_SIZE = 128
        IMG_SIZE_WIDTH=128
        img_array = cv2.imread(file, cv2.IMREAD_GRAYSCALE)
        img_array = img_array / 255.0
        new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE_WIDTH))
        return new_array.reshape(-1, IMG_SIZE, IMG_SIZE_WIDTH, 1)

    except Exception as e:
        print(str(e))

def ocr_core(filename):
    """
    This function will handle the core OCR processing of images.
    """
    # text = pytesseract.image_to_string(Image.open(filename), config="-c tessedit"
    #                                                                 "_char_whitelist=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    #                                                                 " --psm 10"
    #                                                                 " -l osd"
    #                                                                 " ")  # We'll use Pillow's Image class to open the image and pytesseract to detect the string in the image

    model = tf.keras.models.load_model("CNN.model")

    # print(image)
    # new code
    img = cv2.imread('./static/uploads/'+filename)
    plt.imshow(img)

    segmanted_img_name=filename[:-4]+"_segmanted"

    image_mask = create_mask_for_plant(img)
    image_segmented = segment_plant(img)
    image_sharpen = sharpen_image(image_segmented)

    cv2.imwrite(os.getcwd() + UPLOAD_FOLDER+segmanted_img_name+".png", image_sharpen)

    image = prepare('./static/uploads/' + segmanted_img_name+".png")  # your image path segmented image path

    #
    assert not isinstance(image, type(None)), 'image not found'
    #image1=prepare(image)
    prediction = model.predict([image])
    prediction = list(prediction[0])
    text= CATEGORIES[prediction.index(max(prediction))]  # -*- coding: utf-8 -*-

    return text  # Then we will print the text in the image

def create_mask_for_plant(image):
    image_hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

    sensitivity = 35
    lower_hsv = np.array([60 - sensitivity, 100, 40])
    upper_hsv = np.array([60 + sensitivity, 255, 255])

    mask = cv2.inRange(image_hsv, lower_hsv, upper_hsv)
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11, 11))
    mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)

    return mask

def segment_plant(image):
    mask = create_mask_for_plant(image)
    output = cv2.bitwise_and(image, image, mask=mask)
    return output

def sharpen_image(image):
    image_blurred = cv2.GaussianBlur(image, (0, 0), 3)
    image_sharp = cv2.addWeighted(image, 1.5, image_blurred, -0.5, 0)
    return image_sharp

def segment(img):
    # image_mask = create_mask_for_plant(img)
    image_segmented = segment_plant(img)
    image_sharpen = sharpen_image(image_segmented)
    return image_sharpen