# Copyright The PyTorch Lightning team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from typing import Any, Dict, Iterator, List, Optional, Union

import torch

from pytorch_lightning import loops  # import as loops to avoid circular imports
from pytorch_lightning.loops.batch import TrainingBatchLoop
from pytorch_lightning.trainer.connectors.logger_connector.result import ResultCollection
from pytorch_lightning.trainer.progress import Progress, SchedulerProgress
from pytorch_lightning.utilities.exceptions import MisconfigurationException
from pytorch_lightning.utilities.model_helpers import is_overridden
from pytorch_lightning.utilities.types import STEP_OUTPUT
from pytorch_lightning.utilities.warnings import WarningCache

class TrainingEpochLoop(loops.Loop):
    """
    Runs over all batches in a dataloader (one epoch).

    Args:
        min_steps: The minimum number of steps (batches) to process
        max_steps: The maximum number of steps (batches) to process
    """

    def __init__(self, min_steps: int, max_steps: int):
        super().__init__()
        self.min_steps: int = min_steps
        self.max_steps: int = max_steps
        self.global_step: int = 0
        # the total batch index across all epochs
        self.total_batch_idx: int = 0
        self.is_last_batch: Optional[bool] = None
        self.batch_progress = Progress()
        self.scheduler_progress = SchedulerProgress()

        self.batch_loop: Optional[TrainingBatchLoop] = None
        self.val_loop: Optional["loops.EvaluationLoop"] = None

        self._results = ResultCollection(training=True)
        self._dataloader_idx: Optional[int] = None
        self._warning_cache: WarningCache = WarningCache()
        self._epoch_output: Optional[List[List[STEP_OUTPUT]]] = None

    @property
    def batch_idx(self) -> int:
        """Returns the current batch index (within this epoch)"""
        # use `ready` instead of `completed` in case this is accessed after `completed` has been increased
        # but before the next `ready` increase
        return self.batch_progress.current.ready - 1

    @property
    def done(self) -> bool:
        """Returns whether the training should be stopped.
        The criteria are that the number of steps reached the max steps,
        the last batch is reached or the trainer signals to stop (e.g. by early stopping).
        """
        max_steps_reached = self.max_steps is not None and self.global_step >= self.max_steps
        return max_steps_reached or self.trainer.should_stop or self._num_training_batches_reached(self.is_last_batch)

    def connect(
        self, batch_loop: Optional[TrainingBatchLoop] = None, val_loop: Optional["loops.EvaluationLoop"] = None
    ) -> None:
        """Optionally connect a custom batch or validation loop to this training epoch loop."""
        if batch_loop is not None:
            self.batch_loop = batch_loop
        if val_loop is not None:
            self.val_loop = val_loop

    def reset(self) -> None:
        """Resets the internal state of the loop for a new run"""
        self.is_last_batch = False
        self._dataloader_idx = 0

        # track epoch output
        self._epoch_output = [[] for _ in range(self.batch_loop.num_active_optimizers(self.total_batch_idx))]

        if not self.restarting:
            self.batch_progress.current.reset()
            self.scheduler_progress.current.reset()
            self.batch_loop.optim_progress.reset_on_epoch()

    def on_run_start(self, *args: Any, **kwargs: Any) -> None:
        # hook
        self.trainer.logger_connector.on_epoch_start()
        self.trainer.call_hook("on_epoch_start")
        self.trainer.call_hook("on_train_epoch_start")
        self.trainer.fit_loop.epoch_progress.increment_started()

    def advance(self, dataloader_iter: Iterator, **kwargs: Any) -> None:
        """Runs a single training batch.

        Args:
            dataloader_iter: the iterator over the dataloader producing the new batch

        Raises:
            StopIteration: When the epoch is canceled by the user returning -1
        """
        _, (batch, is_last) = next(dataloader_iter)
        self.is_last_batch = is_last

        # ------------------------------------
        # TRAINING_STEP + TRAINING_STEP_END
        # ------------------------------------
        with self.trainer.profiler.profile("training_batch_to_device"):
            batch = self.trainer.accelerator.batch_to_device(batch, dataloader_idx=self._dataloader_idx)

        self.batch_progress.increment_ready()

        with self.trainer.profiler.profile("run_training_batch"):
            batch_output = self.batch_loop.run(batch, self.batch_idx, self._dataloader_idx)

        self.batch_progress.increment_processed()

        # when returning -1 from train_step, we end epoch early
        if batch_output.signal == -1:
            raise StopIteration

        # update non-plateau LR schedulers
        # update epoch-interval ones only when we are at the end of training epoch
        self.update_lr_schedulers("step", update_plateau_schedulers=False)
        if self._num_training_batches_reached(is_last):
            self.update_lr_schedulers("epoch", update_plateau_schedulers=False)

        batch_end_outputs = [opt_idx_out for opt_idx_out in batch_output.training_step_output if len(opt_idx_out)]
        processed_batch_end_outputs = self._prepare_outputs(batch_end_outputs, batch_mode=True)

        # hook
        self.trainer.call_hook(
            "on_train_batch_end", processed_batch_end_outputs, batch, self.batch_idx, self._dataloader_idx
        )
        self.trainer.call_hook("on_batch_end")
        self.trainer.logger_connector.on_batch_end()

        self.batch_progress.increment_completed()

        # figure out what to track for epoch end
        self._track_epoch_end_reduce_metrics(self._epoch_output, batch_end_outputs)

        # -----------------------------------------
        # SAVE METRICS TO LOGGERS AND PROGRESS_BAR
        # -----------------------------------------
        self.trainer.logger_connector.update_train_step_metrics()

    def on_advance_end(self):
        """Runs validation and Checkpointing if necessary.

        Raises:
            StopIteration: if :attr:`done` evaluates to ``True`` to finish this epoch
        """
        # -----------------------------------------
        # VALIDATE IF NEEDED + CHECKPOINT CALLBACK
        # -----------------------------------------
        should_check_val = self._should_check_val_fx(self.batch_idx, self.is_last_batch)
        if should_check_val:
            self.trainer.validating = True
            self._run_validation()
            self.trainer.training = True

        # -----------------------------------------
        # SAVE LOGGERS (ie: Tensorboard, etc...)
        # -----------------------------------------
        self._save_loggers_on_train_batch_end()

        # update plateau LR scheduler after metrics are logged
        self.update_lr_schedulers("step", update_plateau_schedulers=True)

        self.total_batch_idx += 1

        # progress global step according to grads progress
        self._increment_accumulated_grad_global_step()

        if self.done:
            raise StopIteration

    def on_run_end(self) -> List[List[STEP_OUTPUT]]:
        """Calls the on_epoch_end hook.

        Returns:
            The output of each training step for each optimizer

        Raises:
            MisconfigurationException: ``train_epoch_end`` does not return ``None``
        """
        if self.batch_progress.current.ready == 0:
            # dataloader/iterator did not produce a batch
            return

        # inform logger the batch loop has finished
        self.trainer.logger_connector.epoch_end_reached()

        # prepare epoch output
        processed_outputs = self._prepare_outputs(self._epoch_output, batch_mode=False)

        # get the model and call model.training_epoch_end
        model = self.trainer.lightning_module

        if is_overridden("training_epoch_end", model):
            # run training_epoch_end
            # refresh the result for custom logging at the epoch level
            model._current_fx_name = "training_epoch_end"

            # lightningmodule hook
            training_epoch_end_output = model.training_epoch_end(processed_outputs)

            if training_epoch_end_output is not None:
                raise MisconfigurationException(
                    "training_epoch_end expects a return of None. "
                    "HINT: remove the return statement in training_epoch_end"
                )

        self.trainer.fit_loop.epoch_progress.increment_processed()

        # call train epoch end hooks
        self.trainer.call_hook("on_train_epoch_end")
        self.trainer.call_hook("on_epoch_end")
        self.trainer.logger_connector.on_epoch_end()

        self.update_lr_schedulers("epoch", update_plateau_schedulers=True)

        epoch_output = self._epoch_output
        # free memory
        self._epoch_output = None
        return epoch_output

    def teardown(self) -> None:
        self._results.cpu()
        self.batch_loop.teardown()
        self.val_loop.teardown()

    def _run_validation(self):
        # reload dataloaders
        self.val_loop.reload_evaluation_dataloaders()

        with torch.no_grad():
            self.val_loop.run()

    def _accumulated_batches_reached(self) -> bool:
        """Determine if accumulation will be finished by the end of the current batch."""
        return self.batch_progress.current.ready % self.trainer.accumulate_grad_batches == 0

    def _num_training_batches_reached(self, is_last_batch: bool = False) -> bool:
        """Checks if we are in the last batch or if there are more batches to follow.

        Args:
            is_last_batch: Whether the current batch is the last one
        """
        return self.batch_progress.current.ready == self.trainer.num_training_batches or is_last_batch

    def _should_accumulate(self) -> bool:
        """Checks if the optimizer step should be performed or gradients should be accumulated for the current step."""
        accumulation_done = self._accumulated_batches_reached()
        is_final_batch = self._num_training_batches_reached()
        return not (accumulation_done or is_final_batch)

    def _track_epoch_end_reduce_metrics(
        self, epoch_output: List[List[STEP_OUTPUT]], batch_end_outputs: STEP_OUTPUT
    ) -> None:
        """Adds the batch outputs to the epoch outputs and prepares reduction"""
        hook_overridden = is_overridden("training_epoch_end", self.trainer.lightning_module)
        if not hook_overridden:
            return

        # track the outputs to reduce at the end of the epoch
        for opt_idx, opt_outputs in enumerate(batch_end_outputs):
            # with 1 step (no tbptt) don't use a sequence at epoch end
            if isinstance(opt_outputs, list) and len(opt_outputs) == 1:
                opt_outputs = opt_outputs[0]

            epoch_output[opt_idx].append(opt_outputs)

    @staticmethod
    def _prepare_outputs(
        outputs: List[List[List["ResultCollection"]]], batch_mode: bool
    ) -> Union[List[List[List[Dict]]], List[List[Dict]], List[Dict], Dict]:
        """
        Extract required information from batch or epoch end results.

        Args:
            outputs: A 3-dimensional list of ``ResultCollection`` objects with dimensions:
                ``[optimizer outs][batch outs][tbptt steps]``.

            batch_mode: If True, ignore the batch output dimension.

        Returns:
            The cleaned outputs with ``ResultCollection`` objects converted to dictionaries.
            All list dimensions of size one will be collapsed.
        """
        processed_outputs = []
        for opt_outputs in outputs:
            # handle an edge case where an optimizer output is the empty list
            if len(opt_outputs) == 0:
                continue

            processed_batch_outputs = []

            if batch_mode:
                opt_outputs = [opt_outputs]

            for batch_outputs in opt_outputs:
                processed_tbptt_outputs = []

                if isinstance(batch_outputs, ResultCollection):
                    batch_outputs = [batch_outputs]

                for tbptt_output in batch_outputs:
                    out = {}
                    if tbptt_output.minimize is not None:
                        out["loss"] = tbptt_output.minimize.detach()
                    out.update(tbptt_output.extra)
                    processed_tbptt_outputs.append(out)

                # if there was only one tbptt step then we can collapse that dimension
                if len(processed_tbptt_outputs) == 1:
                    processed_tbptt_outputs = processed_tbptt_outputs[0]
                processed_batch_outputs.append(processed_tbptt_outputs)

            # batch_outputs should be just one dict (or a list of dicts if using tbptt) per optimizer
            if batch_mode:
                processed_batch_outputs = processed_batch_outputs[0]
            processed_outputs.append(processed_batch_outputs)

        # if there is only one optimiser then we collapse that dimension
        if len(processed_outputs) == 1:
            processed_outputs = processed_outputs[0]
        return processed_outputs

    def update_lr_schedulers(self, interval: str, update_plateau_schedulers: bool) -> None:
        """updates the lr schedulers based on the given interval"""
        if interval == "step" and self._should_accumulate():
            return
        self.trainer.optimizer_connector.update_learning_rates(
            interval=interval,
            update_plateau_schedulers=update_plateau_schedulers,
            opt_indices=[opt_idx for opt_idx, _ in self.batch_loop.get_active_optimizers(self.total_batch_idx)],
        )

    def _increment_accumulated_grad_global_step(self) -> None:
        """Increments global step according to grads progress"""
        if not self._should_accumulate():
            self.global_step = self.trainer.accelerator.update_global_step(
                self.total_batch_idx, self.trainer.global_step
            )

    def _should_check_val_fx(self, batch_idx: int, is_last_batch: bool) -> bool:
        """Decide if we should run validation."""
        if not self.trainer.enable_validation:
            return False

        is_val_check_epoch = (self.trainer.current_epoch + 1) % self.trainer.check_val_every_n_epoch == 0
        if not is_val_check_epoch:
            return False

        # val_check_batch is inf for iterable datasets with no length defined
        is_infinite_dataset = self.trainer.val_check_batch == float("inf")
        if is_last_batch and is_infinite_dataset:
            return True

        if self.trainer.should_stop:
            return True

        # TODO(@awaelchli): let training/eval loop handle logic around limit_*_batches and val_check_batch
        is_val_check_batch = is_last_batch
        if isinstance(self.trainer.limit_train_batches, int) and is_infinite_dataset:
            is_val_check_batch = (batch_idx + 1) % self.trainer.limit_train_batches == 0
        elif self.trainer.val_check_batch != float("inf"):
            is_val_check_batch = (batch_idx + 1) % self.trainer.val_check_batch == 0
        return is_val_check_batch

    def _save_loggers_on_train_batch_end(self) -> None:
        """Flushes loggers to disk"""
        # when loggers should save to disk
        should_flush_logs = self.trainer.logger_connector.should_flush_logs
        if should_flush_logs and self.trainer.is_global_zero and self.trainer.logger is not None:
            self.trainer.logger.save()


