package fi.utu.ville.exercises.template; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import com.vaadin.server.Resource; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; import com.vaadin.ui.Component; import com.vaadin.ui.Image; import com.vaadin.ui.Label; import com.vaadin.ui.Notification; import com.vaadin.ui.Table; import com.vaadin.ui.TextField; import com.vaadin.ui.VerticalLayout; import fi.utu.ville.exercises.helpers.StatSubmInfoFilterEditor; import fi.utu.ville.exercises.helpers.StatSubmInfoFilterEditor.FilterEditor; import fi.utu.ville.exercises.helpers.StatSubmInfoFilterEditor.FilterEditorFactory; import fi.utu.ville.exercises.helpers.StatSubmInfoFilterTable; import fi.utu.ville.exercises.helpers.StatSubmInfoFilterTable.ShowSubmissionColGenerator; import fi.utu.ville.exercises.helpers.StatSubmInfoFilterTable.SubmInfoColumnGenerator; import fi.utu.ville.exercises.helpers.StatsGiverHelper.BySubmMatcher; import fi.utu.ville.exercises.helpers.StatsGiverHelper.SubmMatcher; import fi.utu.ville.exercises.model.ExerciseException; import fi.utu.ville.exercises.model.StatisticalSubmissionInfo; import fi.utu.ville.exercises.model.StatisticsInfoColumn; import fi.utu.ville.exercises.model.SubmissionStatisticsGiver; import fi.utu.ville.standardutils.Localizer; import fi.utu.ville.standardutils.StandardUIConstants; import fi.utu.ville.standardutils.StandardUIFactory; import fi.utu.ville.standardutils.TempFilesManager; public class TemplateSubmissionStatisticsGiver extends VerticalLayout implements SubmissionStatisticsGiver<TemplateExerciseData, TemplateSubmissionInfo> { /** * */ private static final long serialVersionUID = -1410253605264134011L; private List<StatisticalSubmissionInfo<TemplateSubmissionInfo>> data; private TemplateExerciseData exer; private StatSubmInfoFilterTable<TemplateSubmissionInfo> genTable; private StatSubmInfoFilterEditor<TemplateSubmissionInfo> genTableEditor; private final VerticalLayout answFreqView = new VerticalLayout(); private Localizer localizer; @Override public void initialize( TemplateExerciseData exercise, List<StatisticalSubmissionInfo<TemplateSubmissionInfo>> dataObjects, Localizer localizer, TempFilesManager tempManager) throws ExerciseException { exer = exercise; data = dataObjects; this.localizer = localizer; System.out.println("data: " + data); initAllSubmissionsTable(); doLayout(); } private static class AnswerColGen implements SubmInfoColumnGenerator<String, TemplateSubmissionInfo> { @Override public String getColumnHeader(Localizer localizer) { return localizer.getUIText(StandardUIConstants.ANSWER); } @Override public String getColumnDescription(Localizer localizer) { return localizer.getUIText(TemplateUiConstants.ANSWER_COL_DESC); } @Override public String getDefaultValue() { return null; } @Override public Class<String> getColumnDataType() { return String.class; } @Override public String getColValueFor( StatisticalSubmissionInfo<TemplateSubmissionInfo> statSubmInfo, Localizer localizer) { return statSubmInfo.getSubmissionData().getAnswer(); } @Override public boolean isExportable() { return true; } } private void initAllSubmissionsTable() { List<SubmInfoColumnGenerator<?, TemplateSubmissionInfo>> extraCols = new ArrayList<SubmInfoColumnGenerator<?, TemplateSubmissionInfo>>(); extraCols.add(new AnswerColGen()); // using null for temp-files-manager is safe here as it is known // that TemplateSubmissionViewer does not need TempFilesManager; // though it would not hurt to pass the real TempFilesManager anyway extraCols .add(new ShowSubmissionColGenerator<TemplateExerciseData, TemplateSubmissionInfo>( TemplateTypeDescriptor.INSTANCE, exer, null)); genTable = new StatSubmInfoFilterTable<TemplateSubmissionInfo>( localizer, data, extraCols); List<FilterEditorFactory<TemplateSubmissionInfo>> extras = new ArrayList<FilterEditorFactory<TemplateSubmissionInfo>>(); extras.add(new AnswerLengthFilterEditor(localizer)); genTableEditor = new StatSubmInfoFilterEditor<TemplateSubmissionInfo>( genTable, localizer, extras); } private Table getAnswerLengthFreqTable() { Table res = new Table("Answer-length frequencies"); res.addContainerProperty("Length", Integer.class, null); res.addContainerProperty("Frequency", Integer.class, null); for (Entry<Integer, Integer> freq : getAnswerLengthFrequencies() .entrySet()) { System.out.println("Adding to ans-freq table: " + freq.getKey() + freq.getValue()); res.addItem(new Object[] { freq.getKey(), freq.getValue() }, null); } return res; } private Map<Integer, Integer> getAnswerLengthFrequencies() { Map<Integer, Integer> res = new HashMap<Integer, Integer>(); for (StatisticalSubmissionInfo<TemplateSubmissionInfo> statSubmInf : genTable .getSelectedInfos()) { int answerLength = statSubmInf.getSubmissionData().getAnswer() .length(); Integer currValue = res.get(answerLength); int newValue; if (currValue != null) { newValue = currValue + 1; } else { newValue = 1; } res.put(answerLength, newValue); } return res; } private void doLayout() { this.setWidth("100%"); VerticalLayout centeredLayout = new VerticalLayout(); centeredLayout.setWidth("800px"); Label questionLabel = new Label("Question: " + exer.getQuestion()); questionLabel.addStyleName("template-exercise-title"); centeredLayout.addComponent(questionLabel); centeredLayout.addComponent(genTableEditor.getView()); centeredLayout.addComponent(genTable.getStatInfoTableView()); Button drawAnswLengthTableBtn = StandardUIFactory.getButton( "Draw freq-table", null); drawAnswLengthTableBtn.addClickListener(new ClickListener() { /** * */ private static final long serialVersionUID = -1254314606936710857L; @Override public void buttonClick(ClickEvent event) { answFreqView.removeAllComponents(); answFreqView.addComponent(getAnswerLengthFreqTable()); } }); centeredLayout.addComponent(drawAnswLengthTableBtn); centeredLayout.addComponent(answFreqView); this.addComponent(centeredLayout); setComponentAlignment(centeredLayout, Alignment.TOP_CENTER); } @Override public Component getView() { return this; } private static class AnswerLengthFilter implements SubmMatcher<TemplateSubmissionInfo> { private final int minLength; private final int maxLength; public AnswerLengthFilter(int minLength, int maxLength) { this.maxLength = maxLength; this.minLength = minLength; } @Override public boolean matches(TemplateSubmissionInfo toTest) { int answLength = toTest.getAnswer().length(); return answLength <= maxLength && answLength >= minLength; } } private static class AnswerLengthFilterEditor implements FilterEditor<TemplateSubmissionInfo>, FilterEditorFactory<TemplateSubmissionInfo> { private final TextField min; private final TextField max; private final Localizer localizer; public AnswerLengthFilterEditor(Localizer localizer) { this.localizer = localizer; min = new TextField(); max = new TextField(); } @Override public AnswerLengthFilterEditor newEditorInstance(Localizer localizer) { return new AnswerLengthFilterEditor(localizer); } @Override public String getFilterDesc(Localizer localizer) { return "answer-length-range-editor"; } @Override public String getFilterName(Localizer localizer) { return "answer-length-range-editor"; } @Override public Resource getFilterIcon() { return null; // return StandardIcon.CALCULATOR_MEDIUM.getIcon(); } @Override public BySubmMatcher<TemplateSubmissionInfo> getFilter() { return new BySubmMatcher<TemplateSubmissionInfo>( new AnswerLengthFilter(getMin(), getMax())); } private int getMin() { String val = min.getValue(); if (val.length() == 0) { return 0; } else { return Integer.parseInt(val); } } private int getMax() { String val = max.getValue(); if (val.length() == 0) { return 0; } else { return Integer.parseInt(val); } } @Override public Component getFilterEditView() { VerticalLayout res = new VerticalLayout(); res.addComponent(new Label("min")); res.addComponent(min); res.addComponent(new Label("max")); res.addComponent(max); return res; } @Override public Component getMinifiedView() { Image img = new Image(); img.setSource(getFilterIcon()); img.setDescription(getFilterStateDesc()); return img; } @Override public AnswerLengthFilterEditor getCopy() { AnswerLengthFilterEditor res = new AnswerLengthFilterEditor( localizer); res.min.setValue(getMin() + ""); res.max.setValue(getMax() + ""); return res; } @Override public String getFilterStateDesc() { return getFilterName(localizer) + ": from " + getMin() + " to " + getMax(); } @Override public boolean checkAndNotify() { if (getMin() <= getMax()) { return true; } else { Notification.show("Max must be at least equal to min!"); return false; } } } @Override public List<StatisticsInfoColumn<?>> getAsTabularData() { return genTable.exportByColGenTitle(Collections.singletonList(localizer .getUIText(StandardUIConstants.ANSWER))); } }