/*
* Copyright 2004-2010 Information & Software Engineering Group (188/1)
* Institute of Software Technology and Interactive Systems
* Vienna University of Technology, Austria
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.ifs.tuwien.ac.at/dm/somtoolbox/license.html
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package at.tuwien.ifs.somtoolbox.reportgenerator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
/**
* @author Martin Waitzbauer (0226025)
* @version $Id: SemanticClass.java 3888 2010-11-02 17:42:53Z frank $
*/
@SuppressWarnings("rawtypes")
public class SemanticClass {
public int index;
public String Report = null;
public int[] CenterPoint;
public int SharedClasses = 0;
public ArrayList<SemanticNode> SemanticNodes = new ArrayList<SemanticNode>();
private ArrayList<int[]> UnitswithClassList = new ArrayList<int[]>();
public ArrayList<int[]> ClassPartitions = new ArrayList<int[]>();
public ArrayList ConnectedClasses = new ArrayList();
public int[] regionmix;
public double[] concentrationmix;
public int MemberCount = 0;
private ArrayList<SemanticNode> EdgeNodes = null;
// private double Spread =0.0;
private double Compactness = 0.0;
public SemanticClass(int index, ArrayList<int[]> UnitswithClassList) {
this.index = index;
this.UnitswithClassList = UnitswithClassList;
}
public ArrayList QMIntersectionClassArrayListMAX = new ArrayList();
public ArrayList QMIntersectionClassArrayListMIN = new ArrayList();
public void setMeanPoint(int[] mp) {
this.CenterPoint = mp;
}
/*
* public void setClassPartitions(ArrayList ClassPartitions){ this.ClassPartitions = ClassPartitions; this.Spread =
* UnitswithClassList.size()/ClassPartitions.size(); }
*/
/**
* Lists all different partitions of the class (a Partition is consicered a connected Area of units with no more
* than 1 as distance between each unit)
*/
public void calculateClassPartitions() {
HashMap<String, int[]> result = new HashMap<String, int[]>();
for (int i = 0; i < UnitswithClassList.size(); i++) {
ArrayList<Integer> trail = getTrail(i, new ArrayList<Integer>()); // Gets the trail, since there are
// manyequal
// trails, only keep unique trails
int[] tempTrail = new int[trail.size()];
for (int j = 0; j < trail.size(); j++) {
tempTrail[j] = trail.get(j);
}
Arrays.sort(tempTrail);
String key = "";
for (int element : tempTrail) {
key += element;
}
if (!result.containsKey(key)) {
result.put(key, tempTrail);
}
}
Collection<int[]> col = result.values();
this.ClassPartitions = new ArrayList<int[]>(col);
// this.Spread = (double)UnitswithClassList.size()/(double)ClassPartitions.size();
}
/** Finds a Trail for unit i through the class (all units with distance 1 will be added to one trail) */
private ArrayList<Integer> getTrail(int i, ArrayList<Integer> trail) {
int[] N1 = UnitswithClassList.get(i);
if (!trail.contains(i)) {
trail.add(i);
}
for (int h = 0; h < UnitswithClassList.size(); h++) {
int[] N2 = UnitswithClassList.get(h);
if (!N1.equals(N2)) {
int[] temp = SemanticInterpreterGrid.getDistance(N1, N2);
if (Math.abs(temp[0]) <= 1 && Math.abs(temp[1]) <= 1 && !trail.contains(h)) {
trail = getTrail(h, trail);
}
}
}
return trail;
}
/**
* Calculates How much of the class units lie in a radius around the middle point ( this radius is the mean over all
* distances from the middle point to other class points)
*/
public void calculateCompactness() {
double distance = 0.0;
for (int i = 0; i < this.UnitswithClassList.size(); i++) {
int[] temp = SemanticInterpreterGrid.getDistance(CenterPoint, UnitswithClassList.get(i));
distance += Math.abs((double) temp[0]) + Math.abs((double) temp[1]);
}
distance = Math.round(distance / UnitswithClassList.size() / 2);
double UnitsWithinRange = 0.0;
for (int i = 0; i < this.UnitswithClassList.size(); i++) {
int[] temp = SemanticInterpreterGrid.getDistance(CenterPoint, UnitswithClassList.get(i));
if (Math.abs((double) temp[0]) <= distance && Math.abs((double) temp[1]) <= distance) {
UnitsWithinRange++;
}
}
this.Compactness = UnitsWithinRange / this.UnitswithClassList.size();
}
/** calculates the point with the most distance to the class centre */
public int[] getFurthestMember() {
int max = Integer.MIN_VALUE;
int[] result = new int[2];
for (int i = 0; i < this.UnitswithClassList.size(); i++) {
int temp[] = UnitswithClassList.get(i);
int point[] = SemanticInterpreterGrid.getDistance(this.CenterPoint, temp);
int distance = Math.abs(point[0]) + Math.abs(point[1]);
if (max < distance) {
max = distance;
result = temp;
}
}
return result;
}
public void setReport(String rep) {
this.Report = rep;
}
/**
* Returns an ArrayList containing directions of the Units given in the ArrayList, measured to the Center of the
* Class
*/
public ArrayList<String> getIntersectionDirections(ArrayList l) {
ArrayList<String> result = new ArrayList<String>();
String w = "";
for (int i = 0; i < l.size(); i++) {
ArrayList m = (ArrayList) l.get(i);
for (int r = 0; r < m.size(); r++) {
int e = (Integer) m.get(r);
int[] d = SemanticInterpreterGrid.getDistance(this.CenterPoint, this.UnitswithClassList.get(e));
if (d[0] > 0) {
if (!result.contains("east")) {
w = "east of";
}
}
if (d[0] < 0) {
if (!result.contains("west")) {
w = "west of";
}
}
if (d[1] > 0) {
if (!result.contains("south")) {
w = "south of";
}
}
if (d[1] < 0) {
if (!result.contains("north")) {
w = "north of";
}
}
if (d[1] == 0) {
if (!result.contains("in")) {
w = "in";
}
}
if (d[0] == 0) {
if (!result.contains("in")) {
w = "in";
}
}
}
}
result.add(w);
return result;
}
public void addRegionMix(int[] regions) {
this.regionmix = regions;
}
public void addConcentrationMix(double[] conc) {
this.concentrationmix = conc;
}
public void addNode(SemanticNode s) {
this.SemanticNodes.add(s);
}
public void setSharedClasses(int classes) {
this.SharedClasses = classes;
}
/*
* public Collection getSharedClasses(){ return this.SharedClasses; }
*/
public double getCompactness() {
return this.Compactness;
}
/**
* Return true, if the Class matches the wanted concentration in the region index
*
* @param EP
* @return
*/
/*
* public boolean matchesConcentrationRequirements(EditableReportProperties EP){ boolean out = false; if(EP != null){ int concMIN =
* EP.getMINConcentration(); int concMAX = EP.getMAXConcentration(); if(concMIN!= -1 && concMAX!= -1){ if(this.concentrationmix[index] >= concMIN
* && this.concentrationmix[index] <= concMAX) out = true; } else{ if(concMIN!= -1){ // User made MIN Requirements for this Region
* if(this.concentrationmix[index] >= concMIN) // Matches? out=true; } if(concMAX!= -1){ // User made MAX Requirements for this Region
* if(this.concentrationmix[index] <= concMAX) // Matches? out=true; } } } return out; }
*/
/** Return true, if the Class matches the wanted compactness in the region index */
public boolean matchesCompactnessRequirements(EditableReportProperties EP) {
boolean out = false;
int compMIN = EP.getMINCompactness();
int compMAX = EP.getMAXCompactness();
if (compMIN != -1 && compMAX != -1) {
if (this.Compactness * 100 >= compMIN && this.Compactness * 100 <= compMAX) {
out = true;
}
} else {
if (compMIN != -1) { // User made MIN Requirements for this Region
if (this.Compactness * 100 >= compMIN) {
out = true;
}
}
if (compMAX != -1) { // User made MAX Requirements for this Region
if (this.Compactness * 100 <= compMAX) {
out = true;
}
}
}
return out;
}
/** Sets the Semantic Nodes that were found to be on the edges of the class */
public void setClassEdges(ArrayList<SemanticNode> edges) {
if (this.EdgeNodes == null) {
EdgeNodes = new ArrayList<SemanticNode>();
}
this.EdgeNodes = edges;
}
public ArrayList<SemanticNode> getEdgeNodes() {
return this.EdgeNodes;
}
/**
* Sets the setQMIntersectionClassArrayList, containing the Name of the QM on uneven places, and the
* IntersectionNodes-ArrayList on even Places for Maximum Units of the QM
*/
public void setQMIntersectionClassArrayListMAX(ArrayList QMIntersectionClassArrayList) {
this.QMIntersectionClassArrayListMAX = QMIntersectionClassArrayList;
}
/**
* Sets the setQMIntersectionClassArrayList, containing the Name of the QM on uneven places, and the
* IntersectionNodes-ArrayList on even Places for Minimum Units of the QM
*/
public void setQMIntersectionClassArrayListMIN(ArrayList QMIntersectionClassArrayList) {
this.QMIntersectionClassArrayListMIN = QMIntersectionClassArrayList;
}
}