# amplitude.lib.date -- Date class

from amplitude.dict import Dict
import datetime

class Date(Dict):
    """defines a date that can have any of year, month, day -- it can be ambiguous.
    Usage:
    >>> d = Date(20091027)
    >>> "{Y}-{m}-{d}".format(**d)           # new in Python 2.6: string.format()
    '2009-10-27'
    >>> d.year(2008), d.month(9), d.day(6)
    (2008, 9, 6)
    >>> "{b} {d}, {Y}".format(**d)
    'Sep 6, 2008'
    >>> "{B} {d}".format(**d)
    'September 6'
    >>> "{Y}-{m:02}-{d:02}".format(**d)     # note the format specifiers
    '2008-09-06'
    >>> d = Date(814)              # month and day only -- such as birthday
    >>> "{Y} {b} {d}".format(**d)
    '0 Aug 14'
    >>> d.Y
    0
    """

    def __init__(self, date=None, locale='en'):
        """date: integer in form of [[yyyy]mm]dd"""
        self._locale = locale
        self.date(date or 0, locale)

    def date(self, date=None, locale='en'):
        if date is not None:
            self._date = int(date)
            self._locale = locale
            d = {
                'Y': self.year() != 0 and str(self.year()) or '',
                'y': self.year() != 0 and str(int(self.year() % 100)) or '',
                'm': self.month() != 0 and str(self.month()) or '',
                'd': self.day() != 0 and str(self.day()) or '',
                'B': self.month_name() or '',
                'b': self.mo_name() or ''
            }
            for k in d.keys():
                self[k] = d[k]
        return self._date

    def year(self, yr=None):
        if yr is not None:
            self.date(yr*1e4 + (self.month() or 0)*1e2 + (self.day() or 0))
        if self._date is not None:
            return int(self.date() / 1e4)

    def month(self, mo=None):
        if mo is not None:
            self.date((self.year()*1e4 or 0) + mo*1e2 + (self.day() or 0))
        if self._date is not None:
            return int(self.date() % 1e4 / 1e2)

    def day(self, dy=None):
        if dy is not None:
            self.date((self.year()*1e4 or 0) + (self.month()*1e2 or 0) + dy)
        if self._date is not None:
            return int(self.date() % 1e2)

    def month_name(self):
        return self.months()[self.month()]

    def mo_name(self):
        return self.mos()[self.month()]

    def months(self):
        """returns a list of months, indexed 1..12, for given locale."""
        return eval("self.months_%s()" % self._locale)

    def months_en(self):
        return [None, 'January', 'February', 'March', 'April', 'May', 'June',
                'July', 'August', 'September', 'October', 'November', 'December']

    def mos(self):
        """returns a list of months, indexed 1..12, for given locale."""
        return eval("self.mos_%s()" % self._locale)

    def mos_en(self):
        return [None, 'Jan.', 'Feb.', 'Mar.', 'Apr.', 'May', 'June',
                'July', 'Aug.', 'Sept.', 'Oct.', 'Nov.', 'Dec.']

    def __str__(self):
        return str(int(self.date()))

    def format(self):
        s = u''
        if self.month() != 0:
            s += self.mo_name()
            if self.day() != 0:
                s += " %d" % self.day()
                if self.year() != 0:
                    s += ','
        if self.year() != 0:
            if s != '': s += ' '
            s += str(self.year())
        return s

    def form_field(self, prefix=None, start_year=1900):
        s="<!-- %s -->" % prefix.upper()
        # MONTH
        s+="""<select name="%smonth"><option value=''></option>""" % prefix
        for i in range(1, len(self.mos())):
            if self.month() == i:
                s+="""<option value=%d selected>%s</option>""" % (i, self.mos()[i] or '')
            else:
                s+="""<option value=%d>%s</option>""" % (i, self.mos()[i] or '')
        s+="</select>"
        # DAY
        s+="""<select name="%sday"><option value=''></option>""" % prefix
        for i in range(1, 31+1):
            if self.day() == i:
                s+="""<option value=%d selected>%d</option>""" % (i, i)
            else:
                s+="""<option value=%d>%d</option>""" % (i, i)
        s+="""</select>"""
        # YEAR
        s+="""<select name="%syear"><option value=''></option>""" % prefix
        for i in range(start_year, datetime.date.today().year+1):
            if self.year() == i:
                s+="""<option value=%d selected>%d</option>""" % (i, i)
            else:
                s+="""<option value=%d>%d</option>""" % (i, i)
        s+="""</select>"""
        s+="""<!-- END %s -->""" % prefix.upper()
        return s

    def process_params(self, prefix='', **params):
        """take attributes given for month, day, and year, and create date."""
        if params.has_key("%syear" % prefix):
            yr = params.get("%syear" % prefix)
            if yr is not None:
                if yr == '': yr = 0
                self.year(int(yr))
        if params.has_key("%smonth" % prefix):
            mo = params.get("%smonth" % prefix)
            if mo is not None:
                if mo == '': mo = 0
                self.month(int(mo))
        if params.has_key("%sday" % prefix):
            dy = params.get("%sday" % prefix)
            if dy is not None:
                if dy == '': dy = 0
                self.day(int(dy))
        return self.date()

