from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from .models import Porject, Tag
from .forms import ProjectForm, ReviewForm
from .utils import searchProjects, paginateProjects

def projects(request):
    projectList, search_text = searchProjects(request)
    custom_range, projectList, paginator_num_pages = paginateProjects(request, projectList, 3)

    return render(request, 'projects/projects.html', {
        'projects': projectList,
        'search_query': search_text,
        'paginator_num_pages': paginator_num_pages,
        'custom_range': custom_range,
        'before_last_page': paginator_num_pages - 1
    })

def project(request, name):
    projectObj = Porject.objects.get(id=name)
    tags = projectObj.tags.all()
    form = ReviewForm()
    if request.method == 'POST':
        form = ReviewForm(request.POST)
        review = form.save(commit=False)
        review.project = projectObj
        review.owner = request.user.profile
        review.save()

        projectObj.getVoteCount

        messages.success(request, 'Review added!')

    return render(request, 'projects/project.html', {'project': projectObj, 'tags': tags, 'form': form})

@login_required(login_url='login')
def createProject(request):
    profile = request.user.profile
    form = ProjectForm()

    if request.method == 'POST':
        newtags = request.POST.get('newtags').replace(',', " ").split()

        form = ProjectForm(request.POST, request.FILES)
        if form.is_valid():
            project = form.save(commit=False)
            project.owner = profile
            project.save()
            for tag in newtags:
                tag, created = Tag.objects.get_or_create(name=tag)
                project.tags.add(tag)
            return redirect('projects')
        else:
            messages.error(request, 'An error has occurred during registration')

    return render(request, 'projects/project_form.html', {'form': form})

@login_required(login_url='login')
def updateProject(request, pk):
    profile = request.user.profile
    project = profile.porject_set.get(id=pk)
    if project is None:
        messages.error(request, "Project not found!")
        return redirect('projects')
    form = ProjectForm(instance=project)

    if request.method == 'POST':
        newtags = request.POST.get('newtags').replace(',', " ").split()

        form = ProjectForm(request.POST, request.FILES, instance=project)
        if form.is_valid():
            form.save()
            for tag in newtags:
                tag, created = Tag.objects.get_or_create(name=tag)
                project.tags.add(tag)
            return redirect('projects')
    return render(request, 'projects/project_form.html', {'form': form, 'project':project})

@login_required(login_url='login')
def deleteProject(request, pk):
    profile = request.user.profile

    project = profile.porject_set.get(id=pk)
    if project is None:
        messages.error(request, 'Project not found')
        return redirect('projects')
    if request.method == 'POST':
        project.delete();
        return redirect('projects')
    return render(request, 'delete_template.html', {'object': project})


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

#========================================================================
# Author: doubleQ
# File Name: 5_ranker_train.py
# Created Date: 2022-07-12
# Description:
# =======================================================================

from datetime import datetime
import lightgbm as lgb
from lightgbm import early_stopping
from lightgbm.sklearn import LGBMRanker
import numpy as np
from sklearn.model_selection import KFold
from sklearn.preprocessing import MinMaxScaler
import pandas as pd
import utils
import os
import math
import gc
import sys
version = datetime.now().strftime("%m%d%H%M%S")
print('Version: ', version)

seed = 2022
mode = sys.argv[1]
merge_block_num = 6
n_fold = 3
os.makedirs('result', exist_ok=True)

def modeling(train_X, train_Y, test_X, test_Y, train_baskets, test_baskets, cat_features=None):
    feat_cols = list(train_X.columns)
    ranker = LGBMRanker(
            learning_rate=0.01,
            objective="lambdarank",
            metric="ndcg",
            boosting_type="dart",
            importance_type='gain',
            verbose=10,
            num_threads=10,
            n_estimators=100,
            reg_alpha=0.0,
            reg_lambda=1,
            subsample=0.7,
            colsample_bytree=0.7,
            subsample_freq=1,
        )
    print('Start train and validate...')
    ranker = ranker.fit(
        train_X,
        train_Y,
        categorical_feature=cat_features,
        group=train_baskets,
        eval_group=[test_baskets],
        eval_set=[(test_X, test_Y)],
        eval_at=(100, 200),
        callbacks=[early_stopping(stopping_rounds=5, first_metric_only=True)],
    )
    for i in ranker.feature_importances_.argsort()[::-1]:
        print(feat_cols[i], ranker.feature_importances_[i]/ranker.feature_importances_.sum())
    return ranker

def predict(test_X, model):
    print('Start Predict ...')
    block_num = 6
    block_len = len(test_X)//block_num
    predicts = []
    for block_id in range(block_num):
        l = block_id * block_len
        r = (block_id+1) * block_len
        if block_id == block_num - 1:
            predict = model.predict( test_X.iloc[l:])
        else:
            predict = model.predict( test_X.iloc[l:r])
        predicts.append(predict)
    predict = np.concatenate( predicts )
    return predict

def get_score(df):
    df = df.sort_values(by=['session_id','pred'], ascending=False).groupby('session_id')['label'].apply(lambda x: list(x)[:100]).reset_index()
    mrr = []
    for idx, row in df.iterrows():
        session_id = row['session_id']
        pred = row['label']
        r = 0
        for i, pred in enumerate(row['label']):
            if pred == 1:
                r = 1 / (i + 1)
                break
        mrr.append(r)
    mrr = np.mean(mrr)
    return mrr

drop_list = ['session_id', 'item_id', 'hist_item_ids', 'view_dates', 'label',
             'view_feature_vector', 'item_feature_vector'
            ]
OPT_ROUNDS = 1000

if mode == 'offline':
    datas = []
    for block_id in range(merge_block_num):
        data_path = 'data/user_data/lgb_model_{}_{}.pkl'.format('train', block_id)
        datas.append(utils.load_pickle(data_path))
    train = pd.concat(datas)
    #train['view_dates'] = train['view_dates'].apply(lambda x: x[0])
    #train = train[train['view_dates'] >= '2021-03-01 00:00:00.000'].reset_index(drop=True)
    del datas
    gc.collect()
    datas = []
    for block_id in range(merge_block_num):
        data_path = 'data/user_data/lgb_model_{}_{}.pkl'.format('valid', block_id)
        datas.append(utils.load_pickle(data_path))
    test = pd.concat(datas)
    del datas
    gc.collect()
    print('now train data_shape: ', train.shape)
    print('now test data_shape: ', test.shape)
    drop_list += [column for column in train.columns if column.startswith('cat_')]
    cat_features = None

    ans = test[ ['session_id', 'item_id', 'label'] ]
    #ans['pred'] = test['itemcf_full_retrieval_score']
    #mrr = get_score(ans)
    #print('Recall mrr:', mrr)

    all_sessions = train['session_id'].unique()
    t = train.groupby(['session_id'])['label'].any()
    has_pos_sessions = list( t[t].index )
    train_sessions = list(set(has_pos_sessions))
    train_index = train[ train['session_id'].isin(train_sessions) ].index
    train = train.loc[ train_index ]
    train_baskets = train.groupby(['session_id'])['item_id'].count().values
    test_baskets = test.groupby(['session_id'])['item_id'].count().values

    train_X = train.drop( drop_list, axis=1 )
    train_Y = train['label']

    test_X = test.drop( drop_list, axis=1 )
    test_Y = test['label']

    model = modeling(train_X, train_Y, test_X, test_Y, train_baskets, test_baskets, cat_features=cat_features)
    result = predict(test_X, model)
    ans['pred' ] = result
    ans.to_csv('kankan.tsv', sep='\t', index=False)
    mrr = get_score(ans)
    print('Rank mrr:', mrr)
elif mode == 'online':
    datas = []
    for block_id in range(merge_block_num):
        data_path = 'data/user_data/lgb_model_{}_{}.pkl'.format('train', block_id)
        datas.append(utils.load_pickle(data_path))
    for block_id in range(merge_block_num):
        data_path = 'data/user_data/lgb_model_{}_{}.pkl'.format('valid', block_id)
        datas.append(utils.load_pickle(data_path))
    data = pd.concat(datas).reset_index(drop=True)
    #data['view_dates'] = data['view_dates'].apply(lambda x: x[0])
    #data = data[data['view_dates'] >= '2021-04-01 00:00:00.000'].reset_index(drop=True)
    print(data)
    del datas
    gc.collect()
    print('train data_shape: ', data.shape)
    test_datas = []
    for block_id in range(merge_block_num):
        data_path = 'data/user_data/lgb_model_{}_{}.pkl'.format('test', block_id)
        test_datas.append(utils.load_pickle(data_path))
    test_data = pd.concat( test_datas )
    print(test_data)
    del test_datas
    gc.collect()
    print('test data_shape: ', test_data.shape)
    #drop_list += [column for column in test_data.columns if column.startswith('cat_')]
    cat_features = [column for column in test_data.columns if column.startswith('cat_')]

    test_X = test_data.drop( drop_list, axis=1 )
    ans = test_data[ ['session_id', 'item_id'] ]

    see = data[ ['session_id', 'item_id', 'label'] ]
    see['pred'] = data['itemcf_full_retrieval_score']
    mrr = get_score(see)
    print('Recall mrr:', mrr)
    all_sessions = data['session_id'].unique()
    t = data.groupby(['session_id'])['label'].any()
    has_pos_sessions = list( t[t].index )
    kfold = KFold(n_splits=n_fold, shuffle=True, random_state=2022)
    index = kfold.split(X=all_sessions)
    for i, (train_sessions_index, valid_sessions_index) in enumerate(index):
        print('Fold:', i)
        train_sessions = all_sessions[ train_sessions_index ]
        train_sessions = list(set(train_sessions) & set(has_pos_sessions))
        train_index = data[ data['session_id'].isin(train_sessions) ].index
        train_data = data.loc[ train_index ]

        valid_sessions = all_sessions[ valid_sessions_index ]
        valid_index = data[ data['session_id'].isin(valid_sessions) ].index
        valid_data = data.loc[ valid_index ]
        print('train:', len(train_data), ', valid:', len(valid_data))
        train_baskets = train_data.groupby(['session_id'])['item_id'].count().values
        valid_baskets = valid_data.groupby(['session_id'])['item_id'].count().values

        train_X = train_data.drop( drop_list, axis=1 )
        train_Y = train_data['label']

        valid_X = valid_data.drop( drop_list, axis=1 )
        valid_Y = valid_data['label']

        model = modeling(train_X, train_Y, valid_X, valid_Y, train_baskets, valid_baskets, cat_features=cat_features)
        result = predict(valid_X, model)
        see.loc[ valid_index , 'pred' ] = result
        if i == 0:
            ans['pred'] = predict(test_X, model)
        else:
            ans['pred'] += predict(test_X, model)
    mrr = get_score(see)
    print('Rank mrr:', mrr)

    scaler = MinMaxScaler()
    ans['pred'] = ans.groupby('session_id')['pred'].apply(lambda x:
            scaler.fit_transform(np.array(list(x)).reshape(-1, 1)).reshape(-1)).reset_index().explode('pred').reset_index()['pred']
    ans.to_csv('result/lgbranker_{}_{:.4}_score.csv'.format(version, mrr), index=False)
    ans = ans.sort_values(by=['session_id','pred'], ascending=False).groupby(
            'session_id')['item_id'].apply(lambda x: list(x)[:100]).reset_index()
    ans = ans.explode('item_id')
    ans['rank'] = list(range(1, 101)) * len(set(ans['session_id']))
    board_session = set(pd.read_csv('../data/test_leaderboard_sessions.csv')['session_id'])
    final_session = set(pd.read_csv('../data/test_final_sessions.csv')['session_id'])
    test_leaderboard = ans[ans['session_id'].isin(board_session)]
    final_leaderboard = ans[ans['session_id'].isin(final_session)]
    test_leaderboard.to_csv('result/leaderboard_lgbranker_{}_{:.4}.csv'.format(version, mrr), index=False)
    final_leaderboard.to_csv('result/final_lgbranker_{}_{:.4}.csv'.format(version, mrr), index=False)
