diff --git a/Source/Core/src/ca/uqac/lif/labpal/Experiment.java b/Source/Core/src/ca/uqac/lif/labpal/Experiment.java index 0d61d8cb..10964a0f 100755 --- a/Source/Core/src/ca/uqac/lif/labpal/Experiment.java +++ b/Source/Core/src/ca/uqac/lif/labpal/Experiment.java @@ -47,7 +47,7 @@ public abstract class Experiment implements Runnable, DataOwner /** * The status of the experiment */ - public static enum Status {DUNNO, PREREQ_NOK, PREREQ_OK, PREREQ_F, RUNNING, DONE, DONE_WARNING, FAILED, TIMEOUT, INTERRUPTED, RUNNING_REMOTELY}; + public static enum Status {DUNNO, PREREQ_NOK, PREREQ_RUNNING, PREREQ_OK, PREREQ_F, RUNNING, DONE, DONE_WARNING, FAILED, KILLED, TIMEOUT, INTERRUPTED, RUNNING_REMOTELY}; /** * The queuing status of the experiment @@ -97,6 +97,14 @@ public static enum QueueStatus {QUEUED, QUEUED_REMOTELY, NOT_QUEUED}; */ private long m_maxDuration = -1; + /** + * The maximum duration for this experiment requirements (in milliseconds). + * If the requirements lasts longer than this duration, the lab assistant + * can interrupt experiment. A negative value indicates that no timeout + * applies. + */ + private long m_maxPrereqDuration = -1; + /** * A list of exceptions that the experiment does not throw, but * rather adds to a list @@ -118,6 +126,16 @@ public static enum QueueStatus {QUEUED, QUEUED_REMOTELY, NOT_QUEUED}; */ private long m_endTime = -1; + /** + * The start time of requirements + */ + private long m_startPrereqTime = -1; + + /** + * The end time of requirements + */ + private long m_endPrereqTime = -1; + /** * An approximate measurement of the experiment's progression */ @@ -217,7 +235,15 @@ public final QueueStatus getQueueStatus() */ public boolean prerequisitesFulfilled() { - return true; + if (m_status == Status.PREREQ_F || m_status == Status.PREREQ_NOK || m_status == Status.PREREQ_OK) + { + return true; + } + else + { + return false; + } + } /** @@ -232,6 +258,7 @@ public boolean prerequisitesFulfilled() */ public void fulfillPrerequisites() throws ExperimentException { + m_status = Status.PREREQ_OK; return; } @@ -654,6 +681,29 @@ public final long getEndTime() return m_endTime; } + /** + * Gets the start time of requirement + * @return The difference, measured in milliseconds, + * between the start time and midnight, January 1, 1970 UTC. The + * value is -1 if requirement has not started yet. + */ + public final long getStartPrereqTime() + { + return m_startPrereqTime; + } + + /** + * Gets the end time of requirement + * @return The difference, measured in milliseconds, + * between the end time and midnight, January 1, 1970 UTC. The + * value is -1 if requirement has not started yet or is still + * running. + */ + public final long getEndPrereqTime() + { + return m_endPrereqTime; + } + /** * Gets the name of the lab assistant that ran the experiment * @return The name, or the empty string if the experiment has not run yet @@ -684,6 +734,8 @@ public synchronized final void reset() m_outputParameters.clear(); m_startTime = -1; m_endTime = -1; + m_startPrereqTime = -1; + m_endPrereqTime = -1; m_runBy = ""; m_status = Status.DUNNO; m_errorMessage = ""; @@ -707,7 +759,7 @@ public final void clean() */ public synchronized final Status getStatus() { - if (m_status == Status.DUNNO || m_status == Status.PREREQ_NOK || m_status == Status.PREREQ_OK) + /*if (m_status == Status.DUNNO || m_status == Status.PREREQ_NOK || m_status == Status.PREREQ_OK) { if (prerequisitesFulfilled()) { @@ -717,20 +769,27 @@ public synchronized final Status getStatus() { m_status = Status.PREREQ_NOK; } - } + }*/ return m_status; } @Override public final void run() { - m_running = true; - m_startTime = System.currentTimeMillis(); + + //m_running = true; + //m_startTime = System.currentTimeMillis(); + if (!prerequisitesFulfilled()) { + m_startPrereqTime = System.currentTimeMillis(); try { - fulfillPrerequisites(); + //if (m_status != Status.PREREQ_RUNNING) + //{ + m_status = Status.PREREQ_RUNNING; + fulfillPrerequisites(); + //} } catch (Exception e) { @@ -742,9 +801,11 @@ public final void run() setErrorMessage(sw.toString()); return; } + m_endPrereqTime = System.currentTimeMillis(); } - m_status = Status.PREREQ_OK; + //m_status = Status.PREREQ_OK; m_status = Status.RUNNING; + m_startTime = System.currentTimeMillis(); try { execute(); @@ -967,8 +1028,18 @@ public final Experiment interrupt() m_running = false; m_status = Status.INTERRUPTED; m_errorMessage = "The experiment was manually interrupted"; - m_endTime = System.currentTimeMillis(); - prepareToInterrupt(); + if (m_startTime > -1) + { + m_endTime = System.currentTimeMillis(); + } + if (m_endPrereqTime == -1) + { + m_endPrereqTime = System.currentTimeMillis(); + } + + //m_endTime = System.currentTimeMillis(); + //prepareToInterrupt(); + return this; } @@ -1039,7 +1110,7 @@ public final long getMaxDuration() * If the experiment lasts longer than this duration, the lab assistant * can interrupt it. * @return The duration, in milliseconds. A negative value indicates - * that no timeout applies. + * that no timeout applies. */ public final Experiment setMaxDuration(long duration) { @@ -1047,6 +1118,28 @@ public final Experiment setMaxDuration(long duration) return this; } + /** + * Gets the maximum duration for this experiment requirement + * @return The duration + */ + public final long getMaxPrereqDuration() + { + return m_maxPrereqDuration; + } + + /** + * Sets the maximum duration for this experiment requirement. + * If the experiment lasts longer than this duration, the lab assistant + * can interrupt it. + * @return The duration, in milliseconds. A negative value indicates + * that no timeout applies. m_maxPrereqDuration + */ + public final Experiment setMaxPrereqDuration(long duration) + { + m_maxPrereqDuration = duration; + return this; + } + /** * Interrupts the current experiment * @return This experiment @@ -1056,7 +1149,14 @@ public final Experiment kill() m_running = false; m_status = Status.TIMEOUT; m_errorMessage = "The experiment was interrupted by the lab assistant because it was taking too long"; - m_endTime = System.currentTimeMillis(); + if (m_startTime > -1) + { + m_endTime = System.currentTimeMillis(); + } + if (m_endPrereqTime == -1) + { + m_endPrereqTime = System.currentTimeMillis(); + } return this; } @@ -1141,7 +1241,7 @@ public Experiment getOwner() */ public synchronized boolean mergeWith(Experiment e, boolean is_remote) { - if (m_status == Status.RUNNING) + if (m_status == Status.RUNNING || m_status == Status.PREREQ_RUNNING) { return false; } @@ -1168,6 +1268,8 @@ public synchronized boolean mergeWith(Experiment e, boolean is_remote) m_errorMessage = e.m_errorMessage; m_startTime = e.m_startTime; m_endTime = e.m_endTime; + m_startPrereqTime = e.m_startPrereqTime; + m_endPrereqTime = e.m_endPrereqTime; m_runBy = e.m_runBy; return true; } diff --git a/Source/Core/src/ca/uqac/lif/labpal/Laboratory.java b/Source/Core/src/ca/uqac/lif/labpal/Laboratory.java index 2469d719..af5a1f7a 100755 --- a/Source/Core/src/ca/uqac/lif/labpal/Laboratory.java +++ b/Source/Core/src/ca/uqac/lif/labpal/Laboratory.java @@ -231,7 +231,12 @@ public abstract class Laboratory implements OwnershipManager /** * The default filename assumed for the HTML description */ - private static transient final String s_descriptionDefaultFilename = "description.html"; + private static transient final String s_descriptionDefaultFilename = "description.html"; + + /** + * shadow laboratory + */ + private static transient Laboratory shadow_laboratory = null; /** * Creates a new lab assistant @@ -479,6 +484,16 @@ public Set getTableIds(boolean including_invisible) return ids; } + + /** + * Gets the title given to this assistant + * @return The + */ + public String getTitle() + { + return m_title; + } + /** * Gets the plot with given ID * @param id The ID @@ -498,12 +513,12 @@ public Plot getPlot(int id) /** - * Gets the title given to this assistant - * @return The title + * Gets the shadow_laboratory if the current lab has one + * @return The shadow_laboratory */ - public String getTitle() + public Laboratory getShadowLaboratory() { - return m_title; + return shadow_laboratory; } /** @@ -818,6 +833,10 @@ protected static CliParser setupParser() .withLongName("filter") .withArgument("exp") .withDescription("Filter experiments according to expression exp")); + parser.addArgument(new Argument() + .withLongName("shadow") + .withArgument("x") + .withDescription("Set shadow laboratory to x")); return parser; } @@ -866,21 +885,49 @@ public static final void initialize(String[] args, Class c { new_lab = preloadLab(new_lab, stdout); } + // are we a shadow lab? + if (argument_map.hasOption("shadow")) + { + String shadowLabFile = argument_map.getOptionValue("shadow"); + try + { + shadow_laboratory = clazz.newInstance(); + } + catch (InstantiationException e) + { + e.printStackTrace(); + //System.exit(ERR_LAB); + } + catch (IllegalAccessException e) + { + e.printStackTrace(); + //System.exit(ERR_LAB); + } + shadow_laboratory = loadFromFilename(shadow_laboratory, shadowLabFile); + shadow_laboratory.setAssistant(assistant); + shadow_laboratory.setupCli(parser); + shadow_laboratory.setup(); + } // Are we loading a lab file? If so, this overrides the // lab loaded from an internal file (if any) String filename = ""; List names = argument_map.getOthers(); for (int i = 0; i < names.size(); i++) { - filename = names.get(i); - if (i == 0) - { - new_lab = loadFromFilename(new_lab, filename); - } - else + int ii = 0; + if (names.get(i).toUpperCase().endsWith(".LABO")) { - Laboratory lab_to_merge = loadFromFilename(new_lab, filename); - new_lab.mergeWith(lab_to_merge); + filename = names.get(i); + if (ii == 0) + { + new_lab = loadFromFilename(new_lab, filename); + } + else + { + Laboratory lab_to_merge = loadFromFilename(new_lab, filename); + new_lab.mergeWith(lab_to_merge); + } + ii++; } } new_lab.setAssistant(assistant); @@ -944,6 +991,7 @@ public void run() String assistant_name = argument_map.getOptionValue("name").trim(); assistant.setName(assistant_name); } + // Sets an experiment filter String filter_params = ""; if (argument_map.hasOption("filter")) diff --git a/Source/Core/src/ca/uqac/lif/labpal/LinearAssistant.java b/Source/Core/src/ca/uqac/lif/labpal/LinearAssistant.java index 956845ce..1114b169 100755 --- a/Source/Core/src/ca/uqac/lif/labpal/LinearAssistant.java +++ b/Source/Core/src/ca/uqac/lif/labpal/LinearAssistant.java @@ -117,12 +117,17 @@ public void run() Experiment e = m_queue.get(0); m_queueLock.unlock(); Status s = e.getStatus(); - if (s != Status.RUNNING && s != Status.DONE && s != Status.DONE_WARNING && s != Status.FAILED) + if (s != Status.RUNNING && s != Status.DONE && s != Status.DONE_WARNING && s != Status.FAILED && s != Status.PREREQ_RUNNING) { + // get Experiment max duration + long max_duration = e.getMaxDuration(); + // get Experiment requisites max duration + long max_prereq_duration = e.getMaxPrereqDuration(); // Experiment not started: start + m_experimentThread = new ExperimentThread(e); e.setWhoRan(m_name); - m_experimentThread.start(); + m_experimentThread.start(); while (m_experimentThread.isAlive() && !m_stop) { try @@ -140,8 +145,8 @@ public void run() if (s1 == Status.DONE || s == Status.FAILED || s1 == Status.DONE_WARNING) break; // Move on to next experiment long duration = System.currentTimeMillis() - e.getStartTime(); - long max_duration = e.getMaxDuration(); - if (max_duration > 0 && duration > max_duration) + long prereq_duration = System.currentTimeMillis() - e.getStartPrereqTime(); + if ((max_duration > 0 && duration > max_duration) || (max_prereq_duration > 0 && prereq_duration > max_prereq_duration)) { // Experiment takes too long: kill it m_experimentThread.kill(); diff --git a/Source/Core/src/ca/uqac/lif/labpal/server/AssistantPageCallback.java b/Source/Core/src/ca/uqac/lif/labpal/server/AssistantPageCallback.java index 25aaf5c6..0f7833ec 100755 --- a/Source/Core/src/ca/uqac/lif/labpal/server/AssistantPageCallback.java +++ b/Source/Core/src/ca/uqac/lif/labpal/server/AssistantPageCallback.java @@ -112,6 +112,7 @@ else if (params.containsKey("clean")) } out = out.replaceAll("\\{%MESSAGE%\\}", Matcher.quoteReplacement(message)); out = out.replaceAll("\\{%FAVICON%\\}", getFavicon(IconType.ASSISTANT)); + out = out.replaceAll("\\{%HEADER_PROGRESS_BAR%\\}", getHeaderBar()); return out; } diff --git a/Source/Core/src/ca/uqac/lif/labpal/server/ExperimentsPageCallback.java b/Source/Core/src/ca/uqac/lif/labpal/server/ExperimentsPageCallback.java index 6f83a57f..3ba9daae 100755 --- a/Source/Core/src/ca/uqac/lif/labpal/server/ExperimentsPageCallback.java +++ b/Source/Core/src/ca/uqac/lif/labpal/server/ExperimentsPageCallback.java @@ -113,6 +113,7 @@ public String fill(String page, Map params, boolean is_offline) list_of_lists.append(getExperimentList(m_lab, m_assistant, orphan_ids)); } out = out.replaceAll("\\{%EXP_LIST%\\}", Matcher.quoteReplacement(list_of_lists.toString())); + out = out.replaceAll("\\{%HEADER_PROGRESS_BAR%\\}", getHeaderBar()); return out; } @@ -142,56 +143,150 @@ public static String getExperimentList(Laboratory lab, LabAssistant assistant, L StringBuilder out = new StringBuilder(); // Step 1: fetch all parameters Set param_set = new HashSet(); - for (int id : ids) + + if (lab.getShadowLaboratory() == null) { - Experiment e = lab.getExperiment(id); - if (lab.getFilter().include(e)) + for (int id : ids) { - param_set.addAll(e.getInputKeys(true)); + Experiment e = lab.getExperiment(id); + if (lab.getFilter().include(e)) + { + param_set.addAll(e.getInputKeys(true)); + } + } + List param_list = new ArrayList(param_set.size()); + param_list.addAll(param_set); + Collections.sort(param_list); + // Step 2: create the table + out.append("\n"); + for (String p_name : param_list) + { + + out.append(""); + } + //dupluquer le code ci dessus si shadow + out.append("\n\n"); + for (int id : ids) + { + Experiment e = lab.getExperiment(id); + if (!lab.getFilter().include(e)) + { + // Exclude + continue; + } + out.append(""); + out.append(""); + out.append(""); + for (String p_name : param_list) + { + out.append(""); + } + out.append(""); + out.append("\n"); } } - List param_list = new ArrayList(param_set.size()); - param_list.addAll(param_set); - Collections.sort(param_list); - // Step 2: create the table - out.append("
#").append(p_name).append("Status
").append(id).append(""); + JsonElement val = e.read(p_name); + if (val == null) + { + out.append(""); + } + else if (val instanceof JsonString) + { + out.append(htmlEscape(((JsonString) val).stringValue())); + } + else + { + out.append(htmlEscape(val.toString())); + } + out.append("").append(getStatusIcon(e, assistant)).append("
\n"); - for (String p_name : param_list) - { - - out.append(""); - } - out.append("\n\n"); - for (int id : ids) + // we have an shadow laboratory + else { - Experiment e = lab.getExperiment(id); - if (!lab.getFilter().include(e)) + for (int id : ids) { - // Exclude - continue; + Experiment e = lab.getExperiment(id); + if (lab.getFilter().include(e)) + { + param_set.addAll(e.getInputKeys(true)); + } } - out.append(""); - out.append(""); - out.append(""); + + List param_list = new ArrayList(param_set.size()); + param_list.addAll(param_set); + Collections.sort(param_list); + // Step 2: create the table + out.append("
#").append(p_name).append("Status
").append(id).append("
\n"); + out.append(""); + for (String p_name : param_list) { - out.append(""); + } + out.append(""); + + out.append(""); + for (String shadow_p_name : param_list) + { + + out.append(""); + } + out.append("\n\n"); + + for (int id : ids) + { + Experiment e = lab.getExperiment(id); + Experiment se = lab.getShadowLaboratory().getExperiment(id); + if (!lab.getFilter().include(e)) { - out.append(""); + // Exclude + continue; } - else if (val instanceof JsonString) + out.append(""); + out.append(""); + out.append(""); + for (String p_name : param_list) { - out.append(htmlEscape(((JsonString) val).stringValue())); + out.append(""); } - else + out.append(""); + out.append(""); + + for (String shadow_p_name : param_list) { - out.append(htmlEscape(val.toString())); + out.append(""); } - out.append(""); + out.append(""); + out.append("\n"); } - out.append(""); - out.append("\n"); } out.append("\n
Current Shadow
#"); - JsonElement val = e.read(p_name); - if (val == null) + + out.append("").append(p_name).append("Status#").append(shadow_p_name).append("Status
").append(id).append(""); + JsonElement val = e.read(p_name); + if (val == null) + { + out.append(""); + } + else if (val instanceof JsonString) + { + out.append(htmlEscape(((JsonString) val).stringValue())); + } + else + { + out.append(htmlEscape(val.toString())); + } + out.append("").append(getStatusIcon(e, assistant)).append("").append(se.getId()).append(""); + JsonElement val = se.read(shadow_p_name); + if (val == null) + { + out.append(""); + } + else if (val instanceof JsonString) + { + out.append(htmlEscape(((JsonString) val).stringValue())); + } + else + { + out.append(htmlEscape(val.toString())); + } + out.append("").append(getStatusIcon(se, assistant)).append("
").append(getStatusIcon(e, assistant)).append("
\n"); return out.toString(); diff --git a/Source/Core/src/ca/uqac/lif/labpal/server/FindFormCallback.java b/Source/Core/src/ca/uqac/lif/labpal/server/FindFormCallback.java index 4d4e67b9..8c8f98e9 100644 --- a/Source/Core/src/ca/uqac/lif/labpal/server/FindFormCallback.java +++ b/Source/Core/src/ca/uqac/lif/labpal/server/FindFormCallback.java @@ -95,6 +95,7 @@ public CallbackResponse process(HttpExchange t) file_contents = file_contents.replaceAll("\\{%DOI%\\}", ""); } file_contents = file_contents.replaceAll("\\{%FAVICON%\\}", TemplatePageCallback.getFavicon(TemplatePageCallback.IconType.BINOCULARS)); + file_contents = file_contents.replaceAll("\\{%HEADER_PROGRESS_BAR%\\}", getHeaderBar()); response.setContents(file_contents); response.setCode(CallbackResponse.HTTP_OK); return response; diff --git a/Source/Core/src/ca/uqac/lif/labpal/server/HelpPageCallback.java b/Source/Core/src/ca/uqac/lif/labpal/server/HelpPageCallback.java index a1ea9abd..d9b9c24c 100755 --- a/Source/Core/src/ca/uqac/lif/labpal/server/HelpPageCallback.java +++ b/Source/Core/src/ca/uqac/lif/labpal/server/HelpPageCallback.java @@ -45,6 +45,7 @@ public String fill(String page, Map params, boolean is_offline) String out = page.replaceAll("\\{%TITLE%\\}", "Help"); out = out.replaceAll("\\{%SEL_HELP%\\}", "selected"); out = out.replaceAll("\\{%FAVICON%\\}", getFavicon(IconType.HELP)); + out = out.replaceAll("\\{%HEADER_PROGRESS_BAR%\\}", getHeaderBar()); return out; } diff --git a/Source/Core/src/ca/uqac/lif/labpal/server/HomePageCallback.java b/Source/Core/src/ca/uqac/lif/labpal/server/HomePageCallback.java index 626ad684..d3c09874 100755 --- a/Source/Core/src/ca/uqac/lif/labpal/server/HomePageCallback.java +++ b/Source/Core/src/ca/uqac/lif/labpal/server/HomePageCallback.java @@ -73,6 +73,7 @@ public String fill(String page, Map params, boolean is_offline) out = out.replaceAll("\\{%FAVICON%\\}", getFavicon(IconType.HOME)); // We deliberately DON'T escape the description, as it is already valid HTML out = out.replaceAll("\\{%LAB_DESCRIPTION%\\}", Matcher.quoteReplacement(m_labDescription)); + out = out.replaceAll("\\{%HEADER_PROGRESS_BAR%\\}", getHeaderBar()); out = resolveClassText(out); return out; } diff --git a/Source/Core/src/ca/uqac/lif/labpal/server/MacrosPageCallback.java b/Source/Core/src/ca/uqac/lif/labpal/server/MacrosPageCallback.java index e69b40f4..0fcae12e 100644 --- a/Source/Core/src/ca/uqac/lif/labpal/server/MacrosPageCallback.java +++ b/Source/Core/src/ca/uqac/lif/labpal/server/MacrosPageCallback.java @@ -72,6 +72,7 @@ public String fill(String page, Map params, boolean is_offline) } out = out.replaceAll("\\{%ALL_MACROS%\\}", Matcher.quoteReplacement("

Download all macros

")); out = out.replaceAll("\\{%FAVICON%\\}", getFavicon(IconType.TULIP)); + out = out.replaceAll("\\{%HEADER_PROGRESS_BAR%\\}", getHeaderBar()); return out; } diff --git a/Source/Core/src/ca/uqac/lif/labpal/server/PlotsPageCallback.java b/Source/Core/src/ca/uqac/lif/labpal/server/PlotsPageCallback.java index 4ff1a5a1..af989525 100755 --- a/Source/Core/src/ca/uqac/lif/labpal/server/PlotsPageCallback.java +++ b/Source/Core/src/ca/uqac/lif/labpal/server/PlotsPageCallback.java @@ -66,6 +66,7 @@ public String fill(String page, Map params, boolean is_offline) out = out.replaceAll("\\{%PLOTS%\\}", "

Gnuplot was not detected on this system. The plot functionality is disabled.

"); } out = out.replaceAll("\\{%SEL_PLOTS%\\}", "selected"); + out = out.replaceAll("\\{%HEADER_PROGRESS_BAR%\\}", getHeaderBar()); return out; } diff --git a/Source/Core/src/ca/uqac/lif/labpal/server/StatusPageCallback.java b/Source/Core/src/ca/uqac/lif/labpal/server/StatusPageCallback.java index b1d8cd7b..41c9d8f0 100755 --- a/Source/Core/src/ca/uqac/lif/labpal/server/StatusPageCallback.java +++ b/Source/Core/src/ca/uqac/lif/labpal/server/StatusPageCallback.java @@ -143,14 +143,16 @@ public String getBar() { num_ex++; Experiment ex = m_lab.getExperiment(id); + //out.append("
Running experiment : #").append(id).append("
\n"); switch (ex.getStatus()) { case RUNNING: out.delete(0,out.length()+1); - out.append("
Running experiment : #").append(ex.getId()).append("
\n"); + out.append("
Running experiment : #").append(id).append("
\n"); break; case DONE: num_done++; + break; case FAILED: num_failed++; diff --git a/Source/Core/src/ca/uqac/lif/labpal/server/TablesPageCallback.java b/Source/Core/src/ca/uqac/lif/labpal/server/TablesPageCallback.java index 9d31019f..b3538a3f 100755 --- a/Source/Core/src/ca/uqac/lif/labpal/server/TablesPageCallback.java +++ b/Source/Core/src/ca/uqac/lif/labpal/server/TablesPageCallback.java @@ -65,6 +65,7 @@ public String fill(String page, Map params, boolean is_offline) out = out.replaceAll("\\{%ALL_TABLES%\\}", Matcher.quoteReplacement("

Download all tables

")); out = out.replaceAll("\\{%SEL_TABLES%\\}", "selected"); out = out.replaceAll("\\{%FAVICON%\\}", getFavicon(IconType.TABLE)); + out = out.replaceAll("\\{%HEADER_PROGRESS_BAR%\\}", getHeaderBar()); return out; } diff --git a/Source/Core/src/ca/uqac/lif/labpal/server/TemplatePageCallback.java b/Source/Core/src/ca/uqac/lif/labpal/server/TemplatePageCallback.java index 3de561e7..a905a0c2 100755 --- a/Source/Core/src/ca/uqac/lif/labpal/server/TemplatePageCallback.java +++ b/Source/Core/src/ca/uqac/lif/labpal/server/TemplatePageCallback.java @@ -268,4 +268,5 @@ public String exportToStaticHtml(String path_to_root) contents = relativizeUrls(contents, path_to_root); return contents; } + } diff --git a/Source/Core/src/ca/uqac/lif/labpal/server/UploadCallback.java b/Source/Core/src/ca/uqac/lif/labpal/server/UploadCallback.java index 1bb3393a..59367a93 100644 --- a/Source/Core/src/ca/uqac/lif/labpal/server/UploadCallback.java +++ b/Source/Core/src/ca/uqac/lif/labpal/server/UploadCallback.java @@ -141,6 +141,7 @@ public CallbackResponse process(HttpExchange t) String file_contents = FileHelper.internalFileToString(LabPalServer.class, TemplatePageCallback.s_path + "/upload-ok.html"); file_contents = TemplatePageCallback.resolveInclude(file_contents); file_contents = file_contents.replaceAll("\\{%TITLE%\\}", "File uploaded"); + file_contents = file_contents.replaceAll("\\{%HEADER_PROGRESS_BAR%\\}", getHeaderBar()); cbr.setCode(CallbackResponse.HTTP_OK); cbr.setContents(file_contents); return cbr; diff --git a/Source/Core/src/ca/uqac/lif/labpal/server/WebCallback.java b/Source/Core/src/ca/uqac/lif/labpal/server/WebCallback.java index 31e2e3f7..4010b997 100755 --- a/Source/Core/src/ca/uqac/lif/labpal/server/WebCallback.java +++ b/Source/Core/src/ca/uqac/lif/labpal/server/WebCallback.java @@ -25,6 +25,7 @@ import ca.uqac.lif.jerrydog.CallbackResponse; import ca.uqac.lif.jerrydog.RestCleanCallback; +import ca.uqac.lif.labpal.Experiment; import ca.uqac.lif.labpal.FileHelper; import ca.uqac.lif.labpal.LabAssistant; import ca.uqac.lif.labpal.Laboratory; @@ -134,4 +135,65 @@ public void addToZipBundle(ZipOutputStream zos) throws IOException // Do nothing return; } + + /** + * Produces a status bar indicating the relative completion of the + * experiments in this lab. + * @return HTML code for the status bar + */ + public final String getHeaderBar() + { + // Width of the bar, in pixels + final float bar_width_px = 400; + int num_ex = 0, num_q = 0, num_failed = 0, num_done = 0, num_warn = 0; + StringBuilder out = new StringBuilder(); + for (int id : m_lab.getExperimentIds()) + { + num_ex++; + Experiment ex = m_lab.getExperiment(id); + switch (ex.getStatus()) + { + case RUNNING: + out.delete(0,out.length()+1); + out.append("
Running experiment : #").append(id).append("
\n"); + break; + case DONE: + num_done++; + break; + case FAILED: + num_failed++; + break; + case DONE_WARNING: + num_warn++; + break; + default: + if (m_assistant.isQueued(id)) + { + num_q++; + } + break; + } + } + + //StringBuilder out = new StringBuilder(); + float scale = bar_width_px / num_ex; + int num_remaining = num_ex - num_done - num_q - num_failed; + + out.append("
    "); + out.append("
  • Done: ").append(num_done).append("
  • "); + out.append("
  • Queued: ").append(num_q).append("
  • "); + out.append("
  • Warnings: ").append(num_warn).append("
  • "); + out.append("
  • Failed/cancelled: ").append(num_failed).append("
  • "); + out.append("
  • Other: ").append(num_remaining).append("
  • "); + out.append("
"); + out.append("
").append(num_done).append("/").append(num_ex).append("
"); + out.append("
"); + if (num_q !=0) + { + return out.toString(); + } + else return ""; + + } + } diff --git a/Source/Core/src/ca/uqac/lif/labpal/server/resource/header.inc.html b/Source/Core/src/ca/uqac/lif/labpal/server/resource/header.inc.html index 65ec70da..41b8cda2 100755 --- a/Source/Core/src/ca/uqac/lif/labpal/server/resource/header.inc.html +++ b/Source/Core/src/ca/uqac/lif/labpal/server/resource/header.inc.html @@ -13,4 +13,5 @@
-

{%TITLE%}

\ No newline at end of file +

{%TITLE%}

+{%HEADER_PROGRESS_BAR%} \ No newline at end of file diff --git a/Source/Core/src/ca/uqac/lif/labpal/server/resource/parkbench.js b/Source/Core/src/ca/uqac/lif/labpal/server/resource/parkbench.js index 0a7927a7..f94e4abb 100755 --- a/Source/Core/src/ca/uqac/lif/labpal/server/resource/parkbench.js +++ b/Source/Core/src/ca/uqac/lif/labpal/server/resource/parkbench.js @@ -97,3 +97,25 @@ function resize_top_menu() { * Resize menu on window resize */ $(window).resize(resize_top_menu); + +/** + * set selected file name to input label + */ +var inputs = document.querySelectorAll( '.input-upload' ); +Array.prototype.forEach.call( inputs, function( input ) +{ + var label = input.nextElementSibling, + labelVal = label.innerHTML; + + input.addEventListener( 'change', function( e ) + { + var fileName = ''; + fileName = e.target.value.split( '\\' ).pop(); + if( fileName ) + label.querySelector( 'span' ).innerHTML = fileName; + else + label.innerHTML = labelVal; + }); +}); + +}); \ No newline at end of file diff --git a/Source/Core/src/ca/uqac/lif/labpal/server/resource/screen.css b/Source/Core/src/ca/uqac/lif/labpal/server/resource/screen.css index a08fc963..72761699 100755 --- a/Source/Core/src/ca/uqac/lif/labpal/server/resource/screen.css +++ b/Source/Core/src/ca/uqac/lif/labpal/server/resource/screen.css @@ -208,6 +208,34 @@ h1 { box-shadow: 2px 2px 0px 0px rgba(115,115,115,1); } +.input-upload { + width: 0.1px; + height: 0.1px; + opacity: 0; + overflow: hidden; + position: absolute; + z-index: -1; +} + +.input-upload + label { + border: solid 1px darkgrey; + border-radius: 4px; + height: 22px; + line-height: 20px; + background: {%COLOR 4%}; + padding: 4px; + display: inline-block; + text-decoration: none; + color: #222; + box-shadow: 2px 2px 0px 0px rgba(115,115,115,1); + font-size:13px; + font-family:arial, sans-serif; +} + +.input-upload:hover + label { + background-color: #e8e8e8; +} + #btn-download { background: {%COLOR 4%} url('images/download-24.png') 4px 4px no-repeat; padding-left: 40px; @@ -297,10 +325,15 @@ table.exp-table th { } .top-td { + font-weight: bold; background: {%COLOR 3%}; } -table.exp-table tr:hover td { +.top-td-center { + text-align: center; +} + +table.exp-table tr:hover { background-color: rgba(224, 224, 236, 0.5); } diff --git a/Source/Core/src/ca/uqac/lif/labpal/server/resource/status.html b/Source/Core/src/ca/uqac/lif/labpal/server/resource/status.html index 725739a0..b7b25ead 100755 --- a/Source/Core/src/ca/uqac/lif/labpal/server/resource/status.html +++ b/Source/Core/src/ca/uqac/lif/labpal/server/resource/status.html @@ -18,7 +18,8 @@

Lab info

- + +

Progress

diff --git a/Source/Examples/build.xml b/Source/Examples/build.xml index 9b29e389..c9af6a4f 100755 --- a/Source/Examples/build.xml +++ b/Source/Examples/build.xml @@ -28,7 +28,7 @@ - + diff --git a/docs/doc/package-list b/docs/doc/package-list deleted file mode 100755 index 39ed5be0..00000000 --- a/docs/doc/package-list +++ /dev/null @@ -1,6 +0,0 @@ -ca.uqac.lif.labpal -ca.uqac.lif.labpal.macro -ca.uqac.lif.labpal.provenance -ca.uqac.lif.labpal.server -ca.uqac.lif.labpal.table -ca.uqac.lif.tui diff --git a/docs/doc/script.js b/docs/doc/script.js deleted file mode 100755 index b3463569..00000000 --- a/docs/doc/script.js +++ /dev/null @@ -1,30 +0,0 @@ -function show(type) -{ - count = 0; - for (var key in methods) { - var row = document.getElementById(key); - if ((methods[key] & type) != 0) { - row.style.display = ''; - row.className = (count++ % 2) ? rowColor : altColor; - } - else - row.style.display = 'none'; - } - updateTabs(type); -} - -function updateTabs(type) -{ - for (var value in tabs) { - var sNode = document.getElementById(tabs[value][0]); - var spanNode = sNode.firstChild; - if (value == type) { - sNode.className = activeTableTab; - spanNode.innerHTML = tabs[value][1]; - } - else { - sNode.className = tableTab; - spanNode.innerHTML = "" + tabs[value][1] + ""; - } - } -} diff --git a/docs/doc/stylesheet.css b/docs/doc/stylesheet.css deleted file mode 100755 index cebb4fd8..00000000 --- a/docs/doc/stylesheet.css +++ /dev/null @@ -1,574 +0,0 @@ -/* Javadoc style sheet */ -/* -Overall document style -*/ - -@import url('resources/fonts/dejavu.css'); - -body { - background-color:#ffffff; - color:#353833; - font-family:'DejaVu Sans', Arial, Helvetica, sans-serif; - font-size:14px; - margin:0; -} -a:link, a:visited { - text-decoration:none; - color:#4A6782; -} -a:hover, a:focus { - text-decoration:none; - color:#bb7a2a; -} -a:active { - text-decoration:none; - color:#4A6782; -} -a[name] { - color:#353833; -} -a[name]:hover { - text-decoration:none; - color:#353833; -} -pre { - font-family:'DejaVu Sans Mono', monospace; - font-size:14px; -} -h1 { - font-size:20px; -} -h2 { - font-size:18px; -} -h3 { - font-size:16px; - font-style:italic; -} -h4 { - font-size:13px; -} -h5 { - font-size:12px; -} -h6 { - font-size:11px; -} -ul { - list-style-type:disc; -} -code, tt { - font-family:'DejaVu Sans Mono', monospace; - font-size:14px; - padding-top:4px; - margin-top:8px; - line-height:1.4em; -} -dt code { - font-family:'DejaVu Sans Mono', monospace; - font-size:14px; - padding-top:4px; -} -table tr td dt code { - font-family:'DejaVu Sans Mono', monospace; - font-size:14px; - vertical-align:top; - padding-top:4px; -} -sup { - font-size:8px; -} -/* -Document title and Copyright styles -*/ -.clear { - clear:both; - height:0px; - overflow:hidden; -} -.aboutLanguage { - float:right; - padding:0px 21px; - font-size:11px; - z-index:200; - margin-top:-9px; -} -.legalCopy { - margin-left:.5em; -} -.bar a, .bar a:link, .bar a:visited, .bar a:active { - color:#FFFFFF; - text-decoration:none; -} -.bar a:hover, .bar a:focus { - color:#bb7a2a; -} -.tab { - background-color:#0066FF; - color:#ffffff; - padding:8px; - width:5em; - font-weight:bold; -} -/* -Navigation bar styles -*/ -.bar { - background-color:#4D7A97; - color:#FFFFFF; - padding:.8em .5em .4em .8em; - height:auto;/*height:1.8em;*/ - font-size:11px; - margin:0; -} -.topNav { - background-color:#4D7A97; - color:#FFFFFF; - float:left; - padding:0; - width:100%; - clear:right; - height:2.8em; - padding-top:10px; - overflow:hidden; - font-size:12px; -} -.bottomNav { - margin-top:10px; - background-color:#4D7A97; - color:#FFFFFF; - float:left; - padding:0; - width:100%; - clear:right; - height:2.8em; - padding-top:10px; - overflow:hidden; - font-size:12px; -} -.subNav { - background-color:#dee3e9; - float:left; - width:100%; - overflow:hidden; - font-size:12px; -} -.subNav div { - clear:left; - float:left; - padding:0 0 5px 6px; - text-transform:uppercase; -} -ul.navList, ul.subNavList { - float:left; - margin:0 25px 0 0; - padding:0; -} -ul.navList li{ - list-style:none; - float:left; - padding: 5px 6px; - text-transform:uppercase; -} -ul.subNavList li{ - list-style:none; - float:left; -} -.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited { - color:#FFFFFF; - text-decoration:none; - text-transform:uppercase; -} -.topNav a:hover, .bottomNav a:hover { - text-decoration:none; - color:#bb7a2a; - text-transform:uppercase; -} -.navBarCell1Rev { - background-color:#F8981D; - color:#253441; - margin: auto 5px; -} -.skipNav { - position:absolute; - top:auto; - left:-9999px; - overflow:hidden; -} -/* -Page header and footer styles -*/ -.header, .footer { - clear:both; - margin:0 20px; - padding:5px 0 0 0; -} -.indexHeader { - margin:10px; - position:relative; -} -.indexHeader span{ - margin-right:15px; -} -.indexHeader h1 { - font-size:13px; -} -.title { - color:#2c4557; - margin:10px 0; -} -.subTitle { - margin:5px 0 0 0; -} -.header ul { - margin:0 0 15px 0; - padding:0; -} -.footer ul { - margin:20px 0 5px 0; -} -.header ul li, .footer ul li { - list-style:none; - font-size:13px; -} -/* -Heading styles -*/ -div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { - background-color:#dee3e9; - border:1px solid #d0d9e0; - margin:0 0 6px -8px; - padding:7px 5px; -} -ul.blockList ul.blockList ul.blockList li.blockList h3 { - background-color:#dee3e9; - border:1px solid #d0d9e0; - margin:0 0 6px -8px; - padding:7px 5px; -} -ul.blockList ul.blockList li.blockList h3 { - padding:0; - margin:15px 0; -} -ul.blockList li.blockList h2 { - padding:0px 0 20px 0; -} -/* -Page layout container styles -*/ -.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer { - clear:both; - padding:10px 20px; - position:relative; -} -.indexContainer { - margin:10px; - position:relative; - font-size:12px; -} -.indexContainer h2 { - font-size:13px; - padding:0 0 3px 0; -} -.indexContainer ul { - margin:0; - padding:0; -} -.indexContainer ul li { - list-style:none; - padding-top:2px; -} -.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt { - font-size:12px; - font-weight:bold; - margin:10px 0 0 0; - color:#4E4E4E; -} -.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { - margin:5px 0 10px 0px; - font-size:14px; - font-family:'DejaVu Sans Mono',monospace; -} -.serializedFormContainer dl.nameValue dt { - margin-left:1px; - font-size:1.1em; - display:inline; - font-weight:bold; -} -.serializedFormContainer dl.nameValue dd { - margin:0 0 0 1px; - font-size:1.1em; - display:inline; -} -/* -List styles -*/ -ul.horizontal li { - display:inline; - font-size:0.9em; -} -ul.inheritance { - margin:0; - padding:0; -} -ul.inheritance li { - display:inline; - list-style:none; -} -ul.inheritance li ul.inheritance { - margin-left:15px; - padding-left:15px; - padding-top:1px; -} -ul.blockList, ul.blockListLast { - margin:10px 0 10px 0; - padding:0; -} -ul.blockList li.blockList, ul.blockListLast li.blockList { - list-style:none; - margin-bottom:15px; - line-height:1.4; -} -ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList { - padding:0px 20px 5px 10px; - border:1px solid #ededed; - background-color:#f8f8f8; -} -ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList { - padding:0 0 5px 8px; - background-color:#ffffff; - border:none; -} -ul.blockList ul.blockList ul.blockList ul.blockList li.blockList { - margin-left:0; - padding-left:0; - padding-bottom:15px; - border:none; -} -ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast { - list-style:none; - border-bottom:none; - padding-bottom:0; -} -table tr td dl, table tr td dl dt, table tr td dl dd { - margin-top:0; - margin-bottom:1px; -} -/* -Table styles -*/ -.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary { - width:100%; - border-left:1px solid #EEE; - border-right:1px solid #EEE; - border-bottom:1px solid #EEE; -} -.overviewSummary, .memberSummary { - padding:0px; -} -.overviewSummary caption, .memberSummary caption, .typeSummary caption, -.useSummary caption, .constantsSummary caption, .deprecatedSummary caption { - position:relative; - text-align:left; - background-repeat:no-repeat; - color:#253441; - font-weight:bold; - clear:none; - overflow:hidden; - padding:0px; - padding-top:10px; - padding-left:1px; - margin:0px; - white-space:pre; -} -.overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link, -.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link, -.overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover, -.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover, -.overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active, -.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active, -.overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited, -.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited { - color:#FFFFFF; -} -.overviewSummary caption span, .memberSummary caption span, .typeSummary caption span, -.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span { - white-space:nowrap; - padding-top:5px; - padding-left:12px; - padding-right:12px; - padding-bottom:7px; - display:inline-block; - float:left; - background-color:#F8981D; - border: none; - height:16px; -} -.memberSummary caption span.activeTableTab span { - white-space:nowrap; - padding-top:5px; - padding-left:12px; - padding-right:12px; - margin-right:3px; - display:inline-block; - float:left; - background-color:#F8981D; - height:16px; -} -.memberSummary caption span.tableTab span { - white-space:nowrap; - padding-top:5px; - padding-left:12px; - padding-right:12px; - margin-right:3px; - display:inline-block; - float:left; - background-color:#4D7A97; - height:16px; -} -.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab { - padding-top:0px; - padding-left:0px; - padding-right:0px; - background-image:none; - float:none; - display:inline; -} -.overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd, -.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd { - display:none; - width:5px; - position:relative; - float:left; - background-color:#F8981D; -} -.memberSummary .activeTableTab .tabEnd { - display:none; - width:5px; - margin-right:3px; - position:relative; - float:left; - background-color:#F8981D; -} -.memberSummary .tableTab .tabEnd { - display:none; - width:5px; - margin-right:3px; - position:relative; - background-color:#4D7A97; - float:left; - -} -.overviewSummary td, .memberSummary td, .typeSummary td, -.useSummary td, .constantsSummary td, .deprecatedSummary td { - text-align:left; - padding:0px 0px 12px 10px; - width:100%; -} -th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th, -td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{ - vertical-align:top; - padding-right:0px; - padding-top:8px; - padding-bottom:3px; -} -th.colFirst, th.colLast, th.colOne, .constantsSummary th { - background:#dee3e9; - text-align:left; - padding:8px 3px 3px 7px; -} -td.colFirst, th.colFirst { - white-space:nowrap; - font-size:13px; -} -td.colLast, th.colLast { - font-size:13px; -} -td.colOne, th.colOne { - font-size:13px; -} -.overviewSummary td.colFirst, .overviewSummary th.colFirst, -.overviewSummary td.colOne, .overviewSummary th.colOne, -.memberSummary td.colFirst, .memberSummary th.colFirst, -.memberSummary td.colOne, .memberSummary th.colOne, -.typeSummary td.colFirst{ - width:25%; - vertical-align:top; -} -td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover { - font-weight:bold; -} -.tableSubHeadingColor { - background-color:#EEEEFF; -} -.altColor { - background-color:#FFFFFF; -} -.rowColor { - background-color:#EEEEEF; -} -/* -Content styles -*/ -.description pre { - margin-top:0; -} -.deprecatedContent { - margin:0; - padding:10px 0; -} -.docSummary { - padding:0; -} - -ul.blockList ul.blockList ul.blockList li.blockList h3 { - font-style:normal; -} - -div.block { - font-size:14px; - font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; -} - -td.colLast div { - padding-top:0px; -} - - -td.colLast a { - padding-bottom:3px; -} -/* -Formatting effect styles -*/ -.sourceLineNo { - color:green; - padding:0 30px 0 0; -} -h1.hidden { - visibility:hidden; - overflow:hidden; - font-size:10px; -} -.block { - display:block; - margin:3px 10px 2px 0px; - color:#474747; -} -.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink, -.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel, -.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink { - font-weight:bold; -} -.deprecationComment, .emphasizedPhrase, .interfaceName { - font-style:italic; -} - -div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase, -div.block div.block span.interfaceName { - font-style:normal; -} - -div.contentContainer ul.blockList li.blockList h2{ - padding-bottom:0px; -} diff --git a/docs/manual/status-done-24.png b/docs/manual/status-done-24.png deleted file mode 100755 index 4224d22a..00000000 Binary files a/docs/manual/status-done-24.png and /dev/null differ diff --git a/docs/manual/status-fail-24.png b/docs/manual/status-fail-24.png deleted file mode 100755 index f9d22c2b..00000000 Binary files a/docs/manual/status-fail-24.png and /dev/null differ diff --git a/docs/manual/status-ok-24.png b/docs/manual/status-ok-24.png deleted file mode 100755 index 9360b576..00000000 Binary files a/docs/manual/status-ok-24.png and /dev/null differ diff --git a/docs/manual/status-prereq-24.png b/docs/manual/status-prereq-24.png deleted file mode 100755 index 85288161..00000000 Binary files a/docs/manual/status-prereq-24.png and /dev/null differ diff --git a/docs/manual/status-queued-24.png b/docs/manual/status-queued-24.png deleted file mode 100755 index 199f662c..00000000 Binary files a/docs/manual/status-queued-24.png and /dev/null differ diff --git a/docs/manual/status-running-24.png b/docs/manual/status-running-24.png deleted file mode 100755 index 5dd3b53e..00000000 Binary files a/docs/manual/status-running-24.png and /dev/null differ