/*
* Copyright (C) 2007 Snorre Gylterud, Stein Magnus Jodal, Johannes Knutsen,
* Erik Bagge Ottesen, Ralf Bjarne Taraldset, and Iterate AS
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*/
package no.ntnu.mmfplanner.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import no.ntnu.mmfplanner.model.Mmf;
import no.ntnu.mmfplanner.model.MmfException;
import no.ntnu.mmfplanner.model.Project;
import no.ntnu.mmfplanner.model.ProjectSorter;
/**
* Helper methods for use by {@link ProjectSorter} classes, as well as helper
* functions for sorting by precursor and pretty sorting swimlanes.
*/
public class ProjectSorterUtil {
/**
* At least try to have some basic logical swimlane placement.
*
* @param project
*/
public static void sortSwimlanes(Project project) {
int maxPeriod = 0;
for (Mmf mmf : project.getMmfs()) {
if (mmf.getPeriod() > maxPeriod) {
maxPeriod = mmf.getPeriod();
}
}
int swimlanePositions[] = new int[maxPeriod];
// Set all initial swimlanePositions to one
for (int i = 0; i < swimlanePositions.length; i++) {
swimlanePositions[i] = 1;
}
ArrayList<Mmf> placedMmf = new ArrayList<Mmf>();
List<Mmf> mmfs = new ArrayList<Mmf>();
for (Mmf mmf : project.getMmfs()) {
if (mmf.getPrecursors().size() == 0) {
mmfs.add(mmf);
}
}
mmfs = sortMmfsByPeriodDesc(mmfs);
Collections.reverse(mmfs);
for (Mmf mmf : mmfs) {
placeStrand(mmf, placedMmf, swimlanePositions, project);
}
}
private static void placeStrand(Mmf mmf, ArrayList<Mmf> placedMmf,
int[] swimlanePositions, Project project) {
List<Mmf> children = new ArrayList<Mmf>();
int max = mmf.getPeriod();
for (Mmf child : project.getMmfs()) {
if (!placedMmf.contains(child)
&& child.getPrecursors().contains(mmf)) {
children.add(child);
if (child.getPeriod() > max) {
max = child.getPeriod();
}
}
}
int swimlane = 1;
for (int i = mmf.getPeriod() - 1; i < max; i++) {
if (swimlanePositions[i] > swimlane) {
swimlane = swimlanePositions[i];
}
}
for (int i = mmf.getPeriod(); i < max; i++) {
swimlanePositions[i] = swimlane;
}
swimlanePositions[mmf.getPeriod() - 1] = swimlane + 1;
children = sortMmfsByPeriodDesc(children);
for (Mmf child : children) {
placeStrand(child, placedMmf, swimlanePositions, project);
for (int i = mmf.getPeriod(); i < child.getPeriod(); i++) {
swimlanePositions[i] = swimlanePositions[child.getPeriod() - 1];
}
}
if ((children.size() > 0)
&& (swimlanePositions[mmf.getPeriod() - 1] == swimlane + 1)) {
swimlane = children.get(0).getSwimlane();
swimlanePositions[mmf.getPeriod() - 1] = swimlane + 1;
}
try {
if (swimlane != mmf.getSwimlane()) {
mmf.setSwimlane(swimlane);
}
placedMmf.add(mmf);
} catch (MmfException e) {
e.printStackTrace();
}
}
/**
* Sort a precursor list descending by the period each mmf should be
* implemented in.
*
* @param prelist List of mmfs to sort
* @return
*/
private static List<Mmf> sortMmfsByPeriodDesc(List<Mmf> prelist) {
if (prelist.size() < 2) {
return prelist;
}
ArrayList<Mmf> sorted = new ArrayList<Mmf>();
for (Mmf aMmf : prelist) {
int i;
for (i = 0; (i < sorted.size())
&& (sorted.get(i).getPeriod() > aMmf.getPeriod()); i++) {
}
sorted.add(i, aMmf);
}
return sorted;
}
public static void sortDependencies(Project project) {
List<Mmf> mmfs = project.getMmfs();
int periods[] = new int[mmfs.size()];
int mmfLengths[] = new int[mmfs.size()];
// find all mmf lengths
for (int i = 0; i < mmfs.size(); i++) {
Mmf mmf = mmfs.get(i);
periods[i] = 1;
mmfLengths[i] = 1;
for (int p = 2; (p <= mmf.getRevenueLength())
&& (mmf.getRevenue(p) < 0); p++) {
mmfLengths[i]++;
}
}
// find periods for all mmfs
boolean modified = true;
while (modified) {
modified = false;
for (int i = 0; i < mmfs.size(); i++) {
Mmf mmf = mmfs.get(i);
if (mmf.isLocked()) {
continue;
}
int maxPeriod = periods[i];
for (Mmf pre : mmf.getPrecursors()) {
int preIdx = mmfs.indexOf(pre);
if (preIdx >= 0) {
maxPeriod = Math.max(maxPeriod, periods[preIdx] + mmfLengths[preIdx]);
}
}
if (maxPeriod > periods[i]) {
periods[i] = maxPeriod;
modified = true;
}
}
}
// update period on all mmfs
for (int i = 0; i < mmfs.size(); i++) {
try {
Mmf mmf = mmfs.get(i);
mmf.setPeriod(periods[i]);
} catch (MmfException e) {
e.printStackTrace();
}
}
}
public static long factorial(long i) {
return (i <= 1 ? 1 : i * factorial(i - 1));
}
}