Check if the solution of the Paper is available to User.

@param Exercise $exercise
@param Paper    $paper

@return bool
540570
public function isSolutionAvailable(Exercise $exercise, Paper $paper)
    {
        $correctionMode = $exercise->getCorrectionMode();
        switch ($correctionMode) {
            case ShowCorrectionAt::AFTER_END:
                $available = !empty($paper->getEnd());
                break;

            case ShowCorrectionAt::AFTER_LAST_ATTEMPT:
                $available = 0 === $exercise->getMaxAttempts() || $paper->getNumber() === $exercise->getMaxAttempts();
                break;

            case ShowCorrectionAt::AFTER_DATE:
                $now = new \DateTime();
                $available = empty($exercise->getDateCorrection()) || $now >= $exercise->getDateCorrection();
                break;

            case ShowCorrectionAt::NEVER:
            default:
                $available = false;
                break;
        }

        return $available;
    }
247278
public function exportCsvAction(Exercise $exercise)
    {
        $this->assertHasPermission('MANAGE_PAPERS', $exercise);

        return new StreamedResponse(function () use ($exercise) {
            $this->exerciseManager->exportPapersToCsv($exercise);
        }, 200, [
            'Content-Type' => 'application/force-download',
            'Content-Disposition' => 'attachment; filename="export.csv"',
        ]);
    }
629760
public function getStatistics(Exercise $exercise, $maxScore)
    {
        return [
            'maxScore' => $maxScore,
            'nbSteps' => $exercise->getSteps()->count(),
            'nbQuestions' => $this->exerciseRepository->countExerciseQuestion($exercise),
            'nbPapers' => $this->paperManager->countExercisePapers($exercise),
            'nbRegisteredUsers' => $this->paperManager->countPapersUsers($exercise),
            'nbAnonymousUsers' => $this->paperManager->countAnonymousPapers($exercise),
            'minMaxAndAvgScores' => $this->getMinMaxAverageScores($exercise, $maxScore),
            'paperSuccessDistribution' => $this->getPapersSuccessDistribution($exercise, $maxScore),
            'paperScoreDistribution' => $this->getPaperScoreDistribution($exercise, $maxScore),
            'questionsDifficultyIndex' => $this->getQuestionsDifficultyIndex($exercise),
            'discriminationCoefficient' => $this->getDiscriminationCoefficient($exercise),
        ];
    }
150882
public function isDeletable(Exercise $exercise)
    {
        return !$exercise->getResourceNode()->isPublished() || 0 === $this->paperManager->countExercisePapers($exercise);
    }
263654
private function deserializeSteps(Exercise $exercise, array $steps = [], array $options = [])
    {
        $stepEntities = $exercise->getSteps()->toArray();

        foreach ($steps as $index => $stepData) {
            $existingStep = null;

            // Searches for an existing step entity.
            foreach ($stepEntities as $entityIndex => $entityStep) {
                /** @var Step $entityStep */
                if ($entityStep->getUuid() === $stepData['id']) {
                    $existingStep = $entityStep;
                    unset($stepEntities[$entityIndex]);
                    break;
                }
            }

            $step = $this->stepSerializer->deserialize($stepData, $existingStep, $options);
            // Set order in Exercise
            $step->setOrder($index);

            if (empty($existingStep)) {
                // Creation of a new step (we need to link it to the Exercise)
                $exercise->addStep($step);
            }
        }

        // Remaining steps are no longer in the Exercise
        if (0 < count($stepEntities)) {
            /** @var Step $stepToRemove */
            foreach ($stepEntities as $stepToRemove) {
                $exercise->removeStep($stepToRemove);
                $stepQuestions = $stepToRemove->getStepQuestions()->toArray();

                foreach ($stepQuestions as $stepQuestionToRemove) {
                    $stepToRemove->removeStepQuestion($stepQuestionToRemove);
                }
            }
        }
    }
527067
public function afterExercise(ExerciseCompleted $event)
    {
        if ($this->skipCoverage) {
            return;
        }

        $this->reportService->generateReport($this->coverage);
    }