else:
    print('mode error!')


import numpy as np
import matplotlib.pylab as plt
import sycomore
from sycomore import units

def get_inhomogeneity(B0=1.5, inhomogeneity_ppm=0.0):
    gyromagnetic_ratio = 42.58e6  # Hz/T
    freq_rot = gyromagnetic_ratio * B0
    freq = gyromagnetic_ratio * B0 * (1 - inhomogeneity_ppm)
    delta_freq = (freq - freq_rot) * 1e-6
    return delta_freq * units.Hz

def get_species(T1, T2, delta_omega=0 * units.Hz):
    return sycomore.Species(T1, T2, delta_omega=delta_omega)

def update_and_record_magnetization(M, record, t, update=None):
    if update is not None:
        M = update @ M
    record.append([t.convert_to(units.ms), M[:3] / M[3]])
    return M

def run_simulation_single_tissue(T1_ms, T2_ms, flip_angle_deg, step_size_ms, n_species, n_steps, step_refocus):

    delta_omega = get_inhomogeneity(B0=1.5, inhomogeneity_ppm=-0.2)
    T1 = T1_ms * units.ms
    T2 = T2_ms * units.ms
    n_species = int(n_species)

    species_baseline = [get_species(T1, T2, delta_omega=-delta_omega)]
    species_ensemble = species_baseline + [get_species(T1, T2, delta_omega=delta_omega*np.random.randn()) for _ in range(n_species-1)]

    step_size = step_size_ms * units.ms

    idles = [sycomore.bloch.time_interval(species, step_size) for species in species_ensemble]

    pulse_excitation = sycomore.bloch.pulse(flip_angle_deg * units.deg, phase=np.pi*units.rad)
    pulse_refocus = sycomore.bloch.pulse(180 * units.deg, phase=np.pi*units.rad/2)
    pulse_tipup = sycomore.bloch.pulse(-90 * units.deg, phase=np.pi*units.rad)

    t = 0 * units.ms
    M = [np.array([0, 0, 1, 1]) for _ in range(n_species)]
    records = [[[t.convert_to(units.ms), m[:3] / m[3]]] for m in M]

    for k, m in enumerate(M):
        M[k] = update_and_record_magnetization(m, records[k], t, update=pulse_excitation)

    for step in range(n_steps):
        if (step != step_refocus)&(step != 2*step_refocus):
            t += step_size
            for k, m in enumerate(M):
                M[k] = update_and_record_magnetization(m, records[k], t, update=idles[k])
        elif step == step_refocus:
            for k, m in enumerate(M):
                M[k] = update_and_record_magnetization(m, records[k], t, update=pulse_refocus)
        elif step == (step_refocus * 2):
            for k, m in enumerate(M):
                M[k] = update_and_record_magnetization(m, records[k], t, update=pulse_tipup)

    magnetization = np.stack([np.array([m for _, m in record]) for record in records]).mean(axis=0)
    magnetization_k = np.array([m for _, m in records[0]])
    time = np.array([t for t, _ in records[0]])

    return magnetization, time, magnetization_k


import string
import sys
from restconfDataResource import RestconfDataResource

class RestconfListInstance(object):
    """
    Wraps RESTCONF list-instance URIs

    The module name, if any, should have already been stripped by and provided as input
    to the object constructor

        api-identifier = [module-name ":"] identifier

        list-instance = api-identifier "=" key-value ["," key-value]*

        key-value = string                                            ;; note 1

        string = <a quoted or unquoted string>
    """
    _error_message = ''
    _keys = []

    def __init__(self, identifier, module_name=None):
        self._identifier = ''
        self._module_name = module_name
        self._valid = self._parse_list_instance(module_name, identifier)

    def _parse_list_instance(self, module_name, list_instance):
        """
        Process the list-instance portion of an api-identifier where:

            list-instance = api-identifier "=" key-value ["," key-value]*

               key-value = string

               string = <a quoted or unquoted string>

        :param module_name: (string) The module-name
        :param list_instance: (string) The identifier

        :returns: (boolean) True if successfully parsed.
        """
        # This is either an identifier or a list-instance.  List-instances will always contain
        # and "=" since it is not a valid instance character

        instance_and_keys = list_instance.split('=')

        if len(instance_and_keys) != 2 or len(instance_and_keys[1].strip()) == 0:
            self._error_message = "Invalid list-instance '%s' found in resource path: '%s'" % \
                                  (list_instance, self._resource)
            return False

        self._identifier = instance_and_keys[0]

        if not RestconfDataResource.valid_identifier(self._identifier):
            self._error_message = "Invalid Identifier '%s' found in list-instance resource path: '%s'" % \
                                  (self._identifier, list_instance)
            return False

        # Encode the keys now

        return self._validate_keys(instance_and_keys[1].split(','))

    def _validate_and_modify_keys(self, key_list):
        """
        Validate the key syntax and optionally change it from a string to a more appropriate
        object type (int, boolean, ...)

        Keys can be an empty string, strings, ints, floats, ...
        """
        # TODO: How do we handle -0, do we keep a 'minus' flag available?

        for key in key_list:
            new_value = key
            if not any(x not in key for x in string.whitespace):
                try:
                    new_value = float(key)
                except (TypeError, ValueError):
                    try:
                        if key in ['True', 'true']:  # TODO: Do we really want this conversion (or leave as string?)
                            new_value = True
                        elif key in ['False', 'false']:
                            new_value = False
                        else:
                            raise TypeError
                    except (TypeError, ValueError):
                        try:
                            new_value = long(key)
                            if -sys.maxint - 1 <= key <= sys.maxint:
                                new_value = int(key)
                        except (TypeError, ValueError):
                            pass

            self._keys.extend([new_value])

        return True

    @property
    def is_valid(self):
        return self._valid

    @property
    def error_message(self):
        return self._error_message

    @property
    def module_name(self):
        return self._module_name

    @property
    def keys(self):
        return self._keys

    def __str__(self):
        str_val = '%s=' % self._identifier
        first = True
        for key in self._keys:
            if not first:
                str_val += ','
            str_val += '%s' % str(key)
            first = False

        return str_val


name = input("Enter file:")
if len(name) < 1 : name = "mbox-short.txt"
handle = open(name)
lst=list()
dic=dict()
count=0
newl=list()

for line in handle:
    line=line.rstrip()
    if not line.startswith('From '):continue
    line=line.split()
    if not ':' in line[5]: continue
    date=line[5]
    s=date[:2]
    lst.append(s)
slst=sorted(lst)
for w in slst:
    dic[w]=dic.get(w,0)+1

for k,v in dic.items():
    print(k,v)


# coding: utf-8
'''
Created on 2014��9��24��

图像中的边缘区域，像素值会发生“跳跃”，对这些像素求导，
在其一阶导数在边缘位置为极值，这就是Sobel算子使用的原理——极值处就是边缘。

如果对像素值求二阶导数，会发现边缘处的导数值为0。
Laplace函数实现的方法是先用Sobel 算子计算二阶x和y导数，再求和：

@author: xhj
'''

import cv2
import numpy as np

def laplacian_figureEdge(img):
    '''
       处理前最好先降噪，但是下面处理没有降噪
    '''
    gray_lap = cv2.Laplacian(img, cv2.CV_16S, ksize=3)
    dst = cv2.convertScaleAbs(gray_lap)
    cv2.imshow('laplacian',dst)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

if __name__ == '__main__':
    img = cv2.imread(r'E:\pyopencv\imgs\stuff.jpg')
    laplacian_figureEdge(img)


import numpy as np
import torch
from torch.utils import data
import warnings
import json, csv
import traceback
from collections import Counter
from sybil.augmentations import get_augmentations
from tqdm import tqdm
from sybil.serie import Serie
from sybil.datasets.utils import order_slices, METAFILE_NOTFOUND_ERR, LOAD_FAIL_MSG
from sybil.loaders.image_loaders import OpenCVLoader, DicomLoader

