@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
package/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# FMS Insight Client
|
|
2
|
+
|
|
3
|
+
This is the client half of [FMS
|
|
4
|
+
Insight](https://github.com/SeedTactics/fms-insight). FMS Insight is a program
|
|
5
|
+
for a flexible machining system (FMS) cell controller which tracks material,
|
|
6
|
+
records a log of events, helps with inspections and serial marking, presents
|
|
7
|
+
details about the cell via webpages, and more. These web pages help operators
|
|
8
|
+
on the shop floor manage material, supervisors monitor the day to day
|
|
9
|
+
activities, and engineers evaluate the long-term efficiency of tools and the
|
|
10
|
+
cell.
|
|
11
|
+
|
|
12
|
+
The server is written in C# and available on nuget in the
|
|
13
|
+
[BlackMaple.MachineFramework](https://www.nuget.org/packages/BlackMaple.MachineFramework)
|
|
14
|
+
package. The client in this npm package is a React SPA which communicates with
|
|
15
|
+
the server with HTTP JSON requests. The client is built using vite and served
|
|
16
|
+
as static files, typically by the C# server. Because of that, the nuget package
|
|
17
|
+
for the server contain a built version of the client. If you are just using
|
|
18
|
+
FMS Insight and don't intend any changes to the client, you can just use the
|
|
19
|
+
BlackMaple.MachineFramework nuget. This npm package is needed only if you wish
|
|
20
|
+
to modify the client or import portions of the client into your own pages.
|
|
21
|
+
|
|
22
|
+
## Code Overview
|
|
23
|
+
|
|
24
|
+
The client stores data in [jotai](https://jotai.org/) stores. We use a
|
|
25
|
+
thick-client approach: each client loads a large amout of events at startup and
|
|
26
|
+
then uses a websocket connection to keep the stores updated as new events occur.
|
|
27
|
+
Most of the reports and pages are then generated on the client, typically using
|
|
28
|
+
jotai atoms. The atoms storing the information about the cell are in the
|
|
29
|
+
`src/cell-status` directory. The code in the `src/network` directory handles
|
|
30
|
+
the initial data load and the websocket connection to keep the jotai stores updated.
|
|
31
|
+
|
|
32
|
+
The `src/data` directory contains a large amout of the client-side business logic
|
|
33
|
+
and report generating typescript code. It takes the raw event data from the cell
|
|
34
|
+
status and turns it into a format suitable for display. Finally, the `src/components`
|
|
35
|
+
directory contains the React components which display the various reports and pages.
|
|
36
|
+
To customize, you should look at `src/components/App.tsx` for inspiration: it imports
|
|
37
|
+
the various pages and handles the routing.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ServerEventAndTime } from "./loading.js";
|
|
2
|
+
import { ILogEntry } from "../network/api.js";
|
|
3
|
+
import { HashMap } from "@seedtactics/immutable-collections";
|
|
4
|
+
import { Atom } from "jotai";
|
|
5
|
+
export type BufferType = {
|
|
6
|
+
readonly type: "Rotary";
|
|
7
|
+
readonly machineGroup: string;
|
|
8
|
+
readonly machineNum: number;
|
|
9
|
+
} | {
|
|
10
|
+
readonly type: "StockerWaitForMC";
|
|
11
|
+
readonly stockerNum: number;
|
|
12
|
+
} | {
|
|
13
|
+
readonly type: "StockerWaitForUnload";
|
|
14
|
+
readonly stockerNum: number;
|
|
15
|
+
} | {
|
|
16
|
+
readonly type: "Queue";
|
|
17
|
+
readonly queue: string;
|
|
18
|
+
};
|
|
19
|
+
export interface BufferEntry {
|
|
20
|
+
readonly buffer: BufferType;
|
|
21
|
+
readonly endTime: Date;
|
|
22
|
+
readonly elapsedSeconds: number;
|
|
23
|
+
readonly numMaterial: number;
|
|
24
|
+
}
|
|
25
|
+
export type BufferEntryByCntr = HashMap<number, BufferEntry>;
|
|
26
|
+
export declare const last30BufferEntries: Atom<BufferEntryByCntr>;
|
|
27
|
+
export declare const specificMonthBufferEntries: Atom<BufferEntryByCntr>;
|
|
28
|
+
export declare const setLast30Buffer: import("jotai").WritableAtom<null, [log: readonly Readonly<ILogEntry>[]], void> & {
|
|
29
|
+
init: null;
|
|
30
|
+
};
|
|
31
|
+
export declare const updateLast30Buffer: import("jotai").WritableAtom<null, [ServerEventAndTime], void> & {
|
|
32
|
+
init: null;
|
|
33
|
+
};
|
|
34
|
+
export declare const setSpecificMonthBuffer: import("jotai").WritableAtom<null, [log: readonly Readonly<ILogEntry>[]], void> & {
|
|
35
|
+
init: null;
|
|
36
|
+
};
|
|
@@ -0,0 +1,127 @@
|
|
|
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 { addDays } from "date-fns";
|
|
34
|
+
import { LogType } from "../network/api.js";
|
|
35
|
+
import { durationToSeconds } from "../util/parseISODuration.js";
|
|
36
|
+
import { LazySeq, HashMap } from "@seedtactics/immutable-collections";
|
|
37
|
+
import { atom } from "jotai";
|
|
38
|
+
const last30BufferEntriesRW = atom(HashMap.empty());
|
|
39
|
+
export const last30BufferEntries = last30BufferEntriesRW;
|
|
40
|
+
const specificMonthBufferEntriesRW = atom(HashMap.empty());
|
|
41
|
+
export const specificMonthBufferEntries = specificMonthBufferEntriesRW;
|
|
42
|
+
function convertEntry(e) {
|
|
43
|
+
if (e.elapsed === "")
|
|
44
|
+
return null;
|
|
45
|
+
const elapsedSeconds = durationToSeconds(e.elapsed);
|
|
46
|
+
if (elapsedSeconds <= 0)
|
|
47
|
+
return null;
|
|
48
|
+
switch (e.type) {
|
|
49
|
+
case LogType.RemoveFromQueue:
|
|
50
|
+
return [
|
|
51
|
+
e.counter,
|
|
52
|
+
{
|
|
53
|
+
buffer: { type: "Queue", queue: e.loc },
|
|
54
|
+
endTime: e.endUTC,
|
|
55
|
+
elapsedSeconds,
|
|
56
|
+
numMaterial: e.material.length,
|
|
57
|
+
},
|
|
58
|
+
];
|
|
59
|
+
case LogType.PalletInStocker:
|
|
60
|
+
if (!e.startofcycle && e.result === "WaitForMachine") {
|
|
61
|
+
return [
|
|
62
|
+
e.counter,
|
|
63
|
+
{
|
|
64
|
+
buffer: { type: "StockerWaitForMC", stockerNum: e.locnum },
|
|
65
|
+
endTime: e.endUTC,
|
|
66
|
+
elapsedSeconds,
|
|
67
|
+
numMaterial: e.material.length,
|
|
68
|
+
},
|
|
69
|
+
];
|
|
70
|
+
}
|
|
71
|
+
else if (!e.startofcycle) {
|
|
72
|
+
return [
|
|
73
|
+
e.counter,
|
|
74
|
+
{
|
|
75
|
+
buffer: { type: "StockerWaitForUnload", stockerNum: e.locnum },
|
|
76
|
+
endTime: e.endUTC,
|
|
77
|
+
elapsedSeconds,
|
|
78
|
+
numMaterial: e.material.length,
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
case LogType.PalletOnRotaryInbound:
|
|
86
|
+
if (!e.startofcycle) {
|
|
87
|
+
return [
|
|
88
|
+
e.counter,
|
|
89
|
+
{
|
|
90
|
+
buffer: { type: "Rotary", machineGroup: e.loc, machineNum: e.locnum },
|
|
91
|
+
endTime: e.endUTC,
|
|
92
|
+
elapsedSeconds,
|
|
93
|
+
numMaterial: e.material.length,
|
|
94
|
+
},
|
|
95
|
+
];
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
default:
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export const setLast30Buffer = atom(null, (_, set, log) => {
|
|
105
|
+
set(last30BufferEntriesRW, (oldEntries) => oldEntries.union(LazySeq.of(log)
|
|
106
|
+
.collect(convertEntry)
|
|
107
|
+
.toHashMap((x) => x)));
|
|
108
|
+
});
|
|
109
|
+
export const updateLast30Buffer = atom(null, (_, set, { evt, now, expire }) => {
|
|
110
|
+
if (!evt.logEntry)
|
|
111
|
+
return;
|
|
112
|
+
const log = convertEntry(evt.logEntry);
|
|
113
|
+
if (!log)
|
|
114
|
+
return;
|
|
115
|
+
set(last30BufferEntriesRW, (entries) => {
|
|
116
|
+
if (expire) {
|
|
117
|
+
const expireD = addDays(now, -30);
|
|
118
|
+
entries = entries.filter((e) => e.endTime >= expireD);
|
|
119
|
+
}
|
|
120
|
+
return entries.set(log[0], log[1]);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
export const setSpecificMonthBuffer = atom(null, (_, set, log) => {
|
|
124
|
+
set(specificMonthBufferEntriesRW, LazySeq.of(log)
|
|
125
|
+
.collect(convertEntry)
|
|
126
|
+
.toHashMap((x) => x));
|
|
127
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ICurrentStatus } from "../network/api.js";
|
|
2
|
+
import type { ServerEventAndTime } from "./loading.js";
|
|
3
|
+
import { Atom } from "jotai";
|
|
4
|
+
export declare const currentStatus: Atom<ICurrentStatus>;
|
|
5
|
+
export declare const secondsSinceEpochAtom: import("jotai").PrimitiveAtom<number> & {
|
|
6
|
+
init: number;
|
|
7
|
+
};
|
|
8
|
+
export declare const setJobComment: import("jotai").WritableAtom<null, [uniq: string, newVal: string | null], void> & {
|
|
9
|
+
init: null;
|
|
10
|
+
};
|
|
11
|
+
export declare const addWorkorderComment: import("jotai").WritableAtom<null, [{
|
|
12
|
+
workorder: string;
|
|
13
|
+
comment: string;
|
|
14
|
+
}], void> & {
|
|
15
|
+
init: null;
|
|
16
|
+
};
|
|
17
|
+
export declare const setCurrentStatus: import("jotai").WritableAtom<null, [st: Readonly<ICurrentStatus>], void> & {
|
|
18
|
+
init: null;
|
|
19
|
+
};
|
|
20
|
+
export declare const updateCurrentStatus: import("jotai").WritableAtom<null, [ServerEventAndTime], void> & {
|
|
21
|
+
init: null;
|
|
22
|
+
};
|
|
23
|
+
export interface QueueReordering {
|
|
24
|
+
readonly queue: string;
|
|
25
|
+
readonly matId: number;
|
|
26
|
+
readonly newIdx: number;
|
|
27
|
+
}
|
|
28
|
+
export declare const reorderQueuedMatInCurrentStatus: import("jotai").WritableAtom<null, [QueueReordering], void> & {
|
|
29
|
+
init: null;
|
|
30
|
+
};
|
|
@@ -0,0 +1,200 @@
|
|
|
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 { JobsBackend, LogBackend } from "../network/backend.js";
|
|
34
|
+
import { InProcessMaterial, LogType, LocType, ActiveJob, WorkorderComment, ActiveWorkorder, } from "../network/api.js";
|
|
35
|
+
import { last30JobComment } from "./scheduled-jobs.js";
|
|
36
|
+
import { atom } from "jotai";
|
|
37
|
+
import { currentOperator } from "../data/operators.js";
|
|
38
|
+
const currentStatusRW = atom({
|
|
39
|
+
timeOfCurrentStatusUTC: new Date(),
|
|
40
|
+
jobs: {},
|
|
41
|
+
pallets: {},
|
|
42
|
+
material: [],
|
|
43
|
+
alarms: [],
|
|
44
|
+
queues: {},
|
|
45
|
+
});
|
|
46
|
+
export const currentStatus = currentStatusRW;
|
|
47
|
+
export const secondsSinceEpochAtom = atom(Math.floor(Date.now() / 1000));
|
|
48
|
+
secondsSinceEpochAtom.onMount = (setSelf) => {
|
|
49
|
+
const interval = setInterval(() => {
|
|
50
|
+
setSelf(Math.floor(Date.now() / 1000));
|
|
51
|
+
}, 1000);
|
|
52
|
+
return () => clearInterval(interval);
|
|
53
|
+
};
|
|
54
|
+
export const setJobComment = atom(null, (_, set, uniq, newVal) => {
|
|
55
|
+
const newComment = newVal === null ? "" : newVal;
|
|
56
|
+
set(currentStatusRW, (st) => {
|
|
57
|
+
const oldJob = st.jobs[uniq];
|
|
58
|
+
if (oldJob) {
|
|
59
|
+
const newJob = new ActiveJob(oldJob);
|
|
60
|
+
newJob.comment = newComment;
|
|
61
|
+
return { ...st, jobs: { ...st.jobs, [uniq]: newJob } };
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
return st;
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
set(last30JobComment(uniq), newComment);
|
|
68
|
+
void JobsBackend.setJobComment(uniq, newComment);
|
|
69
|
+
});
|
|
70
|
+
export const addWorkorderComment = atom(null, (get, set, { workorder, comment }) => {
|
|
71
|
+
const operator = get(currentOperator);
|
|
72
|
+
set(currentStatusRW, (st) => {
|
|
73
|
+
if (!st.workorders)
|
|
74
|
+
return st;
|
|
75
|
+
return {
|
|
76
|
+
...st,
|
|
77
|
+
workorders: st.workorders.map((w) => w.workorderId === workorder
|
|
78
|
+
? new ActiveWorkorder({
|
|
79
|
+
...w,
|
|
80
|
+
comments: [...(w.comments ?? []), new WorkorderComment({ comment, timeUTC: new Date() })],
|
|
81
|
+
})
|
|
82
|
+
: w),
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
void LogBackend.recordWorkorderComment(workorder, operator, comment);
|
|
86
|
+
});
|
|
87
|
+
export const setCurrentStatus = atom(null, (_, set, st) => set(currentStatusRW, st));
|
|
88
|
+
export const updateCurrentStatus = atom(null, (_, set, { evt }) => {
|
|
89
|
+
if (evt.logEntry) {
|
|
90
|
+
set(currentStatusRW, processEventsIntoCurrentStatus(evt.logEntry));
|
|
91
|
+
}
|
|
92
|
+
else if (evt.newCurrentStatus) {
|
|
93
|
+
set(currentStatusRW, evt.newCurrentStatus);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
function processEventsIntoCurrentStatus(entry) {
|
|
97
|
+
return (curSt) => {
|
|
98
|
+
const mats = new Map();
|
|
99
|
+
function adjustMat(id, f) {
|
|
100
|
+
if (mats.size === 0) {
|
|
101
|
+
for (const m of curSt.material) {
|
|
102
|
+
mats.set(m.materialID, m);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const oldMat = mats.get(id);
|
|
106
|
+
if (oldMat !== undefined) {
|
|
107
|
+
mats.set(id, new InProcessMaterial(f(oldMat)));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
switch (entry.type) {
|
|
111
|
+
case LogType.PartMark:
|
|
112
|
+
for (const m of entry.material) {
|
|
113
|
+
adjustMat(m.id, (inmat) => ({ ...inmat, serial: entry.result }));
|
|
114
|
+
}
|
|
115
|
+
break;
|
|
116
|
+
case LogType.OrderAssignment:
|
|
117
|
+
for (const m of entry.material) {
|
|
118
|
+
adjustMat(m.id, (inmat) => ({ ...inmat, workorderId: entry.result }));
|
|
119
|
+
}
|
|
120
|
+
break;
|
|
121
|
+
case LogType.Inspection:
|
|
122
|
+
case LogType.InspectionForce:
|
|
123
|
+
if (entry.result.toLowerCase() === "true" || entry.result === "1") {
|
|
124
|
+
let inspType;
|
|
125
|
+
if (entry.type === LogType.InspectionForce) {
|
|
126
|
+
inspType = entry.program;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
inspType = (entry.details || {}).InspectionType;
|
|
130
|
+
}
|
|
131
|
+
if (inspType) {
|
|
132
|
+
for (const m of entry.material) {
|
|
133
|
+
adjustMat(m.id, (inmat) => ({
|
|
134
|
+
...inmat,
|
|
135
|
+
signaledInspections: [...inmat.signaledInspections, inspType],
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
if (mats.size === 0) {
|
|
143
|
+
return curSt;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
return {
|
|
147
|
+
...curSt,
|
|
148
|
+
material: Array.from(mats.values()),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
export const reorderQueuedMatInCurrentStatus = atom(null, (_, set, { queue, matId, newIdx }) => {
|
|
154
|
+
set(currentStatusRW, (curSt) => {
|
|
155
|
+
const oldMat = curSt.material.find((i) => i.materialID === matId);
|
|
156
|
+
if (!oldMat || oldMat.location.type !== LocType.InQueue) {
|
|
157
|
+
return curSt;
|
|
158
|
+
}
|
|
159
|
+
if (oldMat.location.currentQueue === queue && oldMat.location.queuePosition === newIdx) {
|
|
160
|
+
return curSt;
|
|
161
|
+
}
|
|
162
|
+
const oldQueue = oldMat.location.currentQueue;
|
|
163
|
+
const oldIdx = oldMat.location.queuePosition;
|
|
164
|
+
if (oldIdx === undefined || oldQueue === undefined) {
|
|
165
|
+
return curSt;
|
|
166
|
+
}
|
|
167
|
+
const newMats = curSt.material.map((m) => {
|
|
168
|
+
if (m.location.type !== LocType.InQueue ||
|
|
169
|
+
m.location.queuePosition === undefined ||
|
|
170
|
+
m.location.currentQueue === undefined) {
|
|
171
|
+
return m;
|
|
172
|
+
}
|
|
173
|
+
if (m.materialID === matId) {
|
|
174
|
+
return new InProcessMaterial({
|
|
175
|
+
...m,
|
|
176
|
+
location: { type: LocType.InQueue, currentQueue: queue, queuePosition: newIdx },
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
let idx = m.location.queuePosition;
|
|
180
|
+
// old queue material is moved down
|
|
181
|
+
if (m.location.currentQueue === oldQueue && m.location.queuePosition > oldIdx) {
|
|
182
|
+
idx -= 1;
|
|
183
|
+
}
|
|
184
|
+
// new queue material is moved up to make room
|
|
185
|
+
if (m.location.currentQueue === queue && idx >= newIdx) {
|
|
186
|
+
idx += 1;
|
|
187
|
+
}
|
|
188
|
+
if (idx !== m.location.queuePosition) {
|
|
189
|
+
return new InProcessMaterial({
|
|
190
|
+
...m,
|
|
191
|
+
location: { ...m.location, queuePosition: idx },
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
return m;
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
return { ...curSt, material: newMats };
|
|
199
|
+
});
|
|
200
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ILogEntry } from "../network/api.js";
|
|
2
|
+
import { LazySeq, HashMap, OrderedMapKey } from "@seedtactics/immutable-collections";
|
|
3
|
+
import type { PartCycleData } from "./station-cycles.js";
|
|
4
|
+
import { Atom } from "jotai";
|
|
5
|
+
export interface StatisticalCycleTime {
|
|
6
|
+
readonly medianMinutesForSingleMat: number;
|
|
7
|
+
readonly MAD_belowMinutes: number;
|
|
8
|
+
readonly MAD_aboveMinutes: number;
|
|
9
|
+
readonly expectedCycleMinutesForSingleMat: number;
|
|
10
|
+
}
|
|
11
|
+
export declare class PartAndStationOperation {
|
|
12
|
+
readonly part: string;
|
|
13
|
+
readonly statGroup: string;
|
|
14
|
+
readonly operation: string;
|
|
15
|
+
constructor(part: string, statGroup: string, operation: string);
|
|
16
|
+
static ofLogCycle(c: Readonly<ILogEntry>): PartAndStationOperation;
|
|
17
|
+
static ofPartCycle(c: Readonly<PartCycleData>): PartAndStationOperation;
|
|
18
|
+
compare(other: PartAndStationOperation): number;
|
|
19
|
+
hash(): number;
|
|
20
|
+
toString(): string;
|
|
21
|
+
}
|
|
22
|
+
export type EstimatedCycleTimes = HashMap<PartAndStationOperation, StatisticalCycleTime>;
|
|
23
|
+
export declare const last30EstimatedCycleTimes: Atom<EstimatedCycleTimes>;
|
|
24
|
+
export declare const specificMonthEstimatedCycleTimes: Atom<EstimatedCycleTimes>;
|
|
25
|
+
export declare function isOutlier(s: StatisticalCycleTime, mins: number): boolean;
|
|
26
|
+
export declare function isOutlierAbove(s: StatisticalCycleTime, mins: number): boolean;
|
|
27
|
+
export declare function chunkCyclesWithSimilarEndTime<T, K>(allCycles: LazySeq<T>, getKey: (t: T) => K & OrderedMapKey, getTime: (c: T) => Date): LazySeq<[K, ReadonlyArray<ReadonlyArray<T>>]>;
|
|
28
|
+
export interface LogEntryWithSplitElapsed<T> {
|
|
29
|
+
readonly cycle: T;
|
|
30
|
+
readonly elapsedForSingleMaterialMinutes: number;
|
|
31
|
+
}
|
|
32
|
+
export declare function splitElapsedTimeAmongChunk<T extends {
|
|
33
|
+
material: ReadonlyArray<unknown>;
|
|
34
|
+
}>(chunk: ReadonlyArray<T>, getElapsedMins: (c: T) => number, getActiveMins: (c: T) => number): ReadonlyArray<LogEntryWithSplitElapsed<T>>;
|
|
35
|
+
export declare function calcElapsedForCycles(eventLog: ReadonlyArray<Readonly<ILogEntry>>): LazySeq<LogEntryWithSplitElapsed<Readonly<ILogEntry>>>;
|
|
36
|
+
export declare const setLast30EstimatedCycleTimes: import("jotai").WritableAtom<null, [log: readonly Readonly<ILogEntry>[]], void> & {
|
|
37
|
+
init: null;
|
|
38
|
+
};
|
|
39
|
+
export declare const setSpecificMonthEstimatedCycleTimes: import("jotai").WritableAtom<null, [log: readonly Readonly<ILogEntry>[]], void> & {
|
|
40
|
+
init: null;
|
|
41
|
+
};
|