diff --git a/container/oracle/initdb.d/05_test_data.sql b/container/oracle/initdb.d/05_test_data.sql index 80e6532..314322a 100644 --- a/container/oracle/initdb.d/05_test_data.sql +++ b/container/oracle/initdb.d/05_test_data.sql @@ -32,4 +32,8 @@ CREATE SEQUENCE BTM_OWNER.RUN_ID START WITH 2 NOCYCLE NOCACHE - ORDER; \ No newline at end of file + ORDER; + +-- Event First Incident +insert into BTM_OWNER.EVENT_FIRST_INCIDENT values (1, 'Testing Blocked', null, 1, 1, 'Testing Blocked', sysdate, 1); +insert into BTM_OWNER.EVENT_FIRST_INCIDENT values (2, 'Testing Tuning', null, 9, 2, 'Testing Tuning', sysdate, 1); \ No newline at end of file diff --git a/src/main/java/org/jlab/btm/business/service/CcSignatureService.java b/src/main/java/org/jlab/btm/business/service/CcSignatureService.java index fdac325..28e54fd 100644 --- a/src/main/java/org/jlab/btm/business/service/CcSignatureService.java +++ b/src/main/java/org/jlab/btm/business/service/CcSignatureService.java @@ -8,6 +8,7 @@ import jakarta.persistence.PersistenceContext; import jakarta.persistence.TypedQuery; import jakarta.servlet.http.HttpServletRequest; +import java.math.BigInteger; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -345,10 +346,22 @@ public void populateRequestAttributes( multiplicityAvailability.getShiftTotals()); // Downtime check - DowntimeSummaryTotals dtmTotals = downService.reportTotals(startHour, startOfNextShift); + DowntimeSummaryTotals dtmTotals = + downService.reportTotals(startHour, startOfNextShift, BigInteger.ONE); + + DowntimeSummaryTotals tuningHours = + downService.reportTotals(startHour, startOfNextShift, BigInteger.valueOf(9L)); CcDowntimeCrossCheck downCrossCheck = - new CcDowntimeCrossCheck(accAvailability.getShiftTotals(), dtmTotals.getEventSeconds()); + new CcDowntimeCrossCheck( + accAvailability.getShiftTotals(), + dtmTotals.getEventSeconds(), + tuningHours.getEventSeconds()); + + List dtmHourList = downService.getDtmHourList(startHour, startOfNextShift); + + List downHourlyCrossCheckList = + downService.getCrossCheckHourList(accAvailability.getDbHourList(), dtmHourList); request.setAttribute("plan", plan); request.setAttribute("accAvailability", accAvailability); @@ -368,11 +381,15 @@ public void populateRequestAttributes( request.setAttribute("multiCrossCheck", multiCrossCheck); request.setAttribute("downCrossCheck", downCrossCheck); request.setAttribute("dtmTotals", dtmTotals); + request.setAttribute("tuningHours", tuningHours); request.setAttribute("hallAHourCrossCheckList", hallAHourCrossCheckList); request.setAttribute("hallBHourCrossCheckList", hallBHourCrossCheckList); request.setAttribute("hallCHourCrossCheckList", hallCHourCrossCheckList); request.setAttribute("hallDHourCrossCheckList", hallDHourCrossCheckList); + request.setAttribute("dtmHourList", dtmHourList); + request.setAttribute("downHourlyCrossCheckList", downHourlyCrossCheckList); + // DEBUG /*for(int i = 0; i < hallAvailabilityList.size(); i++) { CcHallShiftAvailability ha = hallAvailabilityList.get(i); diff --git a/src/main/java/org/jlab/btm/business/service/DowntimeService.java b/src/main/java/org/jlab/btm/business/service/DowntimeService.java index 8535a99..0a2bfd0 100644 --- a/src/main/java/org/jlab/btm/business/service/DowntimeService.java +++ b/src/main/java/org/jlab/btm/business/service/DowntimeService.java @@ -5,13 +5,14 @@ import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import jakarta.persistence.Query; +import java.math.BigInteger; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.logging.Logger; import org.jlab.btm.persistence.entity.CcAccHour; -import org.jlab.btm.persistence.projection.DowntimeSummaryTotals; +import org.jlab.btm.persistence.projection.*; import org.jlab.smoothness.business.util.DateIterator; import org.jlab.smoothness.business.util.TimeUtil; import org.jlab.smoothness.persistence.util.JPAUtil; @@ -37,18 +38,19 @@ protected EntityManager getEntityManager() { } @PermitAll - public DowntimeSummaryTotals reportTotals(Date start, Date end) { + public DowntimeSummaryTotals reportTotals(Date start, Date end, BigInteger eventTypeId) { Query q = em.createNativeQuery( "select sum(downtime_seconds) as downtime_seconds " + "from (select " + "btm_owner.interval_to_seconds(least(nvl(a.time_up, sysdate), :end) - greatest(a.time_down, :start)) as downtime_seconds " + "from btm_owner.event_first_incident a " - + "where a.event_type_id = 1 " + + "where a.event_type_id = :typeId " + "and a.time_down < :end " + "and nvl(a.time_up, sysdate) >= :start " + "union all (select 0 from dual))"); + q.setParameter("typeId", eventTypeId); q.setParameter("start", start); q.setParameter("end", end); @@ -88,7 +90,7 @@ public List dayTotals(Date start, Date end) { Date realStart = (startDayHourZero.getTime() == day.getTime()) ? start : startOfDay; Date realEnd = iterator.hasNext() ? startOfNextDay : end; - DowntimeSummaryTotals totals = this.reportTotals(realStart, realEnd); + DowntimeSummaryTotals totals = this.reportTotals(realStart, realEnd, BigInteger.ONE); DayTotals mt = new DayTotals(); mt.day = startOfDay; mt.totals = totals; @@ -123,7 +125,7 @@ public List monthTotals(Date start, Date end) { Date realStart = (startMonthDayOne.getTime() == month.getTime()) ? start : startOfMonth; Date realEnd = iterator.hasNext() ? startOfNextMonth : end; - DowntimeSummaryTotals totals = this.reportTotals(realStart, realEnd); + DowntimeSummaryTotals totals = this.reportTotals(realStart, realEnd, BigInteger.ONE); MonthTotals mt = new MonthTotals(); mt.month = startOfMonth; mt.totals = totals; @@ -133,6 +135,61 @@ public List monthTotals(Date start, Date end) { return monthTotals; } + @PermitAll + public List getCrossCheckHourList( + List ccAccHourList, List dtmHourList) { + List checkList = new ArrayList<>(); + + for (int i = 0; i < ccAccHourList.size(); i++) { + CcAccHour ccAccHour = ccAccHourList.get(i); + DtmHour dtmHour = dtmHourList.get(i); + + // System.err.println(ccAccHour + " " + dtmHour); + + DowntimeHourCrossCheck checkHour = + new DowntimeHourCrossCheck(ccAccHour.getDayAndHour(), ccAccHour, dtmHour); + checkList.add(checkHour); + } + + return checkList; + } + + @PermitAll + public List getDtmHourList(Date startHour, Date endHourExclusive) { + + Date endHourInclusive = TimeUtil.addHours(endHourExclusive, -1); + + List dtmHourList = new ArrayList<>(); + DateIterator iterator = new DateIterator(startHour, endHourInclusive, Calendar.HOUR_OF_DAY); + + while (iterator.hasNext()) { + Date hour = iterator.next(); + + Date startOfNextHour = TimeUtil.addHours(hour, 1); + + short blockedSeconds = 0; + short tuningSeconds = 0; + + DowntimeSummaryTotals blockedTotals = + this.reportTotals(hour, startOfNextHour, BigInteger.ONE); + + DowntimeSummaryTotals tuningTotals = + this.reportTotals(hour, startOfNextHour, BigInteger.valueOf(9L)); + + blockedSeconds = (short) blockedTotals.getEventSeconds(); + tuningSeconds = (short) tuningTotals.getEventSeconds(); + + // System.out.println(hour + " - " + startOfNextHour + " blockedSeconds: " + blockedSeconds + + // " tuningSeconds: " + tuningSeconds); + + DtmHour dtmHour = new DtmHour(hour, blockedSeconds, tuningSeconds); + + dtmHourList.add(dtmHour); + } + + return dtmHourList; + } + public class DayTotals { Date day; diff --git a/src/main/java/org/jlab/btm/persistence/entity/CcAccHour.java b/src/main/java/org/jlab/btm/persistence/entity/CcAccHour.java index 4644f34..b79eb06 100644 --- a/src/main/java/org/jlab/btm/persistence/entity/CcAccHour.java +++ b/src/main/java/org/jlab/btm/persistence/entity/CcAccHour.java @@ -198,6 +198,6 @@ public boolean equals(Object object) { @Override public String toString() { - return "org.jlab.btm.persistence.entity.CcAccHour[ ccAccHourId=" + ccAccHourId + " ]"; + return "CcAccHour{" + "dayAndHour=" + dayAndHour + '}'; } } diff --git a/src/main/java/org/jlab/btm/persistence/projection/CcDowntimeCrossCheck.java b/src/main/java/org/jlab/btm/persistence/projection/CcDowntimeCrossCheck.java index 2e3c1f2..9a25bd2 100644 --- a/src/main/java/org/jlab/btm/persistence/projection/CcDowntimeCrossCheck.java +++ b/src/main/java/org/jlab/btm/persistence/projection/CcDowntimeCrossCheck.java @@ -12,29 +12,53 @@ public class CcDowntimeCrossCheck { private final boolean passed; private final boolean lowProgramPassed; + private final boolean highTuningPassed; private final String lowProgramMessage; + private final String highTuningMessage; - public CcDowntimeCrossCheck(CcAccShiftTotals acc, long dtmEventDownSeconds) { + public CcDowntimeCrossCheck(CcAccShiftTotals acc, long dtmEventDownSeconds, long tuningSeconds) { int possibleDowntimeSeconds = acc.calculatePossibleDowntimeSeconds(); + int upSeconds = acc.getUpSeconds(); lowProgramMessage = - "DTM event down (" + "DTM blocked event down (" + BtmFunctions.formatDuration((int) dtmEventDownSeconds, DurationUnits.HOURS) + " hours) is significantly greater than BTM possible down time [PHYSICS + INTERNAL DOWN] (" + BtmFunctions.formatDuration(possibleDowntimeSeconds, DurationUnits.HOURS) + " hours)"; + highTuningMessage = + "DTM tuning event down (" + + BtmFunctions.formatDuration((int) tuningSeconds, DurationUnits.HOURS) + + " hours) is significantly greater than BTM possible Tuning [PHYSICS] (" + + BtmFunctions.formatDuration(upSeconds, DurationUnits.HOURS) + + " hours)"; + lowProgramPassed = possibleDowntimeSeconds >= dtmEventDownSeconds - TEN_MINUTES_OF_SECONDS; - passed = lowProgramPassed; + highTuningPassed = upSeconds >= tuningSeconds - TEN_MINUTES_OF_SECONDS; + + passed = lowProgramPassed && highTuningPassed; } public boolean isPassed() { return passed; } + public boolean isLowProgramPassed() { + return lowProgramPassed; + } + + public boolean isHighTuningPassed() { + return highTuningPassed; + } + + public String getHighTuningMessage() { + return highTuningMessage; + } + public String getLowProgramMessage() { return lowProgramMessage; } diff --git a/src/main/java/org/jlab/btm/persistence/projection/DowntimeHourCrossCheck.java b/src/main/java/org/jlab/btm/persistence/projection/DowntimeHourCrossCheck.java new file mode 100644 index 0000000..3252f59 --- /dev/null +++ b/src/main/java/org/jlab/btm/persistence/projection/DowntimeHourCrossCheck.java @@ -0,0 +1,74 @@ +package org.jlab.btm.persistence.projection; + +import java.util.Date; +import org.jlab.btm.persistence.entity.CcAccHour; +import org.jlab.btm.persistence.enumeration.DurationUnits; +import org.jlab.btm.presentation.util.BtmFunctions; + +/** + * @author ryans + */ +public class DowntimeHourCrossCheck { + + private static final int HALF_HOUR_OF_SECONDS = 1800; + private static final int TEN_MINUTES_OF_SECONDS = 600; + + private final boolean passed; + private final boolean lowProgramPassed; + private final boolean highTuningPassed; + + private final String lowProgramMessage; + private final String highTuningMessage; + + private final Date dayAndHour; + + public DowntimeHourCrossCheck(Date dayAndHour, CcAccHour accHour, DtmHour dtmHour) { + this.dayAndHour = dayAndHour; + + int possibleDowntimeSeconds = accHour.getUpSeconds() + accHour.getDownSeconds(); + int upSeconds = accHour.getUpSeconds(); + + int blockedSeconds = dtmHour.getBlockedSeconds(); + int tuneSeconds = dtmHour.getTuneSeconds(); + + lowProgramMessage = + "DTM blocked event down (" + + BtmFunctions.formatDuration((int) blockedSeconds, DurationUnits.HOURS) + + " hours) is significantly greater than BTM possible down time [PHYSICS + INTERNAL DOWN] (" + + BtmFunctions.formatDuration(possibleDowntimeSeconds, DurationUnits.HOURS) + + " hours)"; + + highTuningMessage = + "DTM tuning event down (" + + BtmFunctions.formatDuration((int) tuneSeconds, DurationUnits.HOURS) + + " hours) is significantly greater than BTM possible Tuning [PHYSICS] (" + + BtmFunctions.formatDuration(upSeconds, DurationUnits.HOURS) + + " hours)"; + + lowProgramPassed = possibleDowntimeSeconds >= blockedSeconds - TEN_MINUTES_OF_SECONDS; + + highTuningPassed = upSeconds >= tuneSeconds - TEN_MINUTES_OF_SECONDS; + + passed = lowProgramPassed && highTuningPassed; + } + + public Date getDayAndHour() { + return dayAndHour; + } + + public boolean isLowProgramPassed() { + return lowProgramPassed; + } + + public boolean isHighTuningPassed() { + return highTuningPassed; + } + + public String getHighTuningMessage() { + return highTuningMessage; + } + + public String getLowProgramMessage() { + return lowProgramMessage; + } +} diff --git a/src/main/java/org/jlab/btm/persistence/projection/DtmHour.java b/src/main/java/org/jlab/btm/persistence/projection/DtmHour.java new file mode 100644 index 0000000..6fb43b8 --- /dev/null +++ b/src/main/java/org/jlab/btm/persistence/projection/DtmHour.java @@ -0,0 +1,76 @@ +package org.jlab.btm.persistence.projection; + +import java.util.Date; + +/** + * @author ryans + */ +public class DtmHour extends Hour { + + private Date dayAndHour; + + private short blockedSeconds; + + private short tuneSeconds; + + public DtmHour(Date dayAndHour, short blockedSeconds, short tuneSeconds) { + this.dayAndHour = dayAndHour; + this.blockedSeconds = blockedSeconds; + this.tuneSeconds = tuneSeconds; + } + + @Override + public Date getDayAndHour() { + return dayAndHour; + } + + @Override + public void setDayAndHour(Date dayAndHour) { + this.dayAndHour = dayAndHour; + } + + public short getBlockedSeconds() { + return blockedSeconds; + } + + public void setBlockedSeconds(short blockedSeconds) { + this.blockedSeconds = blockedSeconds; + } + + public short getTuneSeconds() { + return tuneSeconds; + } + + public void setTuneSeconds(short tuneSeconds) { + this.tuneSeconds = tuneSeconds; + } + + @Override + public int hashCode() { + int hash = 0; + hash += (this.getDayAndHour() != null ? this.getDayAndHour().hashCode() : 0); + return hash; + } + + @Override + public boolean equals(Object object) { + if (!(object instanceof DtmHour)) { + return false; + } + DtmHour other = (DtmHour) object; + return (this.getDayAndHour() != null || other.getDayAndHour() == null) + && (this.getDayAndHour() == null || this.getDayAndHour().equals(other.getDayAndHour())); + } + + @Override + public String toString() { + return "DtmHour{" + + "dayAndHour=" + + dayAndHour + + ", blockedSeconds=" + + blockedSeconds + + ", tuneSeconds=" + + tuneSeconds + + '}'; + } +} diff --git a/src/main/webapp/WEB-INF/includes/cross-check-panel.jsp b/src/main/webapp/WEB-INF/includes/cross-check-panel.jsp index 5c820d2..534abdb 100644 --- a/src/main/webapp/WEB-INF/includes/cross-check-panel.jsp +++ b/src/main/webapp/WEB-INF/includes/cross-check-panel.jsp @@ -12,12 +12,19 @@
-
BTM vs DTM
+
BTM vs DTM Blocked Program Downtime
- - + + @@ -25,17 +32,50 @@ - +
BTM Possible DowntimeDTM Event DowntimeBTM Possible Downtime (Physics + Internal Down) + + + + + + DTM Blocked Event Downtime ⮺ + Cross Check Status
${btm:formatDurationLossy(accAvailability.shiftTotals.calculatePossibleDowntimeSeconds(), durationUnits)} ${btm:formatDurationLossy(dtmTotals.eventSeconds, durationUnits)}${downCrossCheck.isPassed() ? '✔' : 'X'}${downCrossCheck.isLowProgramPassed() ? '✔' : 'X'}
    - +