if __name__ == "__main__":
    import doctest
    doctest.testmod()


#!/usr/bin/env python

import unittest
import sys, os
from ConfigParser import ConfigParser

sys.path.append("..")

from afs.util.AfsConfig import AfsConfig, setupDefaultConfig
from afs.util.options import define, options
from afs.service.VolService import VolService
import afs

class TestVolServiceMethods(unittest.TestCase):
    """
    Tests VolService Methods
    """

    def setUp(self):
        """
        setup token and VolService
        """
        self.TestCfg=ConfigParser()
        self.TestCfg.read(options.setup)
        self.Cell=self.TestCfg.get("general", "Cell")
        afs.defaultConfig.AFSCell=self.Cell
        self.User=self.TestCfg.get("general", "User")
        self.Pass=self.TestCfg.get("general", "Pass")
        self.volMng = VolService()
        self.VolID=int(self.TestCfg.get("VolService", "VolID"))
        self.VolName=self.TestCfg.get("VolService", "VolName")
        self.FS=self.TestCfg.get("VolService", "FS")
        self.Part=self.TestCfg.get("VolService", "Part")
        if afs.defaultConfig.DB_CACHE :
            from sqlalchemy.orm import sessionmaker
            self.DbSession= sessionmaker(bind=afs.defaultConfig.DB_ENGINE)
        return

    def test_getVolbyName(self) :
        vol = self.volMng.getVolume(self.VolName, self.FS, self.Part)
        self.assertEqual(vol.vid, self.VolID)
        self.assertEqual(vol.serv, self.FS)
        self.assertEqual(vol.part, self.Part)
        return

