<commit_before>package org.xcolab.view.pages.profile.beans;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.xcolab.client.contest.ContestClientUtil;
import org.xcolab.client.contest.exceptions.ContestNotFoundException;
import org.xcolab.client.contest.pojo.Contest;
import org.xcolab.client.contest.pojo.phases.ContestPhase;
import org.xcolab.client.contest.pojo.phases.ContestPhaseRibbonType;
import org.xcolab.client.proposals.ProposalAttributeClientUtil;
import org.xcolab.client.proposals.ProposalClientUtil;
import org.xcolab.client.proposals.ProposalPhaseClientUtil;
import org.xcolab.client.proposals.enums.ProposalAttributeKeys;
import org.xcolab.client.proposals.pojo.Proposal;
import org.xcolab.client.proposals.pojo.phases.ProposalContestPhaseAttribute;
import org.xcolab.util.enums.contest.ProposalContestPhaseAttributeKeys;
import org.xcolab.view.pages.profile.entity.Badge;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class BadgeBean implements Serializable {

    private static final long serialVersionUID = 1L;
    private final static Logger _log = LoggerFactory.getLogger(BadgeBean.class);
    private final long userId;
    private final List<Badge> badges;

    public BadgeBean(long userId) {
        this.userId = userId;
        badges = new ArrayList<>();
        fetchBadges();
    }

    private void fetchBadges() {
        for(Proposal p : ProposalClientUtil.getMemberProposals(userId)) {
            try {
                final ContestPhaseRibbonType ribbonType = getRibbonType(p);

                if (ribbonType != null  && ribbonType.getRibbon() > 0) {
                    Contest contest = ProposalClientUtil.getCurrentContestForProposal(p.getProposalId());
                    String proposalTitle = ProposalAttributeClientUtil
                            .getProposalAttribute(p.getProposalId(), ProposalAttributeKeys.NAME, 0L)
                            .getStringValue();
                    badges.add(new Badge(ribbonType, p, proposalTitle, contest));
                }
            } catch (ContestNotFoundException e) {
                _log.warn("Could not add badge to user profile view for userId: {} and proposalId: {}",
                        p.getProposalId(), e);
            }
        }
    }

    private ContestPhaseRibbonType getRibbonType(Proposal p) {
        ContestPhaseRibbonType contestPhaseRibbonType = null;
        List<Long> phasesForProposal = ProposalPhaseClientUtil.getContestPhasesForProposal(p.getProposalId());

        Date phaseStartDate = p.getCreateDate();
        for (Long phaseId : phasesForProposal) {
            final ProposalContestPhaseAttribute ribbonAttribute =
                    ProposalPhaseClientUtil.getProposalContestPhaseAttribute(p.getProposalId(),
                            phaseId, ProposalContestPhaseAttributeKeys.RIBBON);
            if (ribbonAttribute != null) {
                long typeId = ribbonAttribute.getNumericValue();

                ContestPhase contestPhase = ContestClientUtil.getContestPhase(phaseId);

                //if there are several phases with ribbons, the latest takes precedence
                if (!phaseStartDate.after(contestPhase.getPhaseStartDateDt())) {
                    contestPhaseRibbonType = ContestClientUtil.getContestPhaseRibbonType(typeId);
                    phaseStartDate = contestPhase.getPhaseStartDateDt();
                }
            }
        }

        return contestPhaseRibbonType;<commit_msg>[COLAB-2519] Fix retrieval of ribbon year<commit_after>package org.xcolab.view.pages.profile.beans;

import org.xcolab.client.contest.ContestClientUtil;
import org.xcolab.client.contest.pojo.phases.ContestPhase;
import org.xcolab.client.contest.pojo.phases.ContestPhaseRibbonType;
import org.xcolab.client.proposals.ProposalClientUtil;
import org.xcolab.client.proposals.ProposalPhaseClientUtil;
import org.xcolab.client.proposals.pojo.Proposal;
import org.xcolab.client.proposals.pojo.phases.ProposalContestPhaseAttribute;
import org.xcolab.util.enums.contest.ProposalContestPhaseAttributeKeys;
import org.xcolab.view.pages.profile.entity.Badge;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;

public class BadgeBean implements Serializable {

    private static final long serialVersionUID = 1L;

    private final List<Badge> badges = new ArrayList<>();

    public BadgeBean(long userId) {
        populateBadges(userId);
    }

    private void populateBadges(long userId) {
        for (Proposal proposal : ProposalClientUtil.getMemberProposals(userId)) {
            getRibbonAttribute(proposal)
                    .ifPresent(ribbonAttribute -> {
                        final ContestPhaseRibbonType ribbonType = ContestClientUtil
                                .getContestPhaseRibbonType(ribbonAttribute.getNumericValue());

                        if (ribbonType.getRibbon() > 0) {
                            final ContestPhase phase = ContestClientUtil.getContestPhase(
                                    ribbonAttribute.getContestPhaseId());
                            badges.add(new Badge(ribbonType, proposal, proposal.getName(),
                                    phase.getContest()));
                        }
                    });
        }
    }

    private Optional<ProposalContestPhaseAttribute> getRibbonAttribute(Proposal proposal) {
        List<Long> phasesForProposal = ProposalPhaseClientUtil.getContestPhasesForProposal(
                proposal.getProposalId());
        return phasesForProposal.stream()
                .map(getRibbonAttributeFunction(proposal.getProposalId()))
                .filter(Objects::nonNull)
                .max(getStartDateComparator());
    }

    private Comparator<ProposalContestPhaseAttribute> getStartDateComparator() {
        return Comparator.comparing(attribute -> ContestClientUtil
                .getContestPhase(attribute.getContestPhaseId()).getPhaseStartDateDt());
    }

    private Function<Long, ProposalContestPhaseAttribute> getRibbonAttributeFunction(
            Long proposalId) {
        return phaseId -> ProposalPhaseClientUtil
                .getProposalContestPhaseAttribute(proposalId, phaseId,
                        ProposalContestPhaseAttributeKeys.RIBBON);
{'fraction_non_alphanumeric': 0.08288148721920992, 'fraction_numerical': 0.0017041053446940357, 'mean_word_length': 2.8589360430364614, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5045181', 'n_tokens_mistral': 1839, 'n_tokens_neox': 1776, 'n_words': 292}