# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
import h5py
from pkg_resources import resource_filename

#%%
def _load_dataset(filename, partition='complete', data_type='pandas', **kwargs):
    """
    Load an example dataset from deepsurvk.datasets.
    All datasets correspond to the ones used originally in [#katzman0]_.

    Parameters
    ----------
    filename: string
        Name of the dataset (e.g., 'whas.h5')

    partition: string
        Partition of the data to load.

        Possible values are:
            * ``complete`` - The whole dataset (default)
            * ``training`` or ``train`` - Training partition as used in the original DeepSurv
            * ``testing`` or ``test`` - Testing partition as used in the original DeepSurv

    data_type: string
        Data type of the data.

        Possible values are:
            * ``pandas`` or ``pd`` or ``dataframe`` or ``df``- pandas DataFrame (default)
            * ``numpy`` or ``np`` - NumPy array

        .. note::
            NumPy is supported as an option, but DeepSurvK is built
            with pandas in mind.

    Returns
    -------
    tuple of pandas DataFrames
        * X - Features
        * Y - Target variable
        * E - Event variable

    References
    ----------
    .. [#katzman0] Katzman, Jared L., et al. "DeepSurv: personalized treatment recommender system using a Cox proportional hazards deep neural network." BMC medical research methodology 18.1 (2018): 24.
    """

    filename_ = resource_filename('deepsurvk', 'datasets/data/' + filename)

    # Read training data.
    with h5py.File(filename_, 'r') as f:
        X_train = f['train']['x'][()]
        E_train = f['train']['e'][()]
        Y_train = f['train']['t'][()].reshape(-1, 1)

    # Read testing data.
    with h5py.File(filename_, 'r') as f:
        X_test = f['test']['x'][()]
        E_test = f['test']['e'][()]
        Y_test = f['test']['t'][()].reshape(-1, 1)

    # Define data partitions.
    if partition == 'training' or partition == 'train':
        X = X_train
        Y = Y_train
        E = E_train
    elif partition == 'testing' or partition == 'test':
        X = X_test
        Y = Y_test
        E = E_test
    elif partition == 'complete':
        X = np.concatenate((X_train, X_test), axis=0)
        Y = np.concatenate((Y_train, Y_test), axis=0)
        E = np.concatenate((E_train, E_test), axis=0)
    else:
        raise ValueError('Invalid partition.')

    # If NumPy, do nothing (already in that format).
    if (data_type == 'numpy') or (data_type=='np') or (data_type=='array'):
        pass

    # Otherwise, convert to pandas DataFrame.
    elif (data_type == 'pandas') or (data_type=='pd') or (data_type=='dataframe') or (data_type=='df'):
        X, Y, E = _numpy_to_pandas(X, Y, E, filename)

    else:
        raise ValueError("Invalid data type.")

    return X, Y, E

#%%
def _numpy_to_pandas(X, Y, E, filename):
    """
    Convert a data NumPy array to pandas DataFrame.

    Parameters
    ----------
    X: NumPy array
        Feature matrix
    Y: NumPy array
        Output array
    E: NumPy array
        Event array
    filename: string
        Name of the dataset (e.g., 'whas.h5')

    Returns
    -------
    tuple
        Tuple with df_X, df_Y, and df_E
    """
    # Get columns names and data types.
    column_names = _get_column_names(filename)
    data_types = _get_data_types(filename)

    # Create pandas DataFrames
    df_X = pd.DataFrame(data=X, columns=column_names)
    df_X = df_X.astype(data_types)

    df_Y = pd.DataFrame(data=Y, columns=['T'], dtype=np.float64)
    df_E = pd.DataFrame(data=E, columns=['E'], dtype=np.int32)

    return df_X, df_Y, df_E

#%%
def _get_column_names(filename):
    """
    Get the data column names (needed to create a pandas DataFrame).

    Parameters
    ----------
    filename: string
        Name of the dataset (e.g., 'whas.h5')

    Returns
    -------
    column_names: list
        Column names corresponding to the data.
    """
    # Remove file name extension.
    filename = filename.split('.h5')[0]

    # Define column names for each dataset.
    if filename=='metabric':
        column_names = ['gene1', 'gene2', 'gene3', 'gene4', 'radio', 'horm', 'chemo', 'er_status', 'age']
    elif filename=='rgbsg':
        column_names = ['horm_treatment', 'grade', 'menopause' ,'age' ,'n_positive_nodes', 'progesterone' ,'estrogen']
    elif filename=='simulated_gaussian':
        column_names = ['x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9', 'x10']
    elif filename=='simulated_linear':
        column_names = ['x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9', 'x10']
    elif filename=='simulated_treatment':
        column_names = ['x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9', 'x10', 'treatment']
    elif filename=='support':
        column_names = ['age', 'sex', 'race', 'n_comorbidities', 'diabetes', 'dementia', 'cancer', 'blood_pressure', 'heart_rate', 'respiration_rate', 'temperature', 'white_blood_cell', 'serum_sodium', 'serum_creatinine']
    elif filename=='whas':
        column_names = ['shock', 'age', 'sex', 'bmi', 'chf', 'recurrent']

    return column_names