if __name__ == '__main__' :
    define("setup", default="./Test.cfg", help="path to Testconfig")
    setupDefaultConfig()
    if not os.path.exists(options.setup) :
        sys.stderr.write("Test setup file %s does not exist.\n" % options.setup)
        sys.exit(2)
    suite = unittest.TestLoader().loadTestsFromTestCase(TestVolServiceMethods)
    unittest.TextTestRunner(verbosity=2).run(suite)


from torchvision.datasets import MNIST as torchMNIST
from torchvision.datasets import FashionMNIST
from torch.utils.data import Subset
import torchvision.transforms.functional as TF
import torchvision.transforms as transforms
import torch
import numpy as np
import os
import nn_ood

class MNIST(Subset):
    def __init__(self, split, N=None):
        dataset = torchMNIST
        root = os.path.join(nn_ood.DATASET_FOLDER, "MNIST")
        if split == "train":
            mnist_split = "train"
            target_criterion = lambda x: x < 5
        elif split == "val":
            mnist_split = "val"
            target_criterion = lambda x: x < 5
        elif split == "ood":
            mnist_split = "val"
            target_criterion = lambda x: x >= 5
        elif split == "fashion":
            dataset = FashionMNIST
            root = os.path.join(nn_ood.DATASET_FOLDER, "FashionMNIST")
            mnist_split = "val"
            target_criterion = lambda x: x == x

        self.mnist = dataset(root=root, train=(split=="train"), download=True)

        self.normalize = transforms.Normalize((0.1307,), (0.3081,))

        # filter out only 1s
        valid_idx = np.flatnonzero(target_criterion(self.mnist.targets))

        if N is not None:
            valid_idx = valid_idx[:N]

        super().__init__(self.mnist, valid_idx)

    def __getitem__(self, i):
        input, target = super(MNIST, self).__getitem__(i)
        target = target % 5
        input = transforms.ToTensor()(input)
        input = self.normalize(input)
        return input, target


import gym, pygame
from gym import error, spaces, utils
from gym.utils import seeding
from pygame.locals import *
import numpy as np

