Files
shopdb/displayudc.asp
cproudlock 91fe5a6c66 Add UDC Performance Dashboard and Tool Health features
- Add displayudc.asp with Dashboard tab containing:
  - Production Trend chart (daily parts)
  - OOT Rate Trend chart (daily OOT %)
  - Machine Utilization chart (top 10 by runtime hours)
  - Top Operators chart (top 10 by parts produced)
- Add tabs for drill-down: Live Activity, Operators, Machines, Parts,
  Quality/OOT, Timing, Activity Log, Tool Health, Uptime, IT Diagnostics

- Add Tool Health section to displaymachine.asp UDC tab:
  - Summary cards (tools monitored, measurements, OOT count)
  - Tool status table with health indicators
  - Recent OOT events display

- Add UDC API endpoints in api.asp:
  - getUDCPartRuns, getUDCOperatorStats, getUDCMachineStats, getUDCManualTiming

- Add sql/udctables.sql schema for UDC data storage

- Update docs/API.md with UDC endpoint documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-16 07:54:13 -05:00

2174 lines
91 KiB
Plaintext

<%@ Language=VBScript %>
<%
Option Explicit
Response.Expires = -1
Response.ExpiresAbsolute = Now() - 1
Response.AddHeader "pragma", "no-cache"
Response.AddHeader "cache-control", "private, no-cache, must-revalidate"
'=============================================================================
' FILE: displayudc.asp
' PURPOSE: UDC (Universal Data Collector) Management Dashboard
' SECURITY: Parameterized queries, HTML encoding, input validation
' CREATED: 2025-12-12
'=============================================================================
Dim theme, strSQL, rs, objConn
%>
<!DOCTYPE html>
<html lang="en">
<head>
<!--#include file="./includes/header.asp"-->
<!--#include file="./includes/sql.asp"-->
<title>UDC Dashboard - ShopDB</title>
</head>
<%
theme = Request.Cookies("theme")
If theme = "" Then theme = "bg-theme1"
' Get filter parameters
Dim filterMachine, filterBadge, filterPart, filterStart, filterEnd, periodFilter, filterBU
filterMachine = Trim(Request.QueryString("machine") & "")
filterBadge = Trim(Request.QueryString("badge") & "")
filterPart = Trim(Request.QueryString("part") & "")
filterStart = Trim(Request.QueryString("startdate") & "")
filterEnd = Trim(Request.QueryString("enddate") & "")
periodFilter = Trim(Request.QueryString("period") & "")
filterBU = Trim(Request.QueryString("bu") & "")
' Tab persistence
Dim activeTab
activeTab = Trim(Request.QueryString("tab") & "")
If activeTab = "" Then activeTab = "dashboard"
' Shift-span filter for manual response times
Dim excludeShiftSpan, shiftFilter
excludeShiftSpan = (Request.QueryString("excludeshift") = "1")
shiftFilter = ""
If excludeShiftSpan Then
shiftFilter = " AND mr.responseseconds < 1800"
End If
' Default date range: last 30 days
If filterStart = "" Then filterStart = Year(DateAdd("d", -30, Date())) & "-" & Right("0" & Month(DateAdd("d", -30, Date())), 2) & "-" & Right("0" & Day(DateAdd("d", -30, Date())), 2)
If filterEnd = "" Then filterEnd = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2)
' Period shortcuts
Dim periodLabel
If periodFilter = "today" Then
filterStart = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2)
filterEnd = filterStart
periodLabel = "Today"
ElseIf periodFilter = "week" Then
filterStart = Year(DateAdd("d", -7, Date())) & "-" & Right("0" & Month(DateAdd("d", -7, Date())), 2) & "-" & Right("0" & Day(DateAdd("d", -7, Date())), 2)
filterEnd = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2)
periodLabel = "This Week"
ElseIf periodFilter = "month" Then
filterStart = Year(DateAdd("d", -30, Date())) & "-" & Right("0" & Month(DateAdd("d", -30, Date())), 2) & "-" & Right("0" & Day(DateAdd("d", -30, Date())), 2)
filterEnd = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2)
periodLabel = "This Month"
Else
periodLabel = "Custom Range"
End If
%>
<body class="bg-theme <%=Server.HTMLEncode(theme)%>">
<!-- start loader -->
<div id="pageloader-overlay" class="visible incoming"><div class="loader-wrapper-outer"><div class="loader-wrapper-inner"><div class="loader"></div></div></div></div>
<div id="wrapper">
<!--#include file="./includes/leftsidebar.asp"-->
<!--#include file="./includes/topbarheader.asp"-->
<div class="clearfix"></div>
<div class="content-wrapper">
<div class="container-fluid">
<!-- Page Header -->
<div class="row mt-3">
<div class="col-12">
<div class="card">
<div class="card-header" style="background: linear-gradient(45deg, #667eea 0%, #764ba2 100%); color: white;">
<h5 class="mb-0">UDC Performance Dashboard</h5>
</div>
<div class="card-body">
<!-- Filter Controls -->
<form id="udcFilterForm" method="get" class="mb-0">
<div class="row">
<div class="col-md-2">
<label class="small">Quick Range</label>
<select name="period" class="form-control form-control-sm" onchange="this.form.submit()">
<option value="">Custom</option>
<option value="today" <%If periodFilter="today" Then Response.Write("selected")%>>Today</option>
<option value="week" <%If periodFilter="week" Then Response.Write("selected")%>>This Week</option>
<option value="month" <%If periodFilter="month" Then Response.Write("selected")%>>This Month</option>
</select>
</div>
<div class="col-md-2">
<label class="small">Start Date</label>
<input type="date" name="startdate" class="form-control form-control-sm" value="<%=Server.HTMLEncode(filterStart)%>">
</div>
<div class="col-md-2">
<label class="small">End Date</label>
<input type="date" name="enddate" class="form-control form-control-sm" value="<%=Server.HTMLEncode(filterEnd)%>">
</div>
<div class="col-md-2">
<label class="small">Business Unit</label>
<select name="bu" id="buFilter" class="form-control form-control-sm" onchange="this.form.submit()">
<option value="">All BUs</option>
<%
' Get list of business units with UDC machines
Dim rsBUs
Set rsBUs = objConn.Execute("SELECT DISTINCT b.businessunitid, b.businessunit FROM businessunits b " & _
"JOIN machines m ON m.businessunitid = b.businessunitid " & _
"JOIN udcsessions s ON m.machinenumber = s.machinenumber " & _
"ORDER BY b.businessunit")
Do While Not rsBUs.EOF
Response.Write("<option value=""" & Server.HTMLEncode(rsBUs("businessunitid") & "") & """")
If filterBU = rsBUs("businessunitid") & "" Then Response.Write(" selected")
Response.Write(">" & Server.HTMLEncode(rsBUs("businessunit") & "") & "</option>")
rsBUs.MoveNext
Loop
rsBUs.Close
Set rsBUs = Nothing
%>
</select>
</div>
<div class="col-md-2">
<label class="small">Machine</label>
<select name="machine" class="form-control form-control-sm">
<option value="">All Machines</option>
<%
' Get list of machines with UDC data, filtered by BU if selected
Dim rsMachines, machineSQL
machineSQL = "SELECT DISTINCT s.machinenumber FROM udcsessions s " & _
"JOIN machines m ON m.machinenumber = s.machinenumber "
If filterBU <> "" Then
machineSQL = machineSQL & "WHERE m.businessunitid = " & CLng(filterBU) & " "
End If
machineSQL = machineSQL & "ORDER BY s.machinenumber"
Set rsMachines = objConn.Execute(machineSQL)
Do While Not rsMachines.EOF
Response.Write("<option value=""" & Server.HTMLEncode(rsMachines("machinenumber") & "") & """")
If filterMachine = rsMachines("machinenumber") & "" Then Response.Write(" selected")
Response.Write(">" & Server.HTMLEncode(rsMachines("machinenumber") & "") & "</option>")
rsMachines.MoveNext
Loop
rsMachines.Close
Set rsMachines = Nothing
%>
</select>
</div>
<div class="col-md-2">
<label class="small">Operator Badge</label>
<select name="badge" class="form-control form-control-sm">
<option value="">All Operators</option>
<%
' Get list of operators
Dim rsBadges
Set rsBadges = objConn.Execute("SELECT DISTINCT badgenumber FROM udcparts WHERE badgenumber IS NOT NULL AND badgenumber != '' ORDER BY badgenumber")
Do While Not rsBadges.EOF
Response.Write("<option value=""" & Server.HTMLEncode(rsBadges("badgenumber") & "") & """")
If filterBadge = rsBadges("badgenumber") & "" Then Response.Write(" selected")
Response.Write(">" & Server.HTMLEncode(rsBadges("badgenumber") & "") & "</option>")
rsBadges.MoveNext
Loop
rsBadges.Close
Set rsBadges = Nothing
%>
</select>
</div>
<div class="col-md-2 d-flex align-items-end">
<button type="submit" class="btn btn-primary btn-sm mr-2">Filter</button>
<a href="displayudc.asp" class="btn btn-secondary btn-sm">Clear</a>
</div>
</div>
<div class="row mt-2">
<div class="col-12">
<div class="form-check form-check-inline">
<input type="checkbox" class="form-check-input" id="excludeshift" name="excludeshift" value="1" <%If excludeShiftSpan Then Response.Write("checked")%>>
<label class="form-check-label small" for="excludeshift">Exclude idle time (removes responses over 30 min)</label>
</div>
</div>
</div>
<input type="hidden" name="tab" id="activeTabInput" value="<%=Server.HTMLEncode(activeTab)%>">
</form>
</div>
</div>
</div>
</div>
<!-- Summary Cards Row -->
<%
' Build WHERE clause for filters
Dim whereClause
whereClause = " WHERE p.programstart >= '" & Replace(filterStart, "'", "''") & "' " & _
" AND p.programstart <= '" & Replace(filterEnd, "'", "''") & " 23:59:59'"
If filterMachine <> "" Then
whereClause = whereClause & " AND s.machinenumber = '" & Replace(filterMachine, "'", "''") & "'"
End If
If filterBU <> "" Then
whereClause = whereClause & " AND s.machinenumber IN (SELECT machinenumber FROM machines WHERE businessunitid = " & CLng(filterBU) & ")"
End If
If filterBadge <> "" Then
whereClause = whereClause & " AND p.badgenumber = '" & Replace(filterBadge, "'", "''") & "'"
End If
If filterPart <> "" Then
whereClause = whereClause & " AND p.partnumber LIKE '%" & Replace(filterPart, "'", "''") & "%'"
End If
' Get summary statistics
Dim rsSummary, totalParts, totalOOT, partsWithOOT, avgCycleTime, avgManualTime, ootRate, strSQL2, ootCardClass
strSQL2 = "SELECT COUNT(*) as totalparts, " & _
"SUM(ootcount) as totaloot, " & _
"SUM(CASE WHEN ootcount > 0 THEN 1 ELSE 0 END) as partswithoot, " & _
"AVG(cycletime) as avgcycle, " & _
"SUM(manualcount) as totalmanual " & _
"FROM udcparts p " & _
"JOIN udcsessions s ON p.sessionid = s.sessionid " & whereClause
Set rsSummary = objConn.Execute(strSQL2)
If Not rsSummary.EOF Then
If IsNull(rsSummary("totalparts")) Then totalParts = 0 Else totalParts = CLng(rsSummary("totalparts"))
If IsNull(rsSummary("totaloot")) Then totalOOT = 0 Else totalOOT = CLng(rsSummary("totaloot"))
If IsNull(rsSummary("partswithoot")) Then partsWithOOT = 0 Else partsWithOOT = CLng(rsSummary("partswithoot"))
If Not IsNull(rsSummary("avgcycle")) Then
avgCycleTime = FormatNumber(CDbl(rsSummary("avgcycle")) / 60, 1)
Else
avgCycleTime = "0"
End If
If totalParts > 0 Then
ootRate = FormatNumber(CDbl(partsWithOOT) / CDbl(totalParts) * 100, 1)
Else
ootRate = "0"
End If
Else
totalParts = 0
totalOOT = 0
partsWithOOT = 0
avgCycleTime = "0"
ootRate = "0"
End If
rsSummary.Close
Set rsSummary = Nothing
' Get avg manual response time
Dim rsManual, avgManualResp
strSQL2 = "SELECT AVG(mr.responseseconds) as avgresponse " & _
"FROM udcmanualrequests mr " & _
"JOIN udcparts p ON mr.partrunid = p.partrunid " & _
"JOIN udcsessions s ON p.sessionid = s.sessionid " & whereClause & shiftFilter
Set rsManual = objConn.Execute(strSQL2)
If Not rsManual.EOF And Not IsNull(rsManual("avgresponse")) Then
avgManualResp = FormatNumber(CDbl(rsManual("avgresponse")), 0)
Else
avgManualResp = "0"
End If
rsManual.Close
Set rsManual = Nothing
%>
<!-- Summary Cards -->
<div class="row mt-3">
<div class="col-lg-3 col-md-6">
<div class="card bg-success text-white">
<div class="card-body">
<div class="d-flex align-items-center">
<div class="media-body">
<h4 class="mb-0"><%=totalParts%></h4>
<span>Total Parts Produced</span>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6">
<div class="card bg-info text-white">
<div class="card-body">
<div class="d-flex align-items-center">
<div class="media-body">
<h4 class="mb-0"><%=avgCycleTime%>m</h4>
<span>Avg Cycle Time</span>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6">
<%
If CDbl(ootRate) > 5 Then
ootCardClass = "bg-danger"
ElseIf CDbl(ootRate) > 0 Then
ootCardClass = "bg-warning"
Else
ootCardClass = "bg-success"
End If
%>
<div class="card <%=ootCardClass%> text-white">
<div class="card-body">
<div class="d-flex align-items-center">
<div class="media-body">
<h4 class="mb-0"><%=ootRate%>%</h4>
<span>Parts with OOT (<%=partsWithOOT%> of <%=totalParts%>)</span>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6">
<div class="card bg-primary text-white">
<div class="card-body">
<div class="d-flex align-items-center">
<div class="media-body">
<h4 class="mb-0"><%=avgManualResp%>s</h4>
<span>Avg Manual Response</span>
</div>
</div>
</div>
</div>
</div>
</div>
<%
' ============================================================================
' DASHBOARD CHARTS DATA QUERIES
' ============================================================================
' Chart 1: Production Trend (daily parts for date range)
Dim rsProductionTrend, prodLabels, prodData, prodDate
prodLabels = ""
prodData = ""
strSQL2 = "SELECT DATE_FORMAT(DATE(p.programstart), '%m/%d') as day_label, COUNT(*) as parts " & _
"FROM udcparts p " & _
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
whereClause & _
" GROUP BY DATE(p.programstart) ORDER BY DATE(p.programstart) ASC"
Set rsProductionTrend = objConn.Execute(strSQL2)
Do While Not rsProductionTrend.EOF
prodDate = rsProductionTrend("day_label") & ""
If prodLabels <> "" Then prodLabels = prodLabels & ","
If prodData <> "" Then prodData = prodData & ","
prodLabels = prodLabels & """" & prodDate & """"
prodData = prodData & rsProductionTrend("parts")
rsProductionTrend.MoveNext
Loop
rsProductionTrend.Close
Set rsProductionTrend = Nothing
If prodLabels = "" Then prodLabels = """No Data"""
If prodData = "" Then prodData = "0"
' Chart 2: OOT Rate Trend (daily OOT rate for date range)
Dim rsOOTTrend, ootLabels, ootRateData, ootCountData, ootDay, dayRate
ootLabels = ""
ootRateData = ""
ootCountData = ""
strSQL2 = "SELECT DATE_FORMAT(DATE(p.programstart), '%m/%d') as day_label, " & _
"SUM(p.ootcount) as oot_count, COUNT(*) as total_parts, " & _
"ROUND(SUM(p.ootcount)*100.0/COUNT(*), 1) as oot_rate " & _
"FROM udcparts p " & _
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
whereClause & _
" GROUP BY DATE(p.programstart) ORDER BY DATE(p.programstart) ASC"
Set rsOOTTrend = objConn.Execute(strSQL2)
Do While Not rsOOTTrend.EOF
ootDay = rsOOTTrend("day_label") & ""
If ootLabels <> "" Then ootLabels = ootLabels & ","
If ootRateData <> "" Then ootRateData = ootRateData & ","
If ootCountData <> "" Then ootCountData = ootCountData & ","
ootLabels = ootLabels & """" & ootDay & """"
If IsNull(rsOOTTrend("oot_rate")) Then
dayRate = "0"
Else
dayRate = rsOOTTrend("oot_rate") & ""
End If
ootRateData = ootRateData & dayRate
ootCountData = ootCountData & (rsOOTTrend("oot_count") & "0")
rsOOTTrend.MoveNext
Loop
rsOOTTrend.Close
Set rsOOTTrend = Nothing
If ootLabels = "" Then ootLabels = """No Data"""
If ootRateData = "" Then ootRateData = "0"
If ootCountData = "" Then ootCountData = "0"
' Chart 3: Machine Utilization (top 10 by runtime hours)
Dim rsMachineUtil, machLabels, machData, machHours
machLabels = ""
machData = ""
strSQL2 = "SELECT s.machinenumber, ROUND(SUM(p.cycletime)/3600, 1) as runtime_hours " & _
"FROM udcparts p " & _
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
whereClause & _
" AND p.cycletime IS NOT NULL AND p.cycletime > 0 " & _
"GROUP BY s.machinenumber ORDER BY runtime_hours DESC LIMIT 10"
Set rsMachineUtil = objConn.Execute(strSQL2)
Do While Not rsMachineUtil.EOF
If machLabels <> "" Then machLabels = machLabels & ","
If machData <> "" Then machData = machData & ","
machLabels = machLabels & """" & (rsMachineUtil("machinenumber") & "") & """"
If IsNull(rsMachineUtil("runtime_hours")) Then
machHours = "0"
Else
machHours = rsMachineUtil("runtime_hours") & ""
End If
machData = machData & machHours
rsMachineUtil.MoveNext
Loop
rsMachineUtil.Close
Set rsMachineUtil = Nothing
If machLabels = "" Then machLabels = """No Data"""
If machData = "" Then machData = "0"
' Chart 4: Top Operators (top 10 by parts produced)
Dim rsTopOps, opLabels, opData
opLabels = ""
opData = ""
strSQL2 = "SELECT p.badgenumber, COUNT(*) as parts_count " & _
"FROM udcparts p " & _
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
whereClause & _
" AND p.badgenumber IS NOT NULL AND p.badgenumber != '' " & _
"GROUP BY p.badgenumber ORDER BY parts_count DESC LIMIT 10"
Set rsTopOps = objConn.Execute(strSQL2)
Do While Not rsTopOps.EOF
If opLabels <> "" Then opLabels = opLabels & ","
If opData <> "" Then opData = opData & ","
opLabels = opLabels & """" & (rsTopOps("badgenumber") & "") & """"
opData = opData & rsTopOps("parts_count")
rsTopOps.MoveNext
Loop
rsTopOps.Close
Set rsTopOps = Nothing
If opLabels = "" Then opLabels = """No Data"""
If opData = "" Then opData = "0"
%>
<!-- Tabbed Content Area -->
<div class="row mt-3">
<div class="col-12">
<div class="card">
<div class="card-body">
<ul class="nav nav-tabs nav-tabs-primary" id="udcTabs">
<li class="nav-item">
<a href="#dashboard" data-toggle="tab" class="nav-link<%If activeTab="dashboard" Then Response.Write(" active")%>" onclick="setActiveTab('dashboard')"><i class="zmdi zmdi-chart"></i> Dashboard</a>
</li>
<li class="nav-item">
<a href="#liveactivity" data-toggle="tab" class="nav-link<%If activeTab="liveactivity" Then Response.Write(" active")%>" onclick="setActiveTab('liveactivity')"><i class="zmdi zmdi-dot-circle text-success"></i> Live Activity</a>
</li>
<li class="nav-item">
<a href="#operators" data-toggle="tab" class="nav-link<%If activeTab="operators" Then Response.Write(" active")%>" onclick="setActiveTab('operators')">Operators</a>
</li>
<li class="nav-item">
<a href="#machines" data-toggle="tab" class="nav-link<%If activeTab="machines" Then Response.Write(" active")%>" onclick="setActiveTab('machines')">Machines</a>
</li>
<li class="nav-item">
<a href="#parts" data-toggle="tab" class="nav-link<%If activeTab="parts" Then Response.Write(" active")%>" onclick="setActiveTab('parts')">Parts</a>
</li>
<li class="nav-item">
<a href="#quality" data-toggle="tab" class="nav-link<%If activeTab="quality" Then Response.Write(" active")%>" onclick="setActiveTab('quality')">Quality/OOT</a>
</li>
<li class="nav-item">
<a href="#timing" data-toggle="tab" class="nav-link<%If activeTab="timing" Then Response.Write(" active")%>" onclick="setActiveTab('timing')">Timing</a>
</li>
<li class="nav-item">
<a href="#activitylog" data-toggle="tab" class="nav-link<%If activeTab="activitylog" Then Response.Write(" active")%>" onclick="setActiveTab('activitylog')">Activity Log</a>
</li>
<li class="nav-item">
<a href="#toolhealth" data-toggle="tab" class="nav-link<%If activeTab="toolhealth" Then Response.Write(" active")%>" onclick="setActiveTab('toolhealth')">Tool Health</a>
</li>
<li class="nav-item">
<a href="#uptime" data-toggle="tab" class="nav-link<%If activeTab="uptime" Then Response.Write(" active")%>" onclick="setActiveTab('uptime')">Uptime</a>
</li>
<li class="nav-item">
<a href="#itdiagnostics" data-toggle="tab" class="nav-link<%If activeTab="itdiagnostics" Then Response.Write(" active")%>" onclick="setActiveTab('itdiagnostics')">IT Diagnostics</a>
</li>
</ul>
<div class="tab-content p-3">
<!-- Tab: Dashboard (Charts) -->
<div class="tab-pane<%If activeTab="dashboard" Then Response.Write(" active")%>" id="dashboard">
<h5 class="mb-3"><i class="zmdi zmdi-chart"></i> UDC Performance Dashboard</h5>
<!-- Charts Row 1 -->
<div class="row">
<div class="col-lg-6 mb-3">
<div class="card">
<div class="card-header bg-gradient-primary text-white py-2">
<i class="zmdi zmdi-trending-up"></i> Production Trend
</div>
<div class="card-body">
<div style="height: 220px;">
<canvas id="productionChart"></canvas>
</div>
</div>
</div>
</div>
<div class="col-lg-6 mb-3">
<div class="card">
<div class="card-header bg-gradient-danger text-white py-2">
<i class="zmdi zmdi-alert-triangle"></i> OOT Rate Trend
</div>
<div class="card-body">
<div style="height: 220px;">
<canvas id="ootChart"></canvas>
</div>
</div>
</div>
</div>
</div>
<!-- Charts Row 2 -->
<div class="row">
<div class="col-lg-6 mb-3">
<div class="card">
<div class="card-header bg-gradient-info text-white py-2">
<i class="zmdi zmdi-time"></i> Machine Utilization (Hours)
</div>
<div class="card-body">
<div style="height: 220px;">
<canvas id="machineChart"></canvas>
</div>
</div>
</div>
</div>
<div class="col-lg-6 mb-3">
<div class="card">
<div class="card-header bg-gradient-success text-white py-2">
<i class="zmdi zmdi-accounts"></i> Top Operators (Parts)
</div>
<div class="card-body">
<div style="height: 220px;">
<canvas id="operatorChart"></canvas>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Tab: Live Activity -->
<div class="tab-pane<%If activeTab="liveactivity" Then Response.Write(" active")%>" id="liveactivity">
<h5 class="mb-3"><i class="zmdi zmdi-dot-circle text-success"></i> Active Machines <span class="badge badge-success">Live</span></h5>
<p class="text-muted small mb-3">Machines currently running jobs. Data refreshes when page loads.</p>
<%
' Get active sessions with optional machine/BU filter
Dim rsActive, activeCount, activeWhereClause
activeWhereClause = ""
If filterMachine <> "" Then
activeWhereClause = " WHERE a.machinenumber = '" & Replace(filterMachine, "'", "''") & "'"
ElseIf filterBU <> "" Then
activeWhereClause = " WHERE a.machinenumber IN (SELECT machinenumber FROM machines WHERE businessunitid = " & CLng(filterBU) & ")"
End If
strSQL2 = "SELECT a.machinenumber, a.partnumber, a.badgenumber, a.partsrun, a.lastupdate, a.sessionstart, " & _
"TIMESTAMPDIFF(MINUTE, a.sessionstart, NOW()) as runtime_minutes " & _
"FROM udcactivesessions a" & activeWhereClause & " ORDER BY a.lastupdate DESC"
Set rsActive = objConn.Execute(strSQL2)
activeCount = 0
If rsActive.EOF Then
%>
<div class="alert alert-secondary text-center">
<i class="zmdi zmdi-info-outline"></i> No active jobs detected
</div>
<%
Else
%>
<div class="table-responsive">
<table class="table table-hover table-striped" id="activeTable">
<thead>
<tr>
<th>Machine</th>
<th>Part Number</th>
<th>Operator Badge</th>
<th>Parts Run</th>
<th>Runtime</th>
<th>Session Start</th>
<th>Last Activity</th>
</tr>
</thead>
<tbody>
<%
Dim runtimeMinutes, runtimeDisplay
Do While Not rsActive.EOF
activeCount = activeCount + 1
runtimeMinutes = rsActive("runtime_minutes")
If IsNull(runtimeMinutes) Or runtimeMinutes = "" Then
runtimeDisplay = "-"
ElseIf CLng(runtimeMinutes) >= 60 Then
runtimeDisplay = Int(CLng(runtimeMinutes) / 60) & "h " & (CLng(runtimeMinutes) Mod 60) & "m"
Else
runtimeDisplay = CLng(runtimeMinutes) & "m"
End If
Response.Write("<tr>")
Response.Write("<td><a href='displaymachine.asp?machinenumber=" & Server.URLEncode(rsActive("machinenumber") & "") & "'><strong>" & Server.HTMLEncode(rsActive("machinenumber") & "") & "</strong></a></td>")
Response.Write("<td>" & Server.HTMLEncode(rsActive("partnumber") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsActive("badgenumber") & "") & "</td>")
Response.Write("<td><span class='badge badge-info'>" & rsActive("partsrun") & "</span></td>")
Response.Write("<td>" & runtimeDisplay & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsActive("sessionstart") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsActive("lastupdate") & "") & "</td>")
Response.Write("</tr>")
rsActive.MoveNext
Loop
%>
</tbody>
</table>
</div>
<p class="text-muted small mt-2 mb-0"><strong><%=activeCount%></strong> machine(s) currently active</p>
<%
End If
rsActive.Close
Set rsActive = Nothing
%>
</div>
<!-- Tab: Operator Performance -->
<div class="tab-pane<%If activeTab="operators" Then Response.Write(" active")%>" id="operators">
<h5 class="mb-3">Operator Performance Leaderboard</h5>
<div class="table-responsive">
<table class="table table-hover table-striped" id="operatorTable">
<thead>
<tr>
<th>Badge #</th>
<th>Parts Run</th>
<th>Avg Cycle (min)</th>
<th>Avg Manual Response (sec)</th>
<th>Last Active</th>
</tr>
</thead>
<tbody>
<%
' Get operator stats
Dim rsOperators, opCycle, opManual, opRowNum, opRowStyle
strSQL2 = "SELECT p.badgenumber, COUNT(*) as partsrun, " & _
"AVG(p.cycletime) as avgcycle, " & _
"MAX(p.programend) as lastactive, " & _
"(SELECT AVG(mr.responseseconds) FROM udcmanualrequests mr " & _
" JOIN udcparts p2 ON mr.partrunid = p2.partrunid WHERE p2.badgenumber = p.badgenumber) as avgmanual " & _
"FROM udcparts p " & _
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
whereClause & _
" AND p.badgenumber IS NOT NULL AND p.badgenumber != '' " & _
"GROUP BY p.badgenumber ORDER BY partsrun DESC, p.badgenumber ASC"
Set rsOperators = objConn.Execute(strSQL2)
opRowNum = 0
If rsOperators.EOF Then
Response.Write("<tr><td colspan='5' class='text-muted text-center'>No operator data found</td></tr>")
Else
Do While Not rsOperators.EOF
opRowNum = opRowNum + 1
If Not IsNull(rsOperators("avgcycle")) Then
opCycle = FormatNumber(CDbl(rsOperators("avgcycle")) / 60, 1)
Else
opCycle = "-"
End If
If Not IsNull(rsOperators("avgmanual")) Then
opManual = FormatNumber(CDbl(rsOperators("avgmanual")), 0)
Else
opManual = "-"
End If
' Highlight top 3 performers
opRowStyle = ""
If opRowNum = 1 Then
opRowStyle = "background-color:#28a745; color:#fff;"
ElseIf opRowNum = 2 Then
opRowStyle = "background-color:#20c997; color:#fff;"
ElseIf opRowNum = 3 Then
opRowStyle = "background-color:#17a2b8; color:#fff;"
End If
Response.Write("<tr style='" & opRowStyle & "'>")
Response.Write("<td><a href='displayudc.asp?badge=" & Server.URLEncode(rsOperators("badgenumber") & "") & "' style='color:inherit;'>" & Server.HTMLEncode(rsOperators("badgenumber") & "") & "</a></td>")
Response.Write("<td>" & rsOperators("partsrun") & "</td>")
Response.Write("<td>" & opCycle & "</td>")
Response.Write("<td>" & opManual & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsOperators("lastactive") & "") & "</td>")
Response.Write("</tr>")
rsOperators.MoveNext
Loop
End If
rsOperators.Close
Set rsOperators = Nothing
%>
</tbody>
</table>
</div>
</div>
<!-- Tab 2: Machine Performance -->
<div class="tab-pane<%If activeTab="machines" Then Response.Write(" active")%>" id="machines">
<h5 class="mb-3">Machine Performance Comparison</h5>
<div class="table-responsive">
<table class="table table-hover table-striped" id="machineTable">
<thead>
<tr>
<th>Machine #</th>
<th>Parts Run</th>
<th>Avg Cycle (min)</th>
<th>Avg Changeover (min)</th>
<th>Parts with OOT</th>
<th>OOT Rate</th>
<th>Last Run</th>
</tr>
</thead>
<tbody>
<%
' Get machine stats
Dim rsMachStats, machCycle, machChange, machOOTRate, machOOTBadge, machPartsWithOOT
strSQL2 = "SELECT s.machinenumber, COUNT(*) as partsrun, " & _
"AVG(p.cycletime) as avgcycle, " & _
"AVG(p.changeover) as avgchangeover, " & _
"SUM(CASE WHEN p.ootcount > 0 THEN 1 ELSE 0 END) as partswithoot, " & _
"MAX(p.programend) as lastrun " & _
"FROM udcparts p " & _
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
whereClause & _
" GROUP BY s.machinenumber ORDER BY partsrun DESC, s.machinenumber ASC"
Set rsMachStats = objConn.Execute(strSQL2)
If rsMachStats.EOF Then
Response.Write("<tr><td colspan='7' class='text-muted text-center'>No machine data found</td></tr>")
Else
Do While Not rsMachStats.EOF
If Not IsNull(rsMachStats("avgcycle")) Then
machCycle = FormatNumber(CDbl(rsMachStats("avgcycle")) / 60, 1)
Else
machCycle = "-"
End If
If Not IsNull(rsMachStats("avgchangeover")) Then
machChange = FormatNumber(CDbl(rsMachStats("avgchangeover")) / 60, 1)
Else
machChange = "-"
End If
machPartsWithOOT = CLng("0" & rsMachStats("partswithoot"))
If CLng("0" & rsMachStats("partsrun")) > 0 Then
machOOTRate = FormatNumber(CDbl(machPartsWithOOT) / CDbl(rsMachStats("partsrun")) * 100, 2)
Else
machOOTRate = "0"
End If
If CDbl(machOOTRate) > 5 Then
machOOTBadge = "<span class='badge badge-danger'>" & machOOTRate & "%</span>"
ElseIf CDbl(machOOTRate) > 0 Then
machOOTBadge = "<span class='badge badge-warning'>" & machOOTRate & "%</span>"
Else
machOOTBadge = "<span class='badge badge-success'>" & machOOTRate & "%</span>"
End If
Response.Write("<tr>")
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsMachStats("machinenumber") & "") & "'>" & Server.HTMLEncode(rsMachStats("machinenumber") & "") & "</a></td>")
Response.Write("<td>" & rsMachStats("partsrun") & "</td>")
Response.Write("<td>" & machCycle & "</td>")
Response.Write("<td>" & machChange & "</td>")
Response.Write("<td>" & machPartsWithOOT & "</td>")
Response.Write("<td>" & machOOTBadge & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsMachStats("lastrun") & "") & "</td>")
Response.Write("</tr>")
rsMachStats.MoveNext
Loop
End If
rsMachStats.Close
Set rsMachStats = Nothing
%>
</tbody>
</table>
</div>
</div>
<!-- Tab 3: Part Analysis -->
<div class="tab-pane<%If activeTab="parts" Then Response.Write(" active")%>" id="parts">
<h5 class="mb-3">Part Number Analysis</h5>
<div class="table-responsive">
<table class="table table-hover table-striped" id="partsTable">
<thead>
<tr>
<th>Part #</th>
<th>Count</th>
<th>Avg Cycle (min)</th>
<th>Parts with OOT</th>
<th>OOT Rate</th>
</tr>
</thead>
<tbody>
<%
' Get part stats
Dim rsPartStats, partCycle, partOOTRate, partOOTBadge, partPartsWithOOT
strSQL2 = "SELECT p.partnumber, COUNT(*) as cnt, " & _
"AVG(p.cycletime) as avgcycle, " & _
"SUM(CASE WHEN p.ootcount > 0 THEN 1 ELSE 0 END) as partswithoot " & _
"FROM udcparts p " & _
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
whereClause & _
" AND p.partnumber IS NOT NULL AND p.partnumber != '' " & _
"GROUP BY p.partnumber ORDER BY partswithoot DESC, cnt DESC, p.partnumber ASC LIMIT 50"
Set rsPartStats = objConn.Execute(strSQL2)
If rsPartStats.EOF Then
Response.Write("<tr><td colspan='5' class='text-muted text-center'>No part data found</td></tr>")
Else
Do While Not rsPartStats.EOF
If Not IsNull(rsPartStats("avgcycle")) Then
partCycle = FormatNumber(CDbl(rsPartStats("avgcycle")) / 60, 1)
Else
partCycle = "-"
End If
partPartsWithOOT = CLng("0" & rsPartStats("partswithoot"))
If CLng("0" & rsPartStats("cnt")) > 0 Then
partOOTRate = FormatNumber(CDbl(partPartsWithOOT) / CDbl(rsPartStats("cnt")) * 100, 2)
Else
partOOTRate = "0"
End If
If CDbl(partOOTRate) > 5 Then
partOOTBadge = "<span class='badge badge-danger'>" & partOOTRate & "%</span>"
ElseIf CDbl(partOOTRate) > 0 Then
partOOTBadge = "<span class='badge badge-warning'>" & partOOTRate & "%</span>"
Else
partOOTBadge = "<span class='badge badge-success'>0%</span>"
End If
Response.Write("<tr>")
Response.Write("<td>" & Server.HTMLEncode(rsPartStats("partnumber") & "") & "</td>")
Response.Write("<td>" & rsPartStats("cnt") & "</td>")
Response.Write("<td>" & partCycle & "</td>")
Response.Write("<td>" & partPartsWithOOT & "</td>")
Response.Write("<td>" & partOOTBadge & "</td>")
Response.Write("</tr>")
rsPartStats.MoveNext
Loop
End If
rsPartStats.Close
Set rsPartStats = Nothing
%>
</tbody>
</table>
</div>
</div>
<!-- Tab 4: Quality/OOT Analysis -->
<div class="tab-pane<%If activeTab="quality" Then Response.Write(" active")%>" id="quality">
<h5 class="mb-3">Out-of-Tolerance Analysis</h5>
<!-- OOT Summary by Machine -->
<h6 class="mt-3 mb-2">OOT by Machine</h6>
<div class="table-responsive mb-4">
<table class="table table-hover table-striped table-sm">
<thead>
<tr>
<th>Machine</th>
<th>Parts with OOT</th>
<th>Parts Run</th>
<th>OOT Rate</th>
<th style="width:40%">Bar</th>
</tr>
</thead>
<tbody>
<%
' Get OOT by Machine
Dim rsOOTMach, maxOOT, ootMachRate, barWidth, ootMachParts
maxOOT = 1
strSQL2 = "SELECT s.machinenumber, SUM(CASE WHEN p.ootcount > 0 THEN 1 ELSE 0 END) as partswithoot, COUNT(*) as partsrun " & _
"FROM udcparts p " & _
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
whereClause & _
" GROUP BY s.machinenumber ORDER BY partswithoot DESC, s.machinenumber ASC LIMIT 10"
Set rsOOTMach = objConn.Execute(strSQL2)
If rsOOTMach.EOF Then
Response.Write("<tr><td colspan='5' class='text-muted text-center'>No OOT data found</td></tr>")
Else
' Find max for bar scaling
Do While Not rsOOTMach.EOF
If CLng("0" & rsOOTMach("partswithoot")) > maxOOT Then maxOOT = CLng("0" & rsOOTMach("partswithoot"))
rsOOTMach.MoveNext
Loop
rsOOTMach.Close
Set rsOOTMach = objConn.Execute(strSQL2)
Do While Not rsOOTMach.EOF
ootMachParts = CLng("0" & rsOOTMach("partswithoot"))
If CLng("0" & rsOOTMach("partsrun")) > 0 Then
ootMachRate = FormatNumber(CDbl(ootMachParts) / CDbl(rsOOTMach("partsrun")) * 100, 2)
Else
ootMachRate = "0"
End If
barWidth = Int((ootMachParts / maxOOT) * 100)
Response.Write("<tr>")
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsOOTMach("machinenumber") & "") & "'>" & Server.HTMLEncode(rsOOTMach("machinenumber") & "") & "</a></td>")
Response.Write("<td>" & ootMachParts & "</td>")
Response.Write("<td>" & rsOOTMach("partsrun") & "</td>")
Response.Write("<td>" & ootMachRate & "%</td>")
Response.Write("<td><div style='background:#dc3545;height:20px;width:" & barWidth & "%;border-radius:3px;'></div></td>")
Response.Write("</tr>")
rsOOTMach.MoveNext
Loop
End If
rsOOTMach.Close
Set rsOOTMach = Nothing
%>
</tbody>
</table>
</div>
<!-- Recent OOT Measurements -->
<h6 class="mt-4 mb-2">Recent OOT Measurements</h6>
<div class="table-responsive">
<table class="table table-hover table-striped table-sm">
<thead>
<tr>
<th>Time</th>
<th>Machine</th>
<th>Part #</th>
<th>Dimension</th>
<th>Min</th>
<th>Actual</th>
<th>Max</th>
</tr>
</thead>
<tbody>
<%
' Get recent OOT measurements
Dim rsOOT
strSQL2 = "SELECT m.eventtime, s.machinenumber, p.partnumber, m.dimid, m.description, " & _
"m.minval, m.actualval, m.maxval " & _
"FROM udcmeasurements m " & _
"JOIN udcparts p ON m.partrunid = p.partrunid " & _
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
whereClause & _
" AND m.oot = 1 " & _
"ORDER BY m.eventtime DESC LIMIT 50"
Set rsOOT = objConn.Execute(strSQL2)
If rsOOT.EOF Then
Response.Write("<tr><td colspan='7' class='text-muted text-center'>No OOT measurements found</td></tr>")
Else
Do While Not rsOOT.EOF
Response.Write("<tr style='background-color:#dc3545; color:#fff;'>")
Response.Write("<td>" & Server.HTMLEncode(rsOOT("eventtime") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsOOT("machinenumber") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsOOT("partnumber") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsOOT("dimid") & "") & " - " & Server.HTMLEncode(rsOOT("description") & "") & "</td>")
Response.Write("<td>" & rsOOT("minval") & "</td>")
Response.Write("<td><strong>" & rsOOT("actualval") & "</strong></td>")
Response.Write("<td>" & rsOOT("maxval") & "</td>")
Response.Write("</tr>")
rsOOT.MoveNext
Loop
End If
rsOOT.Close
Set rsOOT = Nothing
%>
</tbody>
</table>
</div>
<!-- Best Performing Machines -->
<h6 class="mt-4 mb-2">Best Performing Machines (Lowest OOT Rates)</h6>
<div class="table-responsive">
<table class="table table-hover table-striped table-sm">
<thead>
<tr>
<th>Machine</th>
<th>Parts Run</th>
<th>OOT Count</th>
<th>OOT Rate</th>
<th style="width:40%">Quality Bar</th>
</tr>
</thead>
<tbody>
<%
' Get best performing machines (lowest OOT rate, min 10 parts)
Dim rsBestMach, bestRate, bestStyle, qualityWidth, bestPartsWithOOT
strSQL2 = "SELECT s.machinenumber, COUNT(*) as partsrun, " & _
"SUM(CASE WHEN p.ootcount > 0 THEN 1 ELSE 0 END) as partswithoot, " & _
"ROUND(SUM(CASE WHEN p.ootcount > 0 THEN 1 ELSE 0 END)/COUNT(*)*100, 2) as ootrate " & _
"FROM udcparts p " & _
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
whereClause & _
" GROUP BY s.machinenumber HAVING COUNT(*) >= 10 ORDER BY ootrate ASC, partsrun DESC, s.machinenumber ASC LIMIT 10"
Set rsBestMach = objConn.Execute(strSQL2)
If rsBestMach.EOF Then
Response.Write("<tr><td colspan='5' class='text-muted text-center'>No machine data found (min 10 parts required)</td></tr>")
Else
Do While Not rsBestMach.EOF
bestPartsWithOOT = CLng("0" & rsBestMach("partswithoot"))
bestRate = CDbl("0" & rsBestMach("ootrate"))
qualityWidth = 100 - Int(bestRate)
If qualityWidth < 0 Then qualityWidth = 0
If qualityWidth > 100 Then qualityWidth = 100
If bestRate = 0 Then
bestStyle = "background-color:#28a745; color:#fff;"
ElseIf bestRate < 5 Then
bestStyle = "background-color:#20c997; color:#fff;"
Else
bestStyle = ""
End If
Response.Write("<tr style='" & bestStyle & "'>")
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsBestMach("machinenumber") & "") & "'>" & Server.HTMLEncode(rsBestMach("machinenumber") & "") & "</a></td>")
Response.Write("<td>" & rsBestMach("partsrun") & "</td>")
Response.Write("<td>" & bestPartsWithOOT & "</td>")
Response.Write("<td>" & bestRate & "%</td>")
Response.Write("<td><div style='background:#28a745;height:20px;width:" & qualityWidth & "%;border-radius:3px;'></div></td>")
Response.Write("</tr>")
rsBestMach.MoveNext
Loop
End If
rsBestMach.Close
Set rsBestMach = Nothing
%>
</tbody>
</table>
</div>
</div>
<!-- Tab 5: Timing Analysis -->
<div class="tab-pane<%If activeTab="timing" Then Response.Write(" active")%>" id="timing">
<h5 class="mb-3">Timing Analysis</h5>
<!-- Manual Response Time by Operator -->
<h6 class="mt-3 mb-2">Manual Response Time by Operator</h6>
<div class="table-responsive mb-4">
<table class="table table-hover table-striped table-sm">
<thead>
<tr>
<th>Badge #</th>
<th>Requests</th>
<th>Avg Response (sec)</th>
<th>Max Response (sec)</th>
</tr>
</thead>
<tbody>
<%
' Get manual response time by operator
Dim rsManualOp, manAvg, manMax
strSQL2 = "SELECT p.badgenumber, COUNT(*) as requests, " & _
"AVG(mr.responseseconds) as avgresponse, " & _
"MAX(mr.responseseconds) as maxresponse " & _
"FROM udcmanualrequests mr " & _
"JOIN udcparts p ON mr.partrunid = p.partrunid " & _
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
whereClause & _
" AND p.badgenumber IS NOT NULL AND p.badgenumber != ''" & shiftFilter & _
" GROUP BY p.badgenumber ORDER BY avgresponse ASC, p.badgenumber ASC"
Set rsManualOp = objConn.Execute(strSQL2)
If rsManualOp.EOF Then
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No manual request data found</td></tr>")
Else
Do While Not rsManualOp.EOF
If Not IsNull(rsManualOp("avgresponse")) Then
manAvg = FormatNumber(CDbl(rsManualOp("avgresponse")), 0)
Else
manAvg = "-"
End If
manMax = CLng("0" & rsManualOp("maxresponse"))
Response.Write("<tr>")
Response.Write("<td><a href='displayudc.asp?badge=" & Server.URLEncode(rsManualOp("badgenumber") & "") & "'>" & Server.HTMLEncode(rsManualOp("badgenumber") & "") & "</a></td>")
Response.Write("<td>" & rsManualOp("requests") & "</td>")
Response.Write("<td>" & manAvg & "</td>")
Response.Write("<td>" & manMax & "</td>")
Response.Write("</tr>")
rsManualOp.MoveNext
Loop
End If
rsManualOp.Close
Set rsManualOp = Nothing
%>
</tbody>
</table>
</div>
<!-- Slowest Manual Responses -->
<h6 class="mt-4 mb-2">Slowest Manual Responses</h6>
<div class="table-responsive">
<table class="table table-hover table-striped table-sm">
<thead>
<tr>
<th>Request Time</th>
<th>Machine</th>
<th>Badge</th>
<th>Description</th>
<th>Response Time (sec)</th>
</tr>
</thead>
<tbody>
<%
' Get slowest manual responses
Dim rsSlow, rowStyle
strSQL2 = "SELECT mr.requesttime, s.machinenumber, p.badgenumber, mr.description, mr.responseseconds " & _
"FROM udcmanualrequests mr " & _
"JOIN udcparts p ON mr.partrunid = p.partrunid " & _
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
whereClause & shiftFilter & _
" ORDER BY mr.responseseconds DESC LIMIT 25"
Set rsSlow = objConn.Execute(strSQL2)
If rsSlow.EOF Then
Response.Write("<tr><td colspan='5' class='text-muted text-center'>No manual requests found</td></tr>")
Else
Do While Not rsSlow.EOF
If CLng("0" & rsSlow("responseseconds")) > 300 Then
rowStyle = "background-color:#dc3545; color:#fff;"
ElseIf CLng("0" & rsSlow("responseseconds")) > 120 Then
rowStyle = "background-color:#ffc107; color:#333;"
Else
rowStyle = ""
End If
Response.Write("<tr style='" & rowStyle & "'>")
Response.Write("<td>" & Server.HTMLEncode(rsSlow("requesttime") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsSlow("machinenumber") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsSlow("badgenumber") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsSlow("description") & "") & "</td>")
Response.Write("<td>" & rsSlow("responseseconds") & "</td>")
Response.Write("</tr>")
rsSlow.MoveNext
Loop
End If
rsSlow.Close
Set rsSlow = Nothing
%>
</tbody>
</table>
</div>
<!-- Fastest Manual Responses -->
<h6 class="mt-4 mb-2">Fastest Responses (Top Performers)</h6>
<div class="table-responsive">
<table class="table table-hover table-striped table-sm">
<thead>
<tr>
<th>Request Time</th>
<th>Machine</th>
<th>Badge</th>
<th>Description</th>
<th>Response Time (sec)</th>
</tr>
</thead>
<tbody>
<%
' Get fastest manual responses
Dim rsFast, fastStyle
strSQL2 = "SELECT mr.requesttime, s.machinenumber, p.badgenumber, mr.description, mr.responseseconds " & _
"FROM udcmanualrequests mr " & _
"JOIN udcparts p ON mr.partrunid = p.partrunid " & _
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
whereClause & shiftFilter & _
" AND mr.responseseconds > 0 ORDER BY mr.responseseconds ASC LIMIT 25"
Set rsFast = objConn.Execute(strSQL2)
If rsFast.EOF Then
Response.Write("<tr><td colspan='5' class='text-muted text-center'>No manual requests found</td></tr>")
Else
Do While Not rsFast.EOF
If CLng("0" & rsFast("responseseconds")) < 30 Then
fastStyle = "background-color:#28a745; color:#fff;"
ElseIf CLng("0" & rsFast("responseseconds")) < 60 Then
fastStyle = "background-color:#20c997; color:#fff;"
Else
fastStyle = ""
End If
Response.Write("<tr style='" & fastStyle & "'>")
Response.Write("<td>" & Server.HTMLEncode(rsFast("requesttime") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsFast("machinenumber") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsFast("badgenumber") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsFast("description") & "") & "</td>")
Response.Write("<td>" & rsFast("responseseconds") & "</td>")
Response.Write("</tr>")
rsFast.MoveNext
Loop
End If
rsFast.Close
Set rsFast = Nothing
%>
</tbody>
</table>
</div>
</div>
<!-- Tab 6: Activity Log (Violations & Badge Changes) -->
<div class="tab-pane<%If activeTab="activitylog" Then Response.Write(" active")%>" id="activitylog">
<h5 class="mb-3">Activity Log</h5>
<p class="text-muted small mb-3">Badge changes and item crossing violations recorded during part runs.</p>
<!-- Item Violations Summary -->
<h6 class="mt-3 mb-2">Item Crossing Violations</h6>
<p class="text-muted small">When operators modify item crossing values during a program run.</p>
<div class="table-responsive mb-4">
<table class="table table-hover table-striped table-sm">
<thead>
<tr>
<th>Time</th>
<th>Machine</th>
<th>Badge</th>
<th>Crossing</th>
<th>Item#</th>
<th>Previous</th>
<th>Current</th>
<th>Change</th>
</tr>
</thead>
<tbody>
<%
' Get recent violations
Dim rsViolations, violWhereClause, violPrev, violCurr, violChange, violStyle
violWhereClause = " WHERE eventtime >= '" & Replace(filterStart, "'", "''") & "' " & _
" AND eventtime <= '" & Replace(filterEnd, "'", "''") & " 23:59:59'"
If filterMachine <> "" Then
violWhereClause = violWhereClause & " AND machinenumber = '" & Replace(filterMachine, "'", "''") & "'"
End If
If filterBU <> "" Then
violWhereClause = violWhereClause & " AND machinenumber IN (SELECT machinenumber FROM machines WHERE businessunitid = " & CLng(filterBU) & ")"
End If
If filterBadge <> "" Then
violWhereClause = violWhereClause & " AND badgenumber = '" & Replace(filterBadge, "'", "''") & "'"
End If
strSQL2 = "SELECT eventtime, machinenumber, badgenumber, crossingdesc, itemno, previousval, currentval " & _
"FROM udcviolations " & violWhereClause & _
" ORDER BY eventtime DESC LIMIT 50"
Set rsViolations = objConn.Execute(strSQL2)
If rsViolations.EOF Then
Response.Write("<tr><td colspan='8' class='text-muted text-center'>No item violations found in date range</td></tr>")
Else
Do While Not rsViolations.EOF
violPrev = CDbl("0" & rsViolations("previousval"))
violCurr = CDbl("0" & rsViolations("currentval"))
violChange = violCurr - violPrev
' Color code based on change magnitude
If Abs(violChange) > 10 Then
violStyle = "background-color:#dc3545; color:#fff;"
ElseIf Abs(violChange) > 1 Then
violStyle = "background-color:#ffc107; color:#333;"
Else
violStyle = ""
End If
Response.Write("<tr style='" & violStyle & "'>")
Response.Write("<td>" & Server.HTMLEncode(rsViolations("eventtime") & "") & "</td>")
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsViolations("machinenumber") & "") & "'>" & Server.HTMLEncode(rsViolations("machinenumber") & "") & "</a></td>")
Response.Write("<td><a href='displayudc.asp?badge=" & Server.URLEncode(rsViolations("badgenumber") & "") & "'>" & Server.HTMLEncode(rsViolations("badgenumber") & "") & "</a></td>")
Response.Write("<td>" & Server.HTMLEncode(rsViolations("crossingdesc") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsViolations("itemno") & "") & "</td>")
Response.Write("<td>" & FormatNumber(violPrev, 2) & "</td>")
Response.Write("<td><strong>" & FormatNumber(violCurr, 2) & "</strong></td>")
If violChange > 0 Then
Response.Write("<td><span class='text-success'>+" & FormatNumber(violChange, 2) & "</span></td>")
ElseIf violChange < 0 Then
Response.Write("<td><span class='text-danger'>" & FormatNumber(violChange, 2) & "</span></td>")
Else
Response.Write("<td>0</td>")
End If
Response.Write("</tr>")
rsViolations.MoveNext
Loop
End If
rsViolations.Close
Set rsViolations = Nothing
%>
</tbody>
</table>
</div>
<!-- Violations by Machine -->
<h6 class="mt-4 mb-2">Violations by Machine</h6>
<div class="table-responsive mb-4">
<table class="table table-hover table-striped table-sm">
<thead>
<tr>
<th>Machine</th>
<th>Total Violations</th>
<th>Unique Crossings</th>
<th>Last Violation</th>
</tr>
</thead>
<tbody>
<%
' Get violations summary by machine
Dim rsViolMach, violMachStyle
strSQL2 = "SELECT machinenumber, COUNT(*) as cnt, COUNT(DISTINCT crossingdesc) as crossings, MAX(eventtime) as lasttime " & _
"FROM udcviolations " & violWhereClause & _
" GROUP BY machinenumber ORDER BY cnt DESC, machinenumber ASC LIMIT 10"
Set rsViolMach = objConn.Execute(strSQL2)
If rsViolMach.EOF Then
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No violations found</td></tr>")
Else
Do While Not rsViolMach.EOF
If CLng("0" & rsViolMach("cnt")) > 100 Then
violMachStyle = "background-color:#dc3545; color:#fff;"
ElseIf CLng("0" & rsViolMach("cnt")) > 25 Then
violMachStyle = "background-color:#ffc107; color:#333;"
Else
violMachStyle = ""
End If
Response.Write("<tr style='" & violMachStyle & "'>")
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsViolMach("machinenumber") & "") & "'>" & Server.HTMLEncode(rsViolMach("machinenumber") & "") & "</a></td>")
Response.Write("<td>" & rsViolMach("cnt") & "</td>")
Response.Write("<td>" & rsViolMach("crossings") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsViolMach("lasttime") & "") & "</td>")
Response.Write("</tr>")
rsViolMach.MoveNext
Loop
End If
rsViolMach.Close
Set rsViolMach = Nothing
%>
</tbody>
</table>
</div>
<!-- Badge Changes -->
<h6 class="mt-4 mb-2">Badge Changes</h6>
<p class="text-muted small">Operator badge scans and changes during part runs.</p>
<div class="table-responsive mb-4">
<table class="table table-hover table-striped table-sm">
<thead>
<tr>
<th>Time</th>
<th>Machine</th>
<th>Badge</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<%
' Get recent badge changes
Dim rsBadgeChanges, badgeWhereClause
badgeWhereClause = " WHERE eventtime >= '" & Replace(filterStart, "'", "''") & "' " & _
" AND eventtime <= '" & Replace(filterEnd, "'", "''") & " 23:59:59'"
If filterMachine <> "" Then
badgeWhereClause = badgeWhereClause & " AND machinenumber = '" & Replace(filterMachine, "'", "''") & "'"
End If
If filterBU <> "" Then
badgeWhereClause = badgeWhereClause & " AND machinenumber IN (SELECT machinenumber FROM machines WHERE businessunitid = " & CLng(filterBU) & ")"
End If
If filterBadge <> "" Then
badgeWhereClause = badgeWhereClause & " AND badgenumber = '" & Replace(filterBadge, "'", "''") & "'"
End If
strSQL2 = "SELECT eventtime, machinenumber, badgenumber, details, description " & _
"FROM udcheaderupdates " & badgeWhereClause & _
" ORDER BY eventtime DESC LIMIT 50"
Set rsBadgeChanges = objConn.Execute(strSQL2)
If rsBadgeChanges.EOF Then
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No badge changes found in date range</td></tr>")
Else
Do While Not rsBadgeChanges.EOF
Response.Write("<tr>")
Response.Write("<td>" & Server.HTMLEncode(rsBadgeChanges("eventtime") & "") & "</td>")
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsBadgeChanges("machinenumber") & "") & "'>" & Server.HTMLEncode(rsBadgeChanges("machinenumber") & "") & "</a></td>")
Response.Write("<td><a href='displayudc.asp?badge=" & Server.URLEncode(rsBadgeChanges("badgenumber") & "") & "'><span class='badge badge-info'>" & Server.HTMLEncode(rsBadgeChanges("badgenumber") & "") & "</span></a></td>")
Response.Write("<td>" & Server.HTMLEncode(rsBadgeChanges("description") & "") & "</td>")
Response.Write("</tr>")
rsBadgeChanges.MoveNext
Loop
End If
rsBadgeChanges.Close
Set rsBadgeChanges = Nothing
%>
</tbody>
</table>
</div>
<!-- Badge Activity by Operator -->
<h6 class="mt-4 mb-2">Badge Activity by Operator</h6>
<div class="table-responsive">
<table class="table table-hover table-striped table-sm">
<thead>
<tr>
<th>Badge #</th>
<th>Badge Scans</th>
<th>Machines Used</th>
<th>Last Activity</th>
</tr>
</thead>
<tbody>
<%
' Get badge activity summary
Dim rsBadgeSum
strSQL2 = "SELECT badgenumber, COUNT(*) as cnt, COUNT(DISTINCT machinenumber) as machines, MAX(eventtime) as lasttime " & _
"FROM udcheaderupdates " & badgeWhereClause & _
" AND badgenumber IS NOT NULL AND badgenumber != '' " & _
" GROUP BY badgenumber ORDER BY cnt DESC, badgenumber ASC LIMIT 15"
Set rsBadgeSum = objConn.Execute(strSQL2)
If rsBadgeSum.EOF Then
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No badge activity found</td></tr>")
Else
Do While Not rsBadgeSum.EOF
Response.Write("<tr>")
Response.Write("<td><a href='displayudc.asp?badge=" & Server.URLEncode(rsBadgeSum("badgenumber") & "") & "'><span class='badge badge-info'>" & Server.HTMLEncode(rsBadgeSum("badgenumber") & "") & "</span></a></td>")
Response.Write("<td>" & rsBadgeSum("cnt") & "</td>")
Response.Write("<td>" & rsBadgeSum("machines") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsBadgeSum("lasttime") & "") & "</td>")
Response.Write("</tr>")
rsBadgeSum.MoveNext
Loop
End If
rsBadgeSum.Close
Set rsBadgeSum = Nothing
%>
</tbody>
</table>
</div>
</div>
<!-- Tab 7: Tool Health -->
<div class="tab-pane<%If activeTab="toolhealth" Then Response.Write(" active")%>" id="toolhealth">
<h5 class="mb-3">Tool Health</h5>
<p class="text-muted small mb-3">Tool offset measurements and wear tracking.</p>
<!-- Tool Summary by Machine -->
<h6 class="mt-3 mb-2">Tool Measurements by Machine</h6>
<div class="table-responsive mb-4">
<table class="table table-hover table-striped table-sm">
<thead>
<tr>
<th>Machine</th>
<th>Measurements</th>
<th>Unique Tools</th>
<th>OOT Count</th>
<th>Last Measurement</th>
</tr>
</thead>
<tbody>
<%
' Get tool data summary by machine
Dim rsToolMach, toolWhereClause, toolMachStyle
toolWhereClause = " WHERE t.eventtime >= '" & Replace(filterStart, "'", "''") & "' " & _
" AND t.eventtime <= '" & Replace(filterEnd, "'", "''") & " 23:59:59'"
If filterMachine <> "" Then
toolWhereClause = toolWhereClause & " AND s.machinenumber = '" & Replace(filterMachine, "'", "''") & "'"
End If
If filterBU <> "" Then
toolWhereClause = toolWhereClause & " AND s.machinenumber IN (SELECT machinenumber FROM machines WHERE businessunitid = " & CLng(filterBU) & ")"
End If
strSQL2 = "SELECT s.machinenumber, COUNT(*) as cnt, COUNT(DISTINCT t.toolnumber) as tools, " & _
"SUM(t.oot) as ootcount, MAX(t.eventtime) as lasttime " & _
"FROM udctooldata t " & _
"JOIN udcsessions s ON t.sessionid = s.sessionid " & _
toolWhereClause & _
" GROUP BY s.machinenumber ORDER BY cnt DESC, s.machinenumber ASC LIMIT 15"
Set rsToolMach = objConn.Execute(strSQL2)
If rsToolMach.EOF Then
Response.Write("<tr><td colspan='5' class='text-muted text-center'>No tool data found in date range</td></tr>")
Else
Do While Not rsToolMach.EOF
If CLng("0" & rsToolMach("ootcount")) > 0 Then
toolMachStyle = "background-color:#ffc107; color:#333;"
Else
toolMachStyle = ""
End If
Response.Write("<tr style='" & toolMachStyle & "'>")
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsToolMach("machinenumber") & "") & "'>" & Server.HTMLEncode(rsToolMach("machinenumber") & "") & "</a></td>")
Response.Write("<td>" & rsToolMach("cnt") & "</td>")
Response.Write("<td>" & rsToolMach("tools") & "</td>")
Response.Write("<td>")
If CLng("0" & rsToolMach("ootcount")) > 0 Then
Response.Write("<span class='badge badge-danger'>" & rsToolMach("ootcount") & "</span>")
Else
Response.Write("<span class='badge badge-success'>0</span>")
End If
Response.Write("</td>")
Response.Write("<td>" & Server.HTMLEncode(rsToolMach("lasttime") & "") & "</td>")
Response.Write("</tr>")
rsToolMach.MoveNext
Loop
End If
rsToolMach.Close
Set rsToolMach = Nothing
%>
</tbody>
</table>
</div>
<!-- Tool Usage by Tool Number - Only shown when machine filter selected -->
<%
If filterMachine <> "" Then
%>
<h6 class="mt-4 mb-2">Most Used Tools on Machine <%=Server.HTMLEncode(filterMachine)%></h6>
<div class="table-responsive mb-4">
<table class="table table-hover table-striped table-sm">
<thead>
<tr>
<th>Tool #</th>
<th>Description</th>
<th>Measurements</th>
<th>Avg Deviation</th>
<th>OOT Count</th>
</tr>
</thead>
<tbody>
<%
' Get tool usage by tool number for this specific machine
Dim rsToolNum, toolNumStyle, avgDev
strSQL2 = "SELECT t.toolnumber, MAX(t.description) as description, COUNT(*) as cnt, " & _
"AVG(ABS(t.deviation)) as avgdev, SUM(t.oot) as ootcount " & _
"FROM udctooldata t " & _
"JOIN udcsessions s ON t.sessionid = s.sessionid " & _
toolWhereClause & _
" AND t.toolnumber IS NOT NULL " & _
" GROUP BY t.toolnumber ORDER BY cnt DESC, t.toolnumber ASC LIMIT 20"
Set rsToolNum = objConn.Execute(strSQL2)
If rsToolNum.EOF Then
Response.Write("<tr><td colspan='5' class='text-muted text-center'>No tool data found</td></tr>")
Else
Do While Not rsToolNum.EOF
If CLng("0" & rsToolNum("ootcount")) > 0 Then
toolNumStyle = "background-color:#ffc107; color:#333;"
Else
toolNumStyle = ""
End If
If Not IsNull(rsToolNum("avgdev")) Then
avgDev = FormatNumber(CDbl(rsToolNum("avgdev")), 4)
Else
avgDev = "-"
End If
Response.Write("<tr style='" & toolNumStyle & "'>")
Response.Write("<td><strong>Tool " & rsToolNum("toolnumber") & "</strong></td>")
Response.Write("<td>" & Server.HTMLEncode(Trim(rsToolNum("description") & "")) & "</td>")
Response.Write("<td>" & rsToolNum("cnt") & "</td>")
Response.Write("<td>" & avgDev & "</td>")
Response.Write("<td>")
If CLng("0" & rsToolNum("ootcount")) > 0 Then
Response.Write("<span class='badge badge-danger'>" & rsToolNum("ootcount") & "</span>")
Else
Response.Write("<span class='badge badge-success'>0</span>")
End If
Response.Write("</td>")
Response.Write("</tr>")
rsToolNum.MoveNext
Loop
End If
rsToolNum.Close
Set rsToolNum = Nothing
%>
</tbody>
</table>
</div>
<%
End If ' filterMachine
%>
<!-- Recent Tool Measurements -->
<h6 class="mt-4 mb-2">Recent Tool Measurements</h6>
<div class="table-responsive">
<table class="table table-hover table-striped table-sm">
<thead>
<tr>
<th>Time</th>
<th>Machine</th>
<th>Tool #</th>
<th>Description</th>
<th>Min</th>
<th>Actual</th>
<th>Max</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<%
' Get recent tool measurements
Dim rsToolRecent, toolRecentStyle
strSQL2 = "SELECT t.eventtime, s.machinenumber, t.toolnumber, t.description, " & _
"t.minval, t.actualval, t.maxval, t.oot " & _
"FROM udctooldata t " & _
"JOIN udcsessions s ON t.sessionid = s.sessionid " & _
toolWhereClause & _
" ORDER BY t.eventtime DESC LIMIT 30"
Set rsToolRecent = objConn.Execute(strSQL2)
If rsToolRecent.EOF Then
Response.Write("<tr><td colspan='8' class='text-muted text-center'>No tool measurements found</td></tr>")
Else
Do While Not rsToolRecent.EOF
If CLng("0" & rsToolRecent("oot")) > 0 Then
toolRecentStyle = "background-color:#dc3545; color:#fff;"
Else
toolRecentStyle = ""
End If
Response.Write("<tr style='" & toolRecentStyle & "'>")
Response.Write("<td>" & Server.HTMLEncode(rsToolRecent("eventtime") & "") & "</td>")
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsToolRecent("machinenumber") & "") & "'>" & Server.HTMLEncode(rsToolRecent("machinenumber") & "") & "</a></td>")
Response.Write("<td>Tool " & rsToolRecent("toolnumber") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsToolRecent("description") & "") & "</td>")
Response.Write("<td>" & rsToolRecent("minval") & "</td>")
Response.Write("<td><strong>" & rsToolRecent("actualval") & "</strong></td>")
Response.Write("<td>" & rsToolRecent("maxval") & "</td>")
If CLng("0" & rsToolRecent("oot")) > 0 Then
Response.Write("<td><span class='badge badge-danger'>OOT</span></td>")
Else
Response.Write("<td><span class='badge badge-success'>OK</span></td>")
End If
Response.Write("</tr>")
rsToolRecent.MoveNext
Loop
End If
rsToolRecent.Close
Set rsToolRecent = Nothing
%>
</tbody>
</table>
</div>
</div>
<!-- Tab 8: Uptime -->
<div class="tab-pane<%If activeTab="uptime" Then Response.Write(" active")%>" id="uptime">
<h5 class="mb-3">Machine Uptime</h5>
<p class="text-muted small mb-3">Runtime calculated from actual part cycle times within the selected date range.</p>
<!-- Uptime Summary Cards -->
<div class="row mb-4">
<%
' Calculate uptime summary
Dim rsUptimeSummary, totalRuntimeHours, totalMachines, avgUtilization
strSQL2 = "SELECT COUNT(DISTINCT s.machinenumber) as machines, " & _
"ROUND(SUM(p.cycletime)/3600, 1) as total_hours, " & _
"ROUND(AVG(p.cycletime)/60, 1) as avg_cycle " & _
"FROM udcparts p " & _
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
whereClause & _
" AND p.cycletime IS NOT NULL AND p.cycletime > 0"
Set rsUptimeSummary = objConn.Execute(strSQL2)
If Not rsUptimeSummary.EOF Then
totalMachines = CLng("0" & rsUptimeSummary("machines"))
If Not IsNull(rsUptimeSummary("total_hours")) Then
totalRuntimeHours = FormatNumber(CDbl(rsUptimeSummary("total_hours")), 1)
Else
totalRuntimeHours = "0"
End If
Else
totalMachines = 0
totalRuntimeHours = "0"
End If
rsUptimeSummary.Close
Set rsUptimeSummary = Nothing
%>
<div class="col-md-4">
<div class="card bg-info text-white">
<div class="card-body text-center">
<h3 class="mb-0"><%=totalRuntimeHours%></h3>
<small>Total Runtime Hours</small>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card bg-success text-white">
<div class="card-body text-center">
<h3 class="mb-0"><%=totalMachines%></h3>
<small>Active Machines</small>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card bg-primary text-white">
<div class="card-body text-center">
<h3 class="mb-0"><%=totalParts%></h3>
<small>Parts Produced</small>
</div>
</div>
</div>
</div>
<!-- Machine Uptime Table -->
<h6 class="mt-3 mb-2">Runtime by Machine</h6>
<div class="table-responsive">
<table class="table table-hover table-striped" id="uptimeTable">
<thead>
<tr>
<th>Machine</th>
<th>Runtime (hrs)</th>
<th>Parts Run</th>
<th>Avg Cycle (min)</th>
<th>Days Active</th>
<th>Utilization</th>
</tr>
</thead>
<tbody>
<%
' Get uptime by machine
Dim rsUptime, uptimeHours, uptimeCycle, uptimeDays, uptimeUtil, uptimeUtilClass
strSQL2 = "SELECT s.machinenumber, " & _
"ROUND(SUM(p.cycletime)/3600, 1) as runtime_hours, " & _
"COUNT(*) as parts_run, " & _
"ROUND(AVG(p.cycletime)/60, 1) as avg_cycle_min, " & _
"DATEDIFF(MAX(p.programend), MIN(p.programstart)) + 1 as days_active, " & _
"MIN(p.programstart) as first_run, " & _
"MAX(p.programend) as last_run " & _
"FROM udcparts p " & _
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
whereClause & _
" AND p.cycletime IS NOT NULL AND p.cycletime > 0 " & _
"GROUP BY s.machinenumber ORDER BY runtime_hours DESC"
Set rsUptime = objConn.Execute(strSQL2)
If rsUptime.EOF Then
Response.Write("<tr><td colspan='6' class='text-muted text-center'>No uptime data found</td></tr>")
Else
Do While Not rsUptime.EOF
If Not IsNull(rsUptime("runtime_hours")) Then
uptimeHours = FormatNumber(CDbl(rsUptime("runtime_hours")), 1)
Else
uptimeHours = "0"
End If
If Not IsNull(rsUptime("avg_cycle_min")) Then
uptimeCycle = FormatNumber(CDbl(rsUptime("avg_cycle_min")), 1)
Else
uptimeCycle = "-"
End If
uptimeDays = CLng("0" & rsUptime("days_active"))
If uptimeDays < 1 Then uptimeDays = 1
' Calculate utilization (runtime hours / (days * 16 hours for 2 shifts) * 100)
If uptimeDays > 0 And Not IsNull(rsUptime("runtime_hours")) Then
uptimeUtil = Round((CDbl(rsUptime("runtime_hours")) / (uptimeDays * 16)) * 100, 1)
If uptimeUtil > 100 Then uptimeUtil = 100
Else
uptimeUtil = 0
End If
' Color code utilization
If uptimeUtil >= 70 Then
uptimeUtilClass = "badge badge-success"
ElseIf uptimeUtil >= 40 Then
uptimeUtilClass = "badge badge-warning"
Else
uptimeUtilClass = "badge badge-danger"
End If
Response.Write("<tr>")
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsUptime("machinenumber") & "") & "'>" & Server.HTMLEncode(rsUptime("machinenumber") & "") & "</a></td>")
Response.Write("<td><strong>" & uptimeHours & "</strong></td>")
Response.Write("<td>" & rsUptime("parts_run") & "</td>")
Response.Write("<td>" & uptimeCycle & "</td>")
Response.Write("<td>" & uptimeDays & "</td>")
Response.Write("<td><span class='" & uptimeUtilClass & "'>" & uptimeUtil & "%</span></td>")
Response.Write("</tr>")
rsUptime.MoveNext
Loop
End If
rsUptime.Close
Set rsUptime = Nothing
%>
</tbody>
</table>
</div>
</div>
<!-- Tab 9: IT Diagnostics -->
<div class="tab-pane<%If activeTab="itdiagnostics" Then Response.Write(" active")%>" id="itdiagnostics">
<h5 class="mb-3">IT Diagnostics</h5>
<!-- Error Summary by Type -->
<h6 class="mt-3 mb-2">Error Summary by Type</h6>
<div class="table-responsive mb-4">
<table class="table table-hover table-striped table-sm">
<thead>
<tr>
<th>Error Type</th>
<th>Count</th>
<th>Machines Affected</th>
<th>Last Occurrence</th>
</tr>
</thead>
<tbody>
<%
' Get error summary by type
Dim rsErrSummary, errWhereClause, errRowStyle
errWhereClause = " WHERE eventtime >= '" & Replace(filterStart, "'", "''") & "' " & _
" AND eventtime <= '" & Replace(filterEnd, "'", "''") & " 23:59:59'"
If filterMachine <> "" Then
errWhereClause = errWhereClause & " AND machinenumber = '" & Replace(filterMachine, "'", "''") & "'"
End If
If filterBU <> "" Then
errWhereClause = errWhereClause & " AND machinenumber IN (SELECT machinenumber FROM machines WHERE businessunitid = " & CLng(filterBU) & ")"
End If
strSQL2 = "SELECT errortype, COUNT(*) as cnt, COUNT(DISTINCT machinenumber) as machines, MAX(eventtime) as lasttime " & _
"FROM udcerrors " & errWhereClause & _
" GROUP BY errortype ORDER BY cnt DESC, errortype ASC LIMIT 10"
Set rsErrSummary = objConn.Execute(strSQL2)
If rsErrSummary.EOF Then
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No errors found in date range</td></tr>")
Else
Do While Not rsErrSummary.EOF
If CLng("0" & rsErrSummary("cnt")) > 50 Then
errRowStyle = "background-color:#dc3545; color:#fff;"
ElseIf CLng("0" & rsErrSummary("cnt")) > 10 Then
errRowStyle = "background-color:#ffc107; color:#333;"
Else
errRowStyle = ""
End If
Response.Write("<tr style='" & errRowStyle & "'>")
Response.Write("<td>" & Server.HTMLEncode(rsErrSummary("errortype") & "") & "</td>")
Response.Write("<td>" & rsErrSummary("cnt") & "</td>")
Response.Write("<td>" & rsErrSummary("machines") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsErrSummary("lasttime") & "") & "</td>")
Response.Write("</tr>")
rsErrSummary.MoveNext
Loop
End If
rsErrSummary.Close
Set rsErrSummary = Nothing
%>
</tbody>
</table>
</div>
<!-- Error Summary by Machine -->
<h6 class="mt-4 mb-2">Errors by Machine</h6>
<div class="table-responsive mb-4">
<table class="table table-hover table-striped table-sm">
<thead>
<tr>
<th>Machine</th>
<th>Total Errors</th>
<th>Error Types</th>
<th>Last Error</th>
</tr>
</thead>
<tbody>
<%
' Get errors by machine
Dim rsErrMach, errMachStyle
strSQL2 = "SELECT machinenumber, COUNT(*) as cnt, COUNT(DISTINCT errortype) as types, MAX(eventtime) as lasttime " & _
"FROM udcerrors " & errWhereClause & _
" GROUP BY machinenumber ORDER BY cnt DESC, machinenumber ASC LIMIT 10"
Set rsErrMach = objConn.Execute(strSQL2)
If rsErrMach.EOF Then
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No errors found</td></tr>")
Else
Do While Not rsErrMach.EOF
If CLng("0" & rsErrMach("cnt")) > 100 Then
errMachStyle = "background-color:#dc3545; color:#fff;"
ElseIf CLng("0" & rsErrMach("cnt")) > 25 Then
errMachStyle = "background-color:#ffc107; color:#333;"
Else
errMachStyle = ""
End If
Response.Write("<tr style='" & errMachStyle & "'>")
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsErrMach("machinenumber") & "") & "'>" & Server.HTMLEncode(rsErrMach("machinenumber") & "") & "</a></td>")
Response.Write("<td>" & rsErrMach("cnt") & "</td>")
Response.Write("<td>" & rsErrMach("types") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsErrMach("lasttime") & "") & "</td>")
Response.Write("</tr>")
rsErrMach.MoveNext
Loop
End If
rsErrMach.Close
Set rsErrMach = Nothing
%>
</tbody>
</table>
</div>
<!-- Recent Errors -->
<h6 class="mt-4 mb-2">Recent Errors</h6>
<div class="table-responsive mb-4">
<table class="table table-hover table-striped table-sm">
<thead>
<tr>
<th>Time</th>
<th>Machine</th>
<th>Type</th>
<th>Message</th>
</tr>
</thead>
<tbody>
<%
' Get recent errors
Dim rsRecentErr, recentErrStyle
strSQL2 = "SELECT eventtime, machinenumber, errortype, errormessage " & _
"FROM udcerrors " & errWhereClause & _
" ORDER BY eventtime DESC LIMIT 25"
Set rsRecentErr = objConn.Execute(strSQL2)
If rsRecentErr.EOF Then
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No errors found</td></tr>")
Else
Do While Not rsRecentErr.EOF
If InStr(1, rsRecentErr("errortype") & "", "Exception", 1) > 0 Then
recentErrStyle = "background-color:#dc3545; color:#fff;"
Else
recentErrStyle = ""
End If
Response.Write("<tr style='" & recentErrStyle & "'>")
Response.Write("<td>" & Server.HTMLEncode(rsRecentErr("eventtime") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsRecentErr("machinenumber") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsRecentErr("errortype") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(Left(rsRecentErr("errormessage") & "", 100)) & "</td>")
Response.Write("</tr>")
rsRecentErr.MoveNext
Loop
End If
rsRecentErr.Close
Set rsRecentErr = Nothing
%>
</tbody>
</table>
</div>
<!-- Connection Events -->
<h6 class="mt-4 mb-2">Connection Events by Machine</h6>
<div class="table-responsive mb-4">
<table class="table table-hover table-striped table-sm">
<thead>
<tr>
<th>Machine</th>
<th>Total Events</th>
<th>COM Ports Used</th>
<th>Last Event</th>
</tr>
</thead>
<tbody>
<%
' Get connection events by machine
Dim rsConnMach, connWhereClause
connWhereClause = " WHERE eventtime >= '" & Replace(filterStart, "'", "''") & "' " & _
" AND eventtime <= '" & Replace(filterEnd, "'", "''") & " 23:59:59'"
If filterMachine <> "" Then
connWhereClause = connWhereClause & " AND machinenumber = '" & Replace(filterMachine, "'", "''") & "'"
End If
If filterBU <> "" Then
connWhereClause = connWhereClause & " AND machinenumber IN (SELECT machinenumber FROM machines WHERE businessunitid = " & CLng(filterBU) & ")"
End If
strSQL2 = "SELECT machinenumber, COUNT(*) as cnt, COUNT(DISTINCT comport) as ports, MAX(eventtime) as lasttime " & _
"FROM udcconnections " & connWhereClause & _
" GROUP BY machinenumber ORDER BY cnt DESC, machinenumber ASC LIMIT 10"
Set rsConnMach = objConn.Execute(strSQL2)
If rsConnMach.EOF Then
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No connection events found</td></tr>")
Else
Do While Not rsConnMach.EOF
Response.Write("<tr>")
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsConnMach("machinenumber") & "") & "'>" & Server.HTMLEncode(rsConnMach("machinenumber") & "") & "</a></td>")
Response.Write("<td>" & rsConnMach("cnt") & "</td>")
Response.Write("<td>" & rsConnMach("ports") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsConnMach("lasttime") & "") & "</td>")
Response.Write("</tr>")
rsConnMach.MoveNext
Loop
End If
rsConnMach.Close
Set rsConnMach = Nothing
%>
</tbody>
</table>
</div>
<!-- Recent Connection Events -->
<h6 class="mt-4 mb-2">Recent Connection Events</h6>
<div class="table-responsive">
<table class="table table-hover table-striped table-sm">
<thead>
<tr>
<th>Time</th>
<th>Machine</th>
<th>Event</th>
<th>COM Port</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<%
' Get recent connection events
Dim rsRecentConn, connStyle
strSQL2 = "SELECT eventtime, machinenumber, eventtype, comport, details " & _
"FROM udcconnections " & connWhereClause & _
" ORDER BY eventtime DESC LIMIT 25"
Set rsRecentConn = objConn.Execute(strSQL2)
If rsRecentConn.EOF Then
Response.Write("<tr><td colspan='5' class='text-muted text-center'>No connection events found</td></tr>")
Else
Do While Not rsRecentConn.EOF
If rsRecentConn("eventtype") & "" = "OPEN" Then
connStyle = "background-color:#28a745; color:#fff;"
ElseIf rsRecentConn("eventtype") & "" = "CLOSE" Then
connStyle = "background-color:#6c757d; color:#fff;"
Else
connStyle = ""
End If
Response.Write("<tr style='" & connStyle & "'>")
Response.Write("<td>" & Server.HTMLEncode(rsRecentConn("eventtime") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsRecentConn("machinenumber") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsRecentConn("eventtype") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsRecentConn("comport") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(rsRecentConn("details") & "") & "</td>")
Response.Write("</tr>")
rsRecentConn.MoveNext
Loop
End If
rsRecentConn.Close
Set rsRecentConn = Nothing
%>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div><!-- End container-fluid -->
</div><!-- End content-wrapper -->
<a href="javaScript:void();" class="back-to-top"><i class="fa fa-angle-double-up"></i></a>
<footer class="footer">
<div class="container"><div class="text-center"></div></div>
</footer>
</div><!-- End wrapper -->
<!-- JavaScript -->
<script src="assets/js/jquery.min.js"></script>
<script src="assets/js/popper.min.js"></script>
<script src="assets/js/bootstrap.min.js"></script>
<script src="assets/plugins/simplebar/js/simplebar.js"></script>
<script src="assets/js/sidebar-menu.js"></script>
<script src="assets/js/app-script.js"></script>
<script src="assets/plugins/Chart.js/Chart.min.js"></script>
<script>
// Tab persistence - update hidden input when tab is clicked
function setActiveTab(tabName) {
document.getElementById('activeTabInput').value = tabName;
}
// Dashboard Charts
$(function() {
// Chart 1: Production Trend (Line Chart)
var ctxProd = document.getElementById('productionChart').getContext('2d');
new Chart(ctxProd, {
type: 'line',
data: {
labels: [<%=prodLabels%>],
datasets: [{
label: 'Parts Produced',
data: [<%=prodData%>],
backgroundColor: 'rgba(102, 126, 234, 0.2)',
borderColor: 'rgba(102, 126, 234, 1)',
borderWidth: 2,
pointBackgroundColor: 'rgba(102, 126, 234, 1)',
pointRadius: 4,
fill: true
}]
},
options: {
maintainAspectRatio: false,
legend: { display: false },
scales: {
yAxes: [{ ticks: { beginAtZero: true } }],
xAxes: [{ gridLines: { display: false } }]
},
tooltips: {
callbacks: {
label: function(tooltipItem) {
return tooltipItem.yLabel + ' parts';
}
}
}
}
});
// Chart 2: OOT Rate Trend (Line Chart)
var ctxOOT = document.getElementById('ootChart').getContext('2d');
new Chart(ctxOOT, {
type: 'line',
data: {
labels: [<%=ootLabels%>],
datasets: [{
label: 'OOT Rate %',
data: [<%=ootRateData%>],
backgroundColor: 'rgba(220, 53, 69, 0.2)',
borderColor: 'rgba(220, 53, 69, 1)',
borderWidth: 2,
pointBackgroundColor: 'rgba(220, 53, 69, 1)',
pointRadius: 4,
fill: true
}]
},
options: {
maintainAspectRatio: false,
legend: { display: false },
scales: {
yAxes: [{ ticks: { beginAtZero: true, callback: function(value) { return value + '%'; } } }],
xAxes: [{ gridLines: { display: false } }]
},
tooltips: {
callbacks: {
label: function(tooltipItem) {
return tooltipItem.yLabel + '% OOT';
}
}
}
}
});
// Chart 3: Machine Utilization (Horizontal Bar Chart)
var ctxMach = document.getElementById('machineChart').getContext('2d');
new Chart(ctxMach, {
type: 'horizontalBar',
data: {
labels: [<%=machLabels%>],
datasets: [{
label: 'Runtime Hours',
data: [<%=machData%>],
backgroundColor: 'rgba(23, 162, 184, 0.7)',
borderColor: 'rgba(23, 162, 184, 1)',
borderWidth: 1
}]
},
options: {
maintainAspectRatio: false,
legend: { display: false },
scales: {
xAxes: [{ ticks: { beginAtZero: true } }],
yAxes: [{ gridLines: { display: false } }]
},
tooltips: {
callbacks: {
label: function(tooltipItem) {
return tooltipItem.xLabel + ' hours';
}
}
}
}
});
// Chart 4: Top Operators (Horizontal Bar Chart)
var ctxOps = document.getElementById('operatorChart').getContext('2d');
new Chart(ctxOps, {
type: 'horizontalBar',
data: {
labels: [<%=opLabels%>],
datasets: [{
label: 'Parts Produced',
data: [<%=opData%>],
backgroundColor: 'rgba(40, 167, 69, 0.7)',
borderColor: 'rgba(40, 167, 69, 1)',
borderWidth: 1
}]
},
options: {
maintainAspectRatio: false,
legend: { display: false },
scales: {
xAxes: [{ ticks: { beginAtZero: true } }],
yAxes: [{ gridLines: { display: false } }]
},
tooltips: {
callbacks: {
label: function(tooltipItem) {
return tooltipItem.xLabel + ' parts';
}
}
}
}
});
});
</script>
</body>
</html>
<%
objConn.Close
%>