#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
PyTimber -- A Python wrapping of CALS API

Copyright (c) CERN 2015-2017

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Authors:
    R. De Maria     <riccardo.de.maria@cern.ch>
    T. Levens       <tom.levens@cern.ch>
    C. Hernalsteens <cedric.hernalsteens@cern.ch>
    M. Betz         <michael.betz@cern.ch>
    M. Fitterer     <mfittere@fnal.gov>
    R. Castellotti  <riccardo.castellotti@cern.ch>
    L. Coyle        <loic.coyle@epfl.ch>
    P. Sowinski     <piotr.sowinski@cern.ch>
"""

import time
import datetime
import six
import logging

from .check_kerberos import check_kerberos

try:
    import jpype
    import cmmnbuild_dep_manager
except ImportError:
    print(
        """ERROR: module jpype and cmmnbuild_dep_manager not found!
        Exporting data from the logging database will not be
        available!"""
    )
import numpy as np
from collections import namedtuple

Stat = namedtuple(
    "Stat",
    [
        "MinTstamp",
        "MaxTstamp",
        "ValueCount",
        "MinValue",
        "MaxValue",
        "AvgValue",
        "StandardDeviationValue",
    ],
)

def _Timestamp2float(ts):
    return int(ts.getTime() / 1000.0) + ts.getNanos() / 1e9

if six.PY3:
    long = int

# Documentation CALS API
# http://abwww.cern.ch/ap/dist/accsoft/cals/accsoft-cals-extr-client/PRO/build/docs/api/

class LoggingDB(object):
    try:
        _jpype = jpype
    except NameError:
        print("ERROR: jpype is note defined!")

    def __init__(
        self,
        appid="PYTIMBER3",
        clientid="PYTIMBER3",
        source="all",
        loglevel=None,
    ):
        # Configure logging
        logging.basicConfig()
        self._log = logging.getLogger(__name__)
        if loglevel is not None:
            self._log.setLevel(loglevel)

        # Start JVM
        mgr = cmmnbuild_dep_manager.Manager("pytimber")
        mgr.start_jpype_jvm()
        self._mgr = mgr

        # log4j config
        null = jpype.JPackage("org").apache.log4j.varia.NullAppender()
        jpype.JPackage("org").apache.log4j.BasicConfigurator.configure(null)

        self._source = source

        if source == "nxcals":
            check_kerberos()
            self._System = jpype.java.lang.System
            self._System.setProperty(
                "service.url",
                "https://cs-ccr-nxcals6.cern.ch:19093,https://cs-ccr-nxcals7.cern.ch:19093,https://cs-ccr-nxcals8.cern.ch:19093",
            )
            ServiceBuilder = jpype.JPackage(
                "cern"
            ).nxcals.api.backport.client.service.ServiceBuilder
            builder = ServiceBuilder.getInstance()
            self._md = builder.createMetaService()
            self._ts = builder.createTimeseriesService()
            self._FillService = builder.createLHCFillService()
            self._VariableDataType = jpype.JPackage(
                "cern"
            ).nxcals.api.backport.domain.core.constants.VariableDataType
        else:
            # Data source preferences
            DataLocPrefs = jpype.JPackage(
                "cern"
            ).accsoft.cals.extr.domain.core.datasource.DataLocationPreferences
            loc = {
                "mdb": DataLocPrefs.MDB_PRO,
                "ldb": DataLocPrefs.LDB_PRO,
                "all": DataLocPrefs.MDB_AND_LDB_PRO,
            }[source]

            ServiceBuilder = jpype.JPackage(
                "cern"
            ).accsoft.cals.extr.client.service.ServiceBuilder
            builder = ServiceBuilder.getInstance(appid, clientid, loc)
            self._builder = builder
            self._md = builder.createMetaService()
            self._ts = builder.createTimeseriesService()
            self._FillService = builder.createLHCFillService()
            self.tree = Hierarchy("root", None, None, self._md)
            self._VariableDataType = jpype.JPackage(
                "cern"
            ).accsoft.cals.extr.domain.core.constants.VariableDataType

    def toTimestamp(self, t):
        Timestamp = jpype.java.sql.Timestamp
        if isinstance(t, six.string_types):
            return Timestamp.valueOf(t)
        elif isinstance(t, datetime.datetime):
            return Timestamp.valueOf(t.strftime("%Y-%m-%d %H:%M:%S.%f"))
        elif t is None:
            return None
        elif isinstance(t, Timestamp):
            return t
        else:
            ts = Timestamp(long(t * 1000))
            sec = int(t)
            nanos = int((t - sec) * 1e9)
            ts.setNanos(nanos)
            return ts

    def fromTimestamp(self, ts, unixtime):
        if ts is None:
            return None
        else:
            t = _Timestamp2float(ts)
            if unixtime:
                return t
            else:
                return datetime.datetime.fromtimestamp(t)

    def toStringList(self, myArray):
        myList = jpype.java.util.ArrayList()
        for s in myArray:
            myList.add(s)
        return myList

    def toTimescale(self, timescale_list):
        if self._source == "nxcals":
            Timescale = jpype.JPackage(
                "cern"
            ).nxcals.api.backport.domain.core.constants.TimescalingProperties
        else:
            Timescale = jpype.JPackage(
                "cern"
            ).accsoft.cals.extr.domain.core.constants.TimescalingProperties
        try:
            timescale_str = "_".join(timescale_list)
            return Timescale.valueOf(timescale_str)
        except Exception as e:
            self._log.warning("exception in timescale:{}".format(e))

    def search(self, pattern):
        """Search for parameter names. Wildcard is '%'."""
        types = self._VariableDataType.ALL
        vl = self._md.getVariablesOfDataTypeWithNameLikePattern(pattern, types)
        return [vv.getVariableName() for vv in vl.getVariables()]

    def getDescription(self, pattern):
        """Get Variable Description from pattern. Wildcard is '%'."""
        return dict(
            [
                (vv.getVariableName(), vv.getDescription())
                for vv in self._getVariableList(pattern)
            ]
        )

    def getUnit(self, pattern):
        """Get Variable Unit from pattern. Wildcard is '%'."""
        return dict(
            [
                (vv.getVariableName(), vv.getUnit())
                for vv in self._getVariableList(pattern)
            ]
        )

    def _getFundamentals(self, t1, t2, fundamental):
        self._log.info(
            "Querying fundamentals (pattern: {0}):".format(fundamental)
        )
        fundamentals = self._md.getFundamentalsInTimeWindowWithNameLikePattern(
            t1, t2, fundamental
        )
        if fundamentals is None:
            self._log.info("No fundamental found in time window")
        else:
            logfuns = []
            for f in fundamentals.getVariables():  # workaround 0.7.1
                logfuns.append(f.toString())
            self._log.info(
                "List of fundamentals found: {0}".format(", ".join(logfuns))
            )
        return fundamentals

    def getFundamentals(self, t1, t2, fundamental):
        self._log.warning("getFundamentals will be deprecated")
        return self.searchFundamental(fundamental, t1, t2)

    def getVariableSet(self, pattern_or_list):
        """Get a list of variables based on a list of strings or a pattern.
        Wildcard for the pattern is '%'.
        """
        if isinstance(pattern_or_list, six.string_types):
            types = self._VariableDataType.ALL
            variables = self._md.getVariablesOfDataTypeWithNameLikePattern(
                pattern_or_list, types
            )
        elif isinstance(pattern_or_list, (list, tuple)):
            variables = self._md.getVariablesWithNameInListofStrings(
                jpype.java.util.Arrays.asList(pattern_or_list)
            )
        else:
            raise ValueError(f"{pattern_or_list} not pattern or list")
        return variables

    def _getVariableList(self, pattern_or_list):
        """work around for jpype 0.7.1 as list(vset) gives strings
        """
        return self.getVariableSet(pattern_or_list).getVariables()

    def processDataset(self, dataset, datatype, unixtime):
        spi = jpype.JPackage(
            "cern"
        ).accsoft.cals.extr.domain.core.timeseriesdata.spi

        if type(dataset) is list:
            new_ds = jpype.JPackage(
                "cern"
            ).accsoft.cals.extr.domain.core.timeseriesdata.spi.TimeseriesDataSetImpl()
            for data in dataset:
                new_ds.add(data)
            dataset = new_ds

        if dataset.isEmpty():
            return (np.array([], dtype=float), np.array([], dtype=float))

        # PrimitiveDataSets = jpype.JPackage("cern").lhc.commons.cals.PrimitiveDataSets
        if self._source == "nxcals":
            PrimitiveDataSets = jpype.JPackage(
                "org"
            ).pytimber.utils.BackPortDataSets
        else:
            PrimitiveDataSets = jpype.JPackage(
                "org"
            ).pytimber.utils.PrimitiveDataSets

        timestamps = np.array(
            PrimitiveDataSets.unixTimestamps(dataset)[:], dtype=float
        )
        if not unixtime:
            timestamps = np.array(
                [datetime.datetime.fromtimestamp(t) for t in timestamps]
            )

        dataclass = PrimitiveDataSets.dataClass(dataset)

        if self._source == "nxcals":

            # idx = ~np.array([d.isNullValue() for d in dataset])
            # ds = np.array(dataset)[idx]
            # timestamps = timestamps[idx]

            ds = dataset

            if datatype == "NUMERIC":
                try:
                    ds = np.array([d.getDoubleValue() for d in ds])
                except jpype.java.lang.NoSuchMethodException:
                    try:
                        ds = np.array([d.getLongValue() for d in ds])
                    except jpype.java.lang.NoSuchMethodException:
                        self._log.warning(
                            "unsupported datatype, returning the java object"
                        )
            elif datatype == "VECTORNUMERIC":
                try:
                    ds = np.array([d.getDoubleValues() for d in ds])
                except jpype.java.lang.NoSuchMethodException:
                    try:
                        ds = np.array([d.getLongValues() for d in ds])
                    except jpype.java.lang.NoSuchMethodException:
                        self._log.warning(
                            "unsupported datatype, returning the java object"
                        )
            elif datatype == "TEXTUAL":
                try:
                    ds = np.array([d.getVarcharValue() for d in ds])
                except jpype.java.lang.NoSuchMethodException:
                    self._log.warning(
                        "unsupported datatype, returning the java object"
                    )
            elif datatype == "VECTORSTRING":
                try:
                    ds = np.array([d.getStringValues() for d in ds])
                except jpype.java.lang.NoSuchMethodException:
                    self._log.warning(
                        "unsupported datatype, returning the java object"
                    )
            else:
                self._log.warning(
                    "unsupported datatype, returning the java object"
                )
            return (timestamps, ds)

        if datatype == "MATRIXNUMERIC":
            if dataclass == spi.MatrixNumericDoubleData:
                data = np.array(
                    [
                        [np.array(a[:], dtype=float) for a in matrix]
                        for matrix in PrimitiveDataSets.doubleMatrixData(
                            dataset
                        )
                    ]
                )
            elif dataclass == spi.MatrixNumericLongData:
                data = np.array(
                    [
                        [np.array(a[:], dtype=int) for a in matrix]
                        for matrix in PrimitiveDataSets.longMatrixData(dataset)
                    ]
                )
            else:
                self._log.warning(
                    "'%s' unsupported datatype, returning the java object"
                    % (datatype)
                )
                data = [t for t in dataset]
        elif datatype == "VECTORNUMERIC":
            if dataclass == spi.VectorNumericDoubleData:
                data = np.array(
                    [
                        np.array(a[:], dtype=float)
                        for a in PrimitiveDataSets.doubleVectorData(dataset)
                    ]
                )
            elif dataclass == spi.VectorNumericLongData:
                data = np.array(
                    [
                        np.array(a[:], dtype=int)
                        for a in PrimitiveDataSets.longVectorData(dataset)
                    ]
                )
            else:
                self._log.warning(
                    "Unsupported datatype, returning the " "java object"
                )
                data = [t for t in dataset]
        elif datatype == "VECTORSTRING":
            data = np.array(
                [
                    np.array(a[:], dtype="U")
                    for a in PrimitiveDataSets.stringVectorData(dataset)
                ]
            )
        elif datatype == "NUMERIC":
            if dataclass == spi.NumericDoubleData:
                data = np.array(
                    PrimitiveDataSets.doubleData(dataset)[:], dtype=float
                )
            elif dataclass == spi.NumericLongData:
                data = np.array(
                    PrimitiveDataSets.longData(dataset)[:], dtype=int
                )
            else:
                self._log.warning(
                    "Unsupported datatype, returning the " "java object"
                )
                data = [t for t in dataset]
        elif datatype == "FUNDAMENTAL":
            data = np.ones_like(timestamps, dtype=bool)
        elif datatype == "TEXTUAL":
            data = np.array(
                PrimitiveDataSets.stringData(dataset)[:], dtype="U"
            )
        else:
            self._log.warning(
                "Unsupported datatype, returning the " "java object"
            )
            data = [t for t in dataset]
        return (timestamps, data)

    def getAligned(
        self,
        pattern_or_list,
        t1,
        t2,
        fundamental=None,
        master=None,
        unixtime=True,
    ):
        """Get data aligned to a variable"""
        ts1 = self.toTimestamp(t1)
        ts2 = self.toTimestamp(t2)
        out = {}
        master_variable = None

        # Fundamentals
        if fundamental is not None:
            fundamentals = self._getFundamentals(ts1, ts2, fundamental)
            if fundamentals is None:
                return {}

        # Build variable list
        variables = self._getVariableList(pattern_or_list)

        if master is None:
            if isinstance(pattern_or_list, (list, tuple)):
                master_variable = variables.getVariable(pattern_or_list[0])
            else:
                master_variable = variables.getVariable(0)
        else:
            master_variable = variables.getVariable(master)

        if master_variable is None:
            self._log.warning("Master variable not found.")
            return {}

        master_name = master_variable.toString()

        if len(variables) == 0:
            self._log.warning("No variables found.")
            return {}
        else:
            logvars = []
            for jvar in variables:
                vname = jvar.getVariableName()
                if vname == master_name:
                    logvars.append("{0} (master)".format(vname))
                else:
                    logvars.append(vname)

            self._log.info(
                "List of variables to be queried: {0}".format(
                    ", ".join(logvars)
                )
            )

        # Acquire master dataset
        if fundamental is not None:
            master_ds = self._ts.getDataInTimeWindowFilteredByFundamentals(
                master_variable, ts1, ts2, fundamentals
            )
        else:
            master_ds = self._ts.getDataInTimeWindow(master_variable, ts1, ts2)

        self._log.info(
            "Retrieved {0} values for {1} (master)".format(
                master_ds.size(), master_name
            )
        )

        # Prepare master dataset for output
        out["timestamps"], out[master_name] = self.processDataset(
            master_ds, master_ds.getVariableDataType().toString(), unixtime
        )

        # Acquire aligned data based on master dataset timestamps
        for jvar in variables:
            if jvar.toString() == master_name:
                continue
            start_time = time.time()
            res = self._ts.getDataAlignedToTimestamps(jvar, master_ds)
            self._log.info(
                "Retrieved {0} values for {1}".format(
                    res.size(), jvar.getVariableName()
                )
            )
            self._log.info(
                "{0} seconds for aqn".format(time.time() - start_time)
            )
            out[jvar.getVariableName()] = self.processDataset(
                res, res.getVariableDataType().toString(), unixtime
            )[1]
        return out

    def searchFundamental(self, fundamental, t1, t2=None):
        """Search fundamental"""
        ts1 = self.toTimestamp(t1)
        if t2 is None:
            t2 = time.time()
        ts2 = self.toTimestamp(t2)
        fundamentals = self._getFundamentals(ts1, ts2, fundamental)
        if fundamentals is not None:
            return list(fundamentals.getVariableNames())
        else:
            return []

    def getStats(self, pattern_or_list, t1, t2, unixtime=True):
        ts1 = self.toTimestamp(t1)
        ts2 = self.toTimestamp(t2)

        # Build variable list
        variables = self.getVariableSet(pattern_or_list)
        if len(variables) == 0:
            self._log.warning("No variables found.")
            return {}
        else:
            logvars = []
            for jvar in variables.getVariables():  # workaround 0.7.1
                logvars.append(jvar.toString())
            self._log.info(
                "List of variables to be queried: {0}".format(
                    ", ".join(logvars)
                )
            )

        # Acquire
        data = self._ts.getVariableStatisticsOverMultipleVariablesInTimeWindow(
            variables, ts1, ts2
        )

        out = {}
        for stat in data.getStatisticsList():
            count = stat.getValueCount()
            if count > 0:
                s = Stat(
                    self.fromTimestamp(stat.getMinTstamp(), unixtime),
                    self.fromTimestamp(stat.getMaxTstamp(), unixtime),
                    int(count),
                    stat.getMinValue().doubleValue(),
                    stat.getMaxValue().doubleValue(),
                    stat.getAvgValue().doubleValue(),
                    stat.getStandardDeviationValue().doubleValue(),
                )

                out[stat.getVariableName()] = s

        return out

    #    def getSize(self, pattern_or_list, t1, t2):
    #        ts1 = self.toTimestamp(t1)
    #        ts2 = self.toTimestamp(t2)
    #
    #        # Build variable list
    #        variables = self._getVariableList(pattern_or_list)
    #        if len(variables) == 0:
    #            log.warning('No variables found.')
    #            return {}
    #        else:
    #            logvars = []
    #            for v in variables:
    #                logvars.append(v)
    #            log.info('List of variables to be queried: {0}'.format(
    #                ', '.join(logvars)))
    #        # Acquire
    #        for v in variables:
    #            return self._ts.getJVMHeapSizeEstimationForDataInTimeWindow(v,ts1,ts2,None,None)

    def get(
        self, pattern_or_list, t1, t2=None, fundamental=None, unixtime=True
    ):
        """Query the database for a list of variables or for variables whose
        name matches a pattern (string) in a time window from t1 to t2.

        If t2 is missing, None, "last", the last data point before t1 is given
        If t2 is "next", the first data point after t1 is given.

        If no pattern if given for the fundamental all the data are returned.

        If a fundamental pattern is provided, the end of the time window as to
        be explicitely provided.
        """

        ts1 = self.toTimestamp(t1)
        if t2 not in ["last", "next", None]:
            ts2 = self.toTimestamp(t2)
        out = {}

        # Build variable list
        variables = self._getVariableList(pattern_or_list)
        if len(variables) == 0:
            self._log.warning("No variables found.")
            return {}
        else:
            logvars = []
            for jvar in variables:
                logvars.append(jvar.toString())
            self._log.info(
                "List of variables to be queried: {0}".format(
                    ", ".join(logvars)
                )
            )

        # Fundamentals
        if fundamental is not None and ts2 is None:
            self._log.warning(
                "Unsupported: if filtering by fundamentals "
                "you must provide a correct time window"
            )
            return {}
        if fundamental is not None:
            fundamentals = self._getFundamentals(ts1, ts2, fundamental)
            if fundamentals is None:
                return {}

        # Acquire
        for jvar in variables:
            if t2 is None or t2 == "last":
                res = [
                    self._ts.getLastDataPriorToTimestampWithinDefaultInterval(
                        jvar, ts1
                    )
                ]
                if res[0] is None:
                    res = []
                    datatype = None
                else:
                    datatype = res[0].getVariableDataType().toString()
                    self._log.info(
                        "Retrieved {0} values for {1}".format(
                            1, jvar.getVariableName()
                        )
                    )
            elif t2 == "next":
                res = [
                    self._ts.getNextDataAfterTimestampWithinDefaultInterval(
                        jvar, ts1
                    )
                ]
                if res[0] is None:
                    res = []
                    datatype = None
                else:
                    datatype = res[0].getVariableDataType().toString()
                    self._log.info(
                        "Retrieved {0} values for {1}".format(
                            1, jvar.getVariableName()
                        )
                    )
            else:
                if fundamental is not None:
                    res = self._ts.getDataInTimeWindowFilteredByFundamentals(
                        jvar, ts1, ts2, fundamentals
                    )
                else:
                    res = self._ts.getDataInTimeWindow(jvar, ts1, ts2)
                datatype = res.getVariableDataType().toString()
                self._log.info(
                    "Retrieved {0} values for {1}".format(
                        res.size(), jvar.getVariableName()
                    )
                )
            out[jvar.getVariableName()] = self.processDataset(
                res, datatype, unixtime
            )
        return out

    def getVariable(
        self, variable, t1, t2=None, fundamental=None, unixtime=True
    ):
        return self.get(variable, t1, t2, fundamental, unixtime)[variable]

    def getScaled(
        self,
        pattern_or_list,
        t1,
        t2,
        unixtime=True,
        scaleAlgorithm="SUM",
        scaleInterval="MINUTE",
        scaleSize="1",
    ):
        """Query the database for a list of variables or for variables whose
        name matches a pattern (string) in a time window from t1 to t2.

        If no pattern if given for the fundamental all the data are returned.

        If a fundamental pattern is provided, the end of the time window as to
        be explicitely provided.

        Applies the scaling with supplied scaleAlgorithm, scaleSize, scaleInterval
        """
        ts1 = self.toTimestamp(t1)
        ts2 = self.toTimestamp(t2)
        timescaling = self.toTimescale(
            [scaleSize, scaleInterval, scaleAlgorithm]
        )

        out = {}
        # Build variable list
        variables = self._getVariableList(pattern_or_list)
        if len(variables) == 0:
            self._log.warning("No variables found.")
            return {}
        else:
            logvars = []
            for jvar in variables:
                logvars.append(jvar.toString())
            self._log.info(
                "List of variables to be queried: {0}".format(
                    ", ".join(logvars)
                )
            )

        # Acquire
        for jvar in variables:
            try:
                res = self._ts.getDataInFixedIntervals(
                    jvar, ts1, ts2, timescaling
                )
            except jpype.JException as e:
                print(e.message())
                print(
                    """
                   scaleAlgorithm should be one of:{},
                   scaleInterval one of:{},
                   scaleSize an integer""".format(
                        [
                            "MAX",
                            "MIN",
                            "AVG",
                            "COUNT",
                            "SUM",
                            "REPEAT",
                            "INTERPOLATE",
                        ],
                        [
                            "SECOND",
                            "MINUTE",
                            "HOUR",
                            "DAY",
                            "WEEK",
                            "MONTH",
                            "YEAR",
                        ],
                    )
                )
                return
            datatype = res.getVariableDataType().toString()
            self._log.info(
                "Retrieved {0} values for {1}".format(
                    res.size(), jvar.getVariableName()
                )
            )
            vname = jvar.getVariableName()
            out[vname] = self.processDataset(res, datatype, unixtime)
            if np.isnan(out[vname][1]).any():
                self._log.warning(
                    "Variable {} contains NaN values".format(vname)
                )
        return out

    def getLHCFillData(self, fill_number=None, unixtime=True):
        """Gets times and beam modes for a particular LHC fill.
        Parameter fill_number can be an integer to get a particular fill or
        None to get the last completed fill.
        """
        if isinstance(fill_number, int):
            data = self._FillService.getLHCFillAndBeamModesByFillNumber(
                fill_number
            )
        else:
            data = self._FillService.getLastCompletedLHCFillAndBeamModes()

        if data is None:
            return None
        else:
            return {
                "fillNumber": data.getFillNumber(),
                "startTime": self.fromTimestamp(data.getStartTime(), unixtime),
                "endTime": self.fromTimestamp(data.getEndTime(), unixtime),
                "beamModes": [
                    {
                        "mode": mode.getBeamModeValue().toString(),
                        "startTime": self.fromTimestamp(
                            mode.getStartTime(), unixtime
                        ),
                        "endTime": self.fromTimestamp(
                            mode.getEndTime(), unixtime
                        ),
                    }
                    for mode in data.getBeamModes()
                ],
            }

    def getLHCFillsByTime(self, t1, t2, beam_modes=None, unixtime=True):
        """Returns a list of the fills between t1 and t2.
        Optional parameter beam_modes allows filtering by beam modes.
        """
        ts1 = self.toTimestamp(t1)
        ts2 = self.toTimestamp(t2)

        BeamModeValue = jpype.JPackage(
            "cern"
        ).accsoft.cals.extr.domain.core.constants.BeamModeValue

        if beam_modes is None:
            fills = self._FillService.getLHCFillsAndBeamModesInTimeWindow(
                ts1, ts2
            )
        else:
            if isinstance(beam_modes, str):
                beam_modes = beam_modes.split(",")

            valid_beam_modes = [
                mode
                for mode in beam_modes
                if BeamModeValue.isBeamModeValue(mode)
            ]

            if len(valid_beam_modes) == 0:
                raise ValueError("no valid beam modes found")

            java_beam_modes = BeamModeValue.parseBeamModes(
                ",".join(valid_beam_modes)
            )

            fills = self._FillService.getLHCFillsAndBeamModesInTimeWindowContainingBeamModes(
                ts1, ts2, java_beam_modes
            )

        return [
            self.getLHCFillData(fill, unixtime)
            for fill in fills.getFillNumbers()
        ]

    def getIntervalsByLHCModes(
        self,
        t1,
        t2,
        mode1,
        mode2,
        unixtime=True,
        mode1time="startTime",
        mode2time="endTime",
        mode1idx=0,
        mode2idx=-1,
    ):
        """Returns a list of the fill numbers and interval between t1 and
        t2 between the startTime of first beam mode in mode1 and the
        endTime of the first beam mode.

        The optional parameters 'mode[12]time' can take
        'startTime' or 'endTime'

        The otional parameter 'mode[12]idx' selects which mode in case of
        multiple occurrence of mode

        """
        ts1 = self.toTimestamp(t1)
        ts2 = self.toTimestamp(t2)
        fills = self.getLHCFillsByTime(ts1, ts2, [mode1, mode2])
        out = []
        for fill in fills:
            fn = fill["fillNumber"]
            m1 = []
            m2 = []
            for bm in fill["beamModes"]:
                if bm["mode"] == mode1:
                    m1.append(bm[mode1time])
                if bm["mode"] == mode2:
                    m2.append(bm[mode2time])
            if len(m1) > 0 and len(m2) > 0:
                out.append([fn, m1[mode1idx], m2[mode2idx]])
        return out

    def getMetaData(self, pattern_or_list):
        """Get All MetaData for a variable defined by a pattern_or_list"""
        out = {}
        variables = self._getVariableList(pattern_or_list)
        for jvar in variables:
            metadata = self._md.getVectorElements(
                jvar
            ).getVectornumericElements()
            ts = [_Timestamp2float(tt) for tt in metadata]
            #            vv=[dict([(aa.key,aa.value) for aa in a.iterator()])
            #                    for a in metadata.values()]
            vv = [
                [aa.getValue() for aa in a.iterator()]
                for a in metadata.values()
            ]
            out[jvar.getVariableName()] = ts, vv
        return out

class Hierarchy(object):
    def __init__(self, name, obj, src, varsrc):
        self.name = name
        self.obj = obj
        self.varsrc = varsrc
        if src is not None:
            self.src = src
        for vvv in self._get_vars():
            if len(vvv) > 0:
                setattr(self, self._cleanName(vvv), vvv)

    def _get_childs(self):
        if self.obj is None:
            objs = self.src.getHierachies(1)
        else:
            objs = self.src.getChildHierarchies(self.obj)
        return dict(
            [(self._cleanName(hh.getHierarchyName()), hh) for hh in objs]
        )

    def _cleanName(self, s):
        if s[0].isdigit():
            s = "_" + s
        out = []
        for ss in s:
            if ss in " _-;></:.":
                out.append("_")
            else:
                out.append(ss)
        return "".join(out)

    def __getattr__(self, k):
        if k == "src":
            self.src = self.varsrc.getAllHierarchies()
            return self.src
        elif k == "_dict":
            self._dict = self._get_childs()
            return self._dict
        else:
            return Hierarchy(k, self._dict[k], self.src, self.varsrc)

    def __dir__(self):
        if jpype.isThreadAttachedToJVM() == 0:
            jpype.attachThreadToJVM()
        v = sorted(
            [self._cleanName(i) for i in self._get_vars() if len(i) > 0]
        )
        return sorted(self._dict.keys()) + v

    def __repr__(self):
        if self.obj is None:
            return "<Top Hierarchy>"
        else:
            name = self.obj.getHierarchyName()
            desc = self.obj.getDescription()
            return "<{0}: {1}>".format(name, desc)

    def _get_vars(self):
        VariableDataType = jpype.JPackage(
            "cern"
        ).accsoft.cals.extr.domain.core.constants.VariableDataType
        if self.obj is not None:
            vvv = self.varsrc.getVariablesOfDataTypeAttachedToHierarchy(
                self.obj, VariableDataType.ALL
            )
            return vvv.toString()[1:-1].split(", ")
        else:
            return []

    def get_vars(self):
        return self._get_vars()


import logging
import random
import string

from accounts.models import Customer
from django.db import IntegrityError, models
from products.models import Product

logger = logging.getLogger(__name__)
CODE_LENGTH = 4
SAVE_CODE_ATTEMPTS = 20

class Code(models.Model):
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    code = models.CharField(max_length=7, unique=True)
    create_date = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.code

    def generate_code(self):
        """ Generate random string from template
            [0-9a-b]-[0-9a-b]-[0-9a-b]-[0-9a-b]
        """
        # deside if it number or char
        characters = []
        for i in range(CODE_LENGTH):
            char = ""
            if random.randint(0, 1):
                char = random.choice(string.ascii_lowercase)
            else:
                char = str(random.randint(0, 9))
            if not char:
                raise ValueError()

            characters.append(char)
        return "-".join(characters)

    def save(self, *args, **kwargs):
        """ Overriden save method
            make an attempt to save generated code and if there
            not unique code - try generate new code
        """
        if not self.pk:
            attempt = 0
            while True:
                self.code = self.generate_code()
                try:
                    super().save(*args, **kwargs)
                except IntegrityError as e:
                    if "unique_constraint" in e.message.lower():
                        if attempt < SAVE_CODE_ATTEMPTS:
                            continue
                        else:
                            logger.error(
                                "Unable to create discount code",
                                "Maximum attempts count exceed",
                            )
                            raise IntegrityError(e)
                    else:
                        logging.error("Unable to create discount code", e)
                        raise IntegrityError(e)
                else:
                    break
        else:
            super().save(*args, **kwargs)


import base64
import logging
import json

import requests
from kafka import KafkaProducer
from kafka.errors import KafkaTimeoutError

from DeviceManager.conf import CONFIG
from DeviceManager.Logger import Log
from datetime import datetime
import time

LOGGER = Log().color_log()

class DeviceEvent:
    CREATE = "create"
    UPDATE = "update"
    REMOVE = "remove"
    CONFIGURE = "configure"
    TEMPLATE = "template.update"

class NotificationMessage:
    event = ""
    data = None
    meta = None

    def __init__(self, ev, d, m):
        self.event = ev
        self.data = d
        self.meta = m

    def to_json(self):
        return {"event": self.event, "data": self.data, "meta": self.meta}

class KafkaNotifier:

    def __init__(self):
        self.kafka_address = CONFIG.kafka_host + ':' + CONFIG.kafka_port
        self.kf_prod = None

        self.kf_prod = KafkaProducer(value_serializer=lambda v: json.dumps(v).encode('utf-8'),
                                bootstrap_servers=self.kafka_address)

        # Maps services to their managed topics
        self.topic_map = {}

    def get_topic(self, service, subject):
        if service in self.topic_map.keys():
            if subject in self.topic_map[service].keys():
                return self.topic_map[service][subject]

        target = "{}/topic/{}".format(CONFIG.data_broker, subject)
        userinfo = {
            "username": "device-manager",
            "service": service
        }

        jwt = "{}.{}.{}".format(base64.b64encode("model".encode()).decode(),
                                base64.b64encode(json.dumps(
                                    userinfo).encode()).decode(),
                                base64.b64encode("signature".encode()).decode())

        response = requests.get(target, headers={"authorization": jwt})
        if 200 <= response.status_code < 300:
            payload = response.json()
            if self.topic_map.get(service, None) is None:
                self.topic_map[service] = {}
            self.topic_map[service][subject] = payload['topic']
            return payload['topic']
        return None

    def send_notification(self, event, device, meta):
        # TODO What if Kafka is not yet up?

        full_msg = NotificationMessage(event, device, meta)
        try:
            topic = self.get_topic(meta['service'], CONFIG.subject)
            LOGGER.debug(f" topic for {CONFIG.subject} is {topic}")
            if topic is None:
                LOGGER.error(f" Failed to retrieve named topic to publish to")

            self.kf_prod.send(topic, full_msg.to_json())
            self.kf_prod.flush()
        except KafkaTimeoutError:
            LOGGER.error(f" Kafka timed out.")

    def send_raw(self, raw_data, tenant):
        try:
            topic = self.get_topic(tenant, CONFIG.subject)
            if topic is None:
                LOGGER.error(f" Failed to retrieve named topic to publish to")
            self.kf_prod.send(topic, raw_data)
            self.kf_prod.flush()
        except KafkaTimeoutError:
            LOGGER.error(f" Kafka timed out.")


import pickle

from nose.tools import eq_

from .. import indonesian
from ...datasources import diff, parent_revision, revision
from ...dependencies import solve

BAD = [
    "anjing",
    "bajingan",
    "bangsat",
    "bispak",
    "bloon", "blo'on",
    "brengsek", "brengsex",
    "bencong",
    "babi",
    "cibai",
    "coley",
    "diselama",
    "escoduro",
    "fredrike",
    "fogh",
    "gauguin",
    "goblok",
    "gestapo",
    "husseins",
    "indon",
    "jambut",
    "jellinek",
    "jellygamat",
    "keparat",
    "kontol",
    "lonte",
    "loked",
    "lvmh",
    "malingsia",
    "memek",
    "monyong",
    "netnapa",
    "ngentot",
    "nesbitt",
    "panadta",
    "palaji",
    "perek",
    "pukimak",
    "pedofil",
    "riyhad",
    "sempak",
    "sinting",
    "steinway",
    "sukhano",
    "taenjamras",
    "tetek",
    "titit",
    "toket",
    "tzcesar",
    "thailaland",
    "thaicia"
]

INFORMAL = [
    "hai",
    "halo",
    "jancok"
]

OTHER = [
    """
    Gita Gutawa adalah seorang penyanyi sopran, aktris, dan penulis lagu
    berkebangsaan Indonesia. Ia adalah putri dari komponis Erwin Gutawa.
    Meskipun pada awalnya sempat belajar piano, Gita kemudian beralih ke vokal.
    Bakatnya ditemukan pada tahun 2004 saat ia sedang berlatih vokal,
    kemudian diminta untuk berduet dengan ADA Band.
    """
]

def compare_extraction(extractor, examples, counter_examples):

    for example in examples:
        eq_(extractor.process(example), [example])
        eq_(extractor.process("Sentence " + example + " sandwich."), [example])
        eq_(extractor.process("Sentence end " + example + "."), [example])
        eq_(extractor.process(example + " start of sentence."), [example])

    for example in counter_examples:
        eq_(extractor.process(example), [])
        eq_(extractor.process("Sentence " + example + " sandwich."), [])
        eq_(extractor.process("Sentence end " + example + "."), [])
        eq_(extractor.process(example + " start of sentence."), [])

def test_badwords():
    compare_extraction(indonesian.revision.badwords_list, BAD, OTHER)

def test_informals():
    compare_extraction(indonesian.revision.informals_list, INFORMAL, OTHER)

def test_revision():
    # Words
    cache = {revision.text: "Gita Gutawa adalah seorang m80 sopran, aktris."}
    eq_(solve(indonesian.revision.words_list, cache=cache),
        ["Gita", "Gutawa", "adalah", "seorang", "m80", "sopran", "aktris"])

    # Misspellings
    cache = {revision.text: 'Setelah merilis album duet worngly. <td>'}
    eq_(solve(indonesian.revision.misspellings_list, cache=cache), ["worngly"])


from django.urls import path
from . import views

urlpatterns = [

    path('', views.index, name="index"),
    path('main/', views.main, name='main'),
    path('about/', views.about, name="about"),
    path('comment/', views.comment, name="comment"),
    path('comment_submit/', views.comment_submit, name="comment_submit"),
]


import tensorflow as tf
import pandas as pd
import os
import io
import json

from object_detection.utils import dataset_util
from collections import namedtuple, OrderedDict

from PIL import Image

flags = tf.app.flags
flags.DEFINE_string('output_path', '', 'Path to output TFRecord')

FLAGS = flags.FLAGS

# TO-DO replace this with label map
def class_text_to_int(row_label):
    if row_label == 'red':
        return 2
    if row_label == 'RedLeft':
        return 5
    elif row_label == 'yellow':
        return 7
    elif row_label == 'YellowLeft':
        return 7
    elif row_label == 'green':
        return 1
    elif row_label == 'GreenLeft':
        return 3
    else:
        None

total = 0

def create_tf_example(jsondata,path,rootDir):
  global total
  #print("create_tf_example")
  # TODO(user): Populate the following variables from your example.
  fname = os.path.join(rootDir, '{}'.format(jsondata['filename']))
  statinfo = os.stat(fname)
  #print(fname)
  #print(statinfo.st_size)
  with tf.gfile.GFile(os.path.join(rootDir, '{}'.format(jsondata['filename'])), 'rb') as fid:
      encoded_jpg = fid.read()
  #print(len(encoded_jpg))
  total=total+len(encoded_jpg)
  encoded_jpg_io = io.BytesIO(encoded_jpg)
  image = Image.open(encoded_jpg_io)
  (width, height) = image.size
  #print("image.size")
  #print(image.size)
  #print(width,height)

  #print("widht,height %d %d" , (width,height))
  filename = jsondata['filename'].encode('utf8') # Filename of the image. Empty if image is not from file
  encoded_image_data = encoded_jpg # Encoded image bytes
  image_format = b'jpeg' # b'jpeg' or b'png'

  xmins = [] # List of normalized left x coordinates in bounding box (1 per box)
  xmaxs = [] # List of normalized right x coordinates in bounding box
             # (1 per box)
  ymins = [] # List of normalized top y coordinates in bounding box (1 per box)
  ymaxs = [] # List of normalized bottom y coordinates in bounding box
             # (1 per box)
  classes_text = [] # List of string class name of bounding box (1 per box)
  classes = [] # List of integer class id of bounding box (1 per box)

  for row in jsondata['objects']:
        #print(row)
        xmin = row['x_y_w_h'][0]
        ymin = row['x_y_w_h'][1]
        xmax = xmin+row['x_y_w_h'][2]
        ymax = ymin+row['x_y_w_h'][3]

        xmins.append(float(xmin) / width)
        xmaxs.append(float(xmax) / width)
        ymins.append(float(ymin) / height)
        ymaxs.append(float(ymax) / height)
        classes_text.append(row['label'].encode('utf8'))
        classes.append(class_text_to_int(row['label']))

  #print(height)
  #print(width)
  #print(filename)
  #print(classes_text)
  #print(classes)
  #print(xmins)
  #print(xmaxs)
  tf_example = tf.train.Example(features=tf.train.Features(feature={
      'image/height': dataset_util.int64_feature(height),
      'image/width': dataset_util.int64_feature(width),
      'image/filename': dataset_util.bytes_feature(filename),
      'image/source_id': dataset_util.bytes_feature(filename),
      'image/encoded': dataset_util.bytes_feature(encoded_image_data),
      'image/format': dataset_util.bytes_feature(image_format),
      'image/object/bbox/xmin': dataset_util.float_list_feature(xmins),
      'image/object/bbox/xmax': dataset_util.float_list_feature(xmaxs),
      'image/object/bbox/ymin': dataset_util.float_list_feature(ymins),
      'image/object/bbox/ymax': dataset_util.float_list_feature(ymaxs),
      'image/object/class/text': dataset_util.bytes_list_feature(classes_text),
      'image/object/class/label': dataset_util.int64_list_feature(classes),
  }))
  return tf_example

def batch(writer,writer_val,path):
  i = 0
  train = 0
  val = 0
  # Set the directory you want to start from
  rootDir = 'simulator_imgs/'+path+'/annotations'
  for dirName, subdirList, fileList in os.walk(rootDir):
    print('Found directory: %s' % dirName)
    for fname in fileList:
      if fname.endswith('json') and not fname.startswith('.'):
         fullname = os.path.join(dirName, '{}'.format(fname))
         with open(fullname) as data_file:
           data = json.load(data_file)
           #print('\t%s' % fname)
           #print('\t%s' % data['objects'])
           #print('\t%s' % data['filename'])
           #print('\t%s' % data)
           #print(path,rootDir)
           tf_example = create_tf_example(data,path,'simulator_imgs/'+path)
           # write 20% of samples to validation set
           #if not i % 5:
           #writer_val.write(tf_example.SerializeToString())
           #val = val + 1
           #else:
           writer.write(tf_example.SerializeToString())
           train = train + 1
           #i = i +1
  print(path)
  print("val")
  print(val)
  print("train")
  print(train)

def main(_):
  writer = tf.python_io.TFRecordWriter("simulator_train.record")
  writer_val = tf.python_io.TFRecordWriter("simulator_val.record")
  batch(writer,writer_val,'green')
  batch(writer,writer_val,'yellow')
  batch(writer,writer_val,'red')
  writer.close()
  writer_val.close()

if __name__ == '__main__':
  tf.app.run()


'''
Centro Universitário Adventista de São Paulo
Campus SP

Turma       : CI73A2019
Aluno       : Gilson Nunes dos Santos Junior
RA          : 96992
Matéria     : Desenvolvimento Web
Professor   : Clodonil Honorio Trigo
Laboratório : https://github.com/clodonil/Python-Fundamentals/blob/master/modulo1/Labs/code

Data        : 09 de Março de 2019
Descrição   : Faz a busca por nome de candidatos na tabela de investigados pela Operação Lava-Jato
'''

from  lib.scrapy_table import Scrapy_Table as st

link1 = "https://pt.wikipedia.org/wiki/C%C3%A2mara_Municipal_de_S%C3%A3o_Paulo"
link2 = "https://pt.wikipedia.org/wiki/Lista_de_pessoas_envolvidas_na_Opera%C3%A7%C3%A3o_Lava_Jato"
site1 = st(link1)
site2 = st(link2)
vereadores = tuple(site1.get_tables(5))
lista_lava_jato = tuple(site2.get_tables(1))

lista_investigados = ()
for investigados in  lista_lava_jato[1:] :
    lista_investigados = lista_investigados + (investigados[0],)

# Usuário digita o nome de um(a) candidato(a) para verificar se está na tabela de investigados.
vereador = input('Candidato(a) a verificar : ')
if vereador in lista_investigados :
    print('\nO(A) candidato(a) ' + vereador + ' está na lista de investigados!\n')
else :
    print('\nO(A) candidato(a) ' + vereador + ' não consta na lista de investigados.\n')


import asyncio
import discord
rmadbd = [0,0,0,0,0,0,0]
client = discord.Client()

@client.event
async def on_ready():
    print("Logged in as")
    print(client.user.name)
    print(client.user.id)
    print("===============")

    await client.change_presence(game=discord.Game(name = "반갑습니다 ^&^", type = 1))

@client.event
async def on_message(message):
    if message.author.bot:
        return None
    id = message.author.id
    channel = message.channel
    msg = message.content

    if message.content.startswith('!사용법'):
        await client.send_message(channel, '금융봇 사용법')

    elif message.content.startswith('!상황:'):
        when = msg.strip('!상황:')
        await client.send_message(channel, "확인 되었습니다. \n상황:"+when+"")
        rmadbd[0] = when

    elif message.content.startswith('!대표 결제자:'):
        payer = msg.strip('!대표 결제자:')
        await client.send_message(channel, "확인 되었습니다. \n대표결제자:"+payer+"")
        rmadbd[1] = payer

    elif message.content.startswith('!부담자:'):
        bearer = msg.strip('!부담자:')
        await client.send_message(channel, "확인 되었습니다. \n부담자 명단:"+bearer+"")
        bearer = bearer.split(',')
        rmadbd[2] = bearer

    elif message.content.startswith('!사용처:'):
        where = msg.strip('!사용처:')
        await client.send_message(channel, "확인 되었습니다. \n사용처:"+where+"")
        where = where.strip()
        where1 = where.split(',')
        a = -1
        b = -1
        c = -1
        d = -1
        rmadbd[3] = where1
        where = where.split(' ')
        for x in where:
            b = b+1
            if x.isdigit() == False:
                del where[b]
        for x in where:
            c = c+1
            where[c] = x.strip('원')
        for x in range(0,len(where)):
            d = d+1
            where[d] = int(where[d])
        total = sum(where)
        rmadbd[4] = total
        i = len(rmadbd[2])+1
        rmadbd[5] = total//i #공동부담금액

    elif message.content.startswith('!추가:'):
        dd = msg.strip('!추가:')
        await client.send_message(channel, "확인되었습니다. \n추가:"+dd+"")

        ddd = list()
        ddd.append(dd)
        rmadbd[6] = ddd #추가 목록

    elif message.content.startswith('!추가 목록'):
        f = -1
        for x in rmadbd:
            f = f+1
            if type(x) == list:
                rmadbd[f] = ",",join(rmadbd[f])

        await client.send_message("추가 목록:"+rmadbd[6]+"")

    elif message.content.startswith('!정리'):
        e = -1
        for x in rmadbd:
            e = e+1
            if type(x) == list:
                rmadbd[e] = ",".join(rmadbd[e])
            elif type(x) == int:
                rmadbd[e] = str(rmadbd[e])

        await client.send_message(channel,"상황:"+rmadbd[0]+"\n\n대표 결제자:"+rmadbd[1]+"\n\n부담자:"+rmadbd[2]+"\n\n사용처:"+rmadbd[3]+"\n\n공동부담금액:"+rmadbd[5]+"\n\n추가목록:"+rmadbd[6]+"")

    else:
        await client.send_message(channel, '죄송합니다. 하신말씀을 알아들을수 없습니다.')

f = open("qhwlak.txt.txt",'r')
line = f.readline()
token = line
f.close()
client.run(token)


from flask import Blueprint
from flask_restful import reqparse
from flask import jsonify
from datetime import datetime

from models import Promotion, Booking, Payment, PaymentSchema

task_services = Blueprint('task_services', __name__)

@task_services.route('/get_payment/<int:booking_id>', methods=['GET'])
def get_payment(booking_id):
    payment = Payment.query.filter_by(booking_id=booking_id).first()
    if payment is None:
        message = "Payment is not found."
        response = jsonify(message=message)
        response.statusCode = 400
        return response
    else:
        return jsonify(payment_id=payment.id)

@task_services.route('/change_status/<int:payment_id>', methods=['PUT'])
def change_status(payment_id):
    parser = reqparse.RequestParser()
    parser.add_argument('status', type=bool, required=True)
    args = parser.parse_args()

    payment = Payment.query.get(payment_id)
    if payment is None:
        message = "Payment is not found."
        response = jsonify(message=message)
        response.statusCode = 400
        return response
    else:
        payment.status = args['status']
        payment.save
        payment_schema = PaymentSchema()
        return payment_schema.jsonify(payment)

@task_services.route('/confirm_payment', methods=['POST'])
def confirm_payment():
    parser = reqparse.RequestParser()
    parser.add_argument('booking_id', type=int, required=True)
    parser.add_argument('price', type=float, required=True)
    parser.add_argument('payer_name', type=str, required=True)
    parser.add_argument('payment_type', type=str, required=True)
    args = parser.parse_args()

    booking_id = args['booking_id']
    price = args['price']
    message = "Payment confirmed."

    booking = Booking.query.get(booking_id)

    status = 200
    if booking is None:
        status = 400
        message = "Booking is not found."
    elif (price == booking.total_price):
        # TODO: check payment from Payment Service

        payment = booking.payment
        payment.name = args['payer_name']
        payment.type = args['payment_type']
        payment.save()
    else:
        status = 400
        message = "Amount of payment is not valid."

    response = jsonify(booking_id=booking_id, message=message)
    response.status_code = status
    return response

@task_services.route('/calculate_discount', methods=['GET'])
def calculate_discount():
    parser = reqparse.RequestParser()
    parser.add_argument('price', type=float, required=True)
    parser.add_argument('coupon_code', type=str, required=True)
    args = parser.parse_args()

    coupon_code = args['coupon_code']

    promotion = Promotion.query.filter_by(code=coupon_code).first()
    price = float(args['price'])
    date_now = datetime.now()

    message = "Promotion is applied."

    status = 200
    if promotion is None:
        status = 400
        message = "Promotion is not found."
    elif (promotion.start_date <= date_now and promotion.end_date > date_now):
        if promotion.type == 0:  # percentage
            price *= (100 - promotion.value) / 100
        elif promotion.type == 1:  # fixed
            price -= promotion.value
    else:
        status = 400
        message = "Promotion is not valid."

    response = jsonify(price=price, message=message)
    response.status_code = status
    return response


import pandas as pd
import requests
import os

class BEA_api:
    """class for calling gross output and quantity index values"""

    def __init__(self, years):
        self.base_url = 'https://apps.bea.gov/api/data/'
        apik  = os.getenv("BEA_API_Key")
        apik = apik.replace("'", "")
        self.base_params = {'UserID': apik, 'method': 'GetData',  # apik is API key
                            'Industry': 'ALL', 'Frequency': 'A',
                            'Format': 'json'}
        self.tableID_dict = {'go_quant_index': 16, 'go_nominal': 15,
                             'va_nominal': 1, 'va_quant_index': 8}
        self.years = years

    def call_api(self, params):
        """
        Method for calling BEA api for given range of years [min, max]

        Parameters
        ----------
        years : list
            List of begnning year and ending year of data to retrieve from
            BEA API.

        params : dict
            Dictionary of DataSetName and tableID.

        Returns
        -------
        data : dataframe
            Dataframe of results. Will print API error, if applicable.
        """

        api_params = self.base_params.copy()
        api_params['Year'] = "All" #\
            #[str(y) for y in range(self.years[0], self.years[1]+1)] #

        for k, v in params.items():
            api_params[k] = v

        r = requests.get(self.base_url, params=api_params)
        print('r:\n', type(r.json()['BEAAPI']['Results']), type(r.json()['BEAAPI']['Results'][0]))

        try:
            data_json = r.json()['BEAAPI']['Results']
            data = [pd.DataFrame.from_records(
                data_json[i]['Data']
                ) for i in range(len(data_json))]

        except KeyError:
            print('API Error:{}'.format(
                r.json()['BEAAPI']['Error']['ErrorDetail']['Description']
                ))

        else:
            return data

    def format_data(self, data):
        """format and pivot called data"""

        data['DataValue'] = data.DataValue.astype(float)

        pivoted_data = data.pivot_table(
            index=['IndustrYDescription', 'Industry'], values='DataValue',
            columns='Year'
            )

        pivoted_data.reset_index(inplace=True)

        return pivoted_data

    def get_data(self, table_name):
        """
        Get data using the BEA API call.

        Parameters
        ----------
        years : list
            List of begnning year and ending year of data to retrieve from
            BEA API.

        table_name : str
            go_quant_index (Industry Gross Output, quantity indexes),
            go_nominal (Industry Gross Output, nominal),
            va_nominal (Industry Value Added, nominal),
            va_quant_index (Industry Value Added, quanitity indexes).
            Additional values can be added with their corresponding tableID
            number to tableID_dict

        Returns
        -------
        data : dataframe
            Dataframe of BEA data.

        """

        api_params = {'DataSetName': 'GDPbyIndustry',
                      'tableID': self.tableID_dict[table_name]}

        data = self.call_api(params=api_params)
        print('data: \n', data)
        print('data: \n', data[0])
        print('data: \n', type(data[0]))

        if data:
            data = [self.format_data(data[i]) for i in range(len(data))]
            return data

        else:
            return

    def import_historical(self):
        """Method for importing historical BEA data, saved as csv
        Footnotes: 1. Consists of agriculture, forestry, fishing, and hunting; mining; construction; and manufacturing.
        2. Consists of utilities; wholesale trade; retail trade; transportation and warehousing; information; finance, insurance, real estate, rental, and leasing; professional and business services; educational services, health care, and social assistance; arts, entertainment, recreation, accommodation, and food services; and other services, except government.
        3. Consists of computer and electronic product manufacturing (excluding navigational, measuring, electromedical, and control instruments manufacturing); software publishers; broadcasting and telecommunications; data processing, hosting and related services; internet publishing and broadcasting and web search portals; and computer systems design and related services.
        """
        historical_va_quant_index = pd.read_csv('./EnergyIntensityIndicators/Industry/Data/Chain_Type_Qty_Indexes_Value_Added_by_Industry.csv').set_index('Industry') # 2012 = 100
        historical_va = pd.read_csv('./EnergyIntensityIndicators/Industry/Data/Historical_VA.csv').set_index('Industry')

        historical_go = pd.read_csv('./EnergyIntensityIndicators/Industry/Data/Historical_GO.csv').set_index('Industry')
        historical_go_quant_index = pd.read_csv('./EnergyIntensityIndicators/Industry/Data/historical_go_qty_index.csv').set_index('Industry') # 2012 = 100

        historical_data = {'historical_va': historical_va, 'historical_va_quant_index': historical_va_quant_index,
                           'historical_go': historical_go, 'historical_go_quant_index': historical_go_quant_index}
        return historical_data

    def chain_qty_indexes(self):
        """Merge historical and api data, manipulate as in ChainQtyIndexes
        """
        historical_data = self.import_historical()
        print('historical_data: \n', historical_data)

        go_nominal = self.get_data(table_name='go_nominal')
        if len(go_nominal) == 1:
            go_nominal = go_nominal[0]
            print('go_nominal: \n', go_nominal)
        else:
            raise TypeError(f'list of go_nominal of len {len(go_nominal)}')

        print('len go_nominal: \n', len(go_nominal))
        historical_go = historical_data['historical_go']
        go_nominal_12 = go_nominal[go_nominal["Year"] == 2012][['DataValue', 'IndustrYDescription', 'Industry']].transpose()
        print('go_nominal_12: \n', go_nominal_12)
        go_quant_index = self.get_data(table_name='go_quant_index')
        min_api_year = min([int(y) for y in go_quant_index.columns])

        historical_go_qty_index = historical_data['historical_go_qty_index']
        historical_go_qty_index = historical_go_qty_index.loc[:, : min_api_year]

        go_quant_index = go_quant_index.merge(historical_go_qty_index, left_index=True, right_index=True, how='outer')
        print('go_quant_index: \n', go_quant_index)

        transformed_go_quant_index = go_quant_index.multiply(go_nominal_12, index=1).multiply(0.01)
        # transformed_go_quant_index.loc['          Transportation equipment', :] =

        transformed_go_quant_index = transformed_go_quant_index.transpose()

        # transformed_go_quant_index is further manipulated but I'm not sure exactly how it works
        transformed_go_quant_index = transformed_go_quant_index.divide(transformed_go_quant_index.loc[self.base_year, :], axis=0)

        va_nominal = self.get_data(table_name='va_nominal')
        print('len va_nominal: \n', len(va_nominal))

        historical_va = historical_data['historical_va']
        va_nominal_12 = va_nominal[va_nominal["Year"] == 2012][['DataValue', 'IndustrYDescription', 'Industry']].transpose()
        print('va_nominal_12:\n', va_nominal_12)
        va_quant_index = self.get_data(table_name='va_quant_index')
        historical_va_qty_index = historical_data['historical_va_qty_index']
        va_quant_index = va_quant_index.merge(historical_va_qty_index, left_index=True, right_index=True, how='outer')

        transformed_va_quant_index = va_quant_index.multiply(va_nominal_12, index=1).multiply(.01)
        transformed_va_quant_index = transformed_va_quant_index.transpose()
        # transformed_va_quant_index is further manipulated but I'm not sure exactly how it works

        go_over_va = transformed_go_quant_index.divide(transformed_va_quant_index)
        return transformed_va_quant_index, transformed_go_quant_index

if __name__ == '__main__':
    data = BEA_api(years=list(range(1949, 2018))).get_data(table_name='go_nominal')
    print(data)


import sys
sys.path.append('..')

import core.config as conf
from utils.util import save_memory, split_join

import numpy as np
import pandas as pd, numpy as np, gc
from sklearn.model_selection import KFold
from sklearn.preprocessing import LabelEncoder, MinMaxScaler
import pickle

from tqdm import tqdm

def read_data(path, type='csv', sep='\x01', features=conf.raw_features+conf.labels):
    if type == 'csv':
        df = pd.read_csv(f'{path}', sep=sep, header=None, names=features)
        return df
    else:
        print('cannot read data')

def scaling(df, dense_features):
    mms = MinMaxScaler(feature_range = (0, 1))
    df[dense_features] = mms.fit_transform(df[dense_features])
    return df

def grouping(x, base, div, group=None):
    if group :
        x = x-base
        for i in range(len(group)) :
            if x < group[i] :
                return i
        return len(group)
    return (x-base)//div

def label_encoder(df, sparse_features):
    for feat in sparse_features :
        lbe = LabelEncoder()
        df[feat] = lbe.fit_transform(df[feat])
    return df

def feature_extraction(raw_df, features, train=False):
    labels = conf.labels
    if train:
        df = raw_df[features + labels].copy()
        for label in (labels):
            label_name = label.split('_')[0]
            df.loc[df[label]<=0, label_name ] = 0
            df.loc[df[label]>0, label_name ] = 1
            df = df.drop([label], axis=1)
    else:
        df = raw_df[features].copy()
        for label in (labels):
            label_name = label.split('_')[0]
            # df[label_name] = 0

    del raw_df

    # for timestamp
    df['dt_day']  = pd.to_datetime( df['tweet_timestamp'] , unit='s' ).dt.day.values.astype( np.int8 )
    df['dt_dow']  = pd.to_datetime( df['tweet_timestamp'] , unit='s' ).dt.dayofweek.values.astype( np.int8 )
    df['dt_hour'] = pd.to_datetime( df['tweet_timestamp'] , unit='s' ).dt.hour.values.astype( np.int8 )

    save_memory(df)

    if 'media' in (df.columns):
        df['media'] = df['media'].fillna( '' ).copy()
        gc.collect()
        df['media'] = df['media'].apply( lambda x:  '_'.join(x.split('\t')[:2]) )
        gc.collect()

    for col in (['tweet_type','media']): # except language
        if col in df.columns:
            # df[col] = pd.factorize( df[col], sort=True )[0]
            pkl_path = conf.pickle_data+col+'_dict.pkl'
            with open(pkl_path, 'rb') as f:
                dictionary = pickle.load(f)
            df[col] = df[col].apply(lambda x: dictionary[x])

            gc.collect()
            df[col] = df[col].astype( np.uint8 )
            gc.collect()

    # most_frequent_token
    for col in (['domains','links']):
        if col in df.columns:
            df = most_frequent_token(df, col=col, sep='\t')

    return df

def most_frequent_token(df, col, sep='\t'):
    df['len_'+col] = df[col].apply(lambda x: str(x).count('\t')+1 if not(pd.isnull(x)) else 0)
    var = df[col].fillna('').values.copy()
    gc.collect()

    PD = {}
    null_value = ''
    PD[null_value] = [0,0]
    count = 1
    for vs in var:
        if vs != null_value:
            for v in vs.split('\t'):
                if v not in PD:
                    PD[v] = [count,1]
                    count +=1
                else:
                    x = PD[v]
                    x[1] += 1
                    PD[v] = x
        else:
            x = PD[null_value]
            x[1] += 1
            PD[null_value] = x

    vari = []
    for vs in var:
        if vs != null_value:
            li=[]
            lf=[]
            for v in vs.split('\t'):
                if v!='':
                    li.append(PD[v][0])
                    lf.append(-PD[v][1])
            vari.append( list(np.array(li)[np.argsort(lf)].astype(np.int32) ) )
        else:
            vari.append( [0] )
    del PD

    gc.collect()
    df[col] = np.array( [v[0] for v in vari ] ).astype( np.int32 )
    gc.collect()
    del vari
    del var
    gc.collect()

    return df

def tartget_encoding( tra, col, tar, L=1, smooth_method=0):
    np.random.seed(L)

    cols = col+[tar]
    gf = cudf.from_pandas(tra[cols])
    mn = gf[tar].mean().astype('float32')

    predtrain = np.zeros( tra.shape[0] )

    for fold in [7,8,9,10,11,12]:
        px = np.where( tra.dt_day <fold )[0]
        py = np.where( tra.dt_day==fold )[0]
        mn = gf[tar].iloc[px].mean().astype('float32')
        if smooth_method==0:
            te = gf.iloc[px].groupby(col)[tar].agg(['mean','count'])
            te['smooth']  = (te['mean']*te['count'])
            te['smooth'] += (mn*L)
            te['smooth'] /= (te['count']+L)
            te = te.drop( ['mean','count'], axis=1 )
        elif smooth_method==1:
            te = gf.iloc[px].groupby(col)[tar].agg(['sum','count'])
            te['smooth'] = (te['sum']+L) / (te['count']+1)
            te = te.drop( ['sum','count'], axis=1 )
        gf2 = gf.iloc[py].copy()
        gf2 = gf2.set_index( col )
        gf2['id'] = cupy.arange( gf2.shape[0] )
        gf2 = gf2.join( te, how='left' )
        gf2 = gf2.sort_values( 'id' )
        del te
        del gf2['id']
        predtrain[py] = gf2.smooth.fillna(-999).to_array()
        del gf2

    px = np.where( tra.dt_day <13 )[0]
    py = np.where( tra.dt_day>=13 )[0]
    mn = gf[tar].iloc[px].mean().astype('float32')
    if smooth_method==0:
        te = gf.iloc[px].groupby(col)[tar].agg(['mean','count'])
        te['smooth']  = (te['mean']*te['count'])
        te['smooth'] += (mn*L)
        te['smooth'] /= (te['count']+L)
        te = te.drop( ['mean','count'], axis=1 )
    elif smooth_method==1:
        te = gf.iloc[px].groupby(col)[tar].agg(['sum','count'])
        te['smooth'] = (te['sum']+L) / (te['count']+1)
        te = te.drop( ['sum','count'], axis=1 )
    gf2 = gf.iloc[py].copy()
    gf2 = gf2.set_index( col )
    gf2['id'] = cupy.arange( gf2.shape[0] )
    gf2 = gf2.join( te, how='left' )
    gf2 = gf2.sort_values( 'id' )
    del te
    del gf2['id']
    predtrain[py] = gf2.smooth.fillna(-999).to_array()
    del gf2

    px = np.where( (tra.dt_day>=7)&(tra.dt_day<=11) )[0]
    py = np.where( tra.dt_day==6 )[0]
    mn = gf[tar].iloc[px].mean().astype('float32')
    if smooth_method==0:
        te = gf.iloc[px].groupby(col)[tar].agg(['mean','count'])
        te['smooth']  = (te['mean']*te['count'])
        te['smooth'] += (mn*L)
        te['smooth'] /= (te['count']+L)
        te = te.drop( ['mean','count'], axis=1 )
    elif smooth_method==1:
        te = gf.iloc[px].groupby(col)[tar].agg(['sum','count'])
        te['smooth'] = (te['sum']+L) / (te['count']+1)
        te = te.drop( ['sum','count'], axis=1 )
    gf2 = gf.iloc[py].copy()
    gf2 = gf2.set_index( col )
    gf2['id'] = cupy.arange( gf2.shape[0] )
    gf2 = gf2.join( te, how='left' )
    gf2 = gf2.sort_values( 'id' )
    del te
    del gf2['id']
    predtrain[py] = gf2.smooth.fillna(-999).to_array()
    del gf2

    _ = gc.collect()
    predtrain[predtrain <= -999 ] = np.nan
    return predtrain.astype(np.float32)


import pygame
import sys

from MainGame import Game
from Bot import Bot

class BotGame(Game):
    def __init__(self, window):
        super().__init__(window)
        self.bot = Bot()
        self.zeroPlayer = self.bot
        self.gameDesk.draw_loading()
        self.bot.start()

    def start(self):
        """Reset all parameters and start game with bot reset"""
        super().start()
        self.bot.reset()

    def move(self):
        """Tracking events by player and bot in game with AI"""
        while True:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit()

                if self.motion == self.crossPlayer and event.type == pygame.MOUSEBUTTONDOWN\
                        and event.button == 1:
                    click = self.click_event()
                    if click is False:
                        continue
                    return click

            if self.motion == self.zeroPlayer:
                return self.bot_click_event()

    def click_event(self):
        """Handles click events by player.
        Returns 'back' if back button was pressed,
        True if new cell was created,
        False if nothing happened.
        """
        pos = pygame.mouse.get_pos()
        coordinates = self.gameDesk.button_is_pressed(self.motion, *pos)
        if coordinates == (None, None):
            return 'back'
        if coordinates is not False:
            i, j = coordinates[0], coordinates[1]
            self.field[i][j] = self.motion.value
            # Sending information about event to bot
            self.bot.new_motion(i, j, self.motion)
            self.motion = self.zeroPlayer if self.motion == self.crossPlayer \
                else self.crossPlayer
            self.gameDesk.draw()
            self.gameDesk.draw_score(self.crossPlayer, self.zeroPlayer)
            return True
        return False

    def bot_click_event(self):
        """Handles click events by bot"""
        pygame.time.delay(1000)
        i, j = self.bot.do_move()
        self.gameDesk.button_is_pressed(self.motion, i=i, j=j)
        self.field[i][j] = self.motion.value
        self.motion = self.zeroPlayer if self.motion == self.crossPlayer \
            else self.crossPlayer
        self.gameDesk.draw()
        self.gameDesk.draw_score(self.crossPlayer, self.zeroPlayer)
        return True


from rest_framework.views import APIView
from rest_framework.response import Response
from users.models import *
from employers.models import *
from category.models import *
from skill.models import Skill
from packages.globalfunction import *
from .serializers import *
from users.serializers import *
from skill.serializers import SkillSerializer
import json
from applicants.models import Applicant

from rest_framework import status, generics, permissions
from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope, TokenHasScope

from rest_framework.parsers import MultiPartParser, FormParser

# -------------------- edit profile --------------------------

class editProfile(APIView):
	'''
		Parameters
			user_id : required \n

	'''
	parser_classes = (MultiPartParser, FormParser)
	def post(self,request):
		permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]

		if "user_id" in request.POST and request.POST["user_id"] !="":
			user_id = int(request.POST["user_id"])
		else:
			return Response(responsejson("Please enter user Id", status=422) )

		try :
			empObj = Employer.objects.get(user_id=user_id)
		except Exception as e:
			return Response(responsejson("This user does not exist.", status=422) )

		# Get all post method data
		userData = managePostData(request.POST)

		if "logo_img" in request.FILES and request.FILES["logo_img"] !="":
			fileName = ImageSaveByFile(request,'images','logo_img')
			if fileName !='':
				userData['logo_img'] = fileName

		# print(userData)

		if "employer_name" in userData and userData["employer_name"] !="":
			userData['name'] = userData["employer_name"]
			del userData['employer_name']

		try:
			update_profile_serialize = updateProfileSerializer(data=userData)
			if update_profile_serialize.is_valid():
				Employer.objects.filter(user_id=user_id).update(**userData)
			else:
				return Response(responsejson(update_profile_serialize.errors,status=422))

			# return data
			userDetails = setUserSessionValue(user_id,'employer')
			# userObj = User.objects.get(id=user_id)
			# userSerialize = UserSerializer(userObj)
			# userDetails = makeBlank(userSerialize.data.items())

			# empObj = Employer.objects.get(user_id=user_id)
			# empSerializer = EmployerLoginSerializer(empObj)

			# userDetails.update(makeBlank(empSerializer.data.items()))
			# userDetails['role'] = 'employer'

			return Response(responsejson(userDetails,status=200))
		except Exception as e:
			print(e)
			return Response(responsejson("Something goes wrong with your data, Please try again.",status=422))

# ------------------------------------ Add new job ---------------------------------

class addJob(APIView):
	'''
		Parameters
			user_id : required \n
			industry : required \n
			functional_area : required \n
			positions : required \n
			location : required \n
			responsibilities : required \n
			desired_skills : required \n
			min_vage : required \n
			salary : required \n
			max_applicants : required \n
	'''
	permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
	def post(self,request):
		errorDict = isUserExist(request)

		if errorDict:
			return Response(responsejson(errorDict,status=422))

		# Get all post method data
		jobData = managePostData(request.POST)
		user_id = jobData['user_id']
		jobData['user'] = int(user_id)
		del jobData['user_id']

		skillsId = []
		if "newSkills" in jobData and jobData['newSkills'] != '':
			skillsId = addNewSkills(jobData['newSkills'])
			del jobData['newSkills']

		if "existSkills" in jobData and jobData['existSkills'] != '':
			existSkills = jobData['existSkills']
			existSkills = existSkills.split(",")
			skillsId = list(map(str, skillsId))
			skillsId = skillsId + existSkills
			del jobData['existSkills']

		skillDict = {"skill":skillsId}
		jobData["skills"] = skillDict
		# jobData["skills"] = json.dumps(skillDict)

		try:
			job_serializer = AddJobSerializer(data=jobData)

			if job_serializer.is_valid():
				job_serializer.save()
				return Response(responsejson("Job created successfully", status=200) )
			else:
				return Response(responsejson(job_serializer.errors,status=422))

		except Exception as e:
			print(e)
			errorDict['error'] = "Something goes wrong Please try again"
			return Response(responsejson(errorDict, status=422) )

# ------------------------------------------------------- Job listing api ----------------------------------------------------

class jobList(APIView):
	permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]

	def post(self,request):
		errorDict = isUserExist(request)
		if errorDict:
			return Response(responsejson(errorDict,status=422))

		postData = managePostData(request.POST)
		user_id = postData['user_id']

		try:
			jobs = Job.objects.filter(user_id=user_id).order_by('-created_on')
			jobDict = []
			for job in jobs:
				singleJob = JobListingSerializer(job)
				singleJob = makeBlank(singleJob.data.items())
				jobDict.append(singleJob)

			return Response(responsejson(jobDict,status=200))
		except Exception as e:
			print(e)
			errorDict['error'] = "There are no jobs"
			return Response(responsejson(errorDict,status=422))

# ------------------------------------------------------- Job Delete ----------------------------------------------------

class deleteJob(APIView):
	'''
		Parameters
			user_id : required \n
			job_id : required \n
	'''

	permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
	def post(self,request):

		errorDict = isUserExist(request)
		errorDict = fieldValidation(request,'job_id','Please enter job_id',errorDict)

		if errorDict:
			return Response(responsejson(errorDict,status=422))

		postData = managePostData(request.POST)
		try:
			jobObj = Job.objects.get(id=postData['job_id'],user_id=postData['user_id'])
			jobObj.delete()
			return Response(responsejson("Job Deleted successfully",status=200))

		except Exception as e:
			print(e)
			errorDict['error'] = "This job is not created by that user"
			return Response(responsejson(errorDict, status=422) )

# ----------------------------------------------------------- Get Job Detail ----------------------------------------------------

class getJobDetail(APIView):
	'''
		Parameters
			user_id : required \n
			job_id : required \n
	'''

	permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
	def post(self,request):
		errorDict = isUserExist(request)
		errorDict = fieldValidation(request,'job_id','Please enter job_id',errorDict)

		if errorDict:
			return Response(responsejson(errorDict,status=422))

		postData = managePostData(request.POST)

		user_id = postData['user_id']
		job_id = postData['job_id']
		try:
			jobObj = Job.objects.get(id=job_id)

			getJob = JobListingSerializer(jobObj)
			getJob = makeBlank(getJob.data.items())

			empObj = Employer.objects.get(user_id=getJob['user_id'])
			serializerData = EmployerLoginSerializer(empObj)
			getJob['user_details'] = makeBlank(serializerData.data.items())

			if len(getJob['skills']) > 0:
				skillsIdData = getJob['skills']
				skillsIdData = [int(i) for i in skillsIdData['skill']]
				selectedSkillData = Skill.objects.filter(id__in=skillsIdData).only('id','name')

				skillDict = []
				for skill in selectedSkillData:
					singleSkill = SkillSerializer(skill)
					singleSkill = makeBlank(singleSkill.data.items())
					skillDict.append(singleSkill)

				getJob['skills'] = skillDict

			return Response(responsejson(getJob,status=200))

		except Exception as e:
			print(e)
			errorDict['error'] = "This job is not created by that user"
			return Response(responsejson(errorDict, status=422) )

# -------------------------------------------- Edit Job ----------------------------------------------

class editJob(APIView):
	'''
		Parameters
			user_id : required \n
			job_id : required \n
			industry : required \n
			functional_area : required \n
			positions : required \n
			location : required \n
			responsibilities : required \n
			desired_skills : required \n
			min_vage : required \n
			salary : required \n
			max_applicants : required \n
	'''
	permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
	def post(self,request):
		errorDict = isUserExist(request)
		user_id = request.POST["user_id"]

		if "job_id" in request.POST and request.POST["job_id"] !="":
			job_id = request.POST["job_id"]
			try :
				jobObj = Job.objects.get(id=job_id,user_id=user_id)
			except Exception as e:
				errorDict['error'] = "This Job does not exist."
		else:
			errorDict['job_id'] = "Please enter Job Id"

		if errorDict:
			return Response(responsejson(errorDict,status=422))

		if "title" in request.POST and request.POST["title"] !="":
			jobObj.title = request.POST["title"]
		else:
			errorDict['title'] = "Please enter Title"

		if "industry" in request.POST and request.POST["industry"] !="":
			industry = request.POST["industry"]
			try :
				cateObj = Categories.objects.get(id=int(industry))
				jobObj.industry = cateObj
			except Exception as e:
				errorDict['industry'] = "This industry-category does not exist."

		else:
			errorDict['industry'] = "Please enter industry"

		if "functional_area" in request.POST and request.POST["functional_area"] !="":
			functional_area = request.POST["functional_area"]

			try :
				functObj = Categories.objects.get(id=functional_area)
				jobObj.functional_area = functObj
			except Exception as e:
				errorDict['functional_area'] = "This functional-category does not exist."

		else:
			errorDict['functional_area'] = "Please enter functional area"

		if "positions" in request.POST and request.POST["positions"] !="":
			jobObj.positions = request.POST["positions"]
		else:
			errorDict['positions'] = "Please enter Positions"

		# if "location" in request.POST and request.POST["location"] !="":
		# 	jobObj.location = request.POST["location"]
		# else:
		# 	errorDict['location'] = "Please enter Location"

		if "responsibilities" in request.POST and request.POST["responsibilities"] !="":
			jobObj.responsibilities = request.POST["responsibilities"]
		else:
			errorDict['responsibilities'] = "Please enter responsibility"

		# if "desired_skills" in request.POST and request.POST["desired_skills"] !="":
		# 	jobObj.desired_skills = request.POST["desired_skills"]
		# else:
		# 	errorDict['desired_skills'] = "Please enter responsibility"

		if "min_vage" in request.POST and request.POST["min_vage"] !="":
			jobObj.min_vage = request.POST["min_vage"]
		else:
			errorDict['min_vage'] = "Please enter minimum vages"

		if "min_exp" in request.POST and request.POST["min_exp"] !="":
			jobObj.min_exp = request.POST["min_exp"]
		else:
			errorDict['min_exp'] = "Please enter minimum experience"

		if "max_applicants" in request.POST and request.POST["max_applicants"] !="":
			jobObj.max_applicants = request.POST["max_applicants"]
		else:
			errorDict['max_applicants'] = "Please enter maximum applicants"

		if errorDict:
			return Response(responsejson(errorDict,status=422))

		skillsId = []
		if "newSkills" in request.POST and request.POST['newSkills'] != '':
			skillsId = addNewSkills(request.POST['newSkills'])
			del request.POST['newSkills']

		if "existSkills" in request.POST and request.POST['existSkills'] != '':
			existSkills = request.POST['existSkills']
			existSkills = existSkills.split(",")
			skillsId = list(map(str, skillsId))
			skillsId = skillsId + existSkills
			# del request.POST['existSkills']

		skillDict = {"skill":skillsId}
		jobObj.skills = skillDict
		# jobData["skills"] = skillDict

		try:
			jobObj.save()
			return Response(responsejson("Job Update successfully", status=200) )
		except Exception as e:
			print(e)
			errorDict['error'] = "This job is not created by that user"
			return Response(responsejson(errorDict, status=422) )

# -------------------------------------------- Update Job Status ----------------------------------------------

class updateJobStatus(APIView):
	permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]

	def post(self,request):
		if "user_id" in request.POST and request.POST["user_id"] !="":
			user_id = request.POST["user_id"]

			try :
				userObj = User.objects.get(id=user_id)
			except Exception as e:
				return Response(responsejson("This user does not exist.", status=422) )

		else:
			return Response(responsejson("Please enter user Id", status=422) )

		if "job_id" in request.POST and request.POST["job_id"] !="":
			job_id = request.POST["job_id"]
		else:
			return Response(responsejson("Please enter job Id", status=422) )

		try:
			jobObj = Job.objects.get(id=job_id,user_id=user_id)
			if jobObj.status == 1:
				jobObj.status = 0
			else:
				jobObj.status = 1

			jobObj.save()
			return Response(responsejson("Job Status Update Successfully",status=200))

		except Exception as e:
			print(e)
			return Response(responsejson("This job is not created by that user", status=422) )

# --------------------------------------- Get Job applicants List ---------------------------------------

class getApplicantList(APIView):
	permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]

	def post(self,request,*args, **kwargs):

		from applicants.serializers import ApplicantListSerializer
		from jobseekers.models import Resumes,JobSeeker
		from jobseekers.serializers import ResumeDetailsSerializer,JobseekerLoginSerializer

		errorDict = isUserExist(request)
		errorDict = fieldValidation(request,'job_id','Please enter job_id',errorDict)
		if errorDict:
			return Response(responsejson(errorDict,status=422))

		errorDict = {}
		postData = managePostData(request.POST)

		try:
			applicants = Applicant.objects.filter(job=int(postData['job_id']))
			if not applicants:
				return Response(responsejson([], status=200) )

			applicantDict = []
			for applicant in applicants:
				# applicant deatails
				singleApplicant = {}
				singleApplicant = ApplicantListSerializer(applicant)
				singleApplicant = makeBlank(singleApplicant.data.items())

				# Fetch user name from jobseeker table
				jobseekerData = {}
				jobseekerData = JobSeeker.objects.get(user_id=applicant.user_id)
				jobseekerData = JobseekerLoginSerializer(jobseekerData)
				jobseekerData = makeBlank(jobseekerData.data.items())

				singleApplicant.update(jobseekerData)

				# fetch data from resume table
				try:
					getResumeData = Resumes.objects.get(user_id=applicant.user_id)
					getResumeData = ResumeDetailsSerializer(getResumeData)
					getResumeData = makeBlank(getResumeData.data.items())
					singleApplicant.update(getResumeData);
				except Exception as e:
					print(e)

				applicantDict.append(singleApplicant)
			return Response(responsejson(applicantDict, status=200) )
		except Exception as e:
			print(e)
			return Response(responsejson("This job is not created.", status=422) )

# --------------------------------------- Update Applicant status ---------------------------------------
class updateApplicantStatus(APIView):
	def post(self,request):
		errorDict = isUserExist(request)

		postData = managePostData(request.POST)

		if 'action' not in postData or postData["action"] =="":
			errorDict['action'] = "Action field is required"

		if 'applicant_id' not in postData or postData["applicant_id"] =="":
			errorDict['applicant_id'] = "Applicant field is required"

		if errorDict:
			return Response(responsejson(errorDict,status=422))

		try:
			for id in postData['applicant_id'].split(','):
				updateData = {}
				updateData['status'] = int(postData['action'])
				Applicant.objects.filter(id=int(id)).update(**updateData)

			return Response(responsejson("status update successfully",status=200))
		except Exception as e:
			print(e)
			return Response(responsejson("Something went wrong, Please try again",status=422))

		return Response(responsejson("Something went wrong",status=422))


import configparser
import importlib
import argparse
import bottle
import os

import merakikernel.rediscache
import merakikernel.requests
import merakikernel.rates

def _call_with_config_kwargs(function, config, config_header):
    try:
        kwargs = dict(config[config_header])
    except KeyError:
        kwargs = {}
    function(**kwargs)

def _parse_limit(limit_string):
    limit = limit_string.split("/")
    return (int(limit[0]), int(limit[1]))

@bottle.hook("after_request")
def delete_server_header():
    bottle.response.headers["Server"] = ""

class Server(object):
    def __init__(self, config_file_path):
        self.conf = config_file_path

    def run(self):
        """Reads the config file provided during instantiation.
        If provided in the config file:
            Sets api key
            Initializes rate limiters
            Imports required modules
            Sets cache timeouts
            Connects to a redis cache
            Starts bottle
        """
        # Read config file
        config = configparser.ConfigParser()
        config.optionxform = str  # Preserve config file case
        config.read(self.conf)

        # Set API key and rate limits
        merakikernel.requests.api_key = config["rates"].get("api-key", os.environ.get("API_KEY", ""))
        merakikernel.requests.print_calls = config["rates"].getboolean("print-calls", False)

        try:
            limits = list(map(_parse_limit, config["rates"]["limits"].split("\n")))
            if len(limits) > 1:
                merakikernel.requests.rate_limiter = merakikernel.rates.MultiRateLimiter(*limits)
            else:
                merakikernel.requests.rate_limiter = merakikernel.rates.SingleRateLimiter(limits[0][0], limits[0][1])
        except KeyError:
            # No rate limits specified - don't manage rate limit automatically
            merakikernel.requests.rate_limiter = None

        # Load the bottle modules specified in the config file
        for module in config["modules"]:
            if config["modules"].getboolean(module):
                importlib.import_module(module)

        # Set configurable cache timeouts (and convert from minutes to seconds)
        timeouts = {}
        for typename in config["cache-timeouts"]:
            timeouts[typename] = int(config["cache-timeouts"].getfloat(typename) * 60.0)
        merakikernel.rediscache.timeouts = timeouts

        # Open redis connection and start the server
        _call_with_config_kwargs(merakikernel.rediscache.connect, config, "redis-py")
        _call_with_config_kwargs(bottle.run, config, "bottle")

def main():
    # Set program arguments
    parser = argparse.ArgumentParser(description="Meraki Kernel Server")
    parser.add_argument("-config", type=str, required=True, help="path to the kernel configuration file")
    args = parser.parse_args()

    # Start the server
    server = Server(args.config)
    server.run()

if __name__ == "__main__":
    main()


from django.shortcuts import render, HttpResponse
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .forms import ProfileCreationForm

def register_page(request):
    user_form = None
    profile_form = None
    if request.method == "POST":
        user_form= UserCreationForm(request.POST)
        profile_form = ProfileCreationForm(request.POST, request.FILES)
        if user_form.is_valid() and profile_form.is_valid():
            my_user = user_form.save()
            profile = profile_form.save(commit=False)
            profile.user = my_user
            profile.save()
        return HttpResponse('ok post accepted')

    user_form = UserCreationForm()
    profile_form = ProfileCreationForm()
    context = {
        "user_form": user_form,
        "profile_form": profile_form,
    }
    return render(request, "profiles/register.html", context)