package common.logging; import common.filesystem.FileSystem; import experiment.Subject; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import log.LogfileRow; import util.Util; /** * * @author Tristan Goffman(tgoffman@gmail.com) Oct 12, 2011 */ public class ExperimentLogging { static final String FOLDER_LOGS = FileSystem.FOLDER_LOGS; private static final String DELI = "_"; private static String BACKSLASH = "/"; static{ //make the directory if it does not already exist File dir = new File(FOLDER_LOGS); if(!dir.isDirectory()) try{ dir.mkdir(); }catch(Exception e){ //nothing } } private static boolean addSubject(Subject person) { synchronized(uniqueTimes){ Object time = uniqueTimes.get(person); if ( time == null){ uniqueTimes.put(person, Util.getNow("yyyy-MM-dd_HHmmss")); return true; } return false; } } /** * Return the file associated with the data folder for a given Subject * @param person */ private static File dataFolderFor(Subject person) { return getFile(person, PathParts.Folder); } /** * Return a file associated with a person (only those associated within the enum PathParts) * @param person * @param pathParts * @return */ private static File getFile(Subject person, PathParts pathParts) { return new File(fp(pathParts, person)); } public static enum PathParts { Folder, Data, Summary, StevensTrials, XML, Custom //enum to denote a custom file creation within data folder, the ExperimentLogging does not know more about this file } private static Map<PathParts, String> descriptMap = new HashMap<PathParts, String>(); static { descriptMap.put(PathParts.StevensTrials, "StevensTrials.txt"); descriptMap.put(PathParts.Data, "data.txt"); descriptMap.put(PathParts.Summary, "summary.txt"); descriptMap.put(PathParts.Folder, "dir"); descriptMap.put(PathParts.XML, "XML.xml"); } private static String fp(PathParts part, Subject person, String filename){ String desc; SubjectFilenameBuilder builder = person.getBuilder(); Object pull; synchronized(uniqueTimes){ pull = uniqueTimes.get(person); } String inFst = ""; if(pull != null) inFst = String.class.cast(pull) + SubjectFilenameBuilder.delimiter; synchronized(descriptMap){desc = descriptMap.get(part);} switch (part){ case Custom: return fp(PathParts.Folder, person) + BACKSLASH + builder.buildFileName(person, filename); case Folder: inFst = FOLDER_LOGS + inFst; break; default: inFst = fp(PathParts.Folder, person) + BACKSLASH + inFst; break; } return inFst + builder.buildFileName(person, desc); } private static String fp(PathParts part, Subject person){ return fp(part, person, null); } /* * As new files are created keep a reference to the data used at the time which prefixes all files, so that further calls */ private final static Map uniqueTimes = new HashMap<Subject, String>(); /** * Creates the log file and folder for this experiment. * @param experimentPrefix, string that gets appended to the current time */ public static void createLogfileAndFolder(Subject person) { if(addSubject(person)){ // create log folder (to dump distributions, other data, etc.) try { File myFolder = dataFolderFor(person); myFolder.mkdir(); } catch (Exception e) { e.printStackTrace(); System.exit(0); } // create logfile try { BufferedWriter out = new BufferedWriter(new FileWriter(createFile(PathParts.Data, person), false)); out.write(LogfileRow.getTitle() + "\n"); out.close(); } catch (IOException e) { e.printStackTrace(); System.exit(0); } // create a summary of a subjects data try { BufferedWriter out = new BufferedWriter(new FileWriter(createFile(PathParts.Summary, person), false)); out.write("level above JND trials scalingVal dotSize numPoints dotStyle dotHue" + "\n"); out.close(); } catch (IOException e) { e.printStackTrace(); System.exit(0); } } } public static void writeToFile(PathParts part, Subject person, String string){ if(!getFile(person, part).exists()) createFile(part, person); File file = getFile(person, part); try { BufferedWriter writer = new BufferedWriter(new FileWriter(file)); writer.write(string); writer.close(); } catch (IOException ex) { Logger.getLogger(ExperimentLogging.class.getName()).log(Level.SEVERE, "Unable to write out to file: " + part.toString(), ex); } } public static File createFile(PathParts part, Subject person){ String path = fp(part, person); File file = new File(path); try { file.createNewFile(); } catch (IOException ex) { Logger.getLogger(ExperimentLogging.class.getName()).log(Level.SEVERE, "Can't create file at path: " + path , ex); } return file; } /** * Write data to a file of a known file to the Logging mechanism * @param person * @param pathParts * @param dataString */ public static void writeToFile(Subject person, PathParts part, String dataString) { writeOutToFile(getDataFile(person, part), dataString); } /** * Write data to a file of a custom file found within the data folder (this file should already be created) * @param person * @param pathParts * @param dataString */ public static void writeToFile(Subject person, String filename, String dataString){ writeOutToFile(getCustomDataFile(person, filename), dataString); } /** * Given a file write out a given a data string to it. * @param toWriteTo * @param dataToWrite */ private static void writeOutToFile(File toWriteTo, String dataToWrite){ try { BufferedWriter out = new BufferedWriter(new FileWriter(toWriteTo, true)); out.write(dataToWrite); out.newLine(); out.flush(); out.close(); } catch (Exception e) { e.printStackTrace(); } } /** * Get the File object associated with a known Data file * @param person, subject in use (for finding which folder to lookin) * @param part, PathPart known to logger * @return */ public static File getDataFile(Subject person, PathParts part){ return new File(fp(part, person)); } /** * Get the File object associated with the filename and subject given, will look in the data folder associated with Subject * @param person, subject in use (for finding which folder to lookin) * @param filename, name of file searched for * @return */ public static File getCustomDataFile(Subject person, String filename){ return new File(fp(PathParts.Custom, person, filename)); } }