104032
public function generateResourceEvaluation(Paper $paper, $finished)
    {
        $totalScoreOn = $paper->getExercise()->getTotalScoreOn();
        $total = $totalScoreOn ? $totalScoreOn : $this->calculateTotal($paper);
        $score = $this->calculateScore($paper, $total);
        $successScore = $paper->getExercise()->getSuccessScore();
        $data = [
            'paper' => [
                'id' => $paper->getId(),
                'uuid' => $paper->getUuid(),
            ],
        ];

        if ($finished) {
            if (is_null($successScore)) {
                $status = AbstractResourceEvaluation::STATUS_COMPLETED;
            } else {
                $percentScore = 100 === $totalScoreOn ? $score : $this->calculateScore($paper, 100);
                $status = $percentScore >= $successScore ?
                    AbstractResourceEvaluation::STATUS_PASSED :
                    AbstractResourceEvaluation::STATUS_FAILED;
            }
        } else {
            $status = AbstractResourceEvaluation::STATUS_INCOMPLETE;
        }
        $nbQuestions = 0;
        $structure = json_decode($paper->getStructure(), true);

        if (isset($structure['steps'])) {
            foreach ($structure['steps'] as $step) {
                $nbQuestions += count($step['items']); // TODO : remove content items
            }
        }
        $nbAnswers = 0;

        foreach ($paper->getAnswers() as $answer) {
            if (!is_null($answer->getData())) {
                ++$nbAnswers;
            }
        }

        return $this->resourceEvalManager->createResourceEvaluation(
            $paper->getExercise()->getResourceNode(),
            $paper->getUser(),
            null,
            [
                'status' => $status,
                'score' => $score,
                'scoreMax' => $total,
                'progression' => $nbQuestions > 0 ? floor(($nbAnswers / $nbQuestions) * 100) : null,
                'data' => $data,
            ]
        );
    }
782709
public function checkPaperEvaluated(Paper $paper)
    {
        $fullyEvaluated = $this->repository->isFullyEvaluated($paper);
        if ($fullyEvaluated) {
            $event = new LogExerciseEvaluatedEvent($paper->getExercise(), [
                'result' => $paper->getScore(),
                'resultMax' => $this->calculateTotal($paper),
            ]);

            $this->eventDispatcher->dispatch('log', $event);
        }

        return $fullyEvaluated;
    }
362548
public function check(ExerciseInterface $exercise, Input $input)
    {
        $process = new Process(sprintf('%s -l %s', PHP_BINARY, $input->getArgument('program')));
        $process->run();

        if ($process->isSuccessful()) {
            return Success::fromCheck($this);
        }

        return Failure::fromCheckAndReason($this, $process->getErrorOutput());
    }
26236
public function update(Exercise $exercise, array $data)
    {
        // Validate received data
        $errors = $this->validator->validate($data, [Validation::REQUIRE_SOLUTIONS]);

        if (count($errors) > 0) {
            throw new InvalidDataException('Exercise is not valid', $errors);
        }
        // Start flush suite to avoid persisting and flushing tags before quiz
        $this->om->startFlushSuite();
        // Update Exercise with new data
        $this->serializer->deserialize($data, $exercise, [Transfer::PERSIST_TAG]);

        // Save to DB
        $this->om->persist($exercise);
        $this->om->endFlushSuite();

        // Invalidate unfinished papers
        $this->repository->invalidatePapers($exercise);

        // Log exercise update
        $event = new LogExerciseUpdateEvent($exercise, (array) $this->serializer->serialize($exercise));
        $this->eventDispatcher->dispatch('log', $event);

        return $exercise;
    }
622772
public function serializeExercisePapers(Exercise $exercise, User $user = null)
    {
        if (!empty($user)) {
            // Load papers for of a single user
            $papers = $this->repository->findBy([
                'exercise' => $exercise,
                'user' => $user,
            ]);
        } else {
            // Load all papers submitted for the exercise
            $papers = $this->repository->findBy([
                'exercise' => $exercise,
            ]);
        }

        return array_map(function (Paper $paper) {
            return $this->serialize($paper);
        }, $papers);
    }