#%%
def _get_data_types(filename):
    """
    Get the right data types of the columns (needed to create a pandas DataFrame).

    Parameters
    ----------
    filename: string
        Name of the dataset (e.g., 'whas.h5')

    Returns
    -------
    data_types: dictionary
        Each key corresponds to the column name.
        Each value corresponds to the data type.
    """
    # Remove file name extension.
    filename = filename.split('.h5')[0]

    # Assign data type for each column for each dataset.
    if filename=='metabric':
        data_types_ = ['float64', 'float64', 'float64', 'float64', 'int32', 'int32', 'int32', 'int32', 'float64']
    elif filename=='rgbsg':
        data_types_ = ['int32', 'int32', 'int32', 'int32' ,'int32', 'int32', 'int32']
    elif filename=='simulated_gaussian':
        data_types_ = ['float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64']
    elif filename=='simulated_linear':
        data_types_ = ['float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64']
    elif filename=='simulated_treatment':
        data_types_ = ['float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'int32']
    elif filename=='support':
        data_types_ = ['float64', 'int32', 'int32', 'int32', 'int32', 'int32', 'int32', 'int32', 'int32', 'int32', 'float64', 'int32', 'float64', 'float64']
    elif filename=='whas':
        data_types_ = ['int32', 'int32', 'int32', 'float64', 'int32', 'int32']

    # Create dictionary.
    keys = _get_column_names(filename)
    data_types = dict(zip(keys, data_types_))

    return data_types

#%%
def load_metabric(partition='complete', **kwargs):
    """
    Data from the Molecular Taxonomy of Breast Cancer International
    Consortium (METABRIC), which uses gene and protein expression
    profiles to determine new breast cancer subgroups

    It consists of clinical features of 1980 patients, of which 57.72%
    have an observed death due to breast cancer with a median survival time
    of 116 months. However, the file only contains data of 1904 patients.

    For more information, see [#curtis]_ as well as the accompanying README.

    Parameters
    ----------
    partition: string
        Partition of the data to load.

        Possible values are:
            * ``complete`` - The whole dataset (default)
            * ``training`` or ``train`` - Training partition as used in the original DeepSurv
            * ``testing`` or ``test`` - Testing partition as used in the original DeepSurv

    data_type: string
        Data type of the data.

        Possible values are:
            * ``pandas`` or ``pd`` or ``dataframe`` or ``df``- pandas DataFrame (default)
            * ``numpy`` or ``np`` - NumPy array

        .. note::
            NumPy is supported as an option, but DeepSurvK is built
            with pandas in mind.

    Returns
    -------
    tuple of pandas DataFrames
        * X - Features
        * Y - Target variable
        * E - Event variable

    References
    ----------
    .. [#curtis] Curtis, Christina, et al. "The genomic and transcriptomic architecture of 2,000 breast tumours reveals novel subgroups." Nature 486.7403 (2012): 346-352.
    """
    return _load_dataset('metabric.h5', partition=partition, **kwargs)

#%%
def load_rgbsg(partition='complete', **kwargs):
    """
    The training partition belongs to the Rotterdam tumor bank dataset [#foekens]_.
    It contains records of 1546 patients with node-positive breast cancer.
    Nearly 90% of the patients have an observed death time.

    The testing partitiong belongs to the German Breast Cancer Study
    Group (GBSG) [#schumacher]_. It contains records for 686 patients (of which 56 % are
    censored) in a randomized clinical trial that studied the effects of
    chemotherapy and hormone treatment on survival rate.

    For more information, see [#foekens]_ and [#schumacher]_, as well as the accompanying README.

    Parameters
    ----------
    partition: string
        Partition of the data to load.

        Possible values are:
            * ``complete`` - The whole dataset (default)
            * ``training`` or ``train`` - Training partition as used in the original DeepSurv
            * ``testing`` or ``test`` - Testing partition as used in the original DeepSurv

    data_type: string
        Data type of the data.

        Possible values are:
            * ``pandas`` or ``pd`` or ``dataframe`` or ``df``- pandas DataFrame (default)
            * ``numpy`` or ``np`` - NumPy array

        .. note::
            NumPy is supported as an option, but DeepSurvK is built
            with pandas in mind.

    Returns
    -------
    tuple of pandas DataFrames
        * X - Features
        * Y - Target variable
        * E - Event variable

    References
    ----------
    .. [#foekens] Foekens, John A., et al. "The urokinase system of plasminogen activation and prognosis in 2780 breast cancer patients." Cancer research 60.3 (2000): 636-643.

    .. [#schumacher] Schumacher, M., et al. "Randomized 2 x 2 trial evaluating hormonal treatment and the duration of chemotherapy in node-positive breast cancer patients. German Breast Cancer Study Group." Journal of Clinical Oncology 12.10 (1994): 2086-2093.
    """
    return _load_dataset('rgbsg.h5', partition=partition, **kwargs)

#%%
def load_simulated_gaussian(partition='complete', **kwargs):
    """
    Synthetic data with a Gaussian (non-linear) log-risk function.

    For more information, see [#katzman1]_ as well as the accompanying README.

    Parameters
    ----------
    partition: string
        Partition of the data to load.

        Possible values are:
            * ``complete`` - The whole dataset (default)
            * ``training`` or ``train`` - Training partition as used in the original DeepSurv
            * ``testing`` or ``test`` - Testing partition as used in the original DeepSurv

    data_type: string
        Data type of the data.

        Possible values are:
            * ``pandas`` or ``pd`` or ``dataframe`` or ``df``- pandas DataFrame (default)
            * ``numpy`` or ``np`` - NumPy array

        .. note::
            NumPy is supported as an option, but DeepSurvK is built
            with pandas in mind.

    Returns
    -------
    tuple of pandas DataFrames
        * X - Features
        * Y - Target variable
        * E - Event variable

    References
    ----------
    .. [#katzman1] Katzman, Jared L., et al. "DeepSurv: personalized treatment recommender system using a Cox proportional hazards deep neural network." BMC medical research methodology 18.1 (2018): 24.
    """
    return _load_dataset('simulated_gaussian.h5', partition=partition, **kwargs)

#%%
def load_simulated_linear(partition='complete', **kwargs):
    """
    Synthetic data with a linear log-risk function.

    For more information, see [#katzman2]_ as well as the accompanying README.

    Parameters
    ----------
    partition: string
        Partition of the data to load.

        Possible values are:
            * ``complete`` - The whole dataset (default)
            * ``training`` or ``train`` - Training partition as used in the original DeepSurv
            * ``testing`` or ``test`` - Testing partition as used in the original DeepSurv

    data_type: string
        Data type of the data.

        Possible values are:
            * ``pandas`` or ``pd`` or ``dataframe`` or ``df``- pandas DataFrame (default)
            * ``numpy`` or ``np`` - NumPy array

        .. note::
            NumPy is supported as an option, but DeepSurvK is built
            with pandas in mind.

    Returns
    -------
    tuple of pandas DataFrames
        * X - Features
        * Y - Target variable
        * E - Event variable

    References
    ----------
    .. [#katzman2] Katzman, Jared L., et al. "DeepSurv: personalized treatment recommender system using a Cox proportional hazards deep neural network." BMC medical research methodology 18.1 (2018): 24.
    """
    return _load_dataset('simulated_linear.h5', partition=partition, **kwargs)

#%%
def load_simulated_treatment(partition='complete', **kwargs):
    """
    Synthetic data similar to the simulated_gaussian one, with an additional
    column representing treatment.

    For more information, see [#katzman3]_ as well as the accompanying README.

    Parameters
    ----------
    partition: string
        Partition of the data to load.

        Possible values are:
            * ``complete`` - The whole dataset (default)
            * ``training`` or ``train`` - Training partition as used in the original DeepSurv
            * ``testing`` or ``test`` - Testing partition as used in the original DeepSurv

    data_type: string
        Data type of the data.

        Possible values are:
            * ``pandas`` or ``pd`` or ``dataframe`` or ``df``- pandas DataFrame (default)
            * ``numpy`` or ``np`` - NumPy array

        .. note::
            NumPy is supported as an option, but DeepSurvK is built
            with pandas in mind.

    Returns
    -------
    tuple of pandas DataFrames
        * X - Features
        * Y - Target variable
        * E - Event variable

    References
    ----------
    .. [#katzman3] Katzman, Jared L., et al. "DeepSurv: personalized treatment recommender system using a Cox proportional hazards deep neural network." BMC medical research methodology 18.1 (2018): 24.
    """
    return _load_dataset('simulated_treatment.h5', partition=partition, **kwargs)

#%%
def load_support(partition='complete', **kwargs):
    """
    Data from the Study to Understand Prognoses Preferences Outcomes
    and Risks of Treatment (SUPPORT), which studied the survival time of
    seriously ill hospitalized adults.

    Originally, it consists of 14 clinical features of 9105 patients.
    However, patients with missing features were dropped, leaving a total
    of 8873 patients.

    For more information, see [#knaus]_ as well as the accompanying README.

    Parameters
    ----------
    partition: string
        Partition of the data to load.

        Possible values are:
            * ``complete`` - The whole dataset (default)
            * ``training`` or ``train`` - Training partition as used in the original DeepSurv
            * ``testing`` or ``test`` - Testing partition as used in the original DeepSurv

    data_type: string
        Data type of the data.

        Possible values are:
            * ``pandas`` or ``pd`` or ``dataframe`` or ``df``- pandas DataFrame (default)
            * ``numpy`` or ``np`` - NumPy array

        .. note::
            NumPy is supported as an option, but DeepSurvK is built
            with pandas in mind.

    Returns
    -------
    tuple of pandas DataFrames
        * X - Features
        * Y - Target variable
        * E - Event variable

    References
    ----------
    .. [#knaus] Knaus, William A., et al. "The SUPPORT prognostic model: Objective estimates of survival for seriously ill hospitalized adults." Annals of internal medicine 122.3 (1995): 191-203.
    """
    return _load_dataset('support.h5', partition=partition, **kwargs)

#%%
def load_whas(partition='complete', **kwargs):
    """
    Data from the Worcester Heart Attack Study (WHAS), which investigates
    the effects of a patient's factors on acute myocardial infraction (MI)
    survival.

    It consists of 1638 observations and 5 features: age, sex,
    body-mass-index (BMI), left heart failure complications (CHF), and order
    of MI (MIORD).

    For more information, see [#hosmer]_ as well as the accompanying README.

    Parameters
    ----------
    partition: string
        Partition of the data to load.

        Possible values are:
            * ``complete`` - The whole dataset (default)
            * ``training`` or ``train`` - Training partition as used in the original DeepSurv
            * ``testing`` or ``test`` - Testing partition as used in the original DeepSurv

    data_type: string
        Data type of the data.

        Possible values are:
            * ``pandas`` or ``pd`` or ``dataframe`` or ``df``- pandas DataFrame (default)
            * ``numpy`` or ``np`` - NumPy array

        .. note::
            NumPy is supported as an option, but DeepSurvK is built
            with pandas in mind.

    Returns
    -------
    tuple of pandas DataFrames
        * X - Features
        * Y - Target variable
        * E - Event variable

    References
    ----------
    .. [#hosmer] Hosmer Jr, David W., Stanley Lemeshow, and Susanne May. Applied survival analysis: regression modeling of time-to-event data. Vol. 618. John Wiley & Sons, 2011.
    """
    return _load_dataset('whas.h5', partition=partition, **kwargs)


""" This module holds a torch nn.module sublass for 2D UNets.

by Stefan Schmohl, 2020
"""

import torch
import torch.nn as nn
import sparseconvnet as scn

#class Conv2dSamePadding(nn.Conv2d):
    #"""
    #https://gist.github.com/sumanmichael/4de9dee93f972d47c80c4ade8e149ea6
    #"""
    #def __init__(self,*args,**kwargs):
        #super(Conv2dSamePadding, self).__init__(*args, **kwargs)
        #self.zero_pad_2d = nn.ZeroPad2d[(k // 2) for k in self.kernel_size[::-1]]))

    #def forward(self, input):
        #return  self._conv_forward(self.zero_pad_2d(input), self.weight, self.bias)

class SUNet2D(nn.Module):
    """ Class for a neural network in  U-Net architecture.

    __init__() provides convenient setup utilizing the U-Net generator.
    """

    @classmethod
    def from_config(cls, config):
        nIn = len(config['model']['input_features'])
        noC = len(config['model']['classes'])
        net = cls(**config['model']['network']['net-params'], nIn=nIn, noC=noC)
        return net

    def __init__(self, nIn, noC, input_size, filter_size, bias,
                 residual_blocks, downsample, reps, nPlanes, leakiness=0):
        """
        Args:
            nIn:
                Number of input features.
            noC:
                Number of output classes.
            input_size:
                Spatial input size of samples. Note: only important for the
                framework to check, wheather there is to much downsampling
                happening (apparently).
            filter_size:
                Size of conv-filters, except for down- and upconv layers. One
                value, for all dims.
            bias:
                True / False for neurons to have bias weight.
            residual_block:
                True / False if conv-blocks should be redisual. My experience
                tells to better set to False.
            downsample:
                [filter_size, stride] for down- and upconv layers.
            reps:
                Number of conv layers per Unet block.
            nPlanes:
                Filter number per Unet level. The length defines the depth of
                the network, while the values define the depth.
        """

        super().__init__()

        m = nPlanes[0]  # Base filterbank size.

        self.Model = nn.Sequential(
            nn.Conv2d(nIn, m, filter_size, bias=bias, padding=filter_size//2),
            UNet2D(reps, nPlanes, residual_blocks, downsample, filter_size,
                   bias, leakiness),
            nn.BatchNorm2d(m),
            nn.LeakyReLU(leakiness))

        # 1x1x1 Convolutions in Semantic Segmentation,
        self.linear = nn.Sequential(nn.Conv2d(m, m*3, kernel_size=1),
                                    nn.BatchNorm2d(m*3),
                                    nn.LeakyReLU(leakiness),
                                    nn.Dropout(p=0.5),
                                    nn.Conv2d(m*3, noC, kernel_size=1))
    def forward(self, x):
        x = x[1]  # [1] is data, [0] are coords
        x = self.Model(x)
        x = self.linear(x)
        return x

def UNet2D(reps, nPlanes, residual_blocks=False, downsample=[2, 2],
           filter_size=3, bias=False, leakiness=0, n_input_planes=-1):

    global c
    c = 0

    def block(m, a, b):
        global c
        if residual_blocks: #ResNet style blocks
            raise Exception("not implemented yet")
        else: #VGG style blocks
            m.add_module('batchnorm2d_{}'.format(c), nn.BatchNorm2d(a)); c+=1;
            m.add_module('leakyRelu_{}'.format(c), nn.LeakyReLU(leakiness)); c+=1;
            m.add_module('Conv2d_{}'.format(c), nn.Conv2d(a, b, filter_size, bias=bias, padding=filter_size//2)); c+=1;

    class U(nn.Module):
        def __init__(self,nPlanes,n_input_planes=-1): #Recursive function
            super(U, self).__init__()

            left = nn.Sequential()
            for i in range(reps):
                block(left, n_input_planes if n_input_planes!=-1 else nPlanes[0], nPlanes[0])
                n_input_planes=-1

            if len(nPlanes) > 1:
                mid = U(nPlanes[1:])

                down = nn.Sequential(
                            nn.BatchNorm2d(nPlanes[0]),
                            nn.LeakyReLU(leakiness),
                            nn.Conv2d(nPlanes[0], nPlanes[1],
                                downsample[0], downsample[1], bias=bias))

                up = nn.Sequential(
                            nn.BatchNorm2d(nPlanes[1]),
                            nn.LeakyReLU(leakiness),
                            nn.ConvTranspose2d(nPlanes[1], nPlanes[0],
                                downsample[0], downsample[1], bias=bias))

                right = nn.Sequential()
                for i in range(reps):
                    block(right, nPlanes[0] * (2 if i == 0 else 1), nPlanes[0])

            else:
                down   = None
                mid    = None
                up     = None
                right  = None
            self.left   = left
            self.down   = down
            self.mid    = mid
            self.up     = up
            self.right  = right

        def join(self, input):
            return torch.cat(input, dim=1)

        def forward(self, inputs):
            l = self.left(inputs)
            if self.right is None:
                return l

            d    = self.down(l)
            m    = self.mid(d)
            u    = self.up(m)
            j    = self.join([l,u])
            r    = self.right(j)
            return r

    m = U(nPlanes,n_input_planes)
    return m


import numpy as np
import Functions.Python.setting_utils as su
import logging
import Functions.Python.MIND as pyMIND
import Functions.Python.uncertainty_features as ut
import Functions.Python.preprocessing as pre
import Functions.Python.landmark_utils as lu
import Functions.Python.ANTs.registration_ants as reg_ants
import Functions.Python.ANTs.loss_function as ants_loss

def main(current_experiment=None):
    where_to_run = 'local'  # 'local' , 'sharkCluster' , 'shark'
    database = 'DIR-Lab_COPD'
    current_experiment = 'elastix1'  # 'elastix1', 'ANTs1'
    if not su.load_setting(current_experiment, data=database, where_to_run=where_to_run):
        registration_method = 'ANTs'   # elastix , ANTs
        setting = su.initialize_setting(current_experiment, data=database, where_to_run=where_to_run, registration_method=registration_method)
    else:
        setting = su.load_setting(current_experiment, data=database, where_to_run=where_to_run)

    cn_list = setting['cn_range']
    feature_list = ['stdT', 'E_T', 'stdT_final', 'E_T_final', 'Jac', 'MIND', 'CV', 'NC', 'MI']
    feature_pool_list = ['stdT', 'E_T', 'stdT_final', 'E_T_final', 'Jac', 'MIND', 'CV']

    cn_remove = []
    for cn in cn_list:
        # ------------ pre-processing -------------
        pre.dirlab.dir_lab_copd(cn)
        pre.cylinder_mask(setting, cn=cn)
        pre.chest_segmentation.ptpulmo_segmentation_dirlab(data='DIR-Lab_COPD', cn=cn, segment_organ='Torso')
        pre.chest_segmentation.ptpulmo_segmentation_dirlab(data='DIR-Lab_COPD', cn=cn, segment_organ='Lung')
        pre.chest_segmentation.lung_fill_hole_dirlab(data='DIR-Lab_COPD', cn=cn)
        # pre.chest_segmentation.lung_fill_hole_erode(setting, cn=cn)
        # pre.cylinder_mask(setting, cn=cn, overwrite=False)
        pre.ants_preprocessing.image_normalization(setting, cn=cn)

        #  ------------ registration --------------
        # preferably do the registration by running either do_elastix_registration or do_ANTs_registration
        # do_elastix_registration

        # ------------ post-processing -------------
        reg_ants.convert_nii2mha(setting, cn=cn)

        # ---------- feature extraction -----------
        ut.std_t(setting, cn=cn, mode='initial')
        ut.std_t(setting, cn=cn, mode='final')
        ut.jac(setting, cn=cn)
        output_error = ut.compute_error(setting, cn=cn, write_error_image=True)
        if output_error == 2:
            cn_remove.append(cn)
        ut.ncmi(setting, cn=cn)
        ut.feature_pooling(setting, cn=cn, feature_list=feature_pool_list)

    cn_list = [cn for cn in cn_list if cn not in cn_remove]

    landmarks = lu.load_features(setting, feature_list=feature_list, cn_list=cn_list)
    exp_tre_list = ['elastix1-TRE_nonrigid', 'ANTs1-TRE_nonrigid']
    exp_loss = ['ANTs1']
    cn_list = setting['cn_range']
    lu.plot.boxplot_tre(setting, cn_list=cn_list, exp_tre_list=exp_tre_list)
    lu.plot.table_tre(setting, cn_list=cn_list, exp_tre_list=exp_tre_list)
    lu.plot.table_tre_cn(setting, cn_list=cn_list, exp='ANTs1-TRE_nonrigid')
    ants_loss.plot_loss(setting, cn_list=np.arange(1, 11), exp_list=exp_loss, out=0)

if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG)
    main(current_experiment=None)


import sys
import torch.backends.cudnn as cudnn
import argparse
import logging
from PointMLP.segmentation.model.PointMLP import *
from PointMLP.data_util.ShapeNetDataloader import *
from PointMLP.utils import *

def parse_args(args=None):

    parser = argparse.ArgumentParser(description='3D Shape Part Segmentation')
    parser.add_argument('--model', type=str, default='PointMLP1')
    parser.add_argument('--exp_name', type=str, default='demo1', metavar='N',
                        help='Name of the experiment')
    parser.add_argument('--batch_size', type=int, default=16, metavar='batch_size',
                        help='Size of batch)')
    parser.add_argument('--test_batch_size', type=int, default=16, metavar='batch_size',
                        help='Size of batch)')
    parser.add_argument('--epochs', type=int, default=350, metavar='N',
                        help='number of episode to train')
    parser.add_argument('--gpu', type=str, default='0', help='specify GPU devices')
    parser.add_argument('--use_sgd', type=bool, default=False,
                        help='Use SGD')
    parser.add_argument('--scheduler', type=str, default='step',
                        help='lr scheduler')
    parser.add_argument('--step', type=int, default=40,
                        help='lr decay step')
    parser.add_argument('--lr', type=float, default=0.003, metavar='LR',
                        help='learning rate')
    parser.add_argument('--momentum', type=float, default=0.9, metavar='M',
                        help='SGD momentum (default: 0.9)')
    parser.add_argument('--no_cuda', type=bool, default=False,
                        help='enables CUDA training')
    parser.add_argument('--manual_seed', type=int, metavar='S',
                        help='random seed (default: 1)')
    parser.add_argument('--eval', type=bool,  default=False,
                        help='evaluate the model')
    parser.add_argument('--num_points', type=int, default=2048,
                        help='num of points to use')
    parser.add_argument('--workers', type=int, default=12)
    parser.add_argument('--resume', type=bool, default=False,
                        help='Resume training or not')
    parser.add_argument('--model_type', type=str, default='insiou',
                        help='choose to test the best insiou/clsiou/acc model (options: insiou, clsiou, acc)')

    return parser.parse_args(args)

# 传入命令行参数
sys.argv = ['--batch_size', '--epoch','350','--gpu', '7']
args = parse_args()
print(args)

assert torch.cuda.is_available(), "Please ensure codes are executed in cuda."
# device = torch.device("cuda:5" if torch.cuda.is_available() else "cpu")
torch.cuda.set_device(int(args.gpu))

num_part = 50
# device = torch.device("cuda" if args.cuda else "cpu")

# io.cprint(str(model))
model = PointMLP(num_part).cuda()
# model = model.to(device)

model.apply(weight_init)

if args.use_sgd:
    print("Use SGD")
    opt = optim.SGD(model.parameters(), lr=args.lr*100, momentum=args.momentum, weight_decay=0)
else:
    print("Use Adam")
    opt = optim.Adam(model.parameters(), lr=args.lr, betas=(0.9, 0.999), eps=1e-08, weight_decay=0)

if args.scheduler == 'cos':
    print("Use CosLR")
    scheduler = CosineAnnealingLR(opt, args.epochs, eta_min=args.lr if args.use_sgd else args.lr / 100)
else:
    print("Use StepLR")
    scheduler = StepLR(opt, step_size=args.step, gamma=0.5)

best_acc = 0
best_class_iou = 0
best_instance_iou = 0
num_part = 50
num_classes = 16

train_dataset = PartNormalDataset(root=data_path, npoints=args.num_points, split='trainval', normal_channel=False)
test_dataset = PartNormalDataset(root=data_path, npoints=args.num_points, split='test', normal_channel=False)

trainDataLoader = torch.utils.data.DataLoader(train_dataset, batch_size=args.batch_size, shuffle=True, num_workers=10, drop_last=True)
testDataLoader = torch.utils.data.DataLoader(test_dataset, batch_size=args.batch_size, shuffle=False, num_workers=10)

def train_epoch(train_loader, model, opt, scheduler, epoch, num_part, num_classes):
    train_loss = 0.0
    total_loss = 0
    count = 0.0
    accuracy = []
    shape_ious = 0.0
    metrics = {}
    model.train()

    for batch_id, (points, label, target, norm_plt) in tqdm(enumerate(train_loader), total=len(train_loader),
                                                            smoothing=0.9):
        batch_size, num_point, _ = points.size()

        points, label, target, norm_plt = points.float().cuda(), label.long().squeeze(1).cuda(), target.long().cuda(), \
                                          norm_plt.float().cuda()
        points = points.transpose(2, 1)
        norm_plt = norm_plt.transpose(2, 1)

        # target: b,n
        seg_pred = model(points, norm_plt, to_categorical(label, num_classes))  # seg_pred: b,n,50
        loss = F.nll_loss(seg_pred.contiguous().view(-1, num_part), target.view(-1, 1)[:, 0])

        # instance iou without considering the class average at each batch_size:
        batch_shapeious = compute_overall_iou(seg_pred, target,
                                              num_part)  # list of of current batch_iou:[iou1,iou2,...,iou#b_size]
        # total iou of current batch in each process:
        batch_shapeious = seg_pred.new_tensor([np.sum(batch_shapeious)],
                                              dtype=torch.float64)  # same device with seg_pred!!!

        # Loss backward
        loss = torch.mean(loss)
        opt.zero_grad()
        loss.backward()
        opt.step()

        # accuracy
        seg_pred = seg_pred.contiguous().view(-1, num_part)
        target = target.view(-1, 1)[:, 0]
        pred_choice = seg_pred.contiguous().data.max(1)[1]
        correct = pred_choice.eq(target.contiguous().data).sum()

        # sum
        shape_ious += batch_shapeious.item()
        count += batch_size
        train_loss += loss.item() * batch_size
        accuracy.append(correct.item() / (batch_size * num_point))

    if args.scheduler == 'cos':
        scheduler.step()
    elif args.scheduler == 'step':
        if opt.param_groups[0]['lr'] > 0.9e-5:
            scheduler.step()
        if opt.param_groups[0]['lr'] < 0.9e-5:
            for param_group in opt.param_groups:
                param_group['lr'] = 0.9e-5

    lr = opt.param_groups[0]['lr']
    printf('Learning rate: %f' % opt.param_groups[0]['lr'])

    train_avg_loss = train_loss * 1.0 / count

    metrics['accuracy'] = np.mean(accuracy)
    train_avg_acc = metrics['accuracy']

    metrics['shape_avg_iou'] = shape_ious * 1.0 / count
    train_avg_iou = metrics['shape_avg_iou']

    outstr = 'Train %d, loss: %f, train acc: %f, train ins_iou: %f' % (epoch + 1, train_avg_loss,
                                                                       train_avg_acc, train_avg_iou)
    printf(outstr)
    return train_avg_loss, train_avg_acc, train_avg_iou, lr

train_loss, train_acc, train_iou, val_loss, val_acc, val_iou, val_class_iou, lr_history = [], [], [], [], [], [], [], []

classes_str = ['aero','bag','cap','car','chair','ear','guitar','knife','lamp','lapt','moto','mug','Pistol','rock','stake','table']

for epoch in range(args.epochs):

    train_avg_loss, train_avg_acc, train_avg_iou, lr = train_epoch(trainDataLoader, model, opt, scheduler, epoch,
                                                                   num_part, num_classes)
    lr_history.append(lr)
    train_loss.append(train_avg_loss)
    train_acc.append(train_avg_acc)
    train_iou.append(train_avg_iou)

    test_avg_loss, test_metrics, total_per_cat_iou = test_epoch(testDataLoader, model, epoch, num_part, num_classes)
    val_loss.append(test_avg_loss)
    val_acc.append(test_metrics['accuracy'])
    val_iou.append(test_metrics['shape_avg_iou'])

    if test_metrics['accuracy'] > best_acc:
        best_acc = test_metrics['accuracy']
        printf('Max Acc:%.5f' % best_acc)

    if test_metrics['shape_avg_iou'] > best_instance_iou:
        best_instance_iou = test_metrics['shape_avg_iou']
        printf('Max instance iou:%.5f' % best_instance_iou)

    class_iou = 0
    for cat_idx in range(16):
        class_iou += total_per_cat_iou[cat_idx]
    avg_class_iou = class_iou / 16
    val_class_iou.append(avg_class_iou)

    if avg_class_iou > best_class_iou:
        best_class_iou = avg_class_iou
        # print the iou of each class:
        for cat_idx in range(16):
            printf(classes_str[cat_idx] + ' iou: ' + str(total_per_cat_iou[cat_idx]))
        printf('Max class iou:%.5f' % best_class_iou)

printf('Final Max Acc:%.5f' % best_acc)
printf('Final Max instance iou:%.5f' % best_instance_iou)
printf('Final Max class iou:%.5f' % best_class_iou)


import hashlib
from django.db import models
from django.contrib.auth.models import User, Group

INSTALLABLE_TYPES = (
    (0, 'tool'),
    (1, 'datatype'),
    (2, 'suite'),
    (3, 'viz'),
    (4, 'gie')
    # Wow I miss golang's iota. Just look at that! https://github.com/golang/go/wiki/Iota
)

PACKAGE_TYPES = (
    (0, 'conda'),
)

class UserExtension(models.Model):
    """Extension to the built-in user model, with a 1:1 mapping to users.
    """
    user = models.OneToOneField(User, primary_key=True)
    display_name = models.CharField(max_length=64, blank=True)
    api_key = models.CharField(max_length=32, unique=True, blank=True)
    gpg_pubkey_id = models.CharField(max_length=16)
    github = models.IntegerField()

    @property
    def hashedEmail(self):
        """Return an md5sum digest of the email address, appropriate for
        gravatars

        TODO: convert to a model field, we can denormalize a bit for not
        calculating a gazillion md5sums
        """
        return hashlib.md5(self.user.email).hexdigest()

    @property
    def gravatar_url(self):
        return '//www.gravatar.com/avatar/' + self.hashedEmail

    def __str__(self):
        return '%s <%s>' % (self.display_name, self.user.email)

class GroupExtension(models.Model):
    """Extension to the built-in group model, with a 1:1 mapping to groups.
    """
    group = models.OneToOneField(Group, primary_key=True)

    description = models.TextField(blank=False)
    website = models.TextField()
    gpg_pubkey_id = models.CharField(max_length=16)

    def __str__(self):
        return self.group.name

class Tag(models.Model):
    """User managed tags replace admin managed categories
    """
    display_name = models.CharField(max_length=120, blank=False)
    description = models.TextField(blank=False)

    def __str__(self):
        return self.display_name

class Installable(models.Model):
    """A single installable thing, equivalent to a repository in the old TS.

    Installables represent the repository level "thing", while Versions
    represent the real concrete installable version of a "thing".

    Installables have the usual metadata associated with TS repos, a set of
    tags, and then a set of users and groups with permissions to edit this
    repository. Being granted access to a repository grants the ability to change
    repository metadata, and to create new versions (releases).
    """
    # TODO: prevent renaming
    name = models.CharField(max_length=120, blank=False)
    synopsis = models.TextField(blank=False)
    description = models.TextField(blank=False)

    remote_repository_url = models.URLField()
    homepage_url = models.URLField()

    repository_type = models.IntegerField(choices=INSTALLABLE_TYPES, blank=False)

    tags = models.ManyToManyField(Tag)

    owner = models.ForeignKey(User, related_name='creator')
    user_access = models.ManyToManyField(User, blank=True)
    group_access = models.ManyToManyField(Group, blank=True)

    def can_edit(self, user):
        """Is the user allowed to edit the repo.

        This method will check a direct user access level, as well as via groups.
        """
        if user == self.owner:
            return True

        if user in self.user_access.all():
            return True

        for group in user.groups.all():
            if group in self.group_access.all():
                return True

        return False

    @property
    def total_downloads(self):
        """Query to find the sum of downloads for each version
        """
        return sum([
            rev.downloads for rev in self.version_set.all()
        ])

    @property
    def last_updated(self):
        """Return the upload date of the most recent version
        """
        v = self.latest_version
        if v is None:
            return None
        else:
            return v.uploaded

    @property
    def latest_version(self):
        """Return the upload date of the most recent version
        """
        if self.version_set.all().exists():
            return self.version_set.order_by('-uploaded').first()
        else:
            return None

    @property
    def namespace(self):
        return '.'.join([
            'galaxyproject',
            'shed',
            self.owner.username,
            self.name
        ])

    def __str__(self):
        return self.name

class PackageDependency(models.Model):
    """PackageDependencies are external dependencies not tracked by the TS.
    """
    type = models.IntegerField(choices=PACKAGE_TYPES, blank=False)
    identifier = models.CharField(max_length=32)
    package_version = models.CharField(max_length=16)

    class Meta:
        verbose_name_plural='Package dependencies'

    def __str__(self):
        return '{0.identifier}=={0.package_version}'.format(self)

class Version(models.Model):
    """A single version/version/release of a repository.

    In the old system, changeset IDs were the unique component of a version.
    We're replacing that with the actual version encoded in the file, and the
    hard requirement that they absolutely must be unique within an installable.
    This means we can get rid of two ugly identifiers (``version.id``,
    ``version.changeset_id``) and replace with a single human-readable
    ``version.version``.

    Versions must have an sha256sum, generated on the server side,
    hopefully checked against the uploading client. This is to provide
    transport integrity.

    Versions may have a GPG signature associated to them, signed with a user
    or group GPG key.

    Versions may specify a replacement version. I haven't fully figured out
    how I want that to work, but essentially it should point to the version
    you should upgrade to from the version you're currently looking at. Say
    Alice, Bob, and Charlie all have a different implementation of foobar 0.12,
    in the heydey of tool development. They recognise that this is a problem,
    and band together as the Galaxy foobar developers in a group. With the
    release of foobar 1.0, they've coordinated a great DatasetCollection
    enabled version of the foobar package and make a single release. At that
    time, they can adjust all of their individual repositories to say "point to
    foobar 1.0 from group bazqux." On the Galaxy admin side, it should simply
    say something like "Upgrade foobar 0.12 from Alice" and "The administrator
    foobar 0.12 from Alice's repository has specified that their version is
    replaced with foobar 1.0 from bazqux" giving the admin some assurance that
    this is intended.

    Versions may have dependencies. These are not really user-editable online,
    and must be parsed from tool_dependencies.xml files. This is stored as an
    asymmetrical adjacency table. Versions point to other versions.
    """
    # This must be unique per installable.
    version = models.CharField(max_length=12, blank=False)
    commit_message = models.TextField(blank=False)
    uploaded = models.DateTimeField(blank=False)
    # Link back to our parent installable
    installable = models.ForeignKey(Installable, blank=False)
    # Archive sha256sum for transport integrity
    tar_gz_sha256 = models.CharField(max_length=64)
    # No need to store in an API accessible manner, just on disk.
    # Maybe should have a toolshed GPG key and sign all packages with that.
    tar_gz_sig_available = models.BooleanField(default=False, blank=False)

    # If a user has this version of this package installed, what should they
    # upgrade to. Need to provide a (probably expensive) method to calculate a
    # full upgrade path?
    replacement_version = models.ForeignKey('self', blank=True, null=True, related_name='upgrade_to')

    # Track downloads
    downloads = models.IntegerField(default=0)

    # Dependency graph data
    dependencies = models.ManyToManyField(
        'self',
        through='VersionDependency',
        blank=True,
        symmetrical=False,
        related_name='used_in'
    )

    # Conda dependencies
    package_dependencies = models.ManyToManyField(PackageDependency)

    @property
    def namespace(self):
        return (self.installable.namespace, self.version)

    def __str__(self):
        return '%s %s' % (self.installable.name, self.version)

class VersionDependency(models.Model):
    """Linking table for versions.

    This may not be needed, but everything works? So we're not touching it.
    Maybe someone will have metadata they wish to add to dependencies later on.
    """
    from_version = models.ForeignKey(Version, related_name='from_version')
    to_version = models.ForeignKey(Version, related_name='to_version')

    def __str__(self):
        return 'dependency %s -> %s' % (self.from_version, self.to_version)

class SuiteVersion(models.Model):
    """SuiteVersions are a bit special: they're like an Version in that they
    have a parent installable, and that a SuiteVersion represents a single
    iteration of a suite. However, since they're metapackages and lack
    downloadables, they're unlike versions enough that we have to separate the
    model out.

    This feels like a very weak rationalization. Maybe suites should be
    completely removed and just merged with versions.
    """
    version = models.CharField(max_length=12, blank=False)
    commit_message = models.TextField(blank=False)
    installable = models.ForeignKey(Installable)
    contained_versions = models.ManyToManyField(Version)

    def __str__(self):
        return 'Suite %s %s' % (self.installable.name, self.version)


import cv2 as cv

class MouseHandler:
    def __init__(self, window):
        self.state = [0, 0, 0]
        self.onMouseDown = None
        if window:
            cv.setMouseCallback(window, self.onMouse)

    def onMouse(self, event, x, y, flags, param):
        if event == cv.EVENT_MOUSEMOVE:
            self.state[0] = x
            self.state[1] = y
        if event == cv.EVENT_LBUTTONDOWN:
            self.state[2] = 1
            if self.onMouseDown is not None:
                self.onMouseDown(x, y)
        if event == cv.EVENT_LBUTTONUP:
            self.state[2] = 0


import numpy as np
from scipy.spatial.distance import cdist
from sklearn.gaussian_process.kernels import _check_length_scale, RBF as SRBF

class RBF(SRBF):
    def __call__(self, X, Y=None, eval_gradient=False):
        if eval_gradient and Y is not None:
            X = np.atleast_2d(X)

            length_scale = _check_length_scale(X, self.length_scale)
            dists = cdist(X / length_scale, Y / length_scale, metric='sqeuclidean')

            K = np.exp(-.5 * dists)

            if self.hyperparameter_length_scale.fixed:
                return K, np.empty((X.shape[0], X.shape[0], 0))
            elif not self.anisotropic or length_scale.shape[0] == 1:
                K_gradient = (K * dists)[:, :, np.newaxis]
                return K, K_gradient
            elif self.anisotropic:
                K_gradient = (X[:, np.newaxis, :] - Y[np.newaxis, :, :]) ** 2 \
                             / (length_scale ** 2)
                K_gradient *= K[..., np.newaxis]
                return K, K_gradient

        else:
            return super().__call__(X, Y, eval_gradient)


import requests
import pickle
from datetime import datetime
import pandas as pd

def load_model(filename):
    with open(filename, 'rb') as file:
        model = pickle.load(file)

    return model

def is_holiday(date):
    endpoint = "https://date.nager.at/Api/v2/IsPublicHoliday/{year}-{month}-{day}"

    year = date.year
    month = date.month
    day = date.day

    response = requests.get(endpoint.format(year=year, month=month, day=day))

    if response.status_code == 200 and response.json() is True:
        return 1  # holiday
    else:
        return 0  # not holiday

# def get_weather_data(latitude, longitude):
#     endpoint = "https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}&hourly=relativehumidity_2m,apparent_temperature,precipitation,snowfall,surface_pressure,visibility,windspeed_10m,uv_index"
#
#     response = requests.get(endpoint.format(latitude=latitude, longitude=longitude))
#
#     if response.status_code == 200:
#         data = response.json()
#         forecast = data['hourly']
#
#         weather_data = []
#         for hour in range(24):
#             app_temp = forecast['apparent_temperature'][hour]
#             precip = forecast['precipitation'][hour]
#             pres = forecast['surface_pressure'][hour]
#             rh = forecast['relativehumidity_2m'][hour]
#             snow = forecast['snowfall'][hour]
#             uv = forecast['uv_index'][hour]
#             vis = forecast['visibility'][hour]
#             wind_spd = forecast['windspeed_10m'][hour]
#
#             weather_data.append([app_temp, precip, pres, rh, snow, uv, vis, wind_spd])
#
#         return weather_data
#     else:
#         return None

def get_weather_data(latitude, longitude):
    endpoint = "https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}&hourly=temperature_2m,relativehumidity_2m,weathercode,visibility,windspeed_80m"

    response = requests.get(endpoint.format(latitude=latitude, longitude=longitude))

    if response.status_code == 200:
        data = response.json()
        forecast = data['hourly']

        weather_data = []
        for hour in range(24):
            visibility = forecast['visibility'][hour]
            wind_speed = forecast['windspeed_80m'][hour]
            humidity = forecast['relativehumidity_2m'][hour]
            temp = forecast['temperature_2m'][hour]
            weather = forecast['weathercode'][hour]

            weather_code = {'cloudy': [45, 48], 'rain': [51, 53, 55, 56, 57, 61, 63, 65, 66, 67, 80, 81, 82, 95],
                            'sunny': [0, 1, 2, 3], 'snow': [71, 73, 75, 77, 85, 86, 96, 99]}

            main_weather = None
            for category, codes in weather_code.items():
                if weather in codes:
                    main_weather = category
                    break  # Exit the loop once the main_weather is found

            # Encode 'main_weather' column to one-hot
            cloudy = 1 if main_weather == 'cloudy' else 0
            rain = 1 if main_weather == 'rain' else 0
            snow = 1 if main_weather == 'snow' else 0
            sunny = 1 if main_weather == 'sunny' else 0

            weather_data.append({
                'temp': temp,
                'visibility': visibility,
                'wind_speed': wind_speed,
                'humidity': humidity,
                'cloudy': cloudy,
                'rain': rain,
                'snow': snow,
                'sunny': sunny
            })

        return weather_data
    else:
        return None

def make_prediction(model, data):
    # Make the prediction
    prediction = model.predict(data)
    return prediction


import collections
import heapq
# Similar as LC 0621

# Solution 1,
# Assume most common value is c and its frequency is v, then we have,
# c__c__c...__c
# so we need to fill at least (v - 1) slots, otherwise we cannot make two adjacent
# chars different, so if total length is n, then we have (n - v) chars needs to fill
# v - 1 holes, => n - v >= v - 1
class Solution(object):
    def reorganizeString(self, S):
        """
        :type S: str
        :rtype: str
        """
        if not S:
            return S

        n = len(S)
        d = collections.Counter(S)
        c, v = d.most_common(1)[0]

        if 2 * v - n - 1 > 0:
            return ''

        res = [[c] for _ in range(v)]
        res.append([])

        idx = 0
        for x in sorted(d, key=lambda x: -d[x]):
            if x != c:
                for _ in range(d[x]):
                    res[idx].append(x)
                    idx = (idx + 1) % (v + 1)

        res = ''.join(''.join(x) for x in res)

        return res

# Solution 2, priority queue solution, more elegant
class Solution(object):
    def reorganizeString(self, S):
        """
        :type S: str
        :rtype: str
        """
        d = collections.Counter(S)

        q = [[-v, c] for c, v in d.items()]

        heapq.heapify(q)
        res = []
        while len(q) > 1:
            v1, c1 = heapq.heappop(q)
            v2, c2 = heapq.heappop(q)

            res.append(c1)
            res.append(c2)

            v1 += 1
            v2 += 1

            if v1 != 0:
                heapq.heappush(q, [v1, c1])
            if v2 != 0:
                heapq.heappush(q, [v2, c2])

        if len(q) == 1 and q[0][0] < -1:
            return ''
        if len(q) == 1:
            res.append(q[0][1])

        res = ''.join(res)

        return res


from django.shortcuts import render, redirect
import django
from .models import Faculty, Staff, Publication, Gallery, News, Slide, Award, Timetablenacedemics, Events, Batch, Placement, Internship, Collaboration, Message, File, Company
from .forms import Faculty_form, Staff_form, Event_form, A_cal_form, publication_form, gallery_form, news_form, slide_form, award_form, batch_form, placement_form, internship_form, collaboration_form, message_form
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from json import dumps
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.core import mail
from django.template.loader import render_to_string
from django.utils.html import strip_tags

# Create your views here.

NUM_OBJECTS_PER_PAGE = 10

def only_allow_admin(func):
    def inner(*args, **kwargs):
        if args[0].user.username == 'admin':
            return func(*args, **kwargs)
        return redirect('/')
    return inner

def main(res):
    form = message_form()
    if res.method == 'POST':
        form = message_form(res.POST)
        if form.is_valid():
            form.save()
            messages.success(res, "Message sent successfully")
            return redirect('/')
    announcements = News.objects.filter(category='Announcement').order_by('-id')[:2]
    updates = News.objects.filter(category='Update').order_by('-id')[:2]
    placements = News.objects.filter(category='Placement drive').order_by('-id')[:2]
    print(announcements, updates, placements)
    return render(res, 'index.html', {'announcements':announcements, 'updates':updates, 'placements': placements, 'slides': Slide.objects.all().order_by('-id'), 'form': form})

@login_required
@only_allow_admin
def faculty_form(res, id=None):
    if res.method == 'POST':
        if id:
            form = Faculty_form(res.POST, res.FILES, instance=Faculty.objects.get(id=id))
        else:
            form = Faculty_form(res.POST, res.FILES)
        if form.is_valid():
            o = form.save(commit=False)
            o.approved = True
            o.save()
            messages.success(res, "Successfully submitted")
            return redirect('faculty')
        print(form.errors)
        return render(res, '/admin/faculty.html', {'form': form})
    objects = Faculty.objects.all().order_by('-id')
    page = res.GET.get('page', 1)
    paginator = Paginator(objects, NUM_OBJECTS_PER_PAGE)
    try:
        objects = paginator.page(page)
    except PageNotAnInteger:
        objects = paginator.page(1)
    except EmptyPage:
        objects = paginator.page(paginator.num_pages)
    return render(res, 'admin/faculty.html', {'form': Faculty_form(instance=Faculty.objects.get(id=id)) if id else Faculty_form(), 'faculty': objects, 'id': id if id else None})

@login_required
@only_allow_admin
def admin_events(res, id=None):
    if res.method == 'POST':
        if id:
            form = Event_form(res.POST, res.FILES, instance=Events.objects.get(id=id))
        else:
            form = Event_form(res.POST, res.FILES)
        if form.is_valid():
            form.save()
            messages.success(res, "Successfully submitted")
            return redirect('/admin/events')
        print(form.errors)
        return render(res, 'admin/events.html', {'form': form})
    objects = Events.objects.all().order_by('-id')
    page = res.GET.get('page', 1)
    paginator = Paginator(objects, NUM_OBJECTS_PER_PAGE)
    try:
        objects = paginator.page(page)
    except PageNotAnInteger:
        objects = paginator.page(1)
    except EmptyPage:
        objects = paginator.page(paginator.num_pages)
    return render(res, 'admin/events.html', {'form': Event_form(instance=Events.objects.get(id=id)) if id else Event_form(), 'events': objects, 'id': id if id else None})

@login_required
@only_allow_admin
def admin_staff(res, id=None):
    if res.method == 'POST':
        if id:
            form = Staff_form(res.POST, res.FILES, instance=Staff.objects.get(id=id))
        else:
            form = Staff_form(res.POST, res.FILES)
        if form.is_valid():
            o = form.save(commit=False)
            o.approved = True
            o.save()
            messages.success(res, "Successfully submitted")
            return redirect('/admin/staff')
        print(form.errors)
        return render(res, 'admin/staff.html', {'form': form})
    objects = Staff.objects.all().order_by('-id')
    page = res.GET.get('page', 1)
    paginator = Paginator(objects, NUM_OBJECTS_PER_PAGE)
    try:
        objects = paginator.page(page)
    except PageNotAnInteger:
        objects = paginator.page(1)
    except EmptyPage:
        objects = paginator.page(paginator.num_pages)
    return render(res, 'admin/staff.html', {'form': Staff_form(instance=Staff.objects.get(id=id)) if id else Staff_form(), 'staff': objects, 'id': id if id else None})

@login_required
@only_allow_admin
def admin_a_cal(res):
    if res.method == 'POST':
        form = A_cal_form(res.POST, instance=Timetablenacedemics.objects.get(is_time=False))
        if form.is_valid():
            acad = form.save(commit=False)
            acad.is_time = False
            acad.save()
            messages.success(res, "Successfully submitted")
            return redirect('/admin/academic_calender')
        print(form.errors)
        return render(res, 'admin/academic.html', {'form': form})
    return render(res, 'admin/academic.html', {'form': A_cal_form(instance=Timetablenacedemics.objects.get(is_time=False))})

@login_required
@only_allow_admin
def admin_tt(res):
    if res.method == 'POST':
        form = A_cal_form(res.POST, instance=Timetablenacedemics.objects.get(is_time=True))
        if form.is_valid():
            form.save()
            messages.success(res, "Successfully submitted")
            return redirect('admin/timetable')
        print(form.errors)
        return render(res, '/admin/timetable.html', {'form': form})
    return render(res, 'admin/timetable.html', {'form': A_cal_form(instance=Timetablenacedemics.objects.get(is_time=True))})

def new_faculty_form(res):
    if res.method == 'POST':
        form = Faculty_form(res.POST, res.FILES)
        if form.is_valid():
            form.save()
            messages.success(res, "Successfully submitted")
            return redirect('faculty')
        print(form.errors)
        return render(res, 'faculty_form.html', {'form': form})
    return render(res, 'faculty_form.html', {'form': Faculty_form()})

def new_staff_form(res):
    if res.method == 'POST':
        form = Staff_form(res.POST, res.FILES)
        if form.is_valid():
            form.save()
            messages.success(res, "Successfully submitted")
            return redirect('faculty')
        print(form.errors)
        return render(res, 'staff_form.html', {'form': form})
    return render(res, 'staff_form.html', {'form': Staff_form()})

def new_publication_form(res):
    if res.method == 'POST':
        form = publication_form(res.POST, res.FILES)
        if form.is_valid():
            form.save()
            messages.success(res, "Successfully submitted")
            return redirect('publications')
        print(form.errors)
        return render(res, 'publication_form.html', {'form': form})
    return render(res, 'publication_form.html', {'form': publication_form()})

def new_awards_form(res):
    if res.method == 'POST':
        form = award_form(res.POST, res.FILES)
        if form.is_valid():
            form.save()
            messages.success(res, "Successfully submitted")
            return redirect('awards_honours')
        print(form.errors)
        return render(res, 'publication_form.html', {'form': form})
    return render(res, 'publication_form.html', {'form': award_form()})

def new_placement_form(res):
    if res.method == 'POST':
        form = placement_form(res.POST, res.FILES)
        if form.is_valid():
            form.save()
            messages.success(res, "Successfully submitted")
            return redirect('placements')
        print(form.errors)
        return render(res, 'placement_form.html', {'form': form})
    return render(res, 'placement_form.html', {'form': placement_form()})

def new_internship_form(res):
    if res.method == 'POST':
        form = internship_form(res.POST, res.FILES)
        if form.is_valid():
            form.save()
            messages.success(res, "Successfully submitted")
            return redirect('internships')
        print(form.errors)
        return render(res, 'internship_form.html', {'form': form})
    return render(res, 'internship_form.html', {'form': internship_form()})

@login_required
@only_allow_admin
def admin_publication(res, id=None):
    if res.method == 'POST':
        if id:
            form = publication_form(res.POST, res.FILES, instance=Publication.objects.get(id=id))
        else:
            form = publication_form(res.POST, res.FILES)
        if form.is_valid():
            o = form.save(commit=False)
            o.approved = True
            o.save()
            messages.success(res, "Successfully submitted")
            return redirect('/admin/publications')
        return render(res, 'admin/publication.html', {'form': form})
    objects = Publication.objects.all().order_by('-id')
    page = res.GET.get('page', 1)
    paginator = Paginator(objects, NUM_OBJECTS_PER_PAGE)
    try:
        objects = paginator.page(page)
    except PageNotAnInteger:
        objects = paginator.page(1)
    except EmptyPage:
        objects = paginator.page(paginator.num_pages)
    return render(res, 'admin/publication.html', {'form': publication_form(instance=Publication.objects.get(id=id)) if id else publication_form(), 'objects': objects, 'id': id if id else None})

@login_required
@only_allow_admin
def admin_awards(res, id=None):
    if res.method == 'POST':
        if id:
            form = award_form(res.POST, res.FILES, instance=Award.objects.get(id=id))
        else:
            form = award_form(res.POST, res.FILES)
        if form.is_valid():
            o = form.save(commit=False)
            o.approved = True
            o.save()
            messages.success(res, "Successfully submitted")
            return redirect('/admin/awards_honours')
        print(form.errors)
        return render(res, 'admin/awards.html', {'form': form})
    objects = Award.objects.all().order_by('-id')
    page = res.GET.get('page', 1)
    paginator = Paginator(objects, NUM_OBJECTS_PER_PAGE)
    try:
        objects = paginator.page(page)
    except PageNotAnInteger:
        objects = paginator.page(1)
    except EmptyPage:
        objects = paginator.page(paginator.num_pages)
    return render(res, 'admin/awards.html', {'form': award_form(instance=Award.objects.get(id=id)) if id else award_form(), 'awards': objects, 'id': id if id else None})

@login_required
@only_allow_admin
def admin_gallery(res):
    if res.method == 'POST':
        form = gallery_form(res.POST, res.FILES)
        images = res.FILES.getlist('images')
        if form.is_valid():
            category = form.cleaned_data.get("category")
            name = form.cleaned_data.get("name")
            for image in images:
                o = Gallery()
                o.image = image
                o.category = category
                o.name = name
                o.save()
            messages.success(res, "Successfully submitted")
            return redirect('/admin/gallery')
        print(form.errors)
        return render(res, 'admin/gallery.html', {'form': form})
    return render(res, 'admin/gallery.html', {'form': gallery_form(), 'gallery': Gallery.objects.all().order_by('-id')})

@login_required
@only_allow_admin
def admin_news(res, id=None):
    if res.method == 'POST':
        if id:
            form = news_form(res.POST, res.FILES, instance=News.objects.get(id=id))
        else:
            form = news_form(res.POST, res.FILES)
        files = res.FILES.getlist('files')
        del_prev = res.POST.get('delPrev')
        if form.is_valid():
            news = form.save()
            if del_prev == "on":
                for f in File.objects.filter(f_object=news):
                    f.delete()
            for f in files:
                print(f)
                o = File(a_file=f, f_object=news)
                print(o)
                o.save()
            messages.success(res, "Successfully submitted")
            return redirect('/admin/news')
        print(form.errors)
        return render(res, 'admin/news.html', {'form': form})
    if id:
        files = File.objects.filter(f_object=News.objects.get(id=id))
    objects = News.objects.all().order_by('-id')
    page = res.GET.get('page', 1)
    paginator = Paginator(objects, NUM_OBJECTS_PER_PAGE)
    try:
        objects = paginator.page(page)
    except PageNotAnInteger:
        objects = paginator.page(1)
    except EmptyPage:
        objects = paginator.page(paginator.num_pages)
    return render(res, 'admin/news.html', {'form': news_form(instance=News.objects.get(id=id)) if id else news_form(), 'news': objects, 'id': id if id else None, 'files': files if id else None})

@login_required
@only_allow_admin
def admin_slider(res, id=None):
    if res.method == 'POST':
        if id:
            form = slide_form(res.POST, res.FILES, instance=Slide.objects.get(id=id))
        else:
            form = slide_form(res.POST, res.FILES)
        if form.is_valid():
            form.save()
            messages.success(res, "Successfully submitted")
            return redirect('/admin/slider')
        print(form.errors)
        return render(res, 'admin/slider.html', {'form': form})
    return render(res, 'admin/slider.html', {'form': slide_form(instance=Slide.objects.get(id=id)) if id else slide_form(), 'slides': Slide.objects.all().order_by('-id'), 'id': id if id else None})

@login_required
@only_allow_admin
def admin_students(res, id=None):
    if res.method == 'POST':
        if id:
            form = batch_form(res.POST, instance=Batch.objects.get(id=id))
        else:
            form = batch_form(res.POST)
        if form.is_valid():
            form.save()
            messages.success(res, "Successfully submitted")
            return redirect('/admin/students')
        print(form.errors)
        return render(res, 'admin/students.html', {'form': form})
    objects = Batch.objects.all().order_by('-id')
    page = res.GET.get('page', 1)
    paginator = Paginator(objects, NUM_OBJECTS_PER_PAGE)
    try:
        objects = paginator.page(page)
    except PageNotAnInteger:
        objects = paginator.page(1)
    except EmptyPage:
        objects = paginator.page(paginator.num_pages)
    return render(res, 'admin/students.html', {'form': batch_form(instance=Batch.objects.get(id=id)) if id else batch_form(), 'batches': objects, 'id': id if id else None})

@login_required
@only_allow_admin
def admin_placements(res, id=None):
    if res.method == 'POST':
        if id:
            form = placement_form(res.POST, instance=Placement.objects.get(id=id))
        else:
            form = placement_form(res.POST, res.FILES)
        if form.is_valid():
            o = form.save(commit=False)
            o.approved = True
            o.save()
            messages.success(res, "Successfully submitted")
            return redirect('/admin/placements')
        print(form.errors)
        return render(res, 'admin/placements.html', {'form': form})
    objects = Placement.objects.all().order_by('-id')
    page = res.GET.get('page', 1)
    paginator = Paginator(objects, NUM_OBJECTS_PER_PAGE)
    try:
        objects = paginator.page(page)
    except PageNotAnInteger:
        objects = paginator.page(1)
    except EmptyPage:
        objects = paginator.page(paginator.num_pages)
    return render(res, 'admin/placements.html', {'form': placement_form(instance=Placement.objects.get(id=id)) if id else placement_form(), 'placements': objects, 'id': id if id else None})

@login_required
@only_allow_admin
def admin_internships(res, id=None):
    print(res.user)
    companies = {}
    for i,company in enumerate(Company.objects.all(), start=1):
        companies[f'{i}'] = {'name': company.name, 'link':company.link}
    if res.method == 'POST':
        if id:
            form = internship_form(res.POST, instance=Internship.objects.get(id=id))
        else:
            form = internship_form(res.POST, res.FILES)
        if form.is_valid():
            o = form.save(commit=False)
            o.approved = True
            o.save()
            messages.success(res, "Successfully submitted")
            return redirect('/admin/internships')
        print(form.errors)
        return render(res, 'admin/internships.html', {'form': form})
    objects = Internship.objects.all().order_by('-id')
    page = res.GET.get('page', 1)
    paginator = Paginator(objects, NUM_OBJECTS_PER_PAGE)
    try:
        objects = paginator.page(page)
    except PageNotAnInteger:
        objects = paginator.page(1)
    except EmptyPage:
        objects = paginator.page(paginator.num_pages)
    return render(res, 'admin/internships.html', {'form': internship_form(instance=Internship.objects.get(id=id)) if id else internship_form(), 'internships': objects, 'id': id if id else None, 'companies':dumps(companies)})

@login_required
@only_allow_admin
def admin_collaborations(res, id=None):
    if res.method == 'POST':
        if id:
            form = collaboration_form(res.POST, instance=Collaboration.objects.get(id=id))
        else:
            form = collaboration_form(res.POST, res.FILES)
        if form.is_valid():
            o = form.save(commit=False)
            o.approved = True
            o.save()
            messages.success(res, "Successfully submitted")
            return redirect('/admin/collaborations')
        print(form.errors)
        return render(res, 'admin/collaborations.html', {'form': form})
    objects = Collaboration.objects.all().order_by('-id')
    page = res.GET.get('page', 1)
    paginator = Paginator(objects, NUM_OBJECTS_PER_PAGE)
    try:
        objects = paginator.page(page)
    except PageNotAnInteger:
        objects = paginator.page(1)
    except EmptyPage:
        objects = paginator.page(paginator.num_pages)
    return render(res, 'admin/collaborations.html', {'form': collaboration_form(instance=Collaboration.objects.get(id=id)) if id else collaboration_form(), 'collaborations': objects, 'id': id if id else None})

def faculty(res):
    return render(res, 'faculty.html', {'faculty': Faculty.objects.filter(approved=True)})

def staff(res):
    return render(res, 'staff.html', {'staff': Staff.objects.filter(approved=True)})

def students(res):
    return render(res, 'students.html', {'batches': Batch.objects.all().order_by('-id')})

def publications(res):
    return render(res, 'publication.html', {'publications': Publication.objects.filter(approved=True).order_by('-id')})

def awards_honours(res):
    return render(res, 'awards_honours.html', {'awards_honours': Award.objects.filter(approved=True).order_by('-id')})

def events(res):
    return render(res, 'events.html', {'events': Events.objects.all().order_by('-id')})

def gallery(res):
    return render(res, 'gallery.html', {'gallery': Gallery.objects.all().order_by('-id')})

def news(res):
    news = {}
    for i,n in enumerate(News.objects.all().order_by('-id')):
        news[f'{i}'] = {}
        news[f'{i}']['news'] = n
        print(news)
        news[f'{i}']['files'] = {'1': 'No files attached'}
        for j,m in enumerate(File.objects.filter(f_object=n), start=1):

            news[f'{i}']['files'][f'{j}'] = m
            print(news)
    print(news)
    return render(res, 'news.html', {'news': news})

def internships(res):
    return render(res, 'internships.html', {'internships': Internship.objects.filter(approved=True).order_by('-id')})

def placements(res):
    return render(res, 'placements.html', {'placements': Placement.objects.filter(approved=True).order_by('-id')})

def collaborations(res):
    return render(res, 'collaborations.html', {'collaborations': Collaboration.objects.all().order_by('-id')})

def message(res):
    return render(res, 'admin/messages.html', {'message': Message.objects.all().order_by('-id')})

def admin_dashboard(res):
    return render(res, 'admin/dash_new.html', {'p_pendings': Publication.objects.filter(approved=False), 'a_pendings': Award.objects.filter(approved=False), 'f_pendings': Faculty.objects.filter(approved=False), 's_pendings': Staff.objects.filter(approved=False), 'pl_pendings' : Placement.objects.filter(approved=False), 'in_pendings' : Internship.objects.filter(approved=False)})

@login_required
@only_allow_admin
def admin_accept(res, id, model):
    if model == 'award':
        o = Award.objects.get(id=id)
    elif model == 'faculty':
        o = Faculty.objects.get(id=id)
    elif model == 'staff':
        o = Staff.objects.get(id=id)
    elif model == 'publication':
        o = Publication.objects.get(id=id)
    elif model == 'internship':
        o = Internship.objects.get(id=id)
    elif model == 'placement':
        o = Placement.objects.get(id=id)
    o.approved = True
    o.save()
    messages.success(res, f'{model.title()} object is Approved')
    return redirect('/admin/dashboard')

@login_required
@only_allow_admin
def admin_delete(res, id, model):
    if model == 'award':
        o = Award.objects.get(id=id)
    elif model == 'publication':
        o = Publication.objects.get(id=id)
    elif model == 'faculty':
        o = Faculty.objects.get(id=id)
    elif model == 'staff':
        o = Staff.objects.get(id=id)
    elif model == 'gallery':
        o = Gallery.objects.get(id=id)
    elif model == 'event':
        o = Events.objects.get(id=id)
    elif model == 'news':
        o = News.objects.get(id=id)
    elif model == 'slide':
        o = Slide.objects.get(id=id)
    elif model == 'batch':
        o = Batch.objects.get(id=id)
    elif model == 'placement':
        o = Placement.objects.get(id=id)
    elif model == 'internship':
        o = Internship.objects.get(id=id)
    elif model == 'collaboration':
        o = Collaboration.objects.get(id=id)
    elif model == 'message':
        o = Message.objects.get(id=id)
    o.delete()
    messages.warning(res, f"The {model.title()} object is deleted")
    return redirect(res.META['HTTP_REFERER'])

@login_required
@only_allow_admin
def send_mail(res):
    if res.method == 'POST':
        subject = res.POST.get("subject")
        body = res.POST.get('body')
        html_message = render_to_string('admin/basic_mail_template.html', {'subject': subject, 'body': body})
        plain_message = strip_tags(html_message)
        from_mail = 'cseupdates@rguktsklm.ac.in'
        to = 's160142@rguktsklm.ac.in'

        mail.send_mail(subject, plain_message, from_mail, [to], html_message=html_message)
    return render(res, 'admin/mail.html', {})


# 查询北海365招聘网上的职位信息
# https://www.365zhaopin.com/
# author: kinofgl
# -*- coding: utf-8 -*-

import random
import re
import time
import csv
import requests
from bs4 import BeautifulSoup
from fake_user_agent.main import user_agent
from requests import RequestException
from dingtalkchatbot.chatbot import DingtalkChatbot, ActionCard, CardItem

class BH365Zhaopin(object):
    def __init__(self):
        self.url = 'https://www.365zhaopin.com/'
        self.headers = {'User-Agent': user_agent()}

    def get_html(self, url):
        while True:
            try:
                response = requests.get(url, headers=self.headers, timeout=10)
                response.raise_for_status()
                response.encoding = response.apparent_encoding
                return response.text
            except RequestException:
                print('网络错误，请重试')
                time.sleep(random.random() * 3)

    def get_page_num(self, html):
        while True:
            try:
                soup = BeautifulSoup(html, 'lxml')
                page_num = soup.select('span.ml20')[0].get_text()
                return int(page_num[2:5])
            except:
                return None

    def get_job_info(self, html):
        soup = BeautifulSoup(html, 'lxml')
        job_items = soup.select('div.w1024.f-yehei > div.main-ul > ul > li')
        job_info = []
        for job_item in job_items:
            job_name = job_item.find('div', class_='panl1').find('a').get_text().strip()
            job_company = job_item.find('div', class_='panl10 mt3').get_text().strip()
            job_time = job_item.find('div', class_='panl5').get_text().strip()
            job_url = self.url + job_item.find('div', class_='panl1').find('a')['href']
            job_salary = job_item.find('div', class_='panl3 salary-panl3').get_text().strip()
            if re.search(r'底薪\d{4,5}', job_salary):
                job_salary = re.search(r'(?<=底薪)\d{4,5}', job_salary).group()
            elif re.search(r'￥\d{4,5}', job_salary):
                job_salary = re.search(r'(?<=￥)\d{4,5}', job_salary).group()
            else:
                continue
            job_info.append([job_name, job_salary, job_company, job_time, job_url])
        return job_info

    def job_info_filter(self, list):
        salary_list = []
        for item in list:
            if int(item[1]) > 10000:
                if re.search(r'(助理)|(副)|(行政)|(主管)', item[0]):
                    salary_list.append(item)
        return salary_list

    def save_csv(self, job_info):
        today = time.strftime('%Y-%m-%d', time.localtime())
        filepath = 'BH365Zhaopin_' + today + '.csv'
        with open(filepath, 'a', encoding='utf-8', newline='') as f:
            writer = csv.writer(f)
            writer.writerows(job_info.values())

# 起始链接
start_page = r'https://www.365zhaopin.com/index.php?do=search&p='
# 存放职位信息的文件路径
csv_file = r'C:\Users\Michael\OneDrive\桌面\我的工作区\365job.csv'
zhapin = BH365Zhaopin()

# 解析第1页取得总页数
html = zhapin.get_html(start_page + '1')
page_num = zhapin.get_page_num(html)
print('总页数：', page_num)

my_job_info = []

# 解析第1-2页获取职位信息
for i in range(1, page_num + 1):
    html = zhapin.get_html(start_page + str(i))
    job_info = zhapin.get_job_info(html)
    job_info_filter = zhapin.job_info_filter(job_info)
    if len(job_info_filter) > 0:
        for item in job_info_filter:
            my_job_info.append(item)
    print('第', i, '/ %s 页解析完成' % page_num)
    time.sleep(random.random() * 3)

print(my_job_info)

# WebHook地址
webhook = r'https://oapi.dingtalk.com/robot/send?access_token' \
          r'=80da5c52f55d190c732e25b0d222249c2e509a29df36c78d3b389b14d211c724 '
# 机器人密钥
secret = r'SECf1d13f27bbceb66a187c37e1a4e422e87e52d7718727f3a548f9b9533b94c3c0'
# 可选：创建机器人勾选“加签”选项时使用

# 初始化机器人小丁
xiaoding = DingtalkChatbot(webhook, secret=secret)

xiaoding.send_markdown(title='今日天气', text=str(my_job_info), is_at_all=False)


import os
import logging
import boto3
from botocore.exceptions import ClientError

s3 = boto3.client('s3')
FILE_NAME = 'demo.txt'

def create_file():
    """Create a file called "demo.txt"
    """
    f = open(FILE_NAME, "w")
    f.write("Hello, I am a hacker")
    f.close()

def upload_file(file_name, bucket, object_name=None):
    """Upload a file to an S3 bucket

    :param file_name: File to upload
    :param bucket: Bucket to upload to
    :param object_name: S3 object name. If not specified then file_name is used
    :return: True if file was uploaded, else False
    """

    # If S3 object_name was not specified, use file_name
    if object_name is None:
        object_name = file_name

    try:
        response = s3.upload_file(file_name, bucket, object_name)
    except ClientError as e:
        logging.error(e)
        return False
    return True

def main_program():

    # get buckets
    response = s3.list_buckets()

    for bucket in response['Buckets']:

        # filter bucket names
        if 'frontend' in bucket["Name"]:
            print(f'Uploading {FILE_NAME} in bucket: {bucket["Name"]}')

            # creating demo file
            create_file()

            # upload file to S3
            if upload_file(FILE_NAME, bucket['Name']):
                print('File uploaded')
            break
        else:
            print('Could not find S3 BUCKET, exiting!')

    # clean up
    if os.path.exists(FILE_NAME):
        os.remove(FILE_NAME)

if __name__ == '__main__':
    main_program()


import numpy as np
import cv2
import socket
import PIL.Image as Image

with open('IIPP.txt','r') as r:
    IP=r.read()

host = IP  # 對server端為主機位置
print("host="+host)
port = 5555
address = (host, port)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(address)  # 用來請求連接遠程服務器

size=int(s.recv(1024).decode('utf-8'))
cv2.namedWindow("test", 0)
cv2.resizeWindow("test", 300, 300)  # 设置窗口大小

def show_xy(event,x,y,flags,param):
    if event == cv2.EVENT_LBUTTONDOWN:
        xy=str(x)+"-"+str(y)
        s.send(xy.encode())
        print(x,y)

indata='g'
while True:
    s.send(indata.encode())
    data = s.recv(size)
    img= Image.frombuffer('RGB', (1920, 1080), data)
    img2 = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
    if len(data)==0:
        s.close()
        break
    if cv2.waitKey(10) & 0xFF == ord('q'):
        break

    cv2.imshow("test", img2)
    cv2.setMouseCallback("test",show_xy)
    cv2.waitKey(100)


import numpy as np
from sklearn import svm
from sklearn import cross_validation

def labeler(feature_vectors_list):
    '''Takes an list of feature vectoers and produces two lists X and y
    where len(X) = len(y),
    X is the vectors, y is their (numerical) labels.'''
    X = []
    y = []
    currentLabel = 0
    for feature_vector in feature_vectors_list:
        for vector in feature_vector:
            X.append(vector)
            y.append(currentLabel)
        currentLabel += 1
    return(X, y)

def crossValidate(X, y):
    "7-fold cross-validation with an SVM with a set of labels and vectors"
    clf = svm.LinearSVC()
    scores = cross_validation.cross_val_score(clf, np.array(X), y, cv=7)
    return(scores.mean(), scores.std())


#!/usr/bin/env python
# coding: utf-8

# In[15]:

import streamlit as st
import sklearn

# load model
import pickle
loaded_model = pickle.load(open('models/knn_calculator.sav', 'rb'))

model_name = str(loaded_model.get_params()["estimator"])
param_combinations = str(loaded_model.get_params()["n_iter"])

string = "A " + model_name + " model was trained with " + param_combinations + " combinations of parameters to learn how to sum. Try it out!"

st.title("Machine Learning Calculator")

st.write(string)

# new house with fake data
import pandas as pd
input1 = st.number_input("Number 1")
input2 = st.number_input("Number 2")

input_df = pd.DataFrame({"n1":[input1], "n2":[input2]})

# prediction
st.write("The result of your sum as calculated by Machine Learning is: ", loaded_model.predict(input_df))


# Module entry point
import sys
import argparse
import logging
import datetime
import time
import subprocess
import re

import speedtest
from prometheus_client import start_http_server, Histogram, Gauge

from .utils import configure_log

Bandwidth = Gauge("wan_bandwidth_bps",
                  "Available bandwidth, in bits per second", ['dir', 'server'])
LatencyHist = Histogram("wan_latency_hist_seconds",
                        "Latency to the measurement servers, histogram mode", ['server'])
LatencyGauge = Gauge("wan_latency_seconds",
                     "Current latency to the measurement servers", ['server'])
Connectivity = Gauge(
    "wan_reachable", "Indicates whether the given server is reachable or not", ['server'])

def speedtest_check(speed):
    logging.info('Measuring download speed...')
    speed.download()
    logging.info('Measuring upload speed...')
    speed.upload()
    logging.info('Done!')

    results = speed.results.dict()

    with Bandwidth._lock:
        # Clear old results in this hacky way because the developers don't want to provide a
        # clear() method to avoid old labels persisting.
        #
        # See https://github.com/prometheus/client_python/issues/277
        Bandwidth._metrics.clear()

    Bandwidth.labels('upload', results['server']['host']).set(
        results['upload'])
    Bandwidth.labels('download', results['server']['host']).set(
        results['download'])

ping_time_regex = re.compile(r'time=([0-9]+\.[0-9]+) *ms')

def latency_check():
    ping_hosts = ['1.1.1.1', '8.8.8.8']
    ping_batch = 4

    for host in ping_hosts:
        logging.info(f"Pinging {host}")
        ping_cmd = f'ping -i 0.2 -c {ping_batch} {host}'

        try:
            ping_out = subprocess.check_output(
                ping_cmd.split(' '), encoding='utf-8')
            measures = [
                float(v) / 1000.0 for v in ping_time_regex.findall(ping_out)]

            if len(measures) == 0:
                logging.warning(
                    f'No ping times could be extracted! ping tool output is {ping_out}')
                continue

            avg = sum(measures) / len(measures)

            for m in measures:
                LatencyHist.labels(host).observe(m)

            LatencyGauge.labels(host).set(avg)

            reachable = True
        except subprocess.CalledProcessError:
            logging.error(
                f'Could not ping {host} correctly, an error occurred')
            reachable = False
        except ValueError:
            logging.exception(
                f'Could not parse ping times from output {ping_out}')

        Connectivity.labels(host).set(1.0 if reachable else 0.0)

def main(args=None):
    argp = argparse.ArgumentParser(description='Deadman server for MS Teams')

    argp.add_argument('--verbose', '-v', action='store_true',
                      help='Verbose log output')

    argp.add_argument('--port', '-p', type=int,
                      default=26543, help='Where to listen')

    argp.add_argument('--interval-speedtest', type=int,
                      default=600, help='Interval (in seconds) of speed test')

    argp.add_argument('--interval-latency', type=int, default=10,
                      help='Interval (in seconds) of latency test')

    argp.add_argument('--speedtest-server-refresh-interval', type=int, default=3600,
                      help='How frequently the best speedtest server should be refreshed')

    args = argp.parse_args()

    configure_log(args=args)

    last_speedcheck = None
    last_latency = None
    last_server_refresh = None

    speedcheck_interval = datetime.timedelta(seconds=args.interval_speedtest)
    latency_interval = datetime.timedelta(seconds=args.interval_latency)
    server_refresh_interval = datetime.timedelta(
        seconds=args.speedtest_server_refresh_interval)

    speed = speedtest.Speedtest()

    start_http_server(args.port)

    logging.info(f"Started! Listening on port {args.port}")

    try:
        while True:
            now = datetime.datetime.now()

            # This could be done way better and more generic, but for now it's just a simple
            # script so I prefer to avoid complications
            if last_server_refresh is None or now - last_server_refresh > server_refresh_interval:
                speed.get_servers([])
                speed.get_best_server()
                last_server_refresh = now

            if last_latency is None or now - last_latency > latency_interval:
                latency_check()
                last_latency = now

            if last_speedcheck is None or now - last_speedcheck > speedcheck_interval:
                speedtest_check(speed)
                last_speedcheck = now

            # This is enough for most purposes. Maybe compute the gcm of all the intervals...
            time.sleep(1)
    except KeyboardInterrupt:
        logging.info("Ctrl-C detected, exiting")
        sys.exit(0)

if __name__ == '__main__':
    main()


# vim: set et sw=4 sts=4 encoding=utf-8 foldmethod=marker :

#{{{ Imports
import cherrypy
from turbogears import controllers, expose, redirect
from turbogears import validate, flash, error_handler
from turbogears import validators as V
from turbogears import widgets as W
from turbogears import identity
from turbogears import paginate
from turbogears import config
from docutils.core import publish_parts
from sercom.presentation.subcontrollers import validate as val
from sercom.model import Curso, Ejercicio, Alumno, Docente, Grupo, DocenteInscripto, AlumnoInscripto
from sercom.widgets import FocusJSSource
#}}}

#{{{ Configuración
cls = Curso
name = 'Alumno del curso'
namepl = 'Alumnos del curso'
#}}}

#{{{ Validación
def validate_get(id):
    return val.validate_get(cls, name, id)

def validate_set(id, data):
    return val.validate_set(cls, name, id, data)

def validate_new(data):
    return val.validate_new(cls, name, data)
#}}}

def get_ejercicios():
    return [(e.id, e) for e in Ejercicio.select()]

def get_docentes():
    return [(d.id, d) for d in Docente.select()]

def get_alumnos_inscriptos(curso):
    return [(ai.id, ai) for ai in AlumnoInscripto.selectBy(curso)]

def get_alumnos():
    return [(a.id, a) for a in Alumno.select()]

def get_grupos():
    return [(g.id, g) for g in Grupo.select()]

ajax = u"""
function makeOption(option) {
    return OPTION({"value": option.value}, option.text);
}

function moveOption( fromSelect, toSelect) {
    // add 'selected' nodes toSelect
    appendChildNodes(toSelect,
    map( makeOption,ifilter(itemgetter('selected'), $(fromSelect).options)));
    // remove the 'selected' fromSelect
    replaceChildNodes(fromSelect,
        list(ifilterfalse(itemgetter('selected'), $(fromSelect).options))
    );
}
"""

#{{{ Formulario
class CursoAlumnoForm(W.TableForm):
    class Fields(W.WidgetsList):
        alumnos = W.MultipleSelectField(label=_(u'Alumnos'),
            attrs=dict( style='width:250px'),
            options=get_alumnos,
            validator = V.Int(not_empty=False))
        inscribir = W.Button(default='Inscribir', label='',
            attrs=dict( onclick='moveOption("form_alumnos","form_inscriptos")'))
        desinscribir = W.Button(default='Desinscribir', label='',
            attrs=dict( onclick='moveOption("form_inscriptos","form_alumnos")'))
        inscriptos = W.MultipleSelectField(label=_(u'Alumnos Inscriptos'),
            attrs=dict( style='width:250px'),
            options=get_alumnos,
            validator = V.Int(not_empty=False))
    fields = Fields()
    javascript = [FocusJSSource('form_alumnos'),
                  W.JSSource(ajax)]
form = CursoAlumnoForm()
#}}}

#{{{ Controlador
class CursoAlumnoController(controllers.Controller, identity.SecureResource):
    """Basic model admin interface"""
    require = identity.has_permission('admin')

    @expose()
    def default(self, curso_id):
        """handle non exist urls"""
        return dict(records=r, name=name, namepl=namepl, alumnos=alumnos)

    @expose()
    def index(self):
        raise redirect('/curso/list')

    @expose(template='kid:%s.templates.list' % __name__)
    @paginate('records', limit=config.get('items_por_pagina'))
    def list(self):
        """List records in model"""
        r = cls.select()
        return dict(records=r, name=name, namepl=namepl)

    @expose()
    def activate(self, id, activo):
        """Save or create record to model"""
        r = validate_get(id)
        try:
            r.activo = bool(int(activo))
        except ValueError:
            raise cherrypy.NotFound
        raise redirect('../../list')

    @expose(template='kid:%s.templates.new' % __name__)
    def new(self,curso_id, **kw):
        """Create new records in model"""
        return dict(name=name, namepl=namepl, form=form, values=kw)

    @validate(form=form)
    @error_handler(new)
    @expose()
    def create(self, **kw):
        """Save or create record to model"""
        r = validate_new(kw)
        docentes = kw.get('docentes', [])
        alumnos = kw.get('alumnos', [])
        """ Elimino todos los docentes asignados al curso y los agrego nuevamente"""
        for d in DocenteInscripto.selectBy(curso=r):
            d.destroySelf()
        """ Agrego la nueva seleccion """
        for d in docentes:
            r.add_docente(Docente(d))
        """ Elimino a los alumnos y los vuelvo a agregar """
        for a in AlumnoInscripto.selectBy(curso=r):
            d.destroySelf()
        for a in alumnos:
            r.add_alumno(Alumno(a))
        flash(_(u'Se creó un nuevo %s.') % name)
        raise redirect('list')

    @expose(template='kid:%s.templates.edit' % __name__)
    def edit(self, id, **kw):
        """Edit record in model"""
        r = validate_get(id)
        return dict(name=name, namepl=namepl, record=r, form=form)

    @validate(form=form)
    @error_handler(edit)
    @expose()
    def update(self, id, **kw):
        """Save or create record to model"""
        r = validate_set(id, kw)
        flash(_(u'El %s fue actualizado.') % name)
        raise redirect('../list')

    @expose(template='kid:%s.templates.show' % __name__)
    def show(self,id, **kw):
        """Show record in model"""
        r = validate_get(id)
        return dict(name=name, namepl=namepl, record=r)

    @expose()
    def delete(self, id):
        """Destroy record in model"""
        r = validate_get(id)
        r.destroySelf()
        flash(_(u'El %s fue eliminado permanentemente.') % name)
        raise redirect('../list')
#}}}


#!/usr/bin/python3
"""defining Base module"""
import json
import os
import csv
import turtle

class Base:
    """Class Base"""

    __nb_objects = 0

    def __init__(self, id=None):
        """Initializes Base instance
        Args:
            id: object identifier
        """
        if id is not None:
            self.id = id
        else:
            Base.__nb_objects += 1
            self.id = Base.__nb_objects

    @staticmethod
    def to_json_string(list_dictionaries):
        """JSON string representation of a list of dictionaries"""
        if list_dictionaries == [] or list_dictionaries is None:
            return "[]"
        else:
            return json.dumps(list_dictionaries)

    @classmethod
    def save_to_file(cls, list_objs):
        """write list_objs as JSON into a file
        Args:
            list_objs: list of instances
        """
        flname = cls.__name__ + ".json"
        if list_objs is None or list_objs == []:
            ls = "[]"
        else:
            dict_list = []
            for obj in list_objs:
                dict_list.append(obj.to_dictionary())
            ls = cls.to_json_string(dict_list)
        with open(flname, "w") as file:
            file.write(ls)
        return ls

    @staticmethod
    def from_json_string(json_string):
        """read list of JSON representation
        Args:
            json_string: string represents list of dicts
        """
        if json_string is None or len(json_string) == 0:
            return []
        else:
            return json.loads(json_string)

    @classmethod
    def create(cls, **dictionary):
        """returns an instance with all attributes already set
        Args:
            dictionary: double pointer to a dictionary
        """
        if cls.__name__ == "Rectangle":
            dummy = cls(1, 1)
        else:
            dummy = cls(1)
        dummy.update(**dictionary)
        return dummy

    @classmethod
    def load_from_file(cls):
        """return list of instances from json file"""
        filename = cls.__name__ + ".json"
        list_instances = []
        if os.path.exists(filename):
            with open(filename, "r") as file:
                res = file.read()
                list_dicts = cls.from_json_string(res)
                for dictu in list_dicts:
                    list_instances.append(cls.create(**dictu))
        return list_instances

    @classmethod
    def save_to_file_csv(cls, list_objs):
        """write the csv serialization of a list of objects to csv file
        Args:
            list_objs: a list of instances
        """
        filename = cls.__name__ + ".csv"
        with open(filename, "w", newline="") as file:
            if list_objs is None or list_objs == []:
                file.write("[]")
            else:
                if cls.__name__ == "Rectangle":
                    fields = ["id", "width", "height", "x", "y"]
                else:
                    fields = ["id", "size", "x", "y"]
                w = csv.DictWriter(file, fieldnames=fields)
                for obj in list_objs:
                    w.writerow(obj.to_dictionary())

    @classmethod
    def load_from_file_csv(cls):
        """Deserialize csv from a file"""
        filename = cls.__name__ + ".csv"
        list_i = []
        if os.path.exists(filename):
            with open(filename, "r") as file:
                read = csv.reader(file, delimiter=",")
                if cls.__name__ == "Rectangle":
                    fields = ["id", "width", "height", "x", "y"]
                elif cls.__name__ == "Square":
                    fields = ["id", "size", "x", "y"]
                for i, row in enumerate(read):
                    if i > 0:
                        el = cls(1, 1)
                        for j, k in enumerate(row):
                            if k:
                                setattr(el, fields[j], int(e))
                        list_i.append(el)
        return list_i

    @classmethod
    def draw(list_rectangles, list_squares):
        """opens a window and draws the rectangles and squares
        Args:
            list_rectangles: a list of rectangle instances
            list_squares: a list of square instances
        """
        window = turtle.Screen()
        pen = turtle.Pen()
        figs = list_rectangles + list_squares

        for f in figs:
            pen.up()
            pen.goto(f.x, f.y)
            pen.down()
            pen.forward(f.width)
            pen.right(90)
            pen.forward(f.height)
            pen.right(90)
            pen.forward(f.width)
            pen.right(90)
            pen.forward(f.height)
            pen.right(90)
        window.exitonclick()