class CSVDataset(data.Dataset):
    """
    Dataset used for large validations
    """
    def __init__(self, args, split_group):
        '''
        params: args - config.
        params: split_group - ['train'|'dev'|'test'].

        constructs: standard pytorch Dataset obj, which can be fed in a DataLoader for batching
        '''
        super(CSVDataset, self).__init__()

        self.split_group = split_group
        self.args = args
        self._num_images = args.num_images # number of slices in each volume
        self._max_followup = args.max_followup

        try:
            self.dataset_dicts = self.parse_csv_dataset(args.dataset_file_path)
        except Exception as e:
            raise Exception(METAFILE_NOTFOUND_ERR.format(args.dataset_file_path, e))

        augmentations = get_augmentations(split_group, args)
        if args.img_file_type == 'dicom':
            self.input_loader = DicomLoader(args.cache_path, augmentations, args)
        else:
            self.input_loader = OpenCVLoader(args.cache_path, augmentations, args)

        self.dataset = self.create_dataset(split_group)
        if len(self.dataset) == 0:
            return

        print(self.get_summary_statement(self.dataset, split_group))

        dist_key = 'y'
        label_dist = [d[dist_key] for d in self.dataset]
        label_counts = Counter(label_dist)
        weight_per_label = 1./ len(label_counts)
        label_weights = {
            label: weight_per_label/count for label, count in label_counts.items()
            }

        print("Class counts are: {}".format(label_counts))
        print("Label weights are {}".format(label_weights))
        self.weights = [ label_weights[d[dist_key]] for d in self.dataset]

    def parse_csv_dataset(self, file_path):
        """
        Convert a CSV file into a list of dictionaries for each patient like:
        [
            {
                'patient_id': str,
                'split': str,
                'exam_id': str,
                'series_id': str,
                'ever_has_future_cancer': bool
                'years_to_cancer': int,
                'years_to_last_negative_followup': int,
                'paths': [str],
                'slice_locations': [str]
            }
        ]

        Parameters
        ----------
        file_path : str
            path to csv file

        Returns
        -------
        list
            list patient cases in the above structure
        """
        dataset_dicts = {}
        _reader = csv.DictReader(open(file_path,'r'))
        for _row in _reader:
            row = {k.encode('ascii', 'ignore').decode(): v.encode('ascii', 'ignore').decode() for k,v in _row.items()}
            patient_id, exam_id, series_id = row['patient_id'], row['exam_id'], row['series_id']
            unique_id = '{}_{}_{}'.format(patient_id, exam_id, series_id)
            if unique_id in dataset_dicts:
                dataset_dicts[unique_id]['paths'].append(row['file_path'])
                dataset_dicts[unique_id]['slice_locations'].append(row['fileslice_position_path'])
            else:
                dataset_dicts[unique_id] = {
                    'unique_id': unique_id,
                    'patient_id': patient_id,
                    'exam_id': exam_id,
                    'series_id': series_id,
                    'split': row['split'],
                    'ever_has_future_cancer': row['ever_has_future_cancer'],
                    'years_to_cancer': row['years_to_cancer'],
                    'years_to_last_negative_followup': row['years_to_last_negative_followup'],
                    'paths': [ row['file_path'] ],
                    'slice_locations': [ row['slice_position'] ]
                }

        dataset_dicts = list(dataset_dicts.values())
        return dataset_dicts

    def create_dataset(self, split_group):
        """
        Gets the dataset from the paths and labels in the json.
        Arguments:
            split_group(str): One of ['train'|'dev'|'test'].
        Returns:
            The dataset as a dictionary with img paths, label,
            and additional information regarding exam or participant
        """

        if self.args.assign_splits:
            np.random.seed(self.args.cross_val_seed)
            self.assign_splits(self.metadata_json)

        dataset = []

        for mrn_row in tqdm(self.dataset_dicts, position = 0):

            label = mrn_row['ever_has_future_cancer']
            censor_time = mrn_row['years_to_cancer'] if label else mrn_row['years_to_last_negative_followup']
            paths = order_slices(mrn_row['paths'], mrn_row['slice_locations'])
            try:
                series_object = Serie(
                    paths,
                    label,
                    censor_time,
                    self.args.img_file_type,
                    mrn_row['split']
                    )
            except Exception:
                continue

            if self.skip_sample(series_object, mrn_row, split_group):
                continue

            dataset.append({
                'serie': series_object,
                'exam': mrn_row['unique_id']
                })

        return dataset

    def skip_sample(self, series_object, row, split_group ):
        if row['split'] != split_group:
            return True

        if not series_object.has_label():
            return True

        return False

    def get_summary_statement(self, dataset, split_group):
        summary = "Contructed Sybil Cancer Risk {} dataset with {} records, {} exams, {} patients, and the following class balance \n {}"
        class_balance = Counter([d['y'] for d in dataset])
        exams = set([d['exam'] for d in dataset])
        patients = set([d['patient_id'] for d in dataset])
        statement = summary.format(split_group, len(dataset), len(exams), len(patients), class_balance)
        statement += "\n" + "Censor Times: {}".format( Counter([d['time_at_event'] for d in dataset]))
        return statement

    def __len__(self):
        return len(self.dataset)

    def __getitem__(self, index):
        sample = self.dataset[index]
        serie = sample['serie']
        try:
            labels = serie.get_label()
            item = {
                'x': serie.get_volume(),
                'y': labels.y,
                'y_seq': labels.y_seq,
                'y_mask': labels.y_mask,
                'time_at_event': labels.censor_time,
                'exam': sample['exam']
            }
            return item
        except Exception:
            warnings.warn(LOAD_FAIL_MSG.format(sample['paths'], traceback.print_exc()))


from game_logic.map import Map as BaseMap
from maths.vertex import Vertex2f
from maths.colors import BLUE
from game_logic.room import Room
from game_logic.entity import Entity

class Map(BaseMap):
    def __init__(self, width: int, height: int) -> None:
        super().__init__(width, height)

        workbench = Entity(BLUE)
        workbench._tile_position = Vertex2f(6, 3)
        self.entities.append(workbench)

    def _update_rooms(self) -> None:
        self.rooms = []
        for workbench in self.entities:
            room_closed = False
            room_tiles: list[Vertex2f] = []
            tiles_to_check = [workbench._tile_position]
            while len(room_tiles) < 20:
                tile_to_check = tiles_to_check.pop()
                room_tiles.append(tile_to_check)

                new_tile_positions: list[Vertex2f] = [
                    Vertex2f(tile_to_check.x - 1, tile_to_check.y),
                    Vertex2f(tile_to_check.x + 1, tile_to_check.y),
                    Vertex2f(tile_to_check.x, tile_to_check.y - 1),
                    Vertex2f(tile_to_check.x, tile_to_check.y + 1),
                ]
                for new_tile_position in new_tile_positions:
                    new_tile = self._get_tile(new_tile_position)
                    if (
                        new_tile is not None
                        and (not new_tile.is_wall)
                        and (new_tile_position not in room_tiles)
                        and (new_tile_position not in tiles_to_check)
                    ):
                        tiles_to_check.append(new_tile_position)

                if not tiles_to_check:
                    room_closed = True
                    break

            if room_closed:
                self.rooms.append(Room(room_tiles))


from __future__ import absolute_import
from django.utils.text import capfirst
from modeltranslation.settings import AVAILABLE_LANGUAGES, DEFAULT_LANGUAGE

def mt_fields(fields, nomaster=False, onlydefaultlang=False):
    """
    Returns list of fields for multilanguage fields of model.
    Examples:
        print(mt_fields('name', 'desc'))
        ['name', 'name_en', 'name_uk', 'desc', 'desc_en', 'desc_uk']

        MyModel.objects.only(*mt_fields('name', 'desc', 'content'))

    If nomaster then master field will not be append.
    F.e.: ['name_en', 'name_uk'] -- without master 'name'.

    If onlydefaultlang then wiil be search only default language:
    F.e.: ['name', 'name_en'] -- without additional 'name_uk'.

    If nomaster and onlydefaultlang then will be use both rulses.
    F.e.: ['name_en'] -- without master 'name' and additional 'name_uk'.
    """
    assert isinstance(fields, (list, tuple))
    fl = []
    for field in fields:
        if not nomaster:
            fl.append(field)
        if onlydefaultlang:
            fl.append('{}_{}'.format(field, DEFAULT_LANGUAGE))
        else:
            for lang in AVAILABLE_LANGUAGES:
                fl.append('{}_{}'.format(field, lang))
    return fl

def mt_modelform_field_restore_original_label(field, make_capfirst=False):
    """
    If label of field has suffix with language, you can fix it, for example:

    class MyModelForm(models.ModelForm):
        class Meta:
            model = MyModel
            _mt_fields = mt_fields(('title', 'description'), nomaster=True)
            fields = _mt_fields

        def __init__(self, *args, **kwargs):
            super(ItemCategoryEditForm, self).__init__(*args, **kwargs)

            for field_name in self.Meta._mt_fields:
                mt_modelform_field_restore_original_label(self.fields[field_name], make_capfirst=True)
    """
    field.label = field.label._proxy____args[0]._proxy____args[0]
    if make_capfirst:
        field.label = capfirst(field.label)

def mt_modelform_register_clean_method(form_self, field_name, func, nomaster=False):
    """
    You can add clean_<field_name> for each translated field. For example:

    class MyModelForm(models.ModelForm):
        class Meta:
            model = MyModel
            _mt_fields = mt_fields(('title', 'description'), nomaster=True)
            fields = _mt_fields

        def __init__(self, *args, **kwargs):
            super(ItemCategoryEditForm, self).__init__(*args, **kwargs)

            mt_modelform_register_clean_method(self, 'title', self.mt_clean_title, nomaster=True)

        def mt_clean_title(self, field_name, lang):
            value = self.cleaned_data[field_name]
            # validation here
            return value
    """
    args_list = [('{}_{}'.format(field_name, lang), lang) for lang in AVAILABLE_LANGUAGES]
    if not nomaster:
        args_list.append((field_name, None))

    def _get_mt_clean_method(args):
        def _mt_clean_method():
            return func(*args)
        return _mt_clean_method

    for item_args in args_list:
        method_name = 'clean_{}'.format(item_args[0])
        setattr(form_self, method_name, _get_mt_clean_method(item_args))


