3321 PO Separate reviewers mismatched on language/research area.
Reviewers that can review in all languages will never be mismatched on language. Added a note for projects that have not specified language to communicate with administrators doing assignment why a reviewer is classified as potentially unsuitable.
This commit is contained in:
parent
3836a03b7f
commit
1355dbb92c
core/src
main/java/se/su/dsv/scipro/reviewing
test/java/se/su/dsv/scipro/reviewing
view/src/main/java/se/su/dsv/scipro/admin/pages
@ -7,13 +7,15 @@ import java.util.List;
|
||||
/**
|
||||
* Candidates that can review a project.
|
||||
* @param good reviewers have not met their quota, supervises the language, and matches the projects research area
|
||||
* @param mismatched reviewers have not met their quota, but does not match the projects research area or language
|
||||
* @param wrongResearchArea reviewers have not met their quota, but does not match the projects research area
|
||||
* @param wrongLanguage reviewers have not met their quota, but does not match the projects language
|
||||
* @param busy reviewers that have met their quota
|
||||
* @param unavailable reviewers that are not available
|
||||
*/
|
||||
public record ReviewerCandidates(
|
||||
List<Candidate> good,
|
||||
List<Candidate> mismatched,
|
||||
List<Candidate> wrongResearchArea,
|
||||
List<Candidate> wrongLanguage,
|
||||
List<Candidate> busy,
|
||||
List<Candidate> unavailable)
|
||||
{
|
||||
|
@ -5,6 +5,7 @@ import se.su.dsv.scipro.project.Project;
|
||||
import se.su.dsv.scipro.project.ProjectService;
|
||||
import se.su.dsv.scipro.project.ReviewerAssignedEvent;
|
||||
import se.su.dsv.scipro.security.auth.roles.Roles;
|
||||
import se.su.dsv.scipro.system.Language;
|
||||
import se.su.dsv.scipro.system.Unit;
|
||||
import se.su.dsv.scipro.system.User;
|
||||
import se.su.dsv.scipro.system.UserService;
|
||||
@ -15,6 +16,7 @@ import java.time.Month;
|
||||
import java.time.Year;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
@ -132,7 +134,8 @@ class ReviewerCapacityServiceImpl implements ReviewerCapacityService, ReviewerAs
|
||||
List<User> reviewers = userService.findActiveReviewers();
|
||||
|
||||
List<ReviewerCandidates.Candidate> good = new ArrayList<>();
|
||||
List<ReviewerCandidates.Candidate> mismatched = new ArrayList<>();
|
||||
List<ReviewerCandidates.Candidate> wrongLanguage = new ArrayList<>();
|
||||
List<ReviewerCandidates.Candidate> wrongResearchArea = new ArrayList<>();
|
||||
List<ReviewerCandidates.Candidate> busy = new ArrayList<>();
|
||||
List<ReviewerCandidates.Candidate> unavailable = new ArrayList<>();
|
||||
for (User reviewer : reviewers) {
|
||||
@ -144,13 +147,17 @@ class ReviewerCapacityServiceImpl implements ReviewerCapacityService, ReviewerAs
|
||||
|
||||
if (target > 0) {
|
||||
if (assigned < target) {
|
||||
boolean canSuperviseProjectsLanguage = reviewer.getLanguages().contains(project.getLanguage());
|
||||
boolean canReviewAllLanguages = reviewer.getLanguages().containsAll(EnumSet.allOf(Language.class));
|
||||
boolean canSuperviseProjectsLanguage = canReviewAllLanguages || reviewer.getLanguages().contains(project.getLanguage());
|
||||
boolean matchingResearchArea = reviewer.getResearchAreas().contains(project.getResearchArea());
|
||||
if (canSuperviseProjectsLanguage && matchingResearchArea) {
|
||||
good.add(candidate);
|
||||
}
|
||||
else {
|
||||
mismatched.add(candidate);
|
||||
else if (!canSuperviseProjectsLanguage) {
|
||||
wrongLanguage.add(candidate);
|
||||
}
|
||||
else if (!matchingResearchArea) {
|
||||
wrongResearchArea.add(candidate);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -162,7 +169,7 @@ class ReviewerCapacityServiceImpl implements ReviewerCapacityService, ReviewerAs
|
||||
}
|
||||
}
|
||||
|
||||
return new ReviewerCandidates(good, mismatched, busy, unavailable);
|
||||
return new ReviewerCandidates(good, wrongResearchArea, wrongLanguage, busy, unavailable);
|
||||
}
|
||||
|
||||
private int getPeriodTarget(ReviewerTarget reviewerTarget, LocalDate date) {
|
||||
|
@ -91,7 +91,7 @@ class ReviewerCapacityServiceImplTest extends IntegrationTest {
|
||||
ReviewerCandidates candidates = service.getCandidatesToReview(project, SOME_DATE_IN_AUTUMN);
|
||||
|
||||
// then
|
||||
assertTrue(candidates.mismatched().stream().anyMatch(c -> c.reviewer().equals(reviewer)));
|
||||
assertTrue(candidates.wrongLanguage().stream().anyMatch(c -> c.reviewer().equals(reviewer)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -105,7 +105,7 @@ class ReviewerCapacityServiceImplTest extends IntegrationTest {
|
||||
ReviewerCandidates candidates = service.getCandidatesToReview(project, SOME_DATE_IN_SPRING);
|
||||
|
||||
// then
|
||||
assertTrue(candidates.mismatched().stream().anyMatch(c -> c.reviewer().equals(reviewer)));
|
||||
assertTrue(candidates.wrongResearchArea().stream().anyMatch(c -> c.reviewer().equals(reviewer)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -137,6 +137,21 @@ class ReviewerCapacityServiceImplTest extends IntegrationTest {
|
||||
assertEquals(2, candidates);
|
||||
}
|
||||
|
||||
@Test
|
||||
void a_reviewer_that_can_review_all_languages_is_suitable_even_if_no_language_is_set_on_the_project() {
|
||||
// given
|
||||
reviewer.setLanguages(EnumSet.allOf(Language.class));
|
||||
reviewer.addResearchArea(researchArea);
|
||||
project.setLanguage(null);
|
||||
service.assignTarget(reviewer, springTarget(1));
|
||||
|
||||
// when
|
||||
ReviewerCandidates candidates = service.getCandidatesToReview(project, SOME_DATE_IN_SPRING);
|
||||
|
||||
// then
|
||||
assertTrue(candidates.good().stream().anyMatch(c -> c.reviewer().equals(reviewer)));
|
||||
}
|
||||
|
||||
private static Target springTarget(final int target) {
|
||||
return new Target(YEAR_2024, target, 0, "");
|
||||
}
|
||||
|
@ -36,12 +36,26 @@
|
||||
</div>
|
||||
</wicket:enclosure>
|
||||
|
||||
<wicket:enclosure child="mismatched_candidates">
|
||||
<h3>Mismatched candidates</h3>
|
||||
<wicket:enclosure child="wrong_research_area">
|
||||
<h3>Unsuitable due to research area</h3>
|
||||
<p>
|
||||
These reviewers have not met their review quota, but their language or research areas does not match the project's.
|
||||
These reviewers have not met their review quota, but their research areas does not match the project's.
|
||||
</p>
|
||||
<div class="card bg-warning bg-opacity-50 mb-3" wicket:id="mismatched_candidates">
|
||||
<div class="card bg-warning bg-opacity-50 mb-3" wicket:id="wrong_research_area">
|
||||
<wicket:container wicket:id="details"/>
|
||||
</div>
|
||||
</wicket:enclosure>
|
||||
|
||||
<wicket:enclosure child="wrong_language">
|
||||
<h3>Unsuitable due to language</h3>
|
||||
<p>
|
||||
These reviewers have not met their review quota, but they cannot supervise in the thesis language.
|
||||
</p>
|
||||
<p class="alert alert-warning" wicket:id="no_language_set">
|
||||
The language of the thesis has not been specified. SciPro can not determine if the reviewer is
|
||||
suitable or not and therefore classifies them as unsuitable.
|
||||
</p>
|
||||
<div class="card bg-danger text-white opacity-50 mb-3" wicket:id="wrong_language">
|
||||
<wicket:container wicket:id="details"/>
|
||||
</div>
|
||||
</wicket:enclosure>
|
||||
|
@ -94,7 +94,20 @@ public class AdminAssignReviewerPage extends AbstractAdminProjectPage {
|
||||
item.add(new ReviewerCard("details", item.getModel()));
|
||||
}
|
||||
});
|
||||
add(new AutoHidingListView<>("mismatched_candidates", reviewerCandidates.map(ReviewerCandidates::mismatched)) {
|
||||
add(new AutoHidingListView<>("wrong_research_area", reviewerCandidates.map(ReviewerCandidates::wrongResearchArea)) {
|
||||
@Override
|
||||
protected void populateItem(ListItem<ReviewerCandidates.Candidate> item) {
|
||||
item.add(new ReviewerCard("details", item.getModel()));
|
||||
}
|
||||
});
|
||||
add(new WebMarkupContainer("no_language_set") {
|
||||
@Override
|
||||
protected void onConfigure() {
|
||||
super.onConfigure();
|
||||
setVisible(projectModel.getObject().getLanguage() == null);
|
||||
}
|
||||
});
|
||||
add(new AutoHidingListView<>("wrong_language", reviewerCandidates.map(ReviewerCandidates::wrongLanguage)) {
|
||||
@Override
|
||||
protected void populateItem(ListItem<ReviewerCandidates.Candidate> item) {
|
||||
item.add(new ReviewerCard("details", item.getModel()));
|
||||
|
Loading…
x
Reference in New Issue
Block a user