/*
* 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.apps.viewer.controls;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import edu.umd.cs.piccolo.PNode;
import edu.umd.cs.piccolo.nodes.PPath;
import edu.umd.cs.piccolo.nodes.PText;
import at.tuwien.ifs.somtoolbox.apps.viewer.ArrowPNode;
import at.tuwien.ifs.somtoolbox.apps.viewer.CommonSOMViewerStateData;
import at.tuwien.ifs.somtoolbox.apps.viewer.GeneralUnitPNode;
import at.tuwien.ifs.somtoolbox.layers.Unit;
/**
* @author Jakob Frank
* @version $Id: PlaylistEvaluationPane.java 3589 2010-05-21 10:42:01Z mayer $
*/
public class PlaylistEvaluationPane extends AbstractViewerControl {
/**
*
*/
private static final long serialVersionUID = 1L;
private JTextField txtInfile;
private JButton btnEvalPL;
private JButton btnPrintPL;
private PNode playlistPrint;
private PNode playlistDots;
private PNode playlistLines;
private SpinnerNumberModel spmSeconds;
private JButton btnStopPLMovie;
private boolean stopPLMovie = false;
private JButton btnRememberPlaylist;
public PlaylistEvaluationPane(String title, CommonSOMViewerStateData state) {
super(title, state);
initialize();
}
private void evaluate(File in) throws FileNotFoundException {
evaluate(in, false);
}
private void evaluate(File file, boolean shortPrint) throws FileNotFoundException {
BufferedReader fr = new BufferedReader(new FileReader(file));
String pre = CommonSOMViewerStateData.fileNamePrefix;
String suf = CommonSOMViewerStateData.fileNameSuffix;
LinkedList<Unit> list = new LinkedList<Unit>();
try {
for (String line = fr.readLine(); line != null; line = fr.readLine()) {
line = line.trim();
if (line.length() == 0 || line.startsWith("#")) {
// Blank Lines & Comments
continue;
}
line = line.trim();
if (line.startsWith(pre)) {
line = line.substring(pre.length());
}
if (line.endsWith(suf)) {
line = line.substring(0, line.length() - suf.length());
}
Unit u = state.growingLayer.getUnitForDatum(line);
list.add(u);
}
fr.close();
Unit prev = null;
double max = Double.MIN_VALUE, min = Double.MAX_VALUE, sum = 0;
int count = 0;
LinkedList<Double> dists = new LinkedList<Double>();
for (Unit unit : list) {
if (prev != null) {
count++;
double dist = Math.sqrt(Math.pow(unit.getXPos() - prev.getXPos(), 2)
+ Math.pow(unit.getXPos() - prev.getXPos(), 2));
sum += dist;
if (dist > max) {
max = dist;
}
if (dist < min) {
min = dist;
}
dists.add(dist);
} else {
dists.add(-1d);
}
prev = unit;
}
double avg = sum / count;
PrintStream ps = new PrintStream(file.getName() + ".stat");
ps.print(file.getName());
for (int i = 0; i < dists.size(); i++) {
if (!shortPrint) {
System.out.printf("%d %.3f%n", i, dists.get(i));
}
ps.printf(";%.3f", dists.get(i));
}
ps.println();
ps.close();
System.out.printf("PlayList: %s AVG: %.3f MIN: %.3f MAX: %.3f%n", file.getName(), avg, min, max);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void evaluate(File[] listFiles) throws FileNotFoundException {
for (File file : listFiles) {
evaluate(file, true);
}
}
private void initialize() {
JPanel mainP = new JPanel();
this.setContentPane(mainP);
mainP.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.gridy = 0;
playlistLines = new PNode();
playlistDots = new PNode();
playlistPrint = new PNode();
playlistPrint.addChild(playlistDots);
playlistPrint.addChild(playlistLines);
state.mapPNode.addChild(playlistPrint);
txtInfile = new JTextField();
txtInfile.setColumns(10);
mainP.add(txtInfile, gbc);
JButton btnFCDlg = new JButton("...");
btnFCDlg.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser jfc = state.fileChooser;
if (jfc.showOpenDialog(PlaylistEvaluationPane.this) == JFileChooser.APPROVE_OPTION) {
txtInfile.setText(jfc.getSelectedFile().getAbsolutePath());
}
}
});
mainP.add(btnFCDlg, gbc);
gbc.gridy++;
mainP.add(new JLabel("Seconds per Path"), gbc);
spmSeconds = new SpinnerNumberModel(1.0, 0.5, 20.0, 0.5);
JSpinner spnSeconds = new JSpinner();
spnSeconds.setModel(spmSeconds);
mainP.add(spnSeconds, gbc);
gbc.gridy++;
btnEvalPL = new JButton("Evaluate Playlist(s)");
btnEvalPL.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
File in = new File(txtInfile.getText());
if (!in.exists()) {
return;
}
try {
if (in.isDirectory()) {
evaluate(in.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".m3u");
}
}));
} else {
evaluate(in);
}
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
}
});
mainP.add(btnEvalPL, gbc);
btnPrintPL = new JButton("Print Playlist(s)");
btnPrintPL.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
File pl = new File(txtInfile.getText());
if (pl.isDirectory()) {
doPlaylistMovie(pl);
} else {
printSinglePlaylist(pl);
}
}
});
mainP.add(btnPrintPL, gbc);
gbc.gridy++;
btnStopPLMovie = new JButton("Stop");
btnStopPLMovie.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
stopPLMovie = true;
}
});
btnStopPLMovie.setEnabled(false);
mainP.add(btnStopPLMovie, gbc);
btnRememberPlaylist = new JButton("Remember");
btnRememberPlaylist.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
rememberCurrentPlaylist();
}
});
btnRememberPlaylist.setEnabled(false);
mainP.add(btnRememberPlaylist, gbc);
gbc.gridy++;
gbc.gridwidth = 2;
JButton btnClear = new JButton("Clear");
btnClear.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
playlistDots.removeAllChildren();
playlistLines.removeAllChildren();
}
});
mainP.add(btnClear, gbc);
gbc.gridy++;
gbc.gridwidth = 2;
}
private String currentPlaylist;
private StringBuilder rememberedPlaylists;
private void rememberCurrentPlaylist() {
if (rememberedPlaylists != null) {
rememberedPlaylists.append(currentPlaylist).append('\n');
}
}
private void doPlaylistMovie(final File pl) {
Thread t = new Thread() {
@Override
public void run() {
String buttonText = btnPrintPL.getText();
try {
btnPrintPL.setEnabled(false);
btnStopPLMovie.setEnabled(true);
btnRememberPlaylist.setEnabled(true);
this.setName("PlaylistMovie");
rememberedPlaylists = new StringBuilder();
File[] pls = pl.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".m3u");
}
});
stopPLMovie = false;
int i = 0;
for (File playlist : pls) {
long startTime = System.currentTimeMillis();
if (stopPLMovie) {
break;
}
try {
btnPrintPL.setText("Printing " + ++i + "/" + pls.length);
currentPlaylist = playlist.getName();
printSinglePlaylist(playlist);
long wait = (long) (1000 * spmSeconds.getNumber().doubleValue() - (System.currentTimeMillis() - startTime));
Thread.sleep(wait);
} catch (InterruptedException e) {
}
}
if (rememberedPlaylists.length() > 0) {
System.out.println("Remembered:");
System.out.println(rememberedPlaylists);
System.out.println();
}
} finally {
btnPrintPL.setText(buttonText);
btnPrintPL.setEnabled(true);
btnStopPLMovie.setEnabled(false);
btnRememberPlaylist.setEnabled(false);
}
}
};
t.start();
}
private void printSinglePlaylist(File file) {
try {
playlistDots.removeAllChildren();
playlistLines.removeAllChildren();
float dotS = state.mapPNode.getUnitHeight() / 3;
BufferedReader fr = new BufferedReader(new FileReader(file));
Unit lastU = null;
Map<Unit, Integer> countList = new HashMap<Unit, Integer>();
Map<Unit, PPath> dotList = new HashMap<Unit, PPath>();
Map<Unit, PText> txtList = new HashMap<Unit, PText>();
float lastX = 0, lastY = 0;
int skipCount = 0;
for (String line = fr.readLine(); line != null; line = fr.readLine()) {
// Skip blank lines
if (line.trim().length() == 0) {
continue;
}
// Skip lines starting with #
if (line.trim().startsWith("#")) {
continue;
}
String pre = CommonSOMViewerStateData.fileNamePrefix;
String suf = CommonSOMViewerStateData.fileNameSuffix;
line = line.trim();
if (line.startsWith(pre)) {
line = line.substring(pre.length());
}
if (line.endsWith(suf)) {
line = line.substring(0, line.length() - suf.length());
}
Unit u = state.growingLayer.getUnitForDatum(line);
if (u == null) {
System.err.println(line + " not found...");
skipCount++;
continue;
}
GeneralUnitPNode gup = state.mapPNode.getUnit(u);
float currentX = (float) (gup.getX() + gup.getWidth() / 2);
float currentY = (float) (gup.getY() + gup.getHeight() / 2);
PPath dot = dotList.get(u);
PText txt = txtList.get(u);
if (dot == null) {
// New unit, create a dot
dot = PPath.createEllipse(currentX - dotS / 2, currentY - dotS / 2, dotS, dotS);
dotList.put(u, dot);
txt = new PText("1");
txt.setX(currentX - txt.getWidth() / 2);
txt.setY(currentY - txt.getHeight() / 2);
txtList.put(u, txt);
countList.put(u, 1);
playlistDots.addChild(dot);
playlistDots.addChild(txt);
} else {
// Grow the dot... (+10%)
dot.setWidth(dot.getWidth() + dotS / 10);
dot.setHeight(dot.getHeight() + dotS / 10);
dot.setX(dot.getX() - dotS / 20);
dot.setY(dot.getY() - dotS / 20);
int c = countList.get(u) + 1;
txt.setText(c + "");
txt.setX(currentX - txt.getWidth() / 2);
txt.setY(currentY - txt.getHeight() / 2);
countList.put(u, c);
}
if (lastU != null && u != lastU) {
// lines.addChild(PPath.createLine(lastX, lastY, currentX, currentY));
// double alpha = Math.atan((currentX - lastX) / (currentY - lastY));
// double sigX = 1;//Math.signum(currentX - lastX);
// double sigY = 1;//Math.signum(currentY - lastY);
// double deltax1 = (dot.getWidth() / 2) * Math.sin(alpha);
// double deltay1 = (dot.getHeight() / 2) * Math.cos(alpha);
//
// double deltax2 = (dot.getWidth() / 2) * Math.cos(alpha);
// double deltay2 = (dot.getHeight() / 2) * Math.sin(alpha);
// System.out.printf("last = (%.0f/%.0f) cur = (%.0f/%.0f) dx = %.2f dy = %.2f sX = %.0f sY = %.0f%n",
// lastX, lastY,
// currentX, currentY, deltax1 * sigX, deltay1 * sigY, deltax2, deltay2);
// ArrowPNode ar = new ArrowPNode(lastX, lastY, currentX - (deltax1 * sigX), currentY - (deltay1 *
// sigY));
ArrowPNode ar = new ArrowPNode(lastX, lastY, currentX, currentY);
ar.setColor(Color.RED);
ar.setLineWidth(15);
ar.setArrowHeadScale(.5f);
// ar.setTransparency(.45f);
playlistLines.addChild(ar);
}
lastU = u;
lastX = currentX;
lastY = currentY;
// skipCount = 0;
}
if (skipCount > 0) {
System.out.printf("Skipped %d Songs on this playlist%n", skipCount);
}
playlistDots.repaint();
playlistLines.repaint();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e2) {
e2.printStackTrace();
}
}
}