class MlSteamEnv001(gym.Env):
	metadata = {'render.modes': ['human']}

	def transformar_reward_em_float(self, x):
		if x >= 0:
			return (float(x) / 5) #10
		else:
			return 0.0

	def __init__(self):
		self.lastComando = 10
		self.numDeRodadasParadas = 0
		self.numeroIteracao = 0

		self.numBlueParados = 0
		self.numGreenParados = 0
		self.numRedParados = 0

		#Lista de carros azuis
		self.blueList = [[20,31],[20,32],[20,33],[20,34],[20,35]]
		self.blueDirectionList = ["Cima", "Cima", "Cima", "Cima", "Cima"]

		#Lista de carros verdes
		self.greenList = [[9,10],[8,10],[7,10],[6,10],[5,10]]
		self.greenDirectionList = ["Direita", "Direita", "Direita", "Direita", "Direita"]

		#Lista de carros vermelhos
		self.redList = [[9,30],[8,30],[7,30],[6,30],[5,30]]
		self.redDirectionList = ["Direita", "Direita", "Direita", "Direita", "Direita"]

		#Lista de pontos de virada azul
		self.blueTurningPoints = [[20,10]]
		self.blueTurningPointsDic = {"[20, 10]":"Direita"}
		self.blueEndingPoint = [40,10]

		#Lista de pontos de virada verde
		self.greenTurningPoints = [[10,10],[10,20]]
		self.greenTurningPointsDic = {"[10, 10]":"Baixo", "[10, 20]":"Direita"}
		self.greenEndingPoint = [40,20]

		#Lista de pontos de virada vermelho
		self.redTurningPoints = [[30,30]]
		self.redTurningPointsDic = {"[30, 30]":"Cima"}
		self.redEndingPoint = [30,0]

		#Lista dos semaforos
		self.trafficLightsList = [[10,10],[20,10],[30,10],[10,20],[20,20],[30,20],[10,30],[20,30],[30,30]]
		self.trafficLightsState = [1, 0, 0, 0, 0, 1, 1, 0, 0] #0: O (passa vertical), 1: X (passa horizontal)

		#Lista dos quadrados das ruas
		self.streetList = self.FazerListaDasRuas()

		# 0 a 9
		self.action_space = spaces.Discrete(10)

		#espaco de observacao
		high = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
		low = np.array([-1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0])
		self.observation_space = spaces.Box(low, high, dtype=np.int8)

		self.screen = None

	def step(self, action):
		reward = 15
		comando = int(round(action, 0))
		if comando != 0:
			if self.trafficLightsState[comando-1] == 0:
				self.trafficLightsState[comando-1] = 1
			else:
				self.trafficLightsState[comando-1] = 0

		if self.lastComando != 0 and comando == self.lastComando:
			reward -= 5
		self.lastComando = comando

		i = 0
		tempNumDeCarrosParados = 0
		estadoDeFinalizacao = 0 #3 quer dizer q RGB acabaram
		tempNumBlueParados = 0
		while i < len(self.blueList):
			x = self.blueList[i][0]
			y = self.blueList[i][1]

			if self.ChecarSeChegouAoFim(x, y, i, self.blueEndingPoint) == True:
				del self.blueList[i]
				del self.blueDirectionList[i]
				reward += 3
				continue

			self.ChecarPontoDeViradaAFrenteEVirar(x, y, i, self.blueDirectionList, self.blueTurningPoints, self.blueTurningPointsDic)

			if self.MacroCarroVerSeTemAlgoAFrente(x, y, self.blueDirectionList[i], self.trafficLightsList, self.trafficLightsState,
				self.blueList, self.greenList, self.redList) == False:
				self.CarroMoverParaFrente(i, self.blueList, self.blueDirectionList[i])
				#reward += 1
			else:
				tempNumDeCarrosParados += 1
				tempNumBlueParados += 1
				reward -= 1

			i += 1

		if len(self.blueList) == 0:
			estadoDeFinalizacao += 1

		i = 0
		tempNumGreenParados = 0
		while i < len(self.greenList):
			x = self.greenList[i][0]
			y = self.greenList[i][1]

			if self.ChecarSeChegouAoFim(x, y, i, self.greenEndingPoint) == True:
				del self.greenList[i]
				del self.greenDirectionList[i]
				reward += 3
				continue

			self.ChecarPontoDeViradaAFrenteEVirar(x, y, i, self.greenDirectionList, self.greenTurningPoints, self.greenTurningPointsDic)

			if self.MacroCarroVerSeTemAlgoAFrente(x, y, self.greenDirectionList[i], self.trafficLightsList, self.trafficLightsState,
				self.blueList, self.greenList, self.redList) == False:
				self.CarroMoverParaFrente(i, self.greenList, self.greenDirectionList[i])
				#reward += 1
			else:
				tempNumDeCarrosParados += 1
				tempNumGreenParados += 1
				reward -= 1

			i += 1

		if len(self.greenList) == 0:
			estadoDeFinalizacao += 1

		i = 0
		tempNumRedParados = 0
		while i < len(self.redList):
			x = self.redList[i][0]
			y = self.redList[i][1]

			if self.ChecarSeChegouAoFim(x, y, i, self.redEndingPoint) == True:
				del self.redList[i]
				del self.redDirectionList[i]
				reward += 3
				continue

			self.ChecarPontoDeViradaAFrenteEVirar(x, y, i, self.redDirectionList, self.redTurningPoints, self.redTurningPointsDic)

			if self.MacroCarroVerSeTemAlgoAFrente(x, y, self.redDirectionList[i], self.trafficLightsList, self.trafficLightsState,
				self.blueList, self.greenList, self.redList) == False:
				self.CarroMoverParaFrente(i, self.redList, self.redDirectionList[i])
				#reward += 1
			else:
				tempNumDeCarrosParados += 1
				tempNumRedParados += 1
				reward -= 1

			i += 1

		if len(self.redList) == 0:
			estadoDeFinalizacao += 1

		if tempNumDeCarrosParados == 15:
			self.numDeRodadasParadas += 1
		else:
			self.numDeRodadasParadas = 0

		if tempNumBlueParados >= 1:
			self.numBlueParados += 1
		else:
			self.numBlueParados = 0

		if tempNumGreenParados >= 1:
			self.numGreenParados += 1
		else:
			self.numGreenParados = 0

		if tempNumRedParados >= 1:
			self.numRedParados += 1
		else:
			self.numRedParados = 0

		self.numeroIteracao += 1
		ob = self.RetornarArray(self.blueList, self.greenList, self.redList, self.trafficLightsState, self.trafficLightsList)
		episode_over = False
		if estadoDeFinalizacao == 3 or self.numeroIteracao > 499 or self.numDeRodadasParadas >= 5:
			episode_over = True
		if self.numBlueParados >= 14 or self.numGreenParados >= 14 or self.numRedParados >= 14:
			episode_over = True

		return ob, self.transformar_reward_em_float(reward), episode_over, {}

	def reset(self):
		self.lastComando = 10
		self.numDeRodadasParadas = 0
		self.numeroIteracao = 0

		self.numBlueParados = 0
		self.numGreenParados = 0
		self.numRedParados = 0

		#Lista de carros azuis
		self.blueList = [[20,31],[20,32],[20,33],[20,34],[20,35]]
		self.blueDirectionList = ["Cima", "Cima", "Cima", "Cima", "Cima"]

		#Lista de carros verdes
		self.greenList = [[9,10],[8,10],[7,10],[6,10],[5,10]]
		self.greenDirectionList = ["Direita", "Direita", "Direita", "Direita", "Direita"]

		#Lista de carros vermelhos
		self.redList = [[9,30],[8,30],[7,30],[6,30],[5,30]]
		self.redDirectionList = ["Direita", "Direita", "Direita", "Direita", "Direita"]

		#Lista de pontos de virada azul
		self.blueTurningPoints = [[20,10]]
		self.blueTurningPointsDic = {"[20, 10]":"Direita"}
		self.blueEndingPoint = [40,10]

		#Lista de pontos de virada verde
		self.greenTurningPoints = [[10,10],[10,20]]
		self.greenTurningPointsDic = {"[10, 10]":"Baixo", "[10, 20]":"Direita"}
		self.greenEndingPoint = [40,20]

		#Lista de pontos de virada vermelho
		self.redTurningPoints = [[30,30]]
		self.redTurningPointsDic = {"[30, 30]":"Cima"}
		self.redEndingPoint = [30,0]

		#Lista dos semaforos
		self.trafficLightsList = [[10,10],[20,10],[30,10],[10,20],[20,20],[30,20],[10,30],[20,30],[30,30]]
		self.trafficLightsState = [1, 0, 0, 0, 0, 1, 1, 0, 0] #0: O (passa vertical), 1: X (passa horizontal)

		#Lista dos quadrados das ruas
		self.streetList = self.FazerListaDasRuas()

		return self.RetornarArray(self.blueList, self.greenList, self.redList, self.trafficLightsState, self.trafficLightsList)

	def b_render(self): #mode='human'):
		if self.screen is None:
			pygame.init();
			self.screen=pygame.display.set_mode((800, 800));
			pygame.display.set_caption('PySteamTest001');

		blueimage = pygame.Surface((20,20));
		blueimage.fill((0, 0, 255));
		greenimage = pygame.Surface((20,20));
		greenimage.fill((0, 255, 0));
		redimage = pygame.Surface((20, 20));
		redimage.fill((255, 0, 0));
		yellowimage = pygame.Surface((20,20));
		yellowimage.fill((255, 255, 0));
		orangeimage = pygame.Surface((20,20));
		orangeimage.fill((255, 165, 0));
		greyimage = pygame.Surface((20,20));
		greyimage.fill((128, 128, 128));
		f = pygame.font.SysFont('Arial', 20);
		clock = pygame.time.Clock()

		self.screen.fill((0,0,0))

		for i in range(len(self.streetList)):
			self.screen.blit(greyimage, (self.streetList[i][0]*20, self.streetList[i][1]*20))

		for i in range(len(self.blueList)):
			self.screen.blit(blueimage, (self.blueList[i][0]*20, self.blueList[i][1]*20))
		for i in range(len(self.greenList)):
			self.screen.blit(greenimage, (self.greenList[i][0]*20, self.greenList[i][1]*20))
		for i in range(len(self.redList)):
			self.screen.blit(redimage, (self.redList[i][0]*20, self.redList[i][1]*20))

		for num in range(len(self.trafficLightsList)):
			if self.trafficLightsState[num] == 0:
				self.screen.blit(yellowimage, (self.trafficLightsList[num][0]*20, self.trafficLightsList[num][1]*20))
			else:
				self.screen.blit(orangeimage, (self.trafficLightsList[num][0]*20, self.trafficLightsList[num][1]*20))

		#state_array = self.RetornarArray(self.blueList, self.greenList, self.redList, self.trafficLightsState)
		#t=f.render(str(numeroIteracao), True, (255, 255, 255));
		#st=f.render(str(state_array), True, (255, 255, 255));
		#screen.blit(t, (10, 10));
		#screen.blit(st, (10, 40));

		pygame.display.update()
		clock.tick(30)
		#return None

	def close(self):
		pygame.quit()

	#region defFunctionSelf

	def CarroVerSeTemSemaforoAFrente(self, x, y, direction, tempTrafficLightsList, tempTrafficLightsState):
		for num in range(len(tempTrafficLightsList)):
			xs = tempTrafficLightsList[num][0]
			ys = tempTrafficLightsList[num][1]
			if self.ChecarColisaoAFrente(x, y, xs, ys, direction) == True:
				if direction == "Direita" and tempTrafficLightsState[num] != 0:
					return True
				elif direction == "Esquerda" and tempTrafficLightsState[num] != 0:
					return True
				elif direction == "Cima" and tempTrafficLightsState[num] != 1:
					return True
				elif direction == "Baixo" and tempTrafficLightsState[num] != 1:
					return True

		return False

	def ChecarColisaoAFrente(self, x1, y1, x2, y2, direction):
		if direction == "Cima":
			if x1 == x2 and y1 - 1 == y2:
				return True
			else:
				return False

		elif direction == "Baixo":
			if x1 == x2 and y1 + 1 == y2:
				return True
			else:
				return False

		elif direction == "Direita":
			if x1 + 1 == x2 and y1 == y2:
				return True
			else:
				return False

		elif direction == "Esquerda":
			if x1 - 1 == x2 and y1 == y2:
				return True
			else:
				return False

	def MacroCarroVerSeTemAlgoAFrente(self, x, y, direction, tempTrafficLightsList, tempTrafficLightsState, blueList, greenList, redList):
		if self.CarroVerSeTemSemaforoAFrente(x, y, direction, tempTrafficLightsList, tempTrafficLightsState) == True:
			return True

		for num in range(len(blueList)):
			x2 = blueList[num][0]
			y2 = blueList[num][1]
			if self.ChecarColisaoAFrente(x, y, x2, y2, direction) == True:
				return True

		for num in range(len(greenList)):
			x2 = greenList[num][0]
			y2 = greenList[num][1]
			if self.ChecarColisaoAFrente(x, y, x2, y2, direction) == True:
				return True

		for num in range(len(redList)):
			x2 = redList[num][0]
			y2 = redList[num][1]
			if self.ChecarColisaoAFrente(x, y, x2, y2, direction) == True:
				return True

		return False

	def ChecarPontoDeViradaAFrenteEVirar(self, x, y, i, directionList, turningPoints, turningPointsDic):
		direction = directionList[i]

		for num in range(len(turningPoints)):
			xp = turningPoints[num][0]
			yp = turningPoints[num][1]
			if x == xp and y == yp:
				directionTemp = turningPointsDic[str(turningPoints[num])]
				directionList[i] = directionTemp
				return

	def CarroMoverParaFrente(self, i, colorList, direction):
		x = colorList[i][0]
		y = colorList[i][1]

		if direction == "Cima":
			colorList[i][1] = y - 1

		elif direction == "Baixo":
			colorList[i][1] = y + 1

		elif direction == "Direita":
			colorList[i][0] = x + 1

		elif direction == "Esquerda":
			colorList[i][0] = x - 1

		return

	def ChecarSeChegouAoFim(self, x, y, i, endingPoint):
		if x == endingPoint[0] and y == endingPoint[1]:
			return True
		else:
			return False

	def FazerListaDasRuas(self):
		streetList = []
		for x in range(40):
			streetList.append([x, 10])
			streetList.append([x, 20])
			streetList.append([x, 30])

		for y in range(40):
			if y != 10 and y != 20 and y != 30:
				streetList.append([10, y])
				streetList.append([20, y])
				streetList.append([30, y])

		return streetList

	def RetornarArray(self, blueList, greenList, redList, trafficLightsState, trafficLightsList):
		array = [0, 0, 0, 0, 0, 0, 0, 0, 0]
		for i in range(len(blueList)):
			x = blueList[i][0]
			y = blueList[i][1]
			for num in range(len(trafficLightsList)):
				xs = trafficLightsList[num][0]
				ys = trafficLightsList[num][1]
				if y == ys and x + 1 == xs:
					array[num] = 1
				elif y == ys and x - 1 == xs:
					array[num] = 1
				elif x == xs and y + 1 == ys:
					array[num] = -1
				elif x == xs and y - 1 == ys:
					array[num] = -1

		for i in range(len(greenList)):
			x = greenList[i][0]
			y = greenList[i][1]
			for num in range(len(trafficLightsList)):
				xs = trafficLightsList[num][0]
				ys = trafficLightsList[num][1]
				if y == ys and x + 1 == xs:
					array[num] = 1
				elif y == ys and x - 1 == xs:
					array[num] = 1
				elif x == xs and y + 1 == ys:
					array[num] = -1
				elif x == xs and y - 1 == ys:
					array[num] = -1

		for i in range(len(redList)):
			x = redList[i][0]
			y = redList[i][1]
			for num in range(len(trafficLightsList)):
				xs = trafficLightsList[num][0]
				ys = trafficLightsList[num][1]
				if y == ys and x + 1 == xs:
					array[num] = 1
				elif y == ys and x - 1 == xs:
					array[num] = 1
				elif x == xs and y + 1 == ys:
					array[num] = -1
				elif x == xs and y - 1 == ys:
					array[num] = -1

		for i in range(len(trafficLightsState)):
			array.append(trafficLightsState[i])

		return array

	#endregion


