Skip to content

Commit

Permalink
SAM-3239 changing parts and items reordering process (sakaiproject#5179)
Browse files Browse the repository at this point in the history
  • Loading branch information
bgarciaentornos authored and ottenhoff committed Jan 12, 2018
1 parent e307e43 commit 21cff91
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,7 @@ matrix_width_list_8=80% row choices column/20% column choices column
matrix_width_list_9=90% row choices column/10% column choices column

edit_fib_warning=Please note that adding, removing or modifying the blanks can lead to scoring discrepancies when existing submissions are automatically regraded. For editing this type of question, you should allow resubmission.

edit_order_warning=You may have assigned the same destination position to several parts or questions. The result of the ordering has been modified.

tag_title=Tags
tag_previous=Tags added previously to the question
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,7 @@ matrix_width_list_8=80% columna de las filas de opciones/20% columna de las colu
matrix_width_list_9=90% columna de las filas de opciones/10% columna de las columnas de opciones

edit_fib_warning=Por favor, tenga en cuenta que si elimina o modifica los espacios en blanco puede obtener discrepancias de correcci\u00f3n cuando los ex\u00e1menes ya realizados sean corregidos de nuevo. Para editar este tipo de pregunta deber\u00eda permitir al alumnado que puedan reenviar el examen.

edit_order_warning=El usuario ha asignado la misma posici\u00f3n destino a varias partes o preguntas. El resultado de la ordenaci\u00f3n se ha modificado para evitarlo. Por favor, compru\u00e9belo de nuevo.

tag_title=Etiquetas
tag_previous=Etiquetas a\u00f1adidas anteriormente a la pregunta
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;
Expand All @@ -45,8 +48,13 @@ public class UpdateAssessmentQuestionsOrder implements ActionListener {
AssessmentService assessdelegate;
PublishedAssessmentService publisheddelegate;

int controlP = 1;
int controlQ = 1;

public void processAction(ActionEvent ae) throws AbortProcessingException {

FacesContext context = FacesContext.getCurrentInstance();

AuthorBean author = (AuthorBean) ContextUtil.lookupBean("author");
delegate = new ItemService();

Expand All @@ -64,125 +72,137 @@ public void processAction(ActionEvent ae) throws AbortProcessingException {
assessdelegate = new AssessmentService();
}

reorderItems(published);
if(reorderItems(published)){
String err=(String)ContextUtil.getLocalizedString("org.sakaiproject.tool.assessment.bundle.AuthorMessages", "edit_order_warning");
context.addMessage(null,new FacesMessage(err));
}

assessmentBean.setAssessment(published ? publisheddelegate.getAssessment(assessmentBean.getAssessmentId())
: assessdelegate.getAssessment(assessmentBean.getAssessmentId()));
}

public void reorderItems(boolean published) {
public boolean reorderItems(boolean published) {
AssessmentBean assessmentBean = (AssessmentBean) ContextUtil
.lookupBean("assessmentBean");

Map<Integer,Integer> swapSections = new HashMap<>();

Map<Integer,SectionFacade> sections = new HashMap<>();

Map<Integer,Long> changedSections = new HashMap<>();
int sectionsNum = assessmentBean.getSections().size();
boolean duplicated = false;

//first loop, update parts changed by the instructor
for(SectionContentsBean curSection : assessmentBean.getSections()) {

SectionFacade sectFc = published ?
(PublishedSectionFacade) publisheddelegate.getSection(curSection.getSectionId()) :
(SectionFacade) assessdelegate.getSection(curSection.getSectionId());
boolean dirty = false;

Integer sectionNumber = Integer.valueOf(curSection.getNumber());
Integer secVal = swapSections.get(sectionNumber);
if(sectionNumber != sectFc.getSequence()) {
SectionFacade sec = sections.get(sectionNumber);
if(sec != null) {
sec.setSequence(sectFc.getSequence());
swapSections.put(sec.getSequence(), sectFc.getSequence());
if(changedSections.get(sectionNumber) != null){
//there are several parts with the same new section number, change only the first
duplicated = true;
sections.put(sectFc.getSequence(), sectFc);
} else {
//position has changed, prioritize this value
sectFc.setSequence(sectionNumber);
changedSections.put(sectionNumber, sectFc.getSectionId());
if(published) {
publisheddelegate.saveOrUpdateSection(sec);
publisheddelegate.saveOrUpdateSection(sectFc);
} else {
assessdelegate.saveOrUpdateSection(sec);
assessdelegate.saveOrUpdateSection(sectFc);
}
}
int val = sectionNumber;
swapSections.put(val,sectFc.getSequence());
sectFc.setSequence(val);
dirty = true;
} else if (secVal != null) {
// previous swap, change values
swapSections.put(sectFc.getSequence(),secVal);
sectFc.setSequence(secVal);
dirty = true;
} else {
//position not changed, adding to aux map
sections.put(sectFc.getSequence(), sectFc);
}
if(dirty) {
if(published) {
publisheddelegate.saveOrUpdateSection(sectFc);
} else {
assessdelegate.saveOrUpdateSection(sectFc);
}

//second loop, fill the gaps
IntStream.range(1, sectionsNum+1).forEach(
nbr -> {
if(changedSections.get(nbr) == null){
SectionFacade sectFc = null;
for(int i = controlP; i <= sectionsNum; i++){
if(sections.get(i) != null){
//taking first section left from the not changed map
sectFc = sections.get(i);
sectFc.setSequence(nbr);
controlP = i+1;
if(published) {
publisheddelegate.saveOrUpdateSection(sectFc);
} else {
assessdelegate.saveOrUpdateSection(sectFc);
}
break;
}
}
}
}
sections.put(sectFc.getSequence(), sectFc);
}
);

sections.clear();
swapSections.clear();
updateItemsOrder(assessmentBean);
changedSections.clear();
boolean duplicatedQ = updateItemsOrder(assessmentBean);
return (duplicated) ? duplicated : duplicatedQ;
}

private void updateItemsOrder(AssessmentBean assessmentbean) {
private boolean updateItemsOrder(AssessmentBean assessmentbean) {

boolean duplicated = false;
for(SectionContentsBean curSection : assessmentbean.getSections()) {

int numberOfItems = curSection.getQuestions();

Map<Integer,Integer> swapItems = new HashMap<>();
controlQ = 1;
Map<Integer,Long> changedItems = new HashMap<>();
Map<Integer,ItemFacade> sectionItems = new HashMap<>();

for(ItemContentsBean icb : (List<ItemContentsBean>)curSection.getItemContents()) {
boolean dirty = false;
ItemData curItem = (ItemData) (icb).getItemData();
ItemFacade itemFc = delegate.getItem(String.valueOf(curItem.getItemId()));
int curSequence = curItem.getSequence();
Integer t = swapItems.get(curSequence);
if(curSequence != itemFc.getData().getSequence()) {
swapItems.put(curSequence, itemFc.getData().getSequence());
itemFc.getData().setSequence(curSequence);
itemFc.setSequence(curSequence);
dirty = true;
// deal retroactively
ItemFacade it = sectionItems.get(curSequence);
// change already found items
if(it != null) {
int val = itemFc.getSequence();
// if the position was taken by any other value, swap it for the previous change, prioritize latest change
int control = 0;
// cascade through items until we find an empty one
t = swapItems.get(val);
if(t != null) {
do {
val = swapItems.get(val);
control++;
} while(swapItems.get(val) != null && control <= numberOfItems);
}
it.setSequence(val);
swapItems.put(val, curSequence); // replace latest
sectionItems.put(it.getSequence(), it);
delegate.saveItem(it);
}
} else if (t != null) {
int val = swapItems.get(curSequence);
// do not duplicate, cascade through until and empty one has been found
int control = 0;
t = swapItems.get(val);
if(t != null) {
// loop until no items was swapped with that number
do {
val = swapItems.get(val);
control++;
} while(swapItems.get(val) != null && control <= numberOfItems);

Integer curSequence = curItem.getSequence();
if(curSequence != itemFc.getData().getSequence()) {
if(changedItems.get(curSequence) != null){
//there are several items with the same new section number, change only the first
duplicated = true;
sectionItems.put(itemFc.getSequence(), itemFc);
} else {
//position has changed, prioritize this value
itemFc.getData().setSequence(curSequence);
itemFc.setSequence(curSequence);
changedItems.put(curSequence, itemFc.getItemId());
delegate.saveItem(itemFc);
}
swapItems.put(val, itemFc.getSequence());
itemFc.setSequence(val);
dirty = true;
}
if(dirty) {
delegate.saveItem(itemFc);
} else {
//position not changed, adding to aux map
sectionItems.put(itemFc.getSequence(), itemFc);
}
sectionItems.put(itemFc.getSequence(), itemFc);
}
swapItems.clear();

//second loop, fill the gaps
IntStream.range(1, numberOfItems+1).forEach(
nbr -> {
if(changedItems.get(nbr) == null){
ItemFacade itemFc = null;
for(int i = controlQ; i <= numberOfItems; i++){
if(sectionItems.get(i) != null){
//taking first section left from the not changed map
itemFc = sectionItems.get(i);
itemFc.setSequence(nbr);
controlQ = i+1;
delegate.saveItem(itemFc);
break;
}
}
}
}
);

changedItems.clear();
sectionItems.clear();
}
return duplicated;
}
}

0 comments on commit 21cff91

Please sign in to comment.