+
BTM vs DTM Tuning Downtime
+ + + + + + + + + + + + + + + + + +
BTM Physics Total + + + + + + DTM Tuning Downtime ⮺ + Computed Delivered PhysicsCross Check Status
${btm:formatDurationLossy(accAvailability.shiftTotals.getUpSeconds(), durationUnits)}${btm:formatDurationLossy(tuningHours.eventSeconds, durationUnits)}${btm:formatDurationLossy(accAvailability.shiftTotals.getUpSeconds() - tuningHours.eventSeconds, durationUnits)}${downCrossCheck.isHighTuningPassed() ? '✔' : 'X'}
+
    + +
  • + +
  • +
    +
Hall Time Accounting
+
+ +
diff --git a/src/main/webapp/WEB-INF/tags/cc-timesheet.tag b/src/main/webapp/WEB-INF/tags/cc-timesheet.tag index f379b54..1f1aadb 100644 --- a/src/main/webapp/WEB-INF/tags/cc-timesheet.tag +++ b/src/main/webapp/WEB-INF/tags/cc-timesheet.tag @@ -20,6 +20,7 @@ PHYSICS + (Delivered + Tuning + Down) INTERNAL +<%@taglib prefix="c" uri="jakarta.tags.core" %> +<%@taglib prefix="fn" uri="jakarta.tags.functions" %> +<%@taglib prefix="fmt" uri="jakarta.tags.fmt" %> +<%@taglib prefix="btm" uri="jlab.tags.btm" %> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> +<%@attribute name="hourCrossCheckList" required="true" type="java.util.List" %> +<%@attribute name="dtmHourList" required="true" type="java.util.List" %> +<%@attribute name="btmHourList" required="true" type="java.util.List" %> +

BTM vs DTM

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BTMDTMCOMPUTED
{DELIVERED,BLOCKED,TUNING}{BLOCKED}{PHYSICS, INTERNAL DOWN}{PHYSICS}{PHYSICS-TUNING}
PHYSICSINTERNAL DOWNBLOCKEDTUNINGDELIVERED
+
    + + +
  • + [] +
  • +
    + +
  • + [] +
  • +
    +
    +
+
\ No newline at end of file diff --git a/src/main/webapp/resources/css/timesheet.css b/src/main/webapp/resources/css/timesheet.css index fc1a8ac..8e64202 100644 --- a/src/main/webapp/resources/css/timesheet.css +++ b/src/main/webapp/resources/css/timesheet.css @@ -246,6 +246,7 @@ table.editable-table tbody td span { #exp-avail-panel th.mirror-th, #exp-avail-panel td input, #exp-reasons-panel td, +#tune-check-table td, #dtm-btm-table td { text-align: right; } @@ -347,6 +348,7 @@ table.editable-table tbody td span { #comparison-table td:last-child, .cross-check-details td, +#tune-check-table td:last-child, #dtm-btm-table td:last-child { text-align: center; }