from tqdm import tqdm
import numpy as np
import jax
import jax.numpy as jnp
from absl import flags
FLAGS = flags.FLAGS

from gex.utils import ckpt, metrics, mp, tool

def avg_list_of_trainer(list_of_trainer, dataset_opt=None):
    '''
    Average list of trainer to a single trainer (not replicated).
    [1] Izmailov, Pavel, et al. "Averaging weights leads to wider optima and better generalization." arXiv preprint arXiv:1803.05407 (2018).
    '''
    num_ens = len(list_of_trainer)
    res = 0.
    for i in range(num_ens):
        vec_params, unravel_fn = tool.params_to_vec(list_of_trainer[i].params, True)
        res += vec_params / num_ens
    avg_params = unravel_fn(res)
    trainer = list_of_trainer[0].replace(params=avg_params)
    if FLAGS.use_bn:
        trainer = mp.unreplicate(tool.update_bn(mp.replicate(trainer), dataset_opt))
    return trainer

def gauss_posterior(list_of_trainer, sample_num, dataset_opt=None):
    '''
    Generate Gaussian samples from list of trainer as list of trainer
    [1] Maddox, Wesley J., et al. "A simple baseline for bayesian uncertainty in deep learning." Advances in Neural Information Processing Systems 32 (2019).
    '''
    num_ens = len(list_of_trainer)
    # gather params
    vec_params_list = []
    for i in range(num_ens):
        vec_params, unravel_fn = tool.params_to_vec(list_of_trainer[i].params, True)
        vec_params_list.append(vec_params)
    vec_params_list = jnp.stack(vec_params_list)
    vec_params_avg = vec_params_list.mean(axis=0, keepdims=True)
    vec_params_std = vec_params_list.std(axis=0)

    result = []
    rng = jax.random.PRNGKey(0)
    for i in tqdm(range(sample_num)):
        rng, rng_diag, rng_low_rank = jax.random.split(rng, 3)

        pert_diag = vec_params_std * jax.random.normal(rng_diag, vec_params.shape) / np.sqrt(2)
        pert_low_rank = ((vec_params_list - vec_params_avg) * jax.random.normal(rng_low_rank, (num_ens,1))).sum(axis=0) / np.sqrt(2 * (num_ens - 1))
        pert = pert_diag + pert_low_rank

        member = list_of_trainer[0].replace(
            params = unravel_fn(vec_params_avg[0] + pert))
        if FLAGS.use_bn:
            member = mp.unreplicate(tool.update_bn(mp.replicate(member), dataset_opt))
        result.append(member)
    return result

def get_statistics(list_of_trainer):
    vec_params_list = []
    for i in range(len(list_of_trainer)):
        vec_params, unravel_fn = tool.params_to_vec(list_of_trainer[i].params, True)
        vec_params_list.append(vec_params)
    vec_params_list = jnp.stack(vec_params_list)
    vec_params_avg = vec_params_list.mean(axis=0)
    cov_low_rank = (vec_params_list - vec_params_avg.reshape(1,-1))
    return vec_params_avg, cov_low_rank

def fge_to_swa(posterior, posthoc_dir=None, dataset_opt=None):
    print(f'Compute SWA')
    trainer_swa = mp.replicate(avg_list_of_trainer(posterior, dataset_opt))
    if posthoc_dir is not None:
        ckpt.save_ckpt(trainer_swa, posthoc_dir)
    return trainer_swa

def fge_to_swag(posterior, posthoc_dir=None, dataset_opt=None):
    print(f'Compute SWAG')
    posterior_swag = gauss_posterior(
        posterior,
        FLAGS.swag_num_ens,
        dataset_opt,
        )
    if posthoc_dir is not None:
        ckpt.save_ens(posterior_swag, posthoc_dir, 'swag')
    return posterior_swag


def merge(arr1, arr2):
    i = 0
    j = 0

    out = []

    while i < len(arr1) and j < len(arr2):
        if arr1[i] < arr2[j]:
            out.append(arr1[i])
            i += 1
        else:
            out.append(arr2[j])
            j += 1

    if i >= len(arr1):
        out += arr2[j:]
    if j >= len(arr2):
        out += arr1[i:]

    return out