import json
import logging
from pathlib import Path
from typing import Dict, Optional, Union

import boto3
import yaml
from jsonschema import exceptions

from taskcat._client_factory import ClientFactory
from taskcat._common_utils import absolute_path, schema_validate as validate
from taskcat._s3_stage import S3APIResponse, S3BucketCreatorException
from taskcat.exceptions import TaskCatException

LOG = logging.getLogger(__name__)

class Test:
    def __init__(
        self,
        template_file: Path,
        name: str = "default",
        parameter_input: Path = None,
        parameters: dict = None,
        regions: set = None,
        project_root: Union[Path, str] = "./",
        auth: dict = None,
    ):
        auth = auth if auth is not None else {}
        self._project_root: Path = Path(project_root)
        self.template_file: Path = self._guess_path(template_file)
        self.parameter_input_file: Optional[Path] = None
        if parameter_input:
            self.parameter_input_file = self._guess_path(parameter_input)
        self.parameters: Dict[
            str, Union[str, int, bool]
        ] = self._params_from_file() if parameter_input else {}
        if parameters:
            self.parameters.update(parameters)
        validate(self.parameters, "overrides")
        self.regions: list = list(regions) if regions else []
        self.auth: dict = auth
        self.client_factory: ClientFactory = ClientFactory()
        self.name: str = name

    def _guess_path(self, path):
        abs_path = absolute_path(path)
        if not abs_path:
            abs_path = absolute_path(self._project_root / path)
        if not abs_path:
            abs_path = self._legacy_path_prefix(path)
        if not abs_path:
            raise TaskCatException(
                f"Cannot find {path} with project root" f" {self._project_root}"
            )
        return abs_path

    def _legacy_path_prefix(self, path):
        abs_path = absolute_path(self._project_root / "templates" / path)
        if abs_path:
            LOG.warning(
                "found path with deprecated relative path, support for this will be "
                "removed in future versions, please update %s to templates/%s",
                path,
                path,
            )
            return abs_path
        abs_path = absolute_path(self._project_root / "ci" / path)
        if abs_path:
            LOG.warning(
                "found path with deprecated relative path, support for this will be "
                "removed in future versions, please update %s to ci/%s",
                path,
                path,
            )
        return abs_path

    def _params_from_file(self):
        if not self.parameter_input_file:
            return None
        with open(str(self.parameter_input_file), "r") as f_handle:
            params = yaml.safe_load(f_handle)
        self._validate_params(params)
        try:
            validate(params, "legacy_parameters")
            params = self._convert_legacy_params(params)
        except exceptions.ValidationError:
            pass
        return params

    @staticmethod
    def _convert_legacy_params(legacy_params):
        return {p["ParameterKey"]: p["ParameterValue"] for p in legacy_params}

    def _validate_params(self, params):
        try:
            validate(params, "overrides")
        except exceptions.ValidationError as e:
            try:
                validate(params, "legacy_parameters")
                LOG.warning(
                    "%s parameters are in a format that will be deprecated in "
                    "the next version of taskcat",
                    str(self.parameter_input_file),
                )
            except exceptions.ValidationError:
                # raise original exception
                raise e

    @classmethod
    def from_dict(cls, raw_test: dict, project_root="./"):
        raw_test["project_root"] = Path(project_root)
        return Test(**raw_test)

