@seedtactics/insight-client 16.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -0
- package/dist/cell-status/buffers.d.ts +36 -0
- package/dist/cell-status/buffers.js +127 -0
- package/dist/cell-status/current-status.d.ts +30 -0
- package/dist/cell-status/current-status.js +200 -0
- package/dist/cell-status/estimated-cycle-times.d.ts +41 -0
- package/dist/cell-status/estimated-cycle-times.js +257 -0
- package/dist/cell-status/inspections.d.ts +55 -0
- package/dist/cell-status/inspections.js +213 -0
- package/dist/cell-status/loading.d.ts +26 -0
- package/dist/cell-status/loading.js +112 -0
- package/dist/cell-status/material-details.d.ts +116 -0
- package/dist/cell-status/material-details.js +422 -0
- package/dist/cell-status/material-summary.d.ts +52 -0
- package/dist/cell-status/material-summary.js +312 -0
- package/dist/cell-status/names.d.ts +19 -0
- package/dist/cell-status/names.js +134 -0
- package/dist/cell-status/pallet-cycles.d.ts +24 -0
- package/dist/cell-status/pallet-cycles.js +78 -0
- package/dist/cell-status/rebookings.d.ts +30 -0
- package/dist/cell-status/rebookings.js +139 -0
- package/dist/cell-status/scheduled-jobs.d.ts +18 -0
- package/dist/cell-status/scheduled-jobs.js +94 -0
- package/dist/cell-status/sim-day-usage.d.ts +14 -0
- package/dist/cell-status/sim-day-usage.js +54 -0
- package/dist/cell-status/sim-production.d.ts +22 -0
- package/dist/cell-status/sim-production.js +91 -0
- package/dist/cell-status/sim-station-use.d.ts +25 -0
- package/dist/cell-status/sim-station-use.js +71 -0
- package/dist/cell-status/station-cycles.d.ts +34 -0
- package/dist/cell-status/station-cycles.js +145 -0
- package/dist/cell-status/tool-replacements.d.ts +44 -0
- package/dist/cell-status/tool-replacements.js +155 -0
- package/dist/cell-status/tool-usage.d.ts +25 -0
- package/dist/cell-status/tool-usage.js +95 -0
- package/dist/components/App.d.ts +15 -0
- package/dist/components/App.js +549 -0
- package/dist/components/AxisAndGrid.d.ts +51 -0
- package/dist/components/AxisAndGrid.js +47 -0
- package/dist/components/BarcodeScanning.d.ts +6 -0
- package/dist/components/BarcodeScanning.js +150 -0
- package/dist/components/ChartTooltip.d.ts +28 -0
- package/dist/components/ChartTooltip.js +95 -0
- package/dist/components/ChooseMode.d.ts +18 -0
- package/dist/components/ChooseMode.js +136 -0
- package/dist/components/ChooseOperator.d.ts +1 -0
- package/dist/components/ChooseOperator.js +93 -0
- package/dist/components/ErrorsAndLoading.d.ts +9 -0
- package/dist/components/ErrorsAndLoading.js +55 -0
- package/dist/components/LoadingIcon.d.ts +1 -0
- package/dist/components/LoadingIcon.js +48 -0
- package/dist/components/LogEntry.d.ts +16 -0
- package/dist/components/LogEntry.js +365 -0
- package/dist/components/ManualSerialEntry.d.ts +5 -0
- package/dist/components/ManualSerialEntry.js +91 -0
- package/dist/components/MonthSelect.d.ts +6 -0
- package/dist/components/MonthSelect.js +67 -0
- package/dist/components/Navigation.d.ts +23 -0
- package/dist/components/Navigation.js +120 -0
- package/dist/components/VerboseLogging.d.ts +1 -0
- package/dist/components/VerboseLogging.js +47 -0
- package/dist/components/analysis/AnalysisSelectToolbar.d.ts +1 -0
- package/dist/components/analysis/AnalysisSelectToolbar.js +55 -0
- package/dist/components/analysis/BufferChart.d.ts +1 -0
- package/dist/components/analysis/BufferChart.js +139 -0
- package/dist/components/analysis/CostPerPiece.d.ts +2 -0
- package/dist/components/analysis/CostPerPiece.js +175 -0
- package/dist/components/analysis/CycleChart.d.ts +42 -0
- package/dist/components/analysis/CycleChart.js +281 -0
- package/dist/components/analysis/DataTable.d.ts +83 -0
- package/dist/components/analysis/DataTable.js +215 -0
- package/dist/components/analysis/EfficiencyPage.d.ts +2 -0
- package/dist/components/analysis/EfficiencyPage.js +138 -0
- package/dist/components/analysis/HeatChart.d.ts +22 -0
- package/dist/components/analysis/HeatChart.js +161 -0
- package/dist/components/analysis/InspectionDataTable.d.ts +10 -0
- package/dist/components/analysis/InspectionDataTable.js +148 -0
- package/dist/components/analysis/InspectionSankey.d.ts +12 -0
- package/dist/components/analysis/InspectionSankey.js +140 -0
- package/dist/components/analysis/PalletCycleCards.d.ts +1 -0
- package/dist/components/analysis/PalletCycleCards.js +137 -0
- package/dist/components/analysis/PartCycleCards.d.ts +2 -0
- package/dist/components/analysis/PartCycleCards.js +331 -0
- package/dist/components/analysis/QualityPage.d.ts +1 -0
- package/dist/components/analysis/QualityPage.js +49 -0
- package/dist/components/analysis/ScheduleHistory.d.ts +3 -0
- package/dist/components/analysis/ScheduleHistory.js +108 -0
- package/dist/components/analysis/StationDataTable.d.ts +25 -0
- package/dist/components/analysis/StationDataTable.js +246 -0
- package/dist/components/analysis/ToolReplacements.d.ts +1 -0
- package/dist/components/analysis/ToolReplacements.js +370 -0
- package/dist/components/operations/AllMaterial.d.ts +5 -0
- package/dist/components/operations/AllMaterial.js +267 -0
- package/dist/components/operations/ChartRangeEdit.d.ts +4 -0
- package/dist/components/operations/ChartRangeEdit.js +148 -0
- package/dist/components/operations/CloseoutReport.d.ts +2 -0
- package/dist/components/operations/CloseoutReport.js +172 -0
- package/dist/components/operations/CompletedParts.d.ts +2 -0
- package/dist/components/operations/CompletedParts.js +286 -0
- package/dist/components/operations/CurrentWorkorders.d.ts +3 -0
- package/dist/components/operations/CurrentWorkorders.js +368 -0
- package/dist/components/operations/Dashboard.d.ts +2 -0
- package/dist/components/operations/Dashboard.js +90 -0
- package/dist/components/operations/OEEChart.d.ts +10 -0
- package/dist/components/operations/OEEChart.js +173 -0
- package/dist/components/operations/Outliers.d.ts +4 -0
- package/dist/components/operations/Outliers.js +69 -0
- package/dist/components/operations/ProgramHighlight.d.ts +1 -0
- package/dist/components/operations/ProgramHighlight.js +9 -0
- package/dist/components/operations/Programs.d.ts +5 -0
- package/dist/components/operations/Programs.js +363 -0
- package/dist/components/operations/Rebookings.d.ts +1 -0
- package/dist/components/operations/Rebookings.js +213 -0
- package/dist/components/operations/RecentCycleChart.d.ts +4 -0
- package/dist/components/operations/RecentCycleChart.js +240 -0
- package/dist/components/operations/RecentProduction.d.ts +2 -0
- package/dist/components/operations/RecentProduction.js +213 -0
- package/dist/components/operations/RecentSchedules.d.ts +12 -0
- package/dist/components/operations/RecentSchedules.js +180 -0
- package/dist/components/operations/RecentStationCycles.d.ts +4 -0
- package/dist/components/operations/RecentStationCycles.js +159 -0
- package/dist/components/operations/ShiftSettings.d.ts +6 -0
- package/dist/components/operations/ShiftSettings.js +134 -0
- package/dist/components/operations/SimDayUsage.d.ts +1 -0
- package/dist/components/operations/SimDayUsage.js +133 -0
- package/dist/components/operations/ToolReport.d.ts +3 -0
- package/dist/components/operations/ToolReport.js +233 -0
- package/dist/components/operations/WorkorderGantt.d.ts +1 -0
- package/dist/components/operations/WorkorderGantt.js +124 -0
- package/dist/components/quality/QualityMaterial.d.ts +2 -0
- package/dist/components/quality/QualityMaterial.js +169 -0
- package/dist/components/quality/QualityPaths.d.ts +1 -0
- package/dist/components/quality/QualityPaths.js +53 -0
- package/dist/components/quality/RecentFailedInspections.d.ts +1 -0
- package/dist/components/quality/RecentFailedInspections.js +123 -0
- package/dist/components/routes.d.ts +170 -0
- package/dist/components/routes.js +301 -0
- package/dist/components/station-monitor/BulkRawMaterial.d.ts +11 -0
- package/dist/components/station-monitor/BulkRawMaterial.js +251 -0
- package/dist/components/station-monitor/Closeout.d.ts +5 -0
- package/dist/components/station-monitor/Closeout.js +162 -0
- package/dist/components/station-monitor/CustomStationMonitorDialog.d.ts +1 -0
- package/dist/components/station-monitor/CustomStationMonitorDialog.js +55 -0
- package/dist/components/station-monitor/Inspection.d.ts +8 -0
- package/dist/components/station-monitor/Inspection.js +164 -0
- package/dist/components/station-monitor/InvalidateCycle.d.ts +33 -0
- package/dist/components/station-monitor/InvalidateCycle.js +262 -0
- package/dist/components/station-monitor/JobDetails.d.ts +7 -0
- package/dist/components/station-monitor/JobDetails.js +108 -0
- package/dist/components/station-monitor/LoadStation.d.ts +10 -0
- package/dist/components/station-monitor/LoadStation.js +450 -0
- package/dist/components/station-monitor/Material.d.ts +77 -0
- package/dist/components/station-monitor/Material.js +489 -0
- package/dist/components/station-monitor/MoveMaterialArrows.d.ts +11 -0
- package/dist/components/station-monitor/MoveMaterialArrows.js +118 -0
- package/dist/components/station-monitor/PrintedLabel.d.ts +29 -0
- package/dist/components/station-monitor/PrintedLabel.js +166 -0
- package/dist/components/station-monitor/QuarantineButton.d.ts +4 -0
- package/dist/components/station-monitor/QuarantineButton.js +184 -0
- package/dist/components/station-monitor/Queues.d.ts +23 -0
- package/dist/components/station-monitor/Queues.js +312 -0
- package/dist/components/station-monitor/QueuesAddMaterial.d.ts +30 -0
- package/dist/components/station-monitor/QueuesAddMaterial.js +248 -0
- package/dist/components/station-monitor/SelectInspType.d.ts +2 -0
- package/dist/components/station-monitor/SelectInspType.js +99 -0
- package/dist/components/station-monitor/SelectWorkorder.d.ts +4 -0
- package/dist/components/station-monitor/SelectWorkorder.js +100 -0
- package/dist/components/station-monitor/StationToolbar.d.ts +3 -0
- package/dist/components/station-monitor/StationToolbar.js +168 -0
- package/dist/components/station-monitor/SystemOverview.d.ts +46 -0
- package/dist/components/station-monitor/SystemOverview.js +439 -0
- package/dist/components/station-monitor/Whiteboard.d.ts +10 -0
- package/dist/components/station-monitor/Whiteboard.js +67 -0
- package/dist/data/all-material-bins.d.ts +45 -0
- package/dist/data/all-material-bins.js +224 -0
- package/dist/data/chart-times.d.ts +20 -0
- package/dist/data/chart-times.js +99 -0
- package/dist/data/cost-per-piece.d.ts +32 -0
- package/dist/data/cost-per-piece.js +183 -0
- package/dist/data/current-cycles.d.ts +13 -0
- package/dist/data/current-cycles.js +144 -0
- package/dist/data/inspection-sankey.d.ts +15 -0
- package/dist/data/inspection-sankey.js +147 -0
- package/dist/data/move-arrows.d.ts +48 -0
- package/dist/data/move-arrows.js +217 -0
- package/dist/data/operators.d.ts +2 -0
- package/dist/data/operators.js +44 -0
- package/dist/data/part-summary.d.ts +17 -0
- package/dist/data/part-summary.js +107 -0
- package/dist/data/path-lookup.d.ts +13 -0
- package/dist/data/path-lookup.js +107 -0
- package/dist/data/queue-material.d.ts +46 -0
- package/dist/data/queue-material.js +256 -0
- package/dist/data/results.bufferchart.d.ts +10 -0
- package/dist/data/results.bufferchart.js +90 -0
- package/dist/data/results.completed-parts.d.ts +26 -0
- package/dist/data/results.completed-parts.js +181 -0
- package/dist/data/results.cycles.d.ts +86 -0
- package/dist/data/results.cycles.js +454 -0
- package/dist/data/results.inspection.d.ts +36 -0
- package/dist/data/results.inspection.js +188 -0
- package/dist/data/results.oee.d.ts +40 -0
- package/dist/data/results.oee.js +330 -0
- package/dist/data/results.schedules.d.ts +23 -0
- package/dist/data/results.schedules.js +157 -0
- package/dist/data/tools-programs.d.ts +78 -0
- package/dist/data/tools-programs.js +376 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +60 -0
- package/dist/network/api.d.ts +1390 -0
- package/dist/network/api.js +4971 -0
- package/dist/network/backend-mock.d.ts +11 -0
- package/dist/network/backend-mock.js +512 -0
- package/dist/network/backend.d.ts +57 -0
- package/dist/network/backend.js +77 -0
- package/dist/network/load-specific-month.d.ts +13 -0
- package/dist/network/load-specific-month.js +77 -0
- package/dist/network/server-settings.d.ts +12 -0
- package/dist/network/server-settings.js +92 -0
- package/dist/network/websocket.d.ts +4 -0
- package/dist/network/websocket.js +165 -0
- package/dist/renderer.d.ts +8 -0
- package/dist/renderer.js +55 -0
- package/dist/seedtactics-logo.d.ts +2 -0
- package/dist/seedtactics-logo.js +4 -0
- package/dist/util/chart-colors.d.ts +1 -0
- package/dist/util/chart-colors.js +116 -0
- package/dist/util/chart-helpers.d.ts +3 -0
- package/dist/util/chart-helpers.js +51 -0
- package/dist/util/parseISODuration.d.ts +4 -0
- package/dist/util/parseISODuration.js +40 -0
- package/docs/client-efficiency.md +355 -0
- package/docs/client-engineering.md +54 -0
- package/docs/client-launch.md +55 -0
- package/docs/client-operations.md +88 -0
- package/docs/client-quality.md +74 -0
- package/docs/client-sales.md +61 -0
- package/docs/client-scanners.md +41 -0
- package/docs/client-station-monitor.md +149 -0
- package/docs/client-tools-programs.md +74 -0
- package/docs/improve-fms.md +141 -0
- package/docs/makino.md +40 -0
- package/docs/material-quarantine.md +82 -0
- package/docs/material-tracking.md +236 -0
- package/docs/mazak.md +115 -0
- package/docs/niigata.md +228 -0
- package/docs/operator-procedures.md +106 -0
- package/docs/part-instructions.md +63 -0
- package/docs/screenshots/insight-all-material.png +0 -0
- package/docs/screenshots/insight-analysis-pallets.png +0 -0
- package/docs/screenshots/insight-analysis-part-completed.png +0 -0
- package/docs/screenshots/insight-analysis-sankey.png +0 -0
- package/docs/screenshots/insight-analysis-station-oee.png +0 -0
- package/docs/screenshots/insight-buffer-occupancy.png +0 -0
- package/docs/screenshots/insight-choose-analysis-month.png +0 -0
- package/docs/screenshots/insight-closeout.png +0 -0
- package/docs/screenshots/insight-cost-percentages.png +0 -0
- package/docs/screenshots/insight-dashboard.png +0 -0
- package/docs/screenshots/insight-event-custom-view.jpg +0 -0
- package/docs/screenshots/insight-event-viewer.jpg +0 -0
- package/docs/screenshots/insight-inspection.png +0 -0
- package/docs/screenshots/insight-load-station-details.png +0 -0
- package/docs/screenshots/insight-load-station.png +0 -0
- package/docs/screenshots/insight-loadcycle-graph.png +0 -0
- package/docs/screenshots/insight-loadstation-small.jpg +0 -0
- package/docs/screenshots/insight-machinecycle-graph.png +0 -0
- package/docs/screenshots/insight-machinecycle-table.png +0 -0
- package/docs/screenshots/insight-machinecycles.png +0 -0
- package/docs/screenshots/insight-machinehours.png +0 -0
- package/docs/screenshots/insight-machineoutliers.png +0 -0
- package/docs/screenshots/insight-monthly-schedules.png +0 -0
- package/docs/screenshots/insight-operations-material.png +0 -0
- package/docs/screenshots/insight-operations-overview.png +0 -0
- package/docs/screenshots/insight-operations-reports.png +0 -0
- package/docs/screenshots/insight-part-cost.png +0 -0
- package/docs/screenshots/insight-program-report.png +0 -0
- package/docs/screenshots/insight-quality-material-details.png +0 -0
- package/docs/screenshots/insight-quality-material.png +0 -0
- package/docs/screenshots/insight-quality-quarantine.png +0 -0
- package/docs/screenshots/insight-quality-sankey.png +0 -0
- package/docs/screenshots/insight-quality-similar-paths.png +0 -0
- package/docs/screenshots/insight-queue-details.png +0 -0
- package/docs/screenshots/insight-queues-jobs-table.png +0 -0
- package/docs/screenshots/insight-queues.png +0 -0
- package/docs/screenshots/insight-sim-day-usage.png +0 -0
- package/docs/screenshots/insight-station-system-overview-buttons.png +0 -0
- package/docs/screenshots/insight-station-system-overview.png +0 -0
- package/docs/screenshots/insight-system-overview.png +0 -0
- package/docs/screenshots/insight-tool-replacements.png +0 -0
- package/docs/screenshots/insight-tool-report.png +0 -0
- package/docs/screenshots/insight-toolbar-btns.png +0 -0
- package/docs/screenshots/insight-workorder-gantt.png +0 -0
- package/docs/screenshots/insight-workorders.png +0 -0
- package/docs/security.md +131 -0
- package/docs/server-config.md +56 -0
- package/docs/server-errors.md +44 -0
- package/package.json +90 -0
- package/src/index.ts +65 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/* Copyright (c) 2024, John Lenz
|
|
2
|
+
|
|
3
|
+
All rights reserved.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
* Redistributions of source code must retain the above copyright
|
|
9
|
+
notice, this list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
* Redistributions in binary form must reproduce the above
|
|
12
|
+
copyright notice, this list of conditions and the following
|
|
13
|
+
disclaimer in the documentation and/or other materials provided
|
|
14
|
+
with the distribution.
|
|
15
|
+
|
|
16
|
+
* Neither the name of John Lenz, Black Maple Software, SeedTactics,
|
|
17
|
+
nor the names of other contributors may be used to endorse or
|
|
18
|
+
promote products derived from this software without specific
|
|
19
|
+
prior written permission.
|
|
20
|
+
|
|
21
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
22
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
23
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
24
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
25
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
26
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
27
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
28
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
29
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
30
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
31
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
32
|
+
*/
|
|
33
|
+
import { LogType } from "../network/api.js";
|
|
34
|
+
import { calcElapsedForCycles, isOutlier, last30EstimatedCycleTimes, PartAndStationOperation, specificMonthEstimatedCycleTimes, } from "./estimated-cycle-times.js";
|
|
35
|
+
import { durationToMinutes } from "../util/parseISODuration.js";
|
|
36
|
+
import { addDays } from "date-fns";
|
|
37
|
+
import { HashMap } from "@seedtactics/immutable-collections";
|
|
38
|
+
import { atom } from "jotai";
|
|
39
|
+
export function stat_name_and_num(stationGroup, stationNumber) {
|
|
40
|
+
if (stationGroup.startsWith("Inspect")) {
|
|
41
|
+
return stationGroup;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
return stationGroup + " #" + stationNumber.toString();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const last30StationCyclesRW = atom(HashMap.empty());
|
|
48
|
+
export const last30StationCycles = last30StationCyclesRW;
|
|
49
|
+
const specificMonthStationCyclesRW = atom(HashMap.empty());
|
|
50
|
+
export const specificMonthStationCycles = specificMonthStationCyclesRW;
|
|
51
|
+
function convertLogToCycle(estimatedCycleTimes, cycle, elapsedPerMat) {
|
|
52
|
+
if (cycle.startofcycle ||
|
|
53
|
+
(cycle.type !== LogType.LoadUnloadCycle && cycle.type !== LogType.MachineCycle) ||
|
|
54
|
+
cycle.loc === "") {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
const part = cycle.material.length > 0 ? cycle.material[0].part : "";
|
|
58
|
+
const stats = cycle.material.length > 0
|
|
59
|
+
? estimatedCycleTimes.get(PartAndStationOperation.ofLogCycle(cycle))
|
|
60
|
+
: undefined;
|
|
61
|
+
let activeMins = durationToMinutes(cycle.active);
|
|
62
|
+
if (cycle.active === "" || activeMins <= 0 || cycle.material.length == 0) {
|
|
63
|
+
activeMins = (stats?.expectedCycleMinutesForSingleMat ?? 0) * cycle.material.length;
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
endTime: cycle.endUTC,
|
|
67
|
+
elapsedMinsPerMaterial: elapsedPerMat,
|
|
68
|
+
cntr: cycle.counter,
|
|
69
|
+
activeMinutes: activeMins,
|
|
70
|
+
medianCycleMinutes: (stats?.medianMinutesForSingleMat ?? 0) * cycle.material.length,
|
|
71
|
+
MAD_aboveMinutes: stats?.MAD_aboveMinutes ?? 0,
|
|
72
|
+
part: part,
|
|
73
|
+
pallet: cycle.pal,
|
|
74
|
+
material: cycle.material,
|
|
75
|
+
isLabor: cycle.type === LogType.LoadUnloadCycle,
|
|
76
|
+
isOutlier: stats ? isOutlier(stats, elapsedPerMat) : false,
|
|
77
|
+
stationGroup: cycle.loc,
|
|
78
|
+
stationNumber: cycle.locnum,
|
|
79
|
+
operation: cycle.type === LogType.LoadUnloadCycle ? cycle.result : cycle.program,
|
|
80
|
+
operator: cycle.details ? cycle.details.operator || "" : "",
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function convertOldLogsToCycles(estimateCycleTimes, log) {
|
|
84
|
+
return calcElapsedForCycles(log)
|
|
85
|
+
.collect((c) => convertLogToCycle(estimateCycleTimes, c.cycle, c.elapsedForSingleMaterialMinutes))
|
|
86
|
+
.buildHashMap((c) => c.cntr);
|
|
87
|
+
}
|
|
88
|
+
function process_swap(swap, partCycles) {
|
|
89
|
+
for (const changed of swap.editedEvents) {
|
|
90
|
+
const c = partCycles.get(changed.counter);
|
|
91
|
+
if (c !== undefined) {
|
|
92
|
+
const newC = { ...c, material: changed.material };
|
|
93
|
+
partCycles = partCycles.set(changed.counter, newC);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return partCycles;
|
|
97
|
+
}
|
|
98
|
+
export const setLast30StationCycles = atom(null, (get, set, log) => {
|
|
99
|
+
const estimatedCycleTimes = get(last30EstimatedCycleTimes);
|
|
100
|
+
set(last30StationCyclesRW, (oldCycles) => oldCycles.union(convertOldLogsToCycles(estimatedCycleTimes, log)));
|
|
101
|
+
});
|
|
102
|
+
export const updateLast30StationCycles = atom(null, (get, set, { evt, now, expire }) => {
|
|
103
|
+
if (evt.logEntry && evt.logEntry.type === LogType.InvalidateCycle) {
|
|
104
|
+
const cntrs = evt.logEntry.details?.["EditedCounters"];
|
|
105
|
+
const invalidatedCycles = cntrs ? new Set(cntrs.split(",").map((i) => parseInt(i))) : new Set();
|
|
106
|
+
if (invalidatedCycles.size > 0) {
|
|
107
|
+
set(last30StationCyclesRW, (cycles) => {
|
|
108
|
+
for (const invalid of invalidatedCycles) {
|
|
109
|
+
const c = cycles.get(invalid);
|
|
110
|
+
if (c !== undefined) {
|
|
111
|
+
cycles = cycles.set(invalid, { ...c, activeMinutes: 0 });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return cycles;
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else if (evt.logEntry) {
|
|
119
|
+
const estimatedCycleTimes = get(last30EstimatedCycleTimes);
|
|
120
|
+
// new events arriving over websocket are garuanteed to use the new method of calculating elapsed time
|
|
121
|
+
// where the server already splits the elapsed time among a chunk, so no need to chunk here
|
|
122
|
+
const elapsedPerMat = evt.logEntry.material.length > 0
|
|
123
|
+
? durationToMinutes(evt.logEntry.elapsed) / evt.logEntry.material.length
|
|
124
|
+
: 0;
|
|
125
|
+
const converted = convertLogToCycle(estimatedCycleTimes, evt.logEntry, elapsedPerMat);
|
|
126
|
+
if (!converted)
|
|
127
|
+
return;
|
|
128
|
+
set(last30StationCyclesRW, (cycles) => {
|
|
129
|
+
if (expire) {
|
|
130
|
+
const thirtyDaysAgo = addDays(now, -30);
|
|
131
|
+
cycles = cycles.filter((e) => e.endTime >= thirtyDaysAgo);
|
|
132
|
+
}
|
|
133
|
+
cycles = cycles.set(converted.cntr, converted);
|
|
134
|
+
return cycles;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
else if (evt.editMaterialInLog) {
|
|
138
|
+
const edit = evt.editMaterialInLog;
|
|
139
|
+
set(last30StationCyclesRW, (oldCycles) => process_swap(edit, oldCycles));
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
export const setSpecificMonthStationCycles = atom(null, (get, set, log) => {
|
|
143
|
+
const estimatedCycleTimes = get(specificMonthEstimatedCycleTimes);
|
|
144
|
+
set(specificMonthStationCyclesRW, convertOldLogsToCycles(estimatedCycleTimes, log));
|
|
145
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ILogEntry } from "../network/api.js";
|
|
2
|
+
import { OrderedMap, HashableObj } from "@seedtactics/immutable-collections";
|
|
3
|
+
import type { ServerEventAndTime } from "./loading.js";
|
|
4
|
+
export type ToolReplacement = {
|
|
5
|
+
readonly tool: string;
|
|
6
|
+
readonly pocket: number;
|
|
7
|
+
readonly type: "ReplaceBeforeCycleStart";
|
|
8
|
+
readonly useAtReplacement: number | null;
|
|
9
|
+
readonly cntAtReplacement: number | null;
|
|
10
|
+
} | {
|
|
11
|
+
readonly tool: string;
|
|
12
|
+
readonly pocket: number;
|
|
13
|
+
readonly type: "ReplaceInCycle";
|
|
14
|
+
readonly totalUseAtBeginningOfCycle: number | null;
|
|
15
|
+
readonly totalUseAtEndOfCycle: number | null;
|
|
16
|
+
readonly totalCntAtBeginningOfCycle: number | null;
|
|
17
|
+
readonly totalCntAtEndOfCycle: number | null;
|
|
18
|
+
};
|
|
19
|
+
export type ToolReplacements = {
|
|
20
|
+
readonly time: Date;
|
|
21
|
+
readonly replacements: ReadonlyArray<ToolReplacement>;
|
|
22
|
+
};
|
|
23
|
+
export declare class StationGroupAndNum implements HashableObj {
|
|
24
|
+
readonly group: string;
|
|
25
|
+
readonly num: number;
|
|
26
|
+
constructor(group: string, num: number);
|
|
27
|
+
static ofLogCycle(e: Readonly<ILogEntry>): StationGroupAndNum;
|
|
28
|
+
hash(): number;
|
|
29
|
+
compare(other: StationGroupAndNum): number;
|
|
30
|
+
toString(): string;
|
|
31
|
+
}
|
|
32
|
+
export type ToolReplacementsByCntr = OrderedMap<number, ToolReplacements>;
|
|
33
|
+
export type ToolReplacementsByStation = OrderedMap<StationGroupAndNum, ToolReplacementsByCntr>;
|
|
34
|
+
export declare const last30ToolReplacements: import("jotai").Atom<ToolReplacementsByStation>;
|
|
35
|
+
export declare const specificMonthToolReplacements: import("jotai").Atom<ToolReplacementsByStation>;
|
|
36
|
+
export declare const setLast30ToolReplacements: import("jotai").WritableAtom<null, [log: readonly Readonly<ILogEntry>[]], void> & {
|
|
37
|
+
init: null;
|
|
38
|
+
};
|
|
39
|
+
export declare const updateLastToolReplacements: import("jotai").WritableAtom<null, [ServerEventAndTime], void> & {
|
|
40
|
+
init: null;
|
|
41
|
+
};
|
|
42
|
+
export declare const setSpecificMonthToolReplacements: import("jotai").WritableAtom<null, [log: readonly Readonly<ILogEntry>[]], void> & {
|
|
43
|
+
init: null;
|
|
44
|
+
};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/* Copyright (c) 2022, John Lenz
|
|
2
|
+
|
|
3
|
+
All rights reserved.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
* Redistributions of source code must retain the above copyright
|
|
9
|
+
notice, this list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
* Redistributions in binary form must reproduce the above
|
|
12
|
+
copyright notice, this list of conditions and the following
|
|
13
|
+
disclaimer in the documentation and/or other materials provided
|
|
14
|
+
with the distribution.
|
|
15
|
+
|
|
16
|
+
* Neither the name of John Lenz, Black Maple Software, SeedTactics,
|
|
17
|
+
nor the names of other contributors may be used to endorse or
|
|
18
|
+
promote products derived from this software without specific
|
|
19
|
+
prior written permission.
|
|
20
|
+
|
|
21
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
22
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
23
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
24
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
25
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
26
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
27
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
28
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
29
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
30
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
31
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
32
|
+
*/
|
|
33
|
+
import { addDays } from "date-fns";
|
|
34
|
+
import { LogType } from "../network/api.js";
|
|
35
|
+
import { LazySeq, HashMap, OrderedMap, hashValues } from "@seedtactics/immutable-collections";
|
|
36
|
+
import { durationToMinutes } from "../util/parseISODuration.js";
|
|
37
|
+
import { atom } from "jotai";
|
|
38
|
+
export class StationGroupAndNum {
|
|
39
|
+
constructor(group, num) {
|
|
40
|
+
this.group = group;
|
|
41
|
+
this.num = num;
|
|
42
|
+
}
|
|
43
|
+
static ofLogCycle(e) {
|
|
44
|
+
return new StationGroupAndNum(e.loc, e.locnum);
|
|
45
|
+
}
|
|
46
|
+
hash() {
|
|
47
|
+
return hashValues(this.group, this.num);
|
|
48
|
+
}
|
|
49
|
+
compare(other) {
|
|
50
|
+
return this.group === other.group ? this.num - other.num : this.group.localeCompare(other.group);
|
|
51
|
+
}
|
|
52
|
+
toString() {
|
|
53
|
+
return this.group + " #" + this.num.toString();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const emptyReplacementsAndUse = {
|
|
57
|
+
replacements: OrderedMap.empty(),
|
|
58
|
+
recentUse: HashMap.empty(),
|
|
59
|
+
};
|
|
60
|
+
const last30ToolReplacementsRW = atom(emptyReplacementsAndUse);
|
|
61
|
+
export const last30ToolReplacements = atom((get) => get(last30ToolReplacementsRW).replacements);
|
|
62
|
+
const specificMonthToolReplacementsRW = atom(emptyReplacementsAndUse);
|
|
63
|
+
export const specificMonthToolReplacements = atom((get) => get(specificMonthToolReplacementsRW).replacements);
|
|
64
|
+
function addReplacementsFromLog(old, e) {
|
|
65
|
+
const key = StationGroupAndNum.ofLogCycle(e);
|
|
66
|
+
const newReplacements = old.replacements.alter(key, (cycles) => {
|
|
67
|
+
const replacements = [];
|
|
68
|
+
for (const use of e.tooluse ?? []) {
|
|
69
|
+
// see server/lib/BlackMaple.MachineFramework/backend/ToolSnapshotDiff.cs for the original calculations
|
|
70
|
+
const useDuring = use.toolUseDuringCycle !== null && use.toolUseDuringCycle !== undefined
|
|
71
|
+
? durationToMinutes(use.toolUseDuringCycle)
|
|
72
|
+
: null;
|
|
73
|
+
const totalUseAtEnd = use.totalToolUseAtEndOfCycle !== null && use.totalToolUseAtEndOfCycle !== undefined
|
|
74
|
+
? durationToMinutes(use.totalToolUseAtEndOfCycle)
|
|
75
|
+
: null;
|
|
76
|
+
const cntDuring = use.toolUseCountDuringCycle ?? null;
|
|
77
|
+
const totalCntAtEnd = use.totalToolUseCountAtEndOfCycle ?? null;
|
|
78
|
+
if ((useDuring || cntDuring) && useDuring === totalUseAtEnd && cntDuring === totalCntAtEnd) {
|
|
79
|
+
// replace before cycle start
|
|
80
|
+
const last = old.recentUse.get(key)?.find((e) => e.tool === use.tool && e.pocket === use.pocket);
|
|
81
|
+
if (last) {
|
|
82
|
+
const lastTotalUse = last.totalToolUseAtEndOfCycle
|
|
83
|
+
? durationToMinutes(last.totalToolUseAtEndOfCycle)
|
|
84
|
+
: null;
|
|
85
|
+
if (lastTotalUse || last.totalToolUseCountAtEndOfCycle) {
|
|
86
|
+
replacements.push({
|
|
87
|
+
tool: use.tool,
|
|
88
|
+
pocket: use.pocket,
|
|
89
|
+
type: "ReplaceBeforeCycleStart",
|
|
90
|
+
useAtReplacement: lastTotalUse,
|
|
91
|
+
cntAtReplacement: last.totalToolUseCountAtEndOfCycle ?? null,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else if (use.toolChangeOccurred &&
|
|
97
|
+
((useDuring && use.configuredToolLife) || (cntDuring && use.configuredToolLifeCount))) {
|
|
98
|
+
// replace in the middle of the cycle
|
|
99
|
+
// the server calculates useDuring = lifetime - useAtStartOfCycle + useAtEndOfCycle
|
|
100
|
+
// so solving for useAtStart = lifetime - useDuring + useAtEndOfCycle
|
|
101
|
+
const lifetime = use.configuredToolLife !== null && use.configuredToolLife !== undefined
|
|
102
|
+
? durationToMinutes(use.configuredToolLife)
|
|
103
|
+
: null;
|
|
104
|
+
const lifeCnt = use.configuredToolLifeCount ?? null;
|
|
105
|
+
replacements.push({
|
|
106
|
+
tool: use.tool,
|
|
107
|
+
pocket: use.pocket,
|
|
108
|
+
type: "ReplaceInCycle",
|
|
109
|
+
totalUseAtBeginningOfCycle: lifetime !== null && useDuring !== null ? lifetime - useDuring + (totalUseAtEnd ?? 0) : null,
|
|
110
|
+
totalUseAtEndOfCycle: totalUseAtEnd,
|
|
111
|
+
totalCntAtBeginningOfCycle: lifeCnt !== null && cntDuring !== null ? lifeCnt - cntDuring + (totalCntAtEnd ?? 0) : null,
|
|
112
|
+
totalCntAtEndOfCycle: totalCntAtEnd,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (replacements.length > 0) {
|
|
117
|
+
return (cycles ?? OrderedMap.empty()).set(e.counter, { time: e.endUTC, replacements });
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
return cycles;
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
const newRecent = e.tooluse ? old.recentUse.set(key, e.tooluse) : old.recentUse;
|
|
124
|
+
return { replacements: newReplacements, recentUse: newRecent };
|
|
125
|
+
}
|
|
126
|
+
export const setLast30ToolReplacements = atom(null, (_, set, log) => {
|
|
127
|
+
set(last30ToolReplacementsRW, (oldCycles) => LazySeq.of(log)
|
|
128
|
+
.filter((e) => e.type === LogType.MachineCycle && !e.startofcycle && !!e.tooluse && e.tooluse.length > 0)
|
|
129
|
+
.fold(oldCycles, addReplacementsFromLog));
|
|
130
|
+
});
|
|
131
|
+
export const updateLastToolReplacements = atom(null, (_, set, { evt, now, expire }) => {
|
|
132
|
+
if (evt.logEntry &&
|
|
133
|
+
!evt.logEntry.startofcycle &&
|
|
134
|
+
evt.logEntry.type === LogType.MachineCycle &&
|
|
135
|
+
evt.logEntry.tooluse &&
|
|
136
|
+
evt.logEntry.tooluse.length > 0) {
|
|
137
|
+
const log = evt.logEntry;
|
|
138
|
+
set(last30ToolReplacementsRW, (oldCycles) => {
|
|
139
|
+
if (expire) {
|
|
140
|
+
const thirtyDaysAgo = addDays(now, -30);
|
|
141
|
+
const newReplace = oldCycles.replacements.collectValues((es) => {
|
|
142
|
+
const newEs = es.filter((e) => e.time >= thirtyDaysAgo);
|
|
143
|
+
return newEs.size > 0 ? newEs : null;
|
|
144
|
+
});
|
|
145
|
+
oldCycles = { replacements: newReplace, recentUse: oldCycles.recentUse };
|
|
146
|
+
}
|
|
147
|
+
return addReplacementsFromLog(oldCycles, log);
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
export const setSpecificMonthToolReplacements = atom(null, (_, set, log) => {
|
|
152
|
+
set(specificMonthToolReplacementsRW, LazySeq.of(log)
|
|
153
|
+
.filter((e) => e.type === LogType.MachineCycle && !e.startofcycle && !!e.tooluse && e.tooluse.length > 0)
|
|
154
|
+
.fold(emptyReplacementsAndUse, addReplacementsFromLog));
|
|
155
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ILogEntry } from "../network/api.js";
|
|
2
|
+
import type { ServerEventAndTime } from "./loading.js";
|
|
3
|
+
import { PartAndStationOperation } from "./estimated-cycle-times.js";
|
|
4
|
+
import { HashMap, OrderedSet } from "@seedtactics/immutable-collections";
|
|
5
|
+
import { Atom } from "jotai";
|
|
6
|
+
export type ProgramToolUseInSingleCycle = {
|
|
7
|
+
readonly tools: ReadonlyArray<{
|
|
8
|
+
readonly toolName: string;
|
|
9
|
+
readonly cycleUsageMinutes: number;
|
|
10
|
+
readonly cycleUsageCnt: number;
|
|
11
|
+
readonly toolChangedDuringMiddleOfCycle: boolean;
|
|
12
|
+
}>;
|
|
13
|
+
};
|
|
14
|
+
export type RecentProgramToolUse = {
|
|
15
|
+
readonly machines: OrderedSet<string>;
|
|
16
|
+
readonly recentCycles: ReadonlyArray<ProgramToolUseInSingleCycle>;
|
|
17
|
+
};
|
|
18
|
+
export type ToolUsage = HashMap<PartAndStationOperation, RecentProgramToolUse>;
|
|
19
|
+
export declare const last30ToolUse: Atom<ToolUsage>;
|
|
20
|
+
export declare const setLast30ToolUse: import("jotai").WritableAtom<null, [log: readonly Readonly<ILogEntry>[]], void> & {
|
|
21
|
+
init: null;
|
|
22
|
+
};
|
|
23
|
+
export declare const updateLast30ToolUse: import("jotai").WritableAtom<null, [ServerEventAndTime], void> & {
|
|
24
|
+
init: null;
|
|
25
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/* Copyright (c) 2021, John Lenz
|
|
2
|
+
|
|
3
|
+
All rights reserved.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
* Redistributions of source code must retain the above copyright
|
|
9
|
+
notice, this list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
* Redistributions in binary form must reproduce the above
|
|
12
|
+
copyright notice, this list of conditions and the following
|
|
13
|
+
disclaimer in the documentation and/or other materials provided
|
|
14
|
+
with the distribution.
|
|
15
|
+
|
|
16
|
+
* Neither the name of John Lenz, Black Maple Software, SeedTactics,
|
|
17
|
+
nor the names of other contributors may be used to endorse or
|
|
18
|
+
promote products derived from this software without specific
|
|
19
|
+
prior written permission.
|
|
20
|
+
|
|
21
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
22
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
23
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
24
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
25
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
26
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
27
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
28
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
29
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
30
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
31
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
32
|
+
*/
|
|
33
|
+
import { LogType } from "../network/api.js";
|
|
34
|
+
import { durationToMinutes } from "../util/parseISODuration.js";
|
|
35
|
+
import { isOutlier, last30EstimatedCycleTimes, PartAndStationOperation, } from "./estimated-cycle-times.js";
|
|
36
|
+
import { LazySeq, HashMap, OrderedSet } from "@seedtactics/immutable-collections";
|
|
37
|
+
import { atom } from "jotai";
|
|
38
|
+
import { stat_name_and_num } from "./station-cycles.js";
|
|
39
|
+
const last30ToolUseRW = atom(HashMap.empty());
|
|
40
|
+
export const last30ToolUse = last30ToolUseRW;
|
|
41
|
+
function process_tools(cycle, estimatedCycleTimes, toolUsage) {
|
|
42
|
+
if (cycle.tooluse === undefined || cycle.tooluse.length === 0 || cycle.type !== LogType.MachineCycle) {
|
|
43
|
+
return toolUsage;
|
|
44
|
+
}
|
|
45
|
+
const stats = cycle.material.length > 0
|
|
46
|
+
? estimatedCycleTimes.get(PartAndStationOperation.ofLogCycle(cycle))
|
|
47
|
+
: undefined;
|
|
48
|
+
const elapsed = durationToMinutes(cycle.elapsed);
|
|
49
|
+
if (stats === undefined || isOutlier(stats, elapsed)) {
|
|
50
|
+
return toolUsage;
|
|
51
|
+
}
|
|
52
|
+
const key = PartAndStationOperation.ofLogCycle(cycle);
|
|
53
|
+
const toolsUsedInCycle = LazySeq.of(cycle.tooluse)
|
|
54
|
+
.groupBy((u) => u.tool)
|
|
55
|
+
.map(([toolName, uses]) => {
|
|
56
|
+
const useDuring = LazySeq.of(uses).sumBy((use) => use.toolUseDuringCycle && use.toolUseDuringCycle !== ""
|
|
57
|
+
? durationToMinutes(use.toolUseDuringCycle)
|
|
58
|
+
: 0);
|
|
59
|
+
const cntDuring = LazySeq.of(uses).sumBy((use) => use.toolUseCountDuringCycle ?? 0);
|
|
60
|
+
return {
|
|
61
|
+
toolName,
|
|
62
|
+
cycleUsageMinutes: useDuring,
|
|
63
|
+
cycleUsageCnt: cntDuring,
|
|
64
|
+
toolChangedDuringMiddleOfCycle: LazySeq.of(uses).some((use) => use.toolChangeOccurred ?? false),
|
|
65
|
+
};
|
|
66
|
+
})
|
|
67
|
+
.toRArray();
|
|
68
|
+
if (toolsUsedInCycle.length === 0 && toolUsage.has(key)) {
|
|
69
|
+
return toolUsage;
|
|
70
|
+
}
|
|
71
|
+
return toolUsage.modify(key, (old) => {
|
|
72
|
+
if (old) {
|
|
73
|
+
const n = old.recentCycles.slice(-4);
|
|
74
|
+
n.push({ tools: toolsUsedInCycle });
|
|
75
|
+
return { machines: old.machines.add(stat_name_and_num(cycle.loc, cycle.locnum)), recentCycles: n };
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
return {
|
|
79
|
+
machines: OrderedSet.empty().add(stat_name_and_num(cycle.loc, cycle.locnum)),
|
|
80
|
+
recentCycles: [{ tools: toolsUsedInCycle }],
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
export const setLast30ToolUse = atom(null, (get, set, log) => {
|
|
86
|
+
const estimated = get(last30EstimatedCycleTimes);
|
|
87
|
+
set(last30ToolUseRW, (oldUsage) => log.reduce((usage, log) => process_tools(log, estimated, usage), oldUsage));
|
|
88
|
+
});
|
|
89
|
+
export const updateLast30ToolUse = atom(null, (get, set, { evt }) => {
|
|
90
|
+
if (evt.logEntry) {
|
|
91
|
+
const log = evt.logEntry;
|
|
92
|
+
const estimated = get(last30EstimatedCycleTimes);
|
|
93
|
+
set(last30ToolUseRW, (oldUsage) => process_tools(log, estimated, oldUsage));
|
|
94
|
+
}
|
|
95
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ReactNode, ComponentType } from "react";
|
|
2
|
+
import { ChooseModeItem } from "./ChooseMode.js";
|
|
3
|
+
import * as serverSettings from "../network/server-settings.js";
|
|
4
|
+
export declare function NavTabs({ children }: {
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export interface AppProps {
|
|
8
|
+
readonly renderCustomPage?: (custom: ReadonlyArray<string>) => {
|
|
9
|
+
readonly nav: ComponentType | undefined;
|
|
10
|
+
readonly page: ReactNode;
|
|
11
|
+
};
|
|
12
|
+
readonly chooseModes?: (i: serverSettings.FMSInfoAndUser) => ReadonlyArray<ChooseModeItem> | null;
|
|
13
|
+
}
|
|
14
|
+
declare const App: import("react").NamedExoticComponent<AppProps>;
|
|
15
|
+
export default App;
|