def merge_sort(arr):
    if len(arr) <= 1:
        return arr

    return merge(merge_sort(arr[: len(arr) // 2]), merge_sort(arr[len(arr) // 2: ]))

print(merge_sort([5, 2, 7, 3, 9, 1]))


import pandas as pd
from matplotlib import pyplot as plt
import numpy as np
from datetime import datetime
import csv
from tkinter import *

PRESIDENT_INDEX = 0
BIRTHDATE_INDEX = 1
ORDINATION_INDEX = 2
DEATH_INDEX = 3
PRESIDENT_TEMPLE_ANNOUNCEMENTS_INDEX = 4
PRESIDENT_TEMPLE_GROUNDBREAKINGS_INDEX = 5
PRESIDENT_TEMPLE_DEDICATIONS_INDEX = 6
TEMPLE_NAME_INDEX = 0
TEMPLE_ANNOUNCED_INDEX = 1
TEMPLE_GROUNDBREAKING_INDEX = 2
TEMPLE_DEDICATION_INDEX = 3
TEMPLE_NUMBER_SEALING_ROOMS_INDEX = 4
TEMPLE_SQFT_INDEX = 5

def main():
    # Create the Tk root object
    root = Tk()

    Label(root,
            text="""Please choose an option:""",
            justify = LEFT,
            font=("Times New Roman", 15),
            padx = 20).pack()

    # options for the Radiobutton and its values
    CHOICES = [("Church Presidents", "presidents"),
                ("Temples", "temples"),
                ("Temple Statistics", "statistics"),
                ("Bar Chart of Temple Statistics by Each President", "bar")]

    options = StringVar()
    options.set("presidents") #sets the radiobutton to "Church Presidents" by default

    # this function shows choices for the Radiobutton
    # and calls other functions to show when chosen in the Radiobutton
    def ShowChoice():
        selection = options.get()

        if selection == "presidents":
            populate_president_window(frm_main)

        elif selection == "temples":
            populate_temple_window(frm_main)

        elif options.get() == "statistics":
            populate_statistics_window(frm_main)

        elif options.get() == "bar":
            show_graph()

    for choice, val in CHOICES:
        Radiobutton(root,
                    text=choice,
                    padx = 20,
                    font=("Times New Roman",15),
                    variable=options,
                    command=ShowChoice,
                    value=val).pack(anchor=W)

    Label(root,
            text="""-----------------------------------------------------------------""",
            justify = CENTER,
            font=("Times New Roman", 15),
            padx = 20).pack()

    # Main frame window
    frm_main = Frame(root)
    frm_main.master.title("Church Presidents and Temples")
    frm_main.pack(padx=5, pady=5, fill=BOTH, expand=1)

    root.mainloop()

def populate_president_window(frm_main):
    """Populate the "Church President" window of this program.

    Parameter
        frm_main: the main frame (window)
    Return: nothing
    """

    lbl_name = Label(frm_main, text="Enter president:")
    ent_name = Entry(frm_main, width=25)

    lbl_birthdate = Label(frm_main, text="Birthdate:")
    lbl_ordination = Label(frm_main, text="Ordination:")
    lbl_death = Label(frm_main, text="Death:")
    lbl_announcements = Label(frm_main, text="Announcements:")
    lbl_groundbreakings = Label(frm_main, text="Groundbreakings:")
    lbl_dedications = Label(frm_main, text="Dedications:")
    lbl_blank2 = Label(frm_main, text="")

    lbl_dict_birthdate = Label(frm_main, width=20)
    lbl_dict_ordination = Label(frm_main, width=10)
    lbl_dict_death = Label(frm_main, width=10)
    lbl_dict_announcements = Label(frm_main, width=10)
    lbl_dict_groundbreakings = Label(frm_main, width=10)
    lbl_dict_dedications = Label(frm_main, width=4)

    lbl_3 = Label(frm_main, text="""""")

    lbl_blank = Label(frm_main, width=10)
    lbl_days_short_ag = Label(frm_main, width=10)
    lbl_days_short_gd = Label(frm_main, width=10)
    lbl_days_short_ad = Label(frm_main, width=10)
    lbl_days_long_ag = Label(frm_main, width=10)
    lbl_days_long_gd = Label(frm_main, width=10)
    lbl_days_long_ad = Label(frm_main, width=10)

    # Clear button.
    btn_clear = Button(frm_main, text="Clear")

    # Layout all the labels, entry boxes, and buttons in a grid.
    lbl_name.grid(row=0, column=0, padx=3, pady=3, ipadx=25, ipady=10)
    ent_name.grid(row=0, column=1, padx=3, pady=3, ipady=2)
    lbl_birthdate.grid(row=2, column=0, padx=3, pady=3, ipadx=20)
    lbl_dict_birthdate.grid(row=2, column=1, padx=3, pady=3, ipadx=90)
    lbl_ordination.grid(row=3, column=0, padx=3, pady=3, ipadx=20)
    lbl_dict_ordination.grid(row=3, column=1, padx=3, pady=3, ipadx=60)
    lbl_death.grid(row=4, column=0, padx=3, pady=3, ipadx=30)
    lbl_dict_death.grid(row=4, column=1, padx=3, pady=3, ipadx=60)
    lbl_announcements.grid(row=5, column=0, padx=3, pady=3, ipadx=20)
    lbl_dict_announcements.grid(row=5, column=1, padx=3, pady=3, ipadx=60)
    lbl_groundbreakings.grid(row=6, column=0, padx=3, pady=3, ipadx=20)
    lbl_dict_groundbreakings.grid(row=6, column=1, padx=3, pady=3, ipadx=60)
    lbl_dedications.grid(row=7, column=0, padx=3, pady=3, ipadx=20)
    lbl_dict_dedications.grid(row=7, column=1, padx=3, pady=3, ipadx=60)
    lbl_blank2.grid(row=8, column=0, padx=3, pady=3, ipadx=50)
    btn_clear.grid(row=8, column=1, padx=3, pady=3, ipadx=100, sticky="w")

    lbl_3.grid(row=0, column=2, padx=3, pady=3, ipadx=40)
    lbl_blank.grid(row=2, column=2, padx=3, pady=3)
    lbl_days_short_ag.grid(row=3, column=2, padx=3, pady=3)
    lbl_days_short_gd.grid(row=4, column=2, padx=3, pady=3)
    lbl_days_short_ad.grid(row=5, column=2, padx=3, pady=3)
    lbl_days_long_ag.grid(row=6, column=2, padx=3, pady=3)
    lbl_days_long_gd.grid(row=7, column=2, padx=3, pady=3)
    lbl_days_long_ad.grid(row=8, column=2, padx=3, pady=3)

    # This function will be called each time the user types
    # the name of president correctly
    def view(event):

        try:
            presidents_dict = read_dict("presidents.csv", PRESIDENT_INDEX)
            name = ent_name.get()

            if name in presidents_dict:
                president_name = presidents_dict[name]
                birthdate = president_name[BIRTHDATE_INDEX]
                ordination = president_name[ORDINATION_INDEX]
                death = president_name[DEATH_INDEX]
                announcements = president_name[PRESIDENT_TEMPLE_ANNOUNCEMENTS_INDEX]
                groundbreakings = president_name[PRESIDENT_TEMPLE_GROUNDBREAKINGS_INDEX]
                dedications = president_name[PRESIDENT_TEMPLE_DEDICATIONS_INDEX]

                lbl_dict_birthdate.config(text=f"{birthdate}")
                lbl_dict_ordination.config(text=f"{ordination}")
                lbl_dict_death.config(text=f"{death}")
                lbl_dict_announcements.config(text=f"{announcements}")
                lbl_dict_groundbreakings.config(text=f"{groundbreakings}")
                lbl_dict_dedications.config(text=f"{dedications}")

                lbl_blank.config(text=f"")
                lbl_days_short_ag.config(text=f"")
                lbl_days_short_gd.config(text=f"")
                lbl_days_short_ad.config(text=f"")
                lbl_days_long_ag.config(text=f"")
                lbl_days_long_gd.config(text=f"")
                lbl_days_long_ad.config(text=f"")

        except ValueError:
            lbl_dict_birthdate.config(text="")
            lbl_dict_ordination.config(text="")
            lbl_dict_death.config(text="")
            lbl_dict_announcements.config(text="")
            lbl_dict_groundbreakings.config(text="")
            lbl_dict_dedications.config(text="")

    # This function will be called each time
    # the user presses the "Clear" button.
    def clear():
        """Clear all the inputs and outputs."""
        ent_name.delete(0, END)
        # lbl_dict_president.config(text="")
        lbl_dict_birthdate.config(text="")
        lbl_dict_ordination.config(text="")
        lbl_dict_death.config(text="")
        lbl_dict_announcements.config(text="")
        lbl_dict_groundbreakings.config(text="")
        lbl_dict_dedications.config(text="")
        ent_name.focus()

    ent_name.bind("<KeyRelease>", view)
    btn_clear.config(command=clear)
    ent_name.focus()

def populate_temple_window(frm_main):
    """Populate the "Temples" window of this program.

    Parameter
        frm_main: the main frame (window)
    Return: nothing
    """

    lbl_name = Label(frm_main, text="Enter temple:")
    ent_name = Entry(frm_main, width=25)

    lbl_temple = Label(frm_main, text="Temple:")
    lbl_announced = Label(frm_main, text="Announced:")
    lbl_groundbreaking = Label(frm_main, text="Groundbreaking:")
    lbl_dedication = Label(frm_main, text="Dedication:")
    lbl_sealing_rooms = Label(frm_main, text="Sealing Rooms:")
    lbl_sqft = Label(frm_main, text="Square Footage:")
    lbl_blank2 = Label(frm_main, text="")

    lbl_dict_temple = Label(frm_main, width=20)
    lbl_dict_announced = Label(frm_main, width=10)
    lbl_dict_groundbreaking = Label(frm_main, width=10)
    lbl_dict_dedication = Label(frm_main, width=10)
    lbl_dict_sealing_rooms = Label(frm_main, width=10)
    lbl_dict_sqft = Label(frm_main, width=10)

    lbl_3 = Label(frm_main, text="""""")

    lbl_blank = Label(frm_main, width=10)
    lbl_days_short_ag = Label(frm_main, width=10)
    lbl_days_short_gd = Label(frm_main, width=10)
    lbl_days_short_ad = Label(frm_main, width=10)
    lbl_days_long_ag = Label(frm_main, width=10)
    lbl_days_long_gd = Label(frm_main, width=10)
    lbl_days_long_ad = Label(frm_main, width=10)

    # Clear button
    btn_clear = Button(frm_main, text="Clear")

    # Layout all the labels, entry boxes, and buttons in a grid.
    lbl_name.grid(row=0, column=0, padx=3, pady=3, ipadx=25, ipady=10)
    ent_name.grid(row=0, column=1, padx=3, pady=3, ipady=2)
    lbl_temple.grid(row=2, column=0, padx=3, pady=3, ipadx=20)
    lbl_dict_temple.grid(row=2, column=1, padx=3, pady=3, ipadx=90)
    lbl_announced.grid(row=3, column=0, padx=3, pady=3, ipadx=20)
    lbl_dict_announced.grid(row=3, column=1, padx=3, pady=3, ipadx=60)
    lbl_groundbreaking.grid(row=4, column=0, padx=3, pady=3, ipadx=20)
    lbl_dict_groundbreaking.grid(row=4, column=1, padx=3, pady=3, ipadx=60)
    lbl_dedication.grid(row=5, column=0, padx=3, pady=3, ipadx=20)
    lbl_dict_dedication.grid(row=5, column=1, padx=3, pady=3, ipadx=60)
    lbl_sealing_rooms.grid(row=6, column=0, padx=3, pady=3, ipadx=20)
    lbl_dict_sealing_rooms.grid(row=6, column=1, padx=3, pady=3, ipadx=60)
    lbl_sqft.grid(row=7, column=0, padx=3, pady=3, ipadx=20)
    lbl_dict_sqft.grid(row=7, column=1, padx=3, pady=3, ipadx=60)
    lbl_blank2.grid(row=8, column=0, padx=3, pady=3, ipadx=50)
    btn_clear.grid(row=8, column=1, padx=3, pady=3, ipadx=100, sticky="w")

    lbl_3.grid(row=0, column=2, padx=3, pady=3, ipadx=40)
    lbl_blank.grid(row=2, column=2, padx=3, pady=3)
    lbl_days_short_ag.grid(row=3, column=2, padx=3, pady=3)
    lbl_days_short_gd.grid(row=4, column=2, padx=3, pady=3)
    lbl_days_short_ad.grid(row=5, column=2, padx=3, pady=3)
    lbl_days_long_ag.grid(row=6, column=2, padx=3, pady=3)
    lbl_days_long_gd.grid(row=7, column=2, padx=3, pady=3)
    lbl_days_long_ad.grid(row=8, column=2, padx=3, pady=3)

    # This function will be called each time the user types
    # the name of the temple correctly
    def view(event):

        try:
            temples_dict = read_dict("temples.csv", TEMPLE_NAME_INDEX)
            temple = ent_name.get()

            if temple in temples_dict:
                temple_name = temples_dict[temple]
                temple_full_name = temple_name[TEMPLE_NAME_INDEX]
                announced = temple_name[TEMPLE_ANNOUNCED_INDEX]
                groundbreaking = temple_name[TEMPLE_GROUNDBREAKING_INDEX]
                dedication = temple_name[TEMPLE_DEDICATION_INDEX]
                sealing_rooms = temple_name[TEMPLE_NUMBER_SEALING_ROOMS_INDEX]
                sqft = temple_name[TEMPLE_SQFT_INDEX]

                lbl_dict_temple.config(text=f"{temple_full_name}")
                lbl_dict_announced.config(text=f"{announced}")
                lbl_dict_groundbreaking.config(text=f"{groundbreaking}")
                lbl_dict_dedication.config(text=f"{dedication}")
                lbl_dict_sealing_rooms.config(text=f"{sealing_rooms}")
                lbl_dict_sqft.config(text=f"{sqft} sqft")

                lbl_blank.config(text=f"")
                lbl_days_short_ag.config(text=f"")
                lbl_days_short_gd.config(text=f"")
                lbl_days_short_ad.config(text=f"")
                lbl_days_long_ag.config(text=f"")
                lbl_days_long_gd.config(text=f"")
                lbl_days_long_ad.config(text=f"")

        except ValueError:
            lbl_dict_temple.config(text="")
            lbl_dict_announced.config(text="")
            lbl_dict_groundbreaking.config(text="")
            lbl_dict_dedication.config(text="")
            lbl_dict_sealing_rooms.config(text="")
            lbl_dict_sqft.config(text="")

    # This function will be called each time
    # the user presses the "Clear" button.
    def clear():
        """Clear all the inputs and outputs."""
        ent_name.delete(0, END)
        lbl_dict_temple.config(text="")
        lbl_dict_announced.config(text="")
        lbl_dict_groundbreaking.config(text="")
        lbl_dict_dedication.config(text="")
        lbl_dict_sealing_rooms.config(text="")
        lbl_dict_sqft.config(text="")
        ent_name.focus()

    ent_name.bind("<KeyRelease>", view)
    btn_clear.config(command=clear)
    ent_name.focus()

def populate_statistics_window(frm_main):
    """Populate the "Statistics" window of this program.

    Parameter
        frm_main: the main frame (window)
    Return: nothing
    """

    lbl_1 = Label(frm_main,
            text="""A-Announcement\nG-Groundbreaking\nD-Dedication""",
            justify = LEFT,
            font=("Times New Roman", 8))
    lbl_2 = Label(frm_main,
            text="""Temple Name""",
            justify = LEFT,
            font=("Times New Roman", 15))
    lbl_3 = Label(frm_main,
            text="""Duration""",
            justify = LEFT,
            font=("Times New Roman", 15))

    lbl_oldest = Label(frm_main, text="Oldest Temple:")
    lbl_long_ag = Label(frm_main, text="Longest A to G:")
    lbl_long_gd = Label(frm_main, text="Longest G to D:")
    lbl_long_ad = Label(frm_main, text="Longest A to D:")
    lbl_short_ag = Label(frm_main, text="Shortest A to G:")
    lbl_short_gd = Label(frm_main, text="Shortest G to D:")
    lbl_short_ad = Label(frm_main, text="Shortest A to D:")

    lbl_dict_oldest_temple = Label(frm_main, width=20)
    lbl_dict_short_ag = Label(frm_main, width=30)
    lbl_dict_short_gd = Label(frm_main, width=20)
    lbl_dict_short_ad = Label(frm_main, width=20)
    lbl_dict_long_ag = Label(frm_main, width=20)
    lbl_dict_long_gd = Label(frm_main, width=20)
    lbl_dict_long_ad = Label(frm_main, width=20)

    lbl_days_oldest_temple = Label(frm_main, width=10)
    lbl_days_short_ag = Label(frm_main, width=10)
    lbl_days_short_gd = Label(frm_main, width=10)
    lbl_days_short_ad = Label(frm_main, width=10)
    lbl_days_long_ag = Label(frm_main, width=10)
    lbl_days_long_gd = Label(frm_main, width=10)
    lbl_days_long_ad = Label(frm_main, width=10)

    # Layout all the labels, entry boxes, and buttons in a grid.
    lbl_1.grid(row=0, column=0, padx=3, pady=3, ipadx=20)
    lbl_oldest.grid(row=2, column=0, padx=3, pady=3, ipadx=10)
    lbl_long_ag.grid(row=3, column=0, padx=3, pady=3, ipadx=10)
    lbl_long_gd.grid(row=4, column=0, padx=3, pady=3, ipadx=10)
    lbl_long_ad.grid(row=5, column=0, padx=3, pady=3, ipadx=10)
    lbl_short_ag.grid(row=6, column=0, padx=3, pady=3, ipadx=10)
    lbl_short_gd.grid(row=7, column=0, padx=3, pady=3, ipadx=10)
    lbl_short_ad.grid(row=8, column=0, padx=3, pady=3, ipadx=10)

    lbl_2.grid(row=0, column=1, padx=3, pady=3, ipadx=80, ipady=10)
    lbl_dict_oldest_temple.grid(row=2, column=1, padx=3, pady=3, ipadx=80)
    lbl_dict_short_ag.grid(row=3, column=1, padx=3, pady=3)
    lbl_dict_short_gd.grid(row=4, column=1, padx=3, pady=3)
    lbl_dict_short_ad.grid(row=5, column=1, padx=3, pady=3)
    lbl_dict_long_ag.grid(row=6, column=1, padx=3, pady=3)
    lbl_dict_long_gd.grid(row=7, column=1, padx=3, pady=3)
    lbl_dict_long_ad.grid(row=8, column=1, padx=3, pady=3, ipadx=100, ipady=3)

    lbl_3.grid(row=0, column=2, padx=3, pady=3, ipadx=20)
    lbl_days_oldest_temple.grid(row=2, column=2, padx=3, pady=3)
    lbl_days_short_ag.grid(row=3, column=2, padx=3, pady=3)
    lbl_days_short_gd.grid(row=4, column=2, padx=3, pady=3)
    lbl_days_short_ad.grid(row=5, column=2, padx=3, pady=3)
    lbl_days_long_ag.grid(row=6, column=2, padx=3, pady=3)
    lbl_days_long_gd.grid(row=7, column=2, padx=3, pady=3)
    lbl_days_long_ad.grid(row=8, column=2, padx=3, pady=3)

    # get the current date with the same format in the csv file
    current_date = datetime.now().strftime("%d-%b-%Y")
    temples_dict = read_dict("temples.csv", TEMPLE_NAME_INDEX)

    gb_max_days = -1
    de_max_days = -1
    ade_max_days = -1
    max_days = -1
    gb_min_days = 99999999
    de_min_days = 99999999
    ade_min_days = 99999999
    old_temp_name = ""
    gb_max_temp_name = ""
    de_max_temp_name = ""
    ade_max_temp_name = ""
    gb_min_temp_name = ""
    de_min_temp_name = ""
    ade_min_temp_name = ""

    for temple in temples_dict:
        temple_name = temples_dict[temple]
        temple_full_name = temple_name[TEMPLE_NAME_INDEX]
        announced = temple_name[TEMPLE_ANNOUNCED_INDEX]
        groundbreaking = temple_name[TEMPLE_GROUNDBREAKING_INDEX]
        dedication = temple_name[TEMPLE_DEDICATION_INDEX]

        oldest_temple = days_between(current_date, dedication)
        announcement_to_groundbreaking = days_between(announced, groundbreaking)
        groundbreaking_to_dedication = days_between(groundbreaking, dedication)
        announcement_to_dedication = days_between(announced, dedication)

        # this gets the the highest and lowest difference between two dates
        # as well as its corresponding temple
        if oldest_temple > max_days:
            max_days = oldest_temple
            old_temp_name = temple_full_name

        if announcement_to_groundbreaking > gb_max_days:
            gb_max_days = announcement_to_groundbreaking
            gb_max_temp_name = temple_full_name

        if groundbreaking_to_dedication > de_max_days:
            de_max_days = groundbreaking_to_dedication
            de_max_temp_name = temple_full_name

        if announcement_to_dedication > ade_max_days:
            ade_max_days = announcement_to_dedication
            ade_max_temp_name = temple_full_name

        if announcement_to_groundbreaking < gb_min_days:
            gb_min_days = announcement_to_groundbreaking
            gb_min_temp_name = temple_full_name

        if groundbreaking_to_dedication < de_min_days:
            de_min_days = groundbreaking_to_dedication
            de_min_temp_name = temple_full_name

        if announcement_to_dedication < ade_min_days:
            ade_min_days = announcement_to_dedication
            ade_min_temp_name = temple_full_name

    lbl_dict_oldest_temple.config(text=f"{old_temp_name}")
    lbl_dict_short_ag.config(text=f"{gb_max_temp_name}")
    lbl_dict_short_gd.config(text=f"{de_max_temp_name}")
    lbl_dict_short_ad.config(text=f"{ade_max_temp_name}")
    lbl_dict_long_ag.config(text=f"{gb_min_temp_name}")
    lbl_dict_long_gd.config(text=f"{de_min_temp_name}")
    lbl_dict_long_ad.config(text=f"{ade_min_temp_name}")

    lbl_days_oldest_temple.config(text=f"{max_days} days")
    lbl_days_short_ag.config(text=f"{gb_max_days} days")
    lbl_days_short_gd.config(text=f"{de_max_days} days")
    lbl_days_short_ad.config(text=f"{ade_max_days} days")
    lbl_days_long_ag.config(text=f"{gb_min_days} days")
    lbl_days_long_gd.config(text=f"{de_min_days} days")
    lbl_days_long_ad.config(text=f"{ade_min_days} days")

# this function subtracts two given dates and returns number of days
def days_between(date1, date2):
    date1 = datetime.strptime(date1, "%d-%b-%Y")
    date2 = datetime.strptime(date2, "%d-%b-%Y")

    return abs((date2-date1).days)

# this function reads the csv file using pandas and
# creates a bar graph using matplotlib with the data from the csv file
def show_graph():

    plt.style.use('fivethirtyeight')
    fig = plt.gcf()
    fig.canvas.manager.set_window_title("Bar Chart")
    fig.subplots_adjust(bottom=0.25)

    # read the csv file using pandas and store it in the variable 'temples'
    temples = pd.read_csv("presidents.csv")

    # this gets the entities from the csv file
    # that will be used in the bar chart
    # x axis: presidents
    # y axis: number of groundbreakings, dedications, and announcements
    presidents = temples.President
    groundbreakings = temples.Groundbreakings
    dedications = temples.Dedications
    announcements = temples.Announcements

    x_indexes = np.arange(len(presidents))
    w = 0.25

    # setting the 'w' allows to show multiple bar charts
    plt.bar(x_indexes - w, announcements, width = w, color = '#28536B', label='Announcements')
    plt.bar(x_indexes, groundbreakings, width = w, color = '#4F3130', label='Groundbreakings')
    plt.bar(x_indexes + w, dedications, width = w, color = '#6BA368', label='Dedications')

    # this puts title in the chart, labels for x and y axis, legends,
    # and label font sizes
    title_string = "Temple Statistics per President"
    subtitle_string = "**Data as of April 2022**"

    plt.suptitle(title_string, fontsize=12)
    plt.title(subtitle_string, fontsize=8)
    plt.xlabel("Church Presidents", fontsize=10)
    plt.ylabel("Number of Temples", fontsize=10)
    plt.tick_params(axis='x', which='major', labelsize=6)
    plt.tick_params(axis='y', which='major', labelsize=8)
    plt.xticks(x_indexes, presidents, rotation = 90)
    plt.legend(loc=2, prop={'size': 10})

    plt.show()

# this function reads the csv file and returns a dictionary
def read_dict(filename, key_column_index):

    dictionary = {}

    with open(filename, "rt") as csv_file:

        reader = csv.reader(csv_file)
        next(reader)

        for row_list in reader:
            key = row_list[key_column_index]
            dictionary[key] = row_list

    return dictionary

if __name__ == "__main__":
    main()


# -*- coding: utf-8 -*-
"""Creator plugin for creating workfiles."""
from openpype.pipeline import CreatedInstance, AutoCreator
from openpype.client import get_asset_by_name
from openpype.hosts.maya.api import plugin
from maya import cmds

class CreateWorkfile(plugin.MayaCreatorBase, AutoCreator):
    """Workfile auto-creator."""
    identifier = "io.openpype.creators.maya.workfile"
    label = "Workfile"
    family = "workfile"
    icon = "fa5.file"

    default_variant = "Main"

    def create(self):

        variant = self.default_variant
        current_instance = next(
            (
                instance for instance in self.create_context.instances
                if instance.creator_identifier == self.identifier
            ), None)

        project_name = self.project_name
        asset_name = self.create_context.get_current_asset_name()
        task_name = self.create_context.get_current_task_name()
        host_name = self.create_context.host_name

        if current_instance is None:
            asset_doc = get_asset_by_name(project_name, asset_name)
            subset_name = self.get_subset_name(
                variant, task_name, asset_doc, project_name, host_name
            )
            data = {
                "asset": asset_name,
                "task": task_name,
                "variant": variant
            }
            data.update(
                self.get_dynamic_data(
                    variant, task_name, asset_doc,
                    project_name, host_name, current_instance)
            )
            self.log.info("Auto-creating workfile instance...")
            current_instance = CreatedInstance(
                self.family, subset_name, data, self
            )
            self._add_instance_to_context(current_instance)
        elif (
                current_instance["asset"] != asset_name
                or current_instance["task"] != task_name
        ):
            # Update instance context if is not the same
            asset_doc = get_asset_by_name(project_name, asset_name)
            subset_name = self.get_subset_name(
                variant, task_name, asset_doc, project_name, host_name
            )
            current_instance["asset"] = asset_name
            current_instance["task"] = task_name
            current_instance["subset"] = subset_name

    def collect_instances(self):
        self.cache_subsets(self.collection_shared_data)
        cached_subsets = self.collection_shared_data["maya_cached_subsets"]
        for node in cached_subsets.get(self.identifier, []):
            node_data = self.read_instance_node(node)

            created_instance = CreatedInstance.from_existing(node_data, self)
            self._add_instance_to_context(created_instance)

    def update_instances(self, update_list):
        for created_inst, _changes in update_list:
            data = created_inst.data_to_store()
            node = data.get("instance_node")
            if not node:
                node = self.create_node()
                created_inst["instance_node"] = node
                data = created_inst.data_to_store()

            self.imprint_instance_node(node, data)

    def create_node(self):
        node = cmds.sets(empty=True, name="workfileMain")
        cmds.setAttr(node + ".hiddenInOutliner", True)
        return node


import os

from sanic import Sanic, request, response
from sanic.response import json
from sanic_cors import CORS, cross_origin
import predictor
import iowa_predictor
import json as j

app = Sanic(__name__)
cors = CORS(app)
port = os.environ.get('PORT', 8000)
app.config['CORS_HEADERS'] = 'Content-Type'

test_team = [{'age': 19, 'gender': 'Male', 'married': False},
 {'age': 19, 'gender': 'Male', 'married': True},
 {'age': 57, 'gender': 'Female', 'married': True},
 {'age': 57, 'gender': 'Female', 'married': True}]

@app.route("/" , methods=['POST'])
@cross_origin(app)
async def test_fanction(request):
    answer = married_to_bool(request.json)
    predicted_sentences = predictor.get_answers(answer)
    return response.json({'answer': predicted_sentences})

@app.route("/" , methods=['OPTIONS'])
@cross_origin(app)
async def test_fanction(request):
    return response.json({'looks':'good'})

@app.route("/iowa" , methods=['POST'])
@cross_origin(app)
async def test_fanction(request):
    answer = married_to_bool(request.json)
    predicted_sentences = iowa_predictor.get_answers(answer)
    return response.json({'answer': predicted_sentences})

@app.route("/iowa" , methods=['OPTIONS'])
@cross_origin(app)
async def test_fanction(request):
    return response.json({'looks':'good'})

def married_to_bool(team):
    for i in team:
        i['married'] = i['married'] == 'Married'
    return team

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=port, debug=True)


from flask import Flask, render_template, redirect, request
import ctypes

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/home', methods=['GET', 'POST'])
def home():
    if request.form['usuario'] =='admin' and request.form['senha']=='admin':

        return render_template('home.html')
    else:
        ctypes.windll.user32.MessageBoxW(0, "Usuário e Senha não conferem"),
        return render_template('index.html')

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


# Создайте программу для игры в ""Крестики-нолики"".

def PrintValue(value):
    if value == 'x':
        print("\033[1m\033[31m{}\033[0m".format(value), end='')
    elif value == '○':
        print("\033[1m\033[34m{}\033[0m".format(value), end='')
    else:
        print("\033[2m{}\033[0m".format(value), end='')

def PrintARow(first, second, third):
    print('│  ', end='')
    PrintValue(first)
    print('  │  ', end='')
    PrintValue(second)
    print('  │  ', end='')
    PrintValue(third)
    print('  │')

def PrintGameField(positions):
    print('┌─────┬─────┬─────┐')
    PrintARow(positions[1], positions[2], positions[3])
    print('├─────┼─────┼─────┤')
    PrintARow(positions[4], positions[5], positions[6])
    print('├─────┼─────┼─────┤')
    PrintARow(positions[7], positions[8], positions[9])
    print('└─────┴─────┴─────┘')

def GetUserTurn(mark, positions):
    print(f'Player {mark}`s moove.\nEnter position you want to put {mark}', end=': ')
    position = input()

    while position not in dict.values(positions):
        print(f'Invalid value.\nEnter position you want to put {mark}', end=': ')
        position = input()

    positions[int(position)] = mark

def GameStopCheck(positions):
    for i in 1, 2, 3:
        if positions[i] == positions[i + 3] == positions[i + 6]:
            return positions[i]

    for i in 1, 4, 7:
        if positions[i] == positions[i + 1] == positions[i + 2]:
            return positions[i]

    if positions[1] == positions[2] == positions[9]:
        return positions[1]

    if positions[3] == positions[5] == positions[7]:
        return positions[3]

    return False

def main():
    usermark = 'x'
    positions = {1: '1', 2: '2', 3: '3', 4: '4', 5: '5', 6: '6', 7: '7', 8: '8', 9: '9'}
    winner = False

    PrintGameField(positions)
    print('Let the game begins!')

    for turns in range(9):
        GetUserTurn(usermark, positions)
        PrintGameField(positions)
        winner = GameStopCheck(positions)
        if winner:
            break
        elif usermark == 'x':
            usermark = '○'
        else:
            usermark = 'x'

    if winner:
        print(f'The winner is Player {winner}.')
        print('Congratulations!')
    else:
        print('The game was insane!\nIt`s a DRAW!')

if __name__ == "__main__":
    main()


import pickle
from transformers import GPT2Tokenizer
import torch
import re

SEQ_LEN = 32

# Load word->voc map
word_voc_map = pickle.load(open("save/str_vocab_map.pkl", "rb"))

# get gpt2 tok
tk = GPT2Tokenizer.from_pretrained("gpt2")

# load in sentence data
sentences = open("save/str_real_data.txt", "r")
str_data = [line.rstrip("\n") for line in sentences]

# define outputs
tok_data = []  # tokenized data
gpt_tok_data = []  # gpt2 tok data
tok_mask = []  # for masking out (since can map to > 1)

for i in range(len(str_data)):
    # split
    s_spl = re.findall(r"\w+|[^\w\s]", str_data[i])

    """
        Tokenize into new vocab
    """
    # tokenize each part
    tok_data.append([word_voc_map[w] for w in s_spl])

    """
        Tokenize each token from previous step into GPT2
        token_mask=1 at last token for each word
    """
    tok = tk(s_spl)["input_ids"]

    mask = []
    tok_f = []
    for t in tok:
        mask += (len(t) - 1) * [False] + [True]
        tok_f.extend(t)
    tok_mask.append(mask)
    gpt_tok_data.append(tok_f)

# find max len for padding
max_tok = max([len(x) for x in tok_data])
max_gpt_tok = max([len(x) for x in gpt_tok_data])

# pad
for i in range(len(str_data)):
    tok_data[i] += (max_tok - len(tok_data[i])) * [word_voc_map["eos"]]

    gpt_tok_data[i] += (max_gpt_tok - len(tok_mask[i])) * [50256]
    tok_mask[i] += (max_gpt_tok - len(tok_mask[i])) * [True]

# conv to tensors
tok_data = torch.tensor(tok_data)
gpt_tok_data = torch.tensor(gpt_tok_data)
tok_mask = torch.tensor(tok_mask)

# dump into file
pickle.dump((tok_data, gpt_tok_data, tok_mask), open("save/train_data.pkl", "wb"))


from collections import deque

from exercises.lib.graph import Graph
from exercises.lib.graph import Node

"""
4.7
You are given a list of projects and a list of dependencies (which is a list of
pairs of projects, where the second project is dependent on the first project.)
All of a project's dependencies must be built before the project is.  Find a
build order that will allow the projects to be built.  If there is no valid
build order, return an error.
"""

def build_order(pairs):
    """
    The general idea is to build a directed graph from the dependencies, and
    then traverse the graph's nodes from the "root" nodes, nodes that have zero
    incoming nodes.

    There is two situations where a graph doesn't have a valid build order.
    The first is if a cycle is present.  The second is a subcase of the first,
    in which there are no nodes with zero incoming nodes.

    This problem was more involved than expected, as there are a number of
    pitfalls when carefully trying to determine the order and what has already
    been built.
    """
    graph = Graph()
    for pair in pairs:
        if len(pair) != 2:
            raise ValueError

        source = get_node(pair[0], graph)
        target = get_node(pair[1], graph)

        graph.link(source, target)

    roots = get_roots(graph)
    if len(roots) == 0:
        raise ValueError

    order = []
    built = set()
    queue = deque(roots)

    while len(queue) > 0:
        node = queue.popleft()

        if node in built:
            # cycle detected
            raise ValueError

        # breaks Node encapsulation :(
        if node.incoming.issubset(built):
            built.add(node)
            # don't add in any dependency already in the queue
            queue.extend(node.outgoing - set(queue))

            order.append(node.value)
        else:
            # add it back to the end
            queue.append(node)

    return order

def get_node(value, graph):
    for node in graph.nodes:
        if node.value == value:
            return node

    node = Node(value, directed=True)
    graph.nodes.add(node)

    return node

def get_roots(graph):
    return list(filter(lambda node: len(node.incoming) == 0, graph.nodes))


import numpy as np
import cv2
from holotile import *
from pathlib import Path
import matplotlib.pyplot as plt
import time
from PIL import Image

# PATHS
LOGO_PATH = Path() / "demo targets" / "logo.png"

WAVELENGTH = 532E-9
FOCAL_LENGTH = 150E-3
SLM_PIXEL_SIZE = 8.0E-6
SLM_N = 1080
SLM_DIM = SLM_PIXEL_SIZE * SLM_N
INPUT_BEAM_HALF_WIDTH = 3E-3

slm_enable = True
cam_enable = False

if slm_enable:
    from slm import SLM
    slm = SLM()

if cam_enable:
    from camera.edmundcam import EdmundCamera
    cam = EdmundCamera(exposure_time=.508)

slm_x, slm_y = np.meshgrid(np.linspace(-SLM_DIM / 2, SLM_DIM / 2, SLM_N),
                               np.linspace(-SLM_DIM / 2, SLM_DIM / 2, SLM_N))

def sdu_logo_demo():
    beamshaper = SquareTopHatShaper(WAVELENGTH, FOCAL_LENGTH, (slm_x, slm_y))

    holotile = HoloTile.from_tile_number(WAVELENGTH, FOCAL_LENGTH, INPUT_BEAM_HALF_WIDTH, (slm_x, slm_y), beam_shaping=beamshaper, n_tiles=18)
    #holotile.translate(-3E-3, 0, 0)
    logo_image = cv2.imread(str(LOGO_PATH), -1)
    logo_image = logo_image[:, :, 0]
    logo_image = logo_image.astype(np.float64) / 255.0
    hologram, tiled, psf, target = holotile.generate(logo_image)
    recon = holotile.reconstruct(hologram)

    if slm_enable:
        slm.show_phase(hologram)
        if cam_enable:
            fig, ax = plt.subplots(1,2, figsize=(10,6))
            ax = ax.flatten()
            ax[0].imshow(recon, cmap='gray')
            ax[1].imshow(cam.capture())
            plt.show()
        else:
            fig, ax = plt.subplots(figsize=(6, 6))
            ax.imshow(recon, cmap='gray')
            plt.show()
            plt.waitforbuttonpress()

def find_R():
    beamshaper = SquareTopHatShaper(WAVELENGTH, FOCAL_LENGTH, (slm_x, slm_y))
    fig, ax = plt.subplots(3, 3, sharex=True, sharey=True)
    ax = ax.flatten()
    for i, R in enumerate(np.linspace(2E-3, 3.8E-3, 9)):
        holotile = HoloTile.from_tile_number(WAVELENGTH, FOCAL_LENGTH, INPUT_BEAM_HALF_WIDTH, (slm_x, slm_y), beam_shaping=beamshaper, n_tiles=26)
        #holotile.translate(-3E-3, 0, 0)
        holotile.R = R
        logo_image = cv2.imread(str(LOGO_PATH), -1)
        logo_image = logo_image[:, :, 0]
        logo_image = logo_image.astype(np.float64) / 255.0
        hologram, tiled, psf, target = holotile.generate(logo_image)
        if slm_enable:
            slm.show_phase(hologram)
        ax[i].imshow(cam.capture(), cmap='gray')
        ax[i].set_title(f"{R*1E3: .2f}")
    plt.tight_layout()
    plt.show()

if __name__ == '__main__':
    # SDU Logo
    sdu_logo_demo()
    #find_R()


from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext
import sys
import setuptools

__version__ = '0.0.1'

# Building: MACOSX_DEPLOYMENT_TARGET=10.9 python setup.py build_ext -f --inplace
# Testing: PYTHONPATH=. pytest --benchmark-name=long --benchmark-sort=name --benchmark-save=benchmark_00 --benchmark-warmup=on tests/unit/
# --benchmark-warmup=on is slow as it does about 10000 warmup iterations.
# Benchmark data in .benchmarks

# from setuptools import setup, find_packages
DEBUG = False

EXTRA_COMPILE_ARGS = [
    '-Wall',
    '-Wextra',
#     '-Werror',
#     '-Wfatal-errors',
#     '-pedantic',
]
if DEBUG:
    # Pybind11 in debug mode #if !defined(NDEBUG)
    EXTRA_COMPILE_ARGS += ['-DDEBUG', '-O0', '-g', '-UNDEBUG']

class get_pybind_include(object):
    """Helper class to determine the pybind11 include path

    The purpose of this class is to postpone importing pybind11
    until it is actually installed, so that the ``get_include()``
    method can be invoked. """

    def __init__(self, user=False):
        self.user = user

    def __str__(self):
        import pybind11
        return pybind11.get_include(self.user)

CPY_UTILITY_SOURCES = [
    'xmlwriter/cpy/utils/ConvertPyBytes.cpp',
    'xmlwriter/cpy/utils/ConvertPyBytearray.cpp',
    'xmlwriter/cpy/utils/ConvertPyStr.cpp',
    'xmlwriter/cpy/utils/cpython_asserts.cpp',
]

CPY_UTILITY_HEADER_DIRS = ['xmlwriter/cpy/utils']

ext_modules = [
    # Pybind11 wrapper to the C++ XmlStream
    Extension(
        "pbXmlWrite",
        sources=[
            'xmlwriter/cpy/pbXmlWrite.cpp',
            'xmlwriter/cpy/XmlWrite_docs.cpp',
            'xmlwriter/cpp/XmlWrite.cpp',
            'xmlwriter/cpp/base64.cpp',
        ],
        include_dirs=[
            'xmlwriter/cpp',
            # Path to pybind11 headers
            get_pybind_include(),
            get_pybind_include(user=True)
        ],
        language='c++'
    ),
    # CPython wrapper to the C++ XmlStream
    Extension(
        "cXmlWrite",
        sources=[
            'xmlwriter/cpy/cXmlWrite.cpp',
            'xmlwriter/cpy/XmlWrite_docs.cpp',
            'xmlwriter/cpp/XmlWrite.cpp',
            'xmlwriter/cpp/base64.cpp',
        ] + CPY_UTILITY_SOURCES,
        include_dirs = [
            'xmlwriter/cpp',
            'xmlwriter/cpy',
        ] + CPY_UTILITY_HEADER_DIRS,
        library_dirs = [],
#         extra_compile_args=[],
        language='c++'
    ),
]

# As of Python 3.6, CCompiler has a `has_flag` method.
# cf http://bugs.python.org/issue26689
def has_flag(compiler, flagname):
    """Return a boolean indicating whether a flag name is supported on
    the specified compiler.
    """
    import tempfile
    with tempfile.NamedTemporaryFile('w', suffix='.cpp') as f:
        f.write('int main (int argc, char **argv) { return 0; }')
        try:
            compiler.compile([f.name], extra_postargs=[flagname])
        except setuptools.distutils.errors.CompileError:
            return False
    return True

def cpp_flag(compiler):
    """Return the -std=c++[11/14] compiler flag.

    The c++14 is preferred over c++11 (when it is available).
    """
    # Hack, won't build on mac os x otherwise
    return '-std=c++11'
    if has_flag(compiler, '-std=c++14'):
        return '-std=c++14'
    elif has_flag(compiler, '-std=c++11'):
        return '-std=c++11'
    else:
        raise RuntimeError('Unsupported compiler -- at least C++11 support '
                           'is needed!')

class BuildExt(build_ext):
    """A custom build extension for adding compiler-specific options."""
    c_opts = {
        'msvc': ['/EHsc'],
        'unix': [],
    }

    if sys.platform == 'darwin':
        c_opts['unix'] += ['-stdlib=libc++', '-mmacosx-version-min=10.7']

    def build_extensions(self):
        ct = self.compiler.compiler_type
        opts = self.c_opts.get(ct, [])
        if ct == 'unix':
            opts.append('-DVERSION_INFO="%s"' % self.distribution.get_version())
            opts.append(cpp_flag(self.compiler))
            if has_flag(self.compiler, '-fvisibility=hidden'):
                opts.append('-fvisibility=hidden')
        elif ct == 'msvc':
            opts.append('/DVERSION_INFO=\\"%s\\"' % self.distribution.get_version())
        for ext in self.extensions:
            ext.extra_compile_args = opts + EXTRA_COMPILE_ARGS
        build_ext.build_extensions(self)

test_requirements = [
    'pytest',
    'pytest-benchmark',
]

setup(
    name='xmlwriter',
    version=__version__,
    author='Paul Ross',
    author_email='apaulross@gmail.com',
    url='https://github.com/paulross/xmlwriter',
    packages=setuptools.find_packages('.'), #'xmlwriter/py'),# include=['xmlwriter']),
    package_dir={'' : '.'}, #'xmlwriter/py'},
    description='An XML/HTML/SVG writer project using pybind11',
    long_description='',
    ext_modules=ext_modules,
    install_requires=['pybind11>=2.2'],
    tests_require=test_requirements,
    cmdclass={'build_ext': BuildExt},
    zip_safe=False,
)