package scrum.client.sprint;
import ilarkesto.core.scope.Scope;
import ilarkesto.gwt.client.Date;
import ilarkesto.gwt.client.HyperlinkWidget;
import ilarkesto.gwt.client.TimePeriod;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import scrum.client.ScrumGwt;
import scrum.client.admin.Auth;
import scrum.client.admin.User;
import scrum.client.collaboration.ForumSupport;
import scrum.client.collaboration.Wiki;
import scrum.client.common.ReferenceSupport;
import scrum.client.common.ShowEntityAction;
import scrum.client.impediments.Impediment;
import scrum.client.project.Project;
import scrum.client.project.Requirement;
import scrum.client.release.Release;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.Widget;
public class Sprint extends GSprint implements ForumSupport, ReferenceSupport {
public static final String REFERENCE_PREFIX = "spr";
public Sprint(Project project, String label) {
setProject(project);
setLabel(label);
}
public Sprint(Map data) {
super(data);
}
public Integer getLengthInDays() {
Date begin = getBegin();
Date end = getEnd();
if (begin == null || end == null) return null;
return begin.getPeriodTo(end).toDays();
}
public void setLengthInDays(Integer lenght) {
if (lenght == null || lenght <= 0) return;
Date begin = getBegin();
if (begin == null) return;
Date end = begin.addDays(lenght);
setEnd(end);
}
public List<Task> getTasksBlockedBy(Impediment impediment) {
List<Task> ret = new ArrayList<Task>();
for (Requirement requirement : getRequirements()) {
ret.addAll(requirement.getTasksBlockedBy(impediment));
}
return ret;
}
public List<Release> getReleases() {
List<Release> ret = new ArrayList<Release>();
for (Release release : getDao().getReleasesByProject(getProject())) {
if (release.getSprints().contains(this)) ret.add(release);
}
return ret;
}
public String getChartUrl(int width, int height) {
return GWT.getModuleBaseURL() + "sprintBurndownChart.png?sprintId=" + getId() + "&width=" + width + "&height="
+ height;
}
public TimePeriod getLength() {
return getBegin().getPeriodTo(getEnd());
}
public boolean isCompleted() {
return getVelocity() != null;
}
public float getEstimatedRequirementWork() {
float sum = 0;
for (Requirement requirement : getRequirements()) {
Float work = requirement.getEstimatedWork();
if (work != null) sum += work;
}
return sum;
}
public float getCompletedRequirementWork() {
float sum = 0;
for (Requirement requirement : getRequirements()) {
if (!requirement.isClosed()) continue;
Float work = requirement.getEstimatedWork();
if (work != null) sum += work;
}
return sum;
}
public List<Requirement> getDecidableUndecidedRequirements() {
List<Requirement> ret = new ArrayList<Requirement>();
for (Requirement requirement : getRequirements()) {
if (requirement.isDecidable() && !requirement.isClosed()) ret.add(requirement);
}
return ret;
}
public List<Requirement> getRequirements() {
return getDao().getRequirementsBySprint(this);
}
public List<Task> getUnclaimedTasks(boolean sorted) {
List<Task> ret = new ArrayList<Task>();
List<Requirement> requirements = getRequirements();
if (sorted) Collections.sort(requirements, getProject().getRequirementsOrderComparator());
for (Requirement requirement : requirements) {
ret.addAll(requirement.getUnclaimedTasks());
}
return ret;
}
public List<Task> getTasks(User user) {
List<Task> ret = new ArrayList<Task>();
for (Requirement requirement : getRequirements()) {
for (Task task : requirement.getTasks()) {
if (user == null) {
if (!task.isOwnerSet()) {
ret.add(task);
}
} else {
if (task.isOwner(user)) {
ret.add(task);
}
}
}
}
return ret;
}
public int getBurnedWorkInClosedTasks() {
int sum = 0;
for (Requirement requirement : getRequirements()) {
sum += requirement.getBurnedWorkInClosedTasks();
}
return sum;
}
public int getBurnedWork() {
return Requirement.sumBurnedWork(getRequirements());
}
public int getBurnedWorkInClaimedTasks() {
int sum = 0;
for (Requirement requirement : getRequirements()) {
sum += requirement.getBurnedWorkInClaimedTasks();
}
return sum;
}
public int getRemainingWorkInClaimedTasks() {
int sum = 0;
for (Requirement requirement : getRequirements()) {
sum += requirement.getRemainingWorkInClaimedTasks();
}
return sum;
}
public int getRemainingWorkInUnclaimedTasks() {
int sum = 0;
for (Requirement requirement : getRequirements()) {
sum += requirement.getRemainingWorkInUnclaimedTasks();
}
return sum;
}
public int getRemainingWork() {
int sum = 0;
for (Requirement requirement : getRequirements()) {
sum += requirement.getRemainingWork();
}
return sum;
}
@Override
public String toHtml() {
return ScrumGwt.toHtml(getReference(), getLabel());
}
@Override
public String toString() {
return getReference() + " " + getLabel();
}
@Override
public boolean isEditable() {
if (isCompleted()) return false;
if (!getProject().isProductOwner(Scope.get().getComponent(Auth.class).getUser())) return false;
return true;
}
@Override
public boolean isPlanningEditable() {
if (isCompleted()) return false;
return true;
}
@Override
public boolean isRetrospectiveEditable() {
if (!getProject().isScrumMaster(Scope.get().getComponent(Auth.class).getUser())) return false;
return true;
}
@Override
public boolean isReviewEditable() {
if (!getProject().isProductOwner(Scope.get().getComponent(Auth.class).getUser())) return false;
return true;
}
@Override
public boolean isDatesEditable() {
if (isCompleted()) return false;
if (!getProject().isProductOwner(Scope.get().getComponent(Auth.class).getUser())) return false;
return true;
}
@Override
public String getGoalTemplate() {
return Scope.get().getComponent(Wiki.class).getTemplate("sprint.goal");
}
@Override
public String getPlanningNoteTemplate() {
return Scope.get().getComponent(Wiki.class).getTemplate("sprint.planning");
}
@Override
public String getRetrospectiveNoteTemplate() {
return Scope.get().getComponent(Wiki.class).getTemplate("sprint.retrospective");
}
@Override
public String getReviewNoteTemplate() {
return Scope.get().getComponent(Wiki.class).getTemplate("sprint.review");
}
public boolean isCurrent() {
return getProject().isCurrentSprint(this);
}
public static final Comparator<Sprint> END_DATE_COMPARATOR = new Comparator<Sprint>() {
@Override
public int compare(Sprint a, Sprint b) {
return b.getEnd().compareTo(a.getEnd());
}
};
@Override
public Widget createForumItemWidget() {
String label = isCurrent() ? "Sprint Backlog" : "Sprint";
return new HyperlinkWidget(new ShowEntityAction(this, label));
}
@Override
public String getReference() {
return REFERENCE_PREFIX + getNumber();
}
private transient LengthInDaysModel lengthInDaysModel;
public LengthInDaysModel getLengthInDaysModel() {
if (lengthInDaysModel == null) lengthInDaysModel = new LengthInDaysModel();
return lengthInDaysModel;
}
protected class LengthInDaysModel extends ilarkesto.gwt.client.editor.AIntegerEditorModel {
@Override
public String getId() {
return "Sprint_lengthInDays";
}
@Override
public java.lang.Integer getValue() {
return getLengthInDays();
}
@Override
public void setValue(java.lang.Integer value) {
setLengthInDays(value);
}
@Override
public void increment() {
setLengthInDays(getLengthInDays() + 1);
}
@Override
public void decrement() {
setLengthInDays(getLengthInDays() - 1);
}
@Override
public boolean isEditable() {
return Sprint.this.isEditable();
}
@Override
public boolean isMandatory() {
return true;
}
@Override
public String getTooltip() {
return "The lenght of the sprint in days.";
}
@Override
protected void onChangeValue(java.lang.Integer oldValue, java.lang.Integer newValue) {
super.onChangeValue(oldValue, newValue);
addUndo(this, oldValue);
}
}
}