class S3BucketConfig:
    def __init__(self):
        self.name = ""
        self.public = False

class AWSRegionObject:
    def __init__(self, region_name: str, client_factory: ClientFactory):
        self.name: str = region_name
        self.s3bucket: Optional[S3Bucket] = None
        self.account: Optional[str] = None
        self.parameters: Dict[str, str] = {}
        self._cf: ClientFactory = client_factory
        self._credset_name: Optional[str] = None
        self._credset_modify = True
        self.partition = None

    @property
    def credset_name(self) -> Optional[str]:
        return self._credset_name

    @credset_name.setter
    def credset_name(self, value: str) -> None:
        if not self._credset_modify:
            return
        self._credset_name = value

    def disable_credset_modification(self):
        self._credset_modify = False

    def client(self, service):
        service_session = self._cf.get(
            credential_set=self.credset_name, region=self.name, service=service
        )
        return service_session

    def set_partition(self):
        if not self.credset_name:
            return
        avail_regions = self._cf.get_session(
            self.credset_name, self.name
        ).get_available_regions("s3")
        if "us-east-1" in avail_regions:
            self.partition = "aws"
        elif "us-gov-east-1" in avail_regions:
            self.partition = "aws-us-gov"
        elif "cn-north-1" in avail_regions:
            self.partition = "aws-cn"

    def get_bucket_region_for_partition(self):
        region = "us-east-1"
        if self.partition == "aws-us-gov":
            region = "us-gov-east-1"
        elif self.partition == "aws-cn":
            region = "cn-north-1"
        return region

    def get_s3_client(self):
        return self._cf.get(
            credential_set=self.credset_name,
            region=self.get_bucket_region_for_partition(),
            service="s3",
        )

    def __repr__(self):
        return f"<AWSRegionObject(region_name={self.name}) object at {hex(id(self))}>"

class S3Bucket:
    # pylint: disable=too-many-instance-attributes

    def __init__(
        self,
        config,
        client: boto3.client,
        name: str = "",
        region: str = "us-east-1",
        auto: bool = True,
        account: str = "",
    ):
        self.name: str = name
        self.public: bool = config.s3bucket.public
        self.tags: list = []
        self.region: str = region
        self.sigv4: bool = True
        self._auto: bool = auto
        self._config = config
        self._client = client
        self._acl = ""
        self._policy: Optional[str] = None
        self._created: bool = False
        self._max_name_len = 63
        # Account
        self.account = account
        # Client
        self._determine_bucket_attributes()

    def _determine_bucket_attributes(self):
        self.sigv4 = not self._config.enable_sig_v2
        self.tags = self._config.tags
        self.public = self._config.s3bucket.public
        if not self.auto:
            self._assert_bucket_exists(self.name)
            self._created = True

    @property
    def acl(self):
        return self._acl

    @property
    def policy(self):
        return self._policy

    @property
    def client(self):
        return self._client

    @property
    def auto(self):
        return self._auto

    @property
    def sigv4_policy(self):
        policy = {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Sid": "Test",
                    "Effect": "Deny",
                    "Principal": "*",
                    "Action": "s3:*",
                    "Resource": f"arn:aws:s3:::{self.name}/*",
                    "Condition": {"StringEquals": {"s3:signatureversion": "AWS"}},
                }
            ],
        }
        return json.dumps(policy)

    def _create_in_region(self):
        if self.region == "us-east-1":
            response = self.client.create_bucket(ACL=self.acl, Bucket=self.name)
        else:
            response = self.client.create_bucket(
                ACL=self.acl,
                Bucket=self.name,
                CreateBucketConfiguration={"LocationConstraint": self.region},
            )

        self.client.get_waiter("bucket_exists").wait(Bucket=self.name)
        return S3APIResponse(response)

    def _create_bucket(self, bucket_name):
        _create_resp = self._create_in_region()
        if _create_resp.ok:
            LOG.info(f"Staging Bucket: [{bucket_name}]")

        if self.tags:
            LOG.info(f"Propagating tags to this bucket.")
            self.client.put_bucket_tagging(
                Bucket=bucket_name, Tagging={"TagSet": self.tags}
            )

        if self.sigv4:
            LOG.info(f"Enforcing SigV4 requests for bucket ${bucket_name}")
            self.client.put_bucket_policy(Bucket=self.name, Policy=self.sigv4_policy)

    def _assert_bucket_exists(self, name):

        # Verify bucket exists.
        try:
            _ = self.client.list_objects(Bucket=name)
        except self.client.exceptions.NoSuchBucket:
            raise TaskCatException(
                f"The bucket you provided ({name}) does " f"not exist. Exiting."
            )
        return True

    def create(self):
        if self._created:
            return

        # Verify bucket name length
        if len(self.name) > self._max_name_len:
            raise S3BucketCreatorException(
                f"The bucket name you provided [{self._config.s3bucket}] \
                is greater than {self._max_name_len} characters."
            )

        LOG.info(f"Creating bucket in {self.region} for account {self.account}")
        self._create_bucket(self.name)
        self._created = True

    # TODO Add delete().
    def delete(self):
        pass