562022
public function isFullyEvaluated(Paper $paper)
    {
        return 0 === (int) $this->getEntityManager()
            ->createQuery('
                SELECT COUNT(a)
                FROM UJM\ExoBundle\Entity\Attempt\Answer AS a
                WHERE a.paper = :paper
                  AND a.score IS NULL
            ')
            ->setParameters([
                'paper' => $paper,
            ])
            ->getSingleScalarResult();
    }
1257432
private function pickStepsByTags(Exercise $exercise, array $previousExercise = null)
    {
        $pickConfig = $exercise->getPick();

        // Retrieve the list of items to use
        $items = [];

        if (!empty($previousExercise) && Recurrence::ALWAYS !== $exercise->getRandomPick()) {
            // Just get the list of items from the previous paper
            foreach ($previousExercise['steps'] as $pickedStep) {
                foreach ($pickedStep['items'] as $pickedItem) {
                    $items[] = $exercise->getQuestion($pickedItem['id']);
                }
            }
        } else {
            // Get the list of items from exercise
            foreach ($exercise->getSteps() as $step) {
                $items = array_merge($items, $step->getQuestions());
            }
        }

        // Serialize items (we will automatically get items tags for filtering)
        $serializedItems = array_map(function (Item $pickedItem) {
            return $this->itemSerializer->serialize($pickedItem, [
                Transfer::SHUFFLE_ANSWERS,
                Transfer::INCLUDE_SOLUTIONS,
            ]);
        }, $items);

        $pickedItems = [];

        if (!empty($previousExercise) && Recurrence::ALWAYS !== $exercise->getRandomPick()) {
            // items are already filtered
            $pickedItems = $serializedItems;
        } else {
            // Only pick wanted tags (format : ['tagName', itemCount])
            foreach ($pickConfig['tags'] as $pickedTag) {
                $taggedItems = array_filter($serializedItems, function ($serializedItem) use ($pickedTag) {
                    return !empty($serializedItem['tags']) && in_array($pickedTag[0], $serializedItem['tags']);
                });

                // Get the correct number of items with the current tag
                // There is no error if we want more items than there are in the quiz,
                // we just stop to pick when there are no more available items
                $pickedItems = array_merge($pickedItems, static::pick($taggedItems, $pickedTag[1], true));
            }
        }

        // Shuffle items according to config
        if ((empty($previousExercise) && Recurrence::ONCE === $exercise->getRandomOrder())
            || Recurrence::ALWAYS === $exercise->getRandomOrder()) {
            shuffle($pickedItems);
        }

        // Create steps and fill it with the correct number of questions
        $pickedSteps = [];
        while (!empty($pickedItems)) {
            $pickedStep = $this->stepSerializer->serialize(new Step());
            $pickedStep['items'] = array_splice($pickedItems, 0, $pickConfig['pageSize']);
            $pickedSteps[] = $pickedStep;
        }

        return $pickedSteps;
    }
597987
public function getStatistics(Item $question, Exercise $exercise = null, $finishedPapersOnly = false)
    {
        $questionStats = [];

        // We load all the answers for the question (we need to get the entities as the response in DB are not processable as is)
        $answers = $this->answerRepository->findByQuestion($question, $exercise, $finishedPapersOnly);

        // Number of Users that have seen the question
        $questionStats['seen'] = count($answers);

        // Grab answer data to pass it decoded to the question type
        // it doesn't need to know the whole Answer object
        $answersData = [];

        // get corrected answers for the Item in order to compute question success percentage
        $correctedAnswers = [];

        // Number of Users that have answered the question (no blank answer)
        $questionStats['answered'] = 0;

        if (!empty($answers)) {
            // Let the handler of the question type parse and compile the data
            $definition = $this->itemDefinitions->get($question->getMimeType());

            for ($i = 0; $i < $questionStats['seen']; ++$i) {
                $answer = $answers[$i];
                if (!empty($answer->getData())) {
                    ++$questionStats['answered'];
                    $answersData[] = json_decode($answer->getData(), true);
                }

                // for each answer get corresponding correction
                if ($definition instanceof AnswerableItemDefinitionInterface && isset($answersData[$i])) {
                    $corrected = $definition->correctAnswer($question->getInteraction(), $answersData[$i]);
                    $correctedAnswers[] = $corrected;
                }
            }

            // Let the handler of the question type parse and compile the data
            if ($definition instanceof AnswerableItemDefinitionInterface) {
                $questionStats['solutions'] = $definition->getStatistics($question->getInteraction(), $answersData, $questionStats['seen']);
            }
        }

        // get the number of good answers among all
        $nbGoodAnswers = 0;

        foreach ($correctedAnswers as $corrected) {
            if ($corrected instanceof CorrectedAnswer && 0 === count($corrected->getMissing()) && 0 === count($corrected->getUnexpected())) {
                ++$nbGoodAnswers;
            }
        }
        // compute question success percentage
        $questionStats['successPercent'] = $questionStats['answered'] > 0 ? (100 * $nbGoodAnswers) / $questionStats['answered'] : 0;

        return $questionStats;
    }
995344
private function serializeParameters(Exercise $exercise)
    {
        $parameters = [
            'type' => $exercise->getType(),
            'maxAttempts' => $exercise->getMaxAttempts(),
            'maxAttemptsPerDay' => $exercise->getMaxAttemptsPerDay(),
            'maxPapers' => $exercise->getMaxPapers(),
            'showFeedback' => $exercise->getShowFeedback(),
            'progressionDisplayed' => $exercise->isProgressionDisplayed(),
            'timeLimited' => $exercise->isTimeLimited(), // todo : remove me
            'duration' => $exercise->getDuration(),
            'anonymizeAttempts' => $exercise->getAnonymizeAttempts(),
            'interruptible' => $exercise->isInterruptible(),
            'numbering' => $exercise->getNumbering(),
            'mandatoryQuestions' => $exercise->getMandatoryQuestions(),
            'answersEditable' => $exercise->isAnswersEditable(),
            'showOverview' => $exercise->getShowOverview(),
            'showEndConfirm' => $exercise->getShowEndConfirm(),
            'showEndPage' => $exercise->getShowEndPage(),
            'endNavigation' => $exercise->hasEndNavigation(),
            'showMetadata' => $exercise->isMetadataVisible(),
            'showStatistics' => $exercise->hasStatistics(),
            'allPapersStatistics' => $exercise->isAllPapersStatistics(),
            'showFullCorrection' => !$exercise->isMinimalCorrection(),
            'showScoreAt' => $exercise->getMarkMode(),
            'showCorrectionAt' => $exercise->getCorrectionMode(),
            'successMessage' => $exercise->getSuccessMessage(),
            'failureMessage' => $exercise->getFailureMessage(),
            'totalScoreOn' => $exercise->getTotalScoreOn(),
            'successScore' => $exercise->getSuccessScore(),
            'correctionDate' => $exercise->getDateCorrection() ? DateNormalizer::normalize($exercise->getDateCorrection()) : null,
        ];

        if (!empty($exercise->getEndMessage())) {
            $parameters['endMessage'] = $exercise->getEndMessage();
        }

        return $parameters;
    }
75410
def AnalizarAjusteDebito(self):
        ""
        # para compatibilidad con la generacion de PDF (completo datos)
        liq = {}
        if hasattr(self, "liquidacion") and self.liquidacion:
            liq.update(self.liquidacion)
        if hasattr(self, "ajuste") and 'ajusteDebito' in self.ajuste:
            liq.update(self.ajuste['ajusteDebito'])
        if self.__ajuste_debito:
            liq.update(self.__ajuste_debito)
            self.AnalizarLiquidacion(aut=self.__ajuste_debito, liq=liq, ajuste=True)
            self.AnalizarAjuste(self.__ajuste_base, base=False)  # datos generales
        return True
291831
public function calculateTotal(Paper $paper)
    {
        $total = 0;

        $structure = json_decode($paper->getStructure(), true);

        foreach ($structure['steps'] as $step) {
            foreach ($step['items'] as $item) {
                if (1 === preg_match('#^application\/x\.[^/]+\+json$#', $item['type'])) {
                    $total += $this->itemManager->calculateTotal($item);
                }
            }
        }

        return $total;
    }