diff --git a/benchtop-fe/src/App.vue b/benchtop-fe/src/App.vue
index 1c06106..8563fb6 100644
--- a/benchtop-fe/src/App.vue
+++ b/benchtop-fe/src/App.vue
@@ -1,9 +1,14 @@
-
+
+
diff --git a/benchtop-fe/src/parsers/Hardware.js b/benchtop-fe/src/parsers/Hardware.js
new file mode 100644
index 0000000..d4ff4cd
--- /dev/null
+++ b/benchtop-fe/src/parsers/Hardware.js
@@ -0,0 +1,71 @@
+parseInstrumentInfo = (text) => {
+ const instrumentInfo = {};
+ const lines = text.split("\n").slice(2);
+
+ for (const line of lines) {
+ if (line) {
+ const [key, value] = line.trim().split(/\s\s+/);
+ instrumentInfo[key.trim()] = value.trim();
+ }
+ }
+
+ return instrumentInfo;
+}
+
+parsePorts = (text) => {
+ text += "\n\n"; // Ensure extra newline to match on
+ const pattern = /(Test Port \d)/g;
+ const matches = text.split(pattern).slice(1);
+ const portData = {};
+
+ for (let i = 0; i < matches.length; i += 2) {
+ const port = matches[i];
+ const calibration = matches[i + 1];
+ portData[port] = parseCalibrationData(calibration);
+ }
+
+ return portData;
+}
+
+const KEEP = {
+ "Mass Flow Trans": ["Instrument Flow", "Master Reading"],
+ "Pressure Transducer": ["Instrument Pressure", "Master Value"],
+};
+
+parseCalibrationData = (text) => {
+ const pattern = /(Mass Flow Trans|Pressure Transducer)\n([\s\S]+?)\n\n/g;
+ const matches = [...text.matchAll(pattern)];
+ const calibrationData = {};
+
+ for (const match of matches) {
+ const blockTitle = match[1];
+ const blockContent = match[2];
+ const lines = blockContent.trim().split("\n");
+ lines.shift(); // Remove "=======" line
+ const deviceName = lines.shift().trim().split(/\s+/).slice(-1)[0].trim();
+ const deviceData = { name: deviceName };
+
+ for (const line of lines) {
+ const [key, value] = line.trim().split(/\s\s+/);
+ const keyTrimmed = key.trim();
+
+ for (const start of KEEP[blockTitle]) {
+ if (keyTrimmed.startsWith(start)) {
+ deviceData[keyTrimmed] = value.trim();
+ }
+ }
+ }
+
+ calibrationData[blockTitle] = deviceData;
+ }
+
+ return calibrationData;
+}
+
+export default parseHardwareCalibration = (content, accuracy) => {
+ const sections = content.split("|| Hardware Calibration Report ||");
+ const instrumentInfo = parseInstrumentInfo(sections[0]);
+ const calibrationData = parsePorts(sections[1]);
+
+ return { instrument: instrumentInfo, calibration: calibrationData };
+}
\ No newline at end of file
diff --git a/benchtop-fe/src/parsers/Transducer.js b/benchtop-fe/src/parsers/Transducer.js
new file mode 100644
index 0000000..bd64467
--- /dev/null
+++ b/benchtop-fe/src/parsers/Transducer.js
@@ -0,0 +1,111 @@
+inRange = (index, value, masterValues) => {
+ return (
+ masterValues[index]["Low Limit"] <= value && value <= masterValues[index]["High Limit"]
+ );
+}
+
+delta = (index, value, masterValues) => {
+ return Math.abs(masterValues[index]["Low Limit"] - value);
+}
+
+export default parseTransducer = (content, accuracy) => {
+ accuracy = accuracy / 100.0; // Comes in as Percent
+ const transducerData = [];
+
+ // Split the content into sections based on the blank line
+ const sections = content.trim().split("\n\n");
+
+ for (const section of sections) {
+ // Split each section into lines
+ const lines = section.trim().split("\n");
+ const filteredLines = lines.filter(
+ (line) => !line.startsWith("==") && line !== "|| Transducer Verify Report ||"
+ );
+ filteredLines.shift();
+
+ // Extract the Transducer number and Transducer type
+ const transducerLine = filteredLines.shift().trim();
+ const [, transducerName, partNumber] = transducerLine.split(null, 2);
+
+ // Get part number and values
+ let value = null;
+ let unit = null;
+ let transducerType = null;
+ if (partNumber !== "Custom") {
+ value = partNumber.split(" ").pop();
+ partNumber = partNumber.split(" ")[1];
+ const match = value.match(/([0-9]+)([A-Z]+)/i);
+ if (match) {
+ [, value, unit] = match;
+ value = parseInt(value);
+ }
+ if (unit === "SCCM") {
+ transducerType = "Flow";
+ }
+ if (unit === "PSIA") {
+ transducerType = "Pressure";
+ }
+ }
+
+ // Create an object to store the data for each transducer
+ const transducerInfo = {
+ Accuracy: accuracy,
+ "Part Number": partNumber,
+ Value: value,
+ Unit: unit,
+ "Limit ABS": value * accuracy * 1000,
+ "Transducer Name": transducerName,
+ "Transducer Type": transducerType,
+ "Gauge Reading": [],
+ "Master Value": [],
+ "Verify Date": "",
+ "Verify Time": "",
+ };
+
+ // Extract other information for the transducer
+ for (const line of filteredLines) {
+ const [key, val] = line.trim().split(/\s\s+/);
+ if (key.includes("Verify Date")) {
+ transducerInfo["Verify Date"] = val;
+ } else if (key.includes("Verify Time")) {
+ transducerInfo["Verify Time"] = val;
+ } else {
+ // Toss anything else where it belongs
+ const [, cleanKey] = key.split(/\W\d/);
+ if (
+ cleanKey in transducerInfo ||
+ key.includes(`Instrument ${transducerType}`)
+ ) {
+ const value = parseInt(val.split(" ")[0]) * 1000;
+ // special case Master to get the limits
+ if (cleanKey.includes("Master")) {
+ const hi = value + transducerInfo["Limit ABS"];
+ const lo = value - transducerInfo["Limit ABS"];
+ transducerInfo[cleanKey].push({
+ "Low Limit": lo,
+ "Master Value": value,
+ "High Limit": hi,
+ });
+ }
+ // Turn both Instrument Pressure and Instrument Flow to Gauge Reading
+ else if (key.includes(`Instrument ${transducerType}`)) {
+ transducerInfo["Gauge Reading"].push(value);
+ } else {
+ transducerInfo[cleanKey].push(value);
+ }
+ }
+ }
+ }
+
+ // Once we have the readings and master values, we can do the math
+ transducerInfo["Gauge Reading"] = transducerInfo["Gauge Reading"].map((v, idx) => ({
+ Value: v,
+ "In Range": inRange(idx, v, transducerInfo["Master Value"]),
+ Delta: delta(idx, v, transducerInfo["Master Value"]),
+ }));
+
+ transducerData.push(transducerInfo);
+ }
+
+ return transducerData;
+}
\ No newline at end of file
diff --git a/benchtop-fe/src/style.css b/benchtop-fe/src/style.css
index fcca92e..ce2edb1 100644
--- a/benchtop-fe/src/style.css
+++ b/benchtop-fe/src/style.css
@@ -33,6 +33,9 @@ body {
margin: 0.25rem;
margin-bottom: 2%;
border-radius: 3px;
+ /* purple
+ background-color: #b39ddb;
+ border: 1px solid #7e57c2; */
background-color: #a1cbfa;
border: 1px solid #4290e2;
box-shadow: 0 2px 2px rgba(0,90,250,0.05),
diff --git a/benchtopdevices/sheets/parsers/transducer.py b/benchtopdevices/sheets/parsers/transducer.py
index eeb5e65..7acc6e0 100644
--- a/benchtopdevices/sheets/parsers/transducer.py
+++ b/benchtopdevices/sheets/parsers/transducer.py
@@ -1,7 +1,5 @@
import re
import json
-from pprint import pprint
-
def in_range(index, value, master_values):
return (
diff --git a/benchtopdevices/sheets/templates/sheets/upload.html b/benchtopdevices/sheets/templates/sheets/upload.html
deleted file mode 100644
index dd6b159..0000000
--- a/benchtopdevices/sheets/templates/sheets/upload.html
+++ /dev/null
@@ -1,147 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-{% verbatim %}
-
-{% endverbatim %}
-
-
\ No newline at end of file
diff --git a/benchtopdevices/sheets/views.py b/benchtopdevices/sheets/views.py
index c764eba..b75cbaa 100644
--- a/benchtopdevices/sheets/views.py
+++ b/benchtopdevices/sheets/views.py
@@ -1,4 +1,4 @@
-from django.http import HttpResponseRedirect
+from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render
from django.core.exceptions import ValidationError
@@ -30,4 +30,4 @@ def upload_file(request):
return HttpResponseRedirect("/")
else:
form = SheetForm()
- return render(request, "sheets/upload.html", {"form": form})
\ No newline at end of file
+ return HttpResponse("hi")