# uncompyle6 version 3.7.4
# Python bytecode 2.4 (62061)
# Decompiled from: Python 3.6.9 (default, Apr 18 2020, 01:56:04)
# [GCC 8.4.0]
# Embedded file name: build/bdist.linux-i686/egg/ks/schema/html/html.py
# Compiled at: 2008-12-22 08:23:24
"""HTML field class for the Zope 3 based ks.schema.html package

$Id: html.py 23861 2007-11-25 00:13:00Z xen $
"""
__author__ = 'Anatoly Zaretsky'
__license__ = 'ZPL'
__version__ = '$Revision: 23861 $'
__date__ = '$Date: 2007-11-25 02:13:00 +0200 (Sun, 25 Nov 2007) $'
from zope.schema import Text
from zope.interface import implements
from interfaces import IHTML

class HTML(Text):
    __module__ = __name__
    implements(IHTML)


__author__ = 'Pandera'
import sys
sys.path.append('../common')
import json
import time
import configparser
import collections
import operator
import math
from datetime import datetime
from pymongo import MongoClient
#from dateutil import parser
from collections import Counter
from debugException import DebugException
from scoringMethods import reqScorer
from scoringMethods import scoreInserter
from scoringMethods import candidateScorer

#config = configparser.ConfigParser()
#config.read('../common/ConfigFile.properties')

#uri = config.get("DatabaseSection", "database.connection_string")
#db_name = config.get("DatabaseSection", "database.dbname")
#client=MongoClient(uri)
#db = client[db_name]

def requisitionIncrementalScorer(requisitionId, db, logFile):
    try:

        reqParsed = list(db.requisition_skills_from_parsed_requisition.find({"requisition_id":requisitionId},{"parsedWords":1,"_id":0}))
        for words in reqParsed:
            if(words["parsedWords"] == []):
                reqParsed = []
        if(len(reqParsed) == 0):
            status = scoreInserter(requisitionId)
            return("No Requisition description")
            logFile.write("[" + datetime.now().isoformat() + "] RequisitionId [" + str(requisitionId) + "] No description" + "\n")

        ### - Submitted Candidates processing
        scBeginTime = datetime.now()
        candidateCount = db.requisition_candidate.find({"requisition_id":requisitionId}).count()
        jobid = list(db.requisition.find({"requisition_id": requisitionId}, {"new_global_job_category_id": 1, "_id": 0}))
        for id in jobid:
            gjid1 = id["new_global_job_category_id"]
        idealSkillList = db.ideal_candidate_characteritics.find_one({"global_job_category_id": gjid1}, {"Skills": 1, "_id": 0})
        if(idealSkillList is None):
            idealSkills = 'NA'
        else:
            idealSkills = idealSkillList['Skills']
        if(candidateCount >=1):
            #print("Working on Submitted Candidates")
            status = reqScorer(reqParsed, jobid, idealSkills, requisitionId)
            logFile.write("[" + datetime.now().isoformat() + "] RequisitionId [" + str(requisitionId) + "] Submitted candidates scoring complete. Candidate Count ["+ str(candidateCount) + "] Elapsed time [" + str(datetime.now() - scBeginTime) + "]" + "\n")
        else:
            logFile.write("[" + datetime.now().isoformat() + "] RequisitionId [" + str(requisitionId) + "] no submitted candidates found" + "\n")

        ## - Search & Score
        ssBeginTime = datetime.now()
        candidateList = []
        candidates = list(db.category_candidate_map.find({"global_job_category_id":gjid1}, {"candidates":1,"_id":0}))
        for candidate in candidates:
            candidateList = candidate["candidates"]
        candidateTotal = len(candidateList)
        if(candidateTotal == 0):
            logFile.write("[" + datetime.now().isoformat() + "] RequisitionId [" + str(requisitionId) + "] No Candidates associated to this Job Category [" + str(gjid1) + "]" + "\n")
            #print("No Candidates associated to this Job Category")
            return("Scoring Method Completed Successfully")
        #print("Requisition %s has %s affiliated candidates" % (requisitionId, candidateTotal))
        status = candidateScorer(candidateList, reqParsed, idealSkills, requisitionId)
        logFile.write("[" + datetime.now().isoformat() + "] RequisitionId [" + str(requisitionId) + "] Search & Score scoring complete. Candidate Count ["+ str(candidateTotal) + "] Elapsed time [" + str(datetime.now() - ssBeginTime) + "]" + "\n")
        return("Scoring Complete")
    except Exception as e:
        DebugException(e)
        logFile.write("[" + datetime.now().isoformat() + "] RequisitionId [" + str(requisitionId) + "] [requisitionIncrementalScorer()] Requisition Incremental Scorer failed due to error [" + str(e) + "]" + "\n")

def subReqCandScorer(requisitionId, db, logFile):
    try:
        scBeginTime = datetime.now()
        reqParsed = list(db.requisition_skills_from_parsed_requisition.find({"requisition_id":requisitionId},{"parsedWords":1,"_id":0}))
        for words in reqParsed:
            if(words["parsedWords"] == []):
                reqParsed = []

        if(len(reqParsed) == 0):
            status = scoreInserter(requisitionId)
            logFile.write("[" + datetime.now().isoformat() + "] RequisitionId [" + str(requisitionId) + "] No description" + "\n")
            return("No Requisition description")

        jobid = list(db.requisition.find({"requisition_id":requisitionId},{"new_global_job_category_id":1,"_id":0}))
        for id in jobid:
            gjid1 = id["new_global_job_category_id"]
        idealSkillList = db.ideal_candidate_characteritics.find_one({"global_job_category_id":gjid1},{"Skills":1,"_id":0})
        if(idealSkillList is None):
            idealSkills = 'NA'
        else:
            idealSkills = idealSkillList['Skills']
        status = reqScorer(reqParsed, jobid, idealSkills, requisitionId)
        logFile.write("[" + datetime.now().isoformat() + "] RequisitionId [" + str(requisitionId) + "] Submitted candidates scoring complete. Elapsed time [" + str(datetime.now() - scBeginTime) + "]" + "\n")
        return("Scoring Complete")
    except Exception as e:
        DebugException(e)
        #print("Requisition Incremental Scorer failed due to error [" + str(e) + "]")
        logFile.write("[" + datetime.now().isoformat() + "] RequisitionId [" + str(requisitionId) + "] [subReqCandScorer()] Requisition Incremental Scorer failed due to error [" + str(e) + "]" + "\n")