001    package org.hackystat.projectbrowser.page.trajectory.datapanel;
002    
003    import java.io.Serializable;
004    import java.util.ArrayList;
005    import java.util.List;
006    
007    import org.hackystat.projectbrowser.page.trajectory.dtw.DTWUtilFactory;
008    import org.hackystat.telemetry.service.resource.chart.jaxb.TelemetryPoint;
009    import org.hackystat.telemetry.service.resource.chart.jaxb.TelemetryStream;
010    
011    /**
012     * Group a selected flag with a TelemetryStream, so that this instance can be flaged as selected or
013     * not.
014     * 
015     * @author Shaoxuan, Pavel Senin.
016     * 
017     */
018    public class SelectableTrajectoryStream implements Serializable {
019      /** Support serialization. */
020      public static final long serialVersionUID = 1L;
021      /** Determine this stream is selected or not. */
022      private boolean selected = false;
023      /** The TelemetryStream of this stream. */
024      private TelemetryStream telemetryStream;
025      /** The color associated with this stream. */
026      private String color = "";
027      /** the marker of this stream. */
028      private String marker = "";
029      /** thickness of the line. */
030      private double thickness = 2;
031      /** length of the line segment. */
032      private double lineLength = 1;
033      /** length of the blank segment. */
034      private double blankLength = 0;
035      /** the maximum of this stream. */
036      private double maximum;
037      /** the minimum of this stream. */
038      private double minimum;
039      private Integer indent;
040    
041      /**
042       * Constructor.
043       * 
044       * @param telemetryStream the TelemetryStream of this instance.
045       */
046      public SelectableTrajectoryStream(TelemetryStream telemetryStream) {
047        this.telemetryStream = telemetryStream;
048        // initial the maximum and minimum value.
049        List<Double> streamData = this.getStreamData();
050        maximum = -1;
051        minimum = 99999999;
052        for (Double value : streamData) {
053          if (value > maximum) {
054            maximum = value;
055          }
056          if (value >= 0 && value < minimum) {
057            minimum = value;
058          }
059        }
060      }
061    
062      /**
063       * Constructor.
064       * 
065       * @param stream The telemetry stream.
066       * @param indent The indent value.
067       */
068      public SelectableTrajectoryStream(TelemetryStream stream, Integer indent) {
069        this.telemetryStream = stream;
070        // initial the maximum and minimum value.
071        List<Double> streamData = this.getStreamData();
072        maximum = -1;
073        minimum = 99999999;
074        for (Double value : streamData) {
075          if (value > maximum) {
076            maximum = value;
077          }
078          if (value >= 0 && value < minimum) {
079            minimum = value;
080          }
081        }
082        this.indent = indent;
083      }
084    
085      /**
086       * @param selected the selected to set
087       */
088      public void setSelected(boolean selected) {
089        this.selected = selected;
090      }
091    
092      /**
093       * @return the selected
094       */
095      public boolean isSelected() {
096        return selected;
097      }
098    
099      /**
100       * @param telemetryStream the telemetryStream to set
101       */
102      public void setTelemetryStream(TelemetryStream telemetryStream) {
103        this.telemetryStream = telemetryStream;
104      }
105    
106      /**
107       * @return the telemetryStream
108       */
109      public TelemetryStream getTelemetryStream() {
110        return telemetryStream;
111      }
112    
113      /**
114       * @param color the color to set
115       */
116      public void setColor(String color) {
117        this.color = color;
118      }
119    
120      /**
121       * @return the color
122       */
123      public String getColor() {
124        return color;
125      }
126    
127      /**
128       * Returns a background-color attribute with the value of color.
129       * 
130       * @return The background-color key-value pair.
131       */
132      public String getBackgroundColorValue() {
133        return "background-color:#" + getColor();
134      }
135    
136      /**
137       * @param marker the marker to set
138       */
139      public void setMarker(String marker) {
140        this.marker = marker;
141      }
142    
143      /**
144       * @return the marker
145       */
146      public String getMarker() {
147        return marker;
148      }
149    
150      /**
151       * @return the isEmpty
152       */
153      public boolean isEmpty() {
154        return this.maximum < 0;
155      }
156    
157      /**
158       * @return the maximum
159       */
160      public double getMaximum() {
161        return maximum;
162      }
163    
164      /**
165       * @return the minimum
166       */
167      public double getMinimum() {
168        return minimum;
169      }
170    
171      /**
172       * @param thickness the thickness to set
173       */
174      public void setThickness(double thickness) {
175        this.thickness = thickness;
176      }
177    
178      /**
179       * @return the thickness
180       */
181      public double getThickness() {
182        return thickness;
183      }
184    
185      /**
186       * @param lineLength the lineLength to set
187       */
188      public void setLineLength(double lineLength) {
189        this.lineLength = lineLength;
190      }
191    
192      /**
193       * @return the lineLength
194       */
195      public double getLineLength() {
196        return lineLength;
197      }
198    
199      /**
200       * @param blankLength the blankLength to set
201       */
202      public void setBlankLength(double blankLength) {
203        this.blankLength = blankLength;
204      }
205    
206      /**
207       * @return the blankLength
208       */
209      public double getBlankLength() {
210        return blankLength;
211      }
212    
213      /**
214       * Get the stream data.
215       * 
216       * @param maxStreamLength The expected length of the list to plot. N/A points will be added to
217       *        reach the length specified.
218       * @return the list of data of this stream
219       */
220      public final List<Double> getStreamData(Integer maxStreamLength) {
221        List<Double> streamData = new ArrayList<Double>();
222        for (int i = 0; i < this.indent; i++) {
223          streamData.add(-1.0);
224        }
225        for (TelemetryPoint point : this.getTelemetryStream().getTelemetryPoint()) {
226          if (point.getValue() == null) {
227            streamData.add(-1.0);
228          }
229          else {
230            Double value = Double.valueOf(point.getValue());
231            if (value.isNaN()) {
232              value = -2.0;
233            }
234            streamData.add(value);
235          }
236        }
237        // extend the list
238        while (streamData.size() < maxStreamLength) {
239          streamData.add(-2.0);
240        }
241        return streamData;
242      }
243    
244      /**
245       * Get the stream data.
246       * 
247       * @return the list of data of this stream
248       */
249      public final List<Double> getNormalizedStreamData() {
250        double[] streamData = new double[this.indent
251            + this.getTelemetryStream().getTelemetryPoint().size()];
252        for (int i = 0; i < this.indent; i++) {
253          streamData[i] = 0.0D;
254        }
255        int currElement = this.indent;
256        for (TelemetryPoint point : this.getTelemetryStream().getTelemetryPoint()) {
257          if (point.getValue() == null) {
258            streamData[currElement] = 0.0D;
259          }
260          else {
261            Double value = Double.valueOf(point.getValue());
262            if (value.isNaN()) {
263              value = 0.0D;
264            }
265            streamData[currElement] = value;
266          }
267          currElement++;
268        }
269        // normalize
270        streamData = DTWUtilFactory.normalize(streamData);
271        ArrayList<Double> res = new ArrayList<Double>();
272        for (int i = 0; i < streamData.length; i++) {
273          res.add(streamData[i]);
274        }
275        return res;
276      }
277    
278      /**
279       * Return a image url that shows only one marker. Using google chart to generate this image. there
280       * is an example output: http://chart.apis.google.com/chart?
281       * chs=20x20&cht=ls&chd=t:-1,1.0,-1&chds=0.9,1.1&chm=c,FF0000,0,-1,20.0
282       * 
283       * @return the image url
284       */
285      public String getMarkerImageUrl() {
286        if (!this.isSelected() || this.isEmpty() || this.marker.length() <= 0) {
287          return "";
288        }
289        String imageUrl = "http://chart.apis.google.com/chart?"
290            + "chs=45x15&cht=ls&chd=t:1.0,1.0,1.0&chds=0.9,1.1&" + "chm=" + marker + "," + color
291            + ",0,1,10.0&" + "chls=" + thickness + "," + lineLength + "," + blankLength + "&" + "chco="
292            + color;
293        return imageUrl;
294      }
295    
296      /**
297       * Return the Units of this stream.
298       * 
299       * @return String of the units.
300       */
301      public String getUnitName() {
302        return this.telemetryStream.getYAxis().getUnits();
303      }
304    
305      /**
306       * Get the stream data.
307       * 
308       * @return the list of data of this stream
309       */
310      public final List<Double> getStreamData() {
311        List<Double> streamData = new ArrayList<Double>();
312        for (TelemetryPoint point : this.getTelemetryStream().getTelemetryPoint()) {
313          if (point.getValue() == null) {
314            streamData.add(-1.0);
315          }
316          else {
317            Double value = Double.valueOf(point.getValue());
318            if (value.isNaN()) {
319              value = -2.0;
320            }
321            streamData.add(value);
322          }
323        }
324        return streamData;
325      }
326    
327      /**
328       * Set the indent.
329       * 
330       * @param indent The indent value.
331       */
332      public void setIndent(Integer indent) {
333        this.indent = indent;
334      }
335    
336      /**
337       * Get the indent.
338       * 
339       * @return the indent value.
340       */
341      public Integer getIndent() {
342        return this.indent;
343      }
344    }