Files
Novodraft/ax3Services/docParserService/docParser.js
2026-05-23 17:08:47 -04:00

709 lines
19 KiB
JavaScript

const fs = require("fs");
const docClassifer = require("./docClassifier.js");
//const checkService = require("../checkService/checkService.js");
const modelController = require("../agent/ModelController.js");
const { updateDB } = require("../firebase/firebase.js");
const { v4: uuidv4 } = require("uuid");
const path = require("path");
const { count } = require("firebase/firestore");
async function readDir(direcPath, folder, countObject) {
const fdirup = path.join(
__dirname,
"..",
"Documents",
"Textfiles",
`${folder}`
);
try {
const dirArray = countObject.files.map((file) => {
return `${fdirup}/${file.split(".")[0]}.txt`;
});
const sortedFilePaths = dirArray.sort();
const docType = await docClassifer.classifyDoc(sortedFilePaths, folder);
console.log("====================================== docParser readDir");
let parseOneCount = 0;
methodSelector(
docType,
sortedFilePaths,
folder,
parseOneCount,
countObject
);
} catch (err) {
console.log("read error", err);
}
}
async function methodSelector(
docType,
filePaths,
folder,
parseOneCount,
countObject
) {
let searchStr;
let determinedDocType;
if (docType.combined === "combined-numbered") {
determinedDocType = "combined-numbered";
const isRequests = true;
console.log(
"=========================================determinedDocType in docParser methodSelecotr",
determinedDocType
);
updateDB(docId, determinedDocType);
modelController.createArrayOfQuestions(
folder,
determinedDocType,
isRequests,
countObject
);
return;
} else if (docType.rogs > docType.docProd && docType.rogs > docType.admit) {
determinedDocType = "interrogatories";
let parseRogsCount = 0;
parseRogs(docType, filePaths, folder, determinedDocType, parseRogsCount);
} else if (
docType.docProd > docType.rogs &&
docType.docProd > docType.admit
) {
determinedDocType = "production";
parseProdCount = 0;
parseProduction(
docType,
filePaths,
folder,
parseOneCount,
determinedDocType,
parseProdCount
);
return;
} else if (docType.admit > docType.rogs && docType.admit > docType.docProd) {
determinedDocType = "admissions";
let parseAdmitCount = 0;
parseAdmissions(
docType,
filePaths,
folder,
parseOneCount,
determinedDocType,
parseAdmitCount
);
return;
} else if (
docType.combined > docType.rogs &&
docType.combined > docType.docProd &&
docType.combined > docType.admit
) {
// maybe deprecate
determinedDocType = "combined";
parseCombined(docType, filePaths, folder, parseOneCount, determinedDocType);
} else {
// To avoid undefined errors in later checks (for now)
searchStr = "N~U**LL";
}
return determinedDocType;
}
/*******************************************************************************
*
* Combined (Interrogatories and Requests for Production) Request parser
*
*******************************************************************************/
async function parseCombined(
docType,
filePaths,
folder,
parseOneCount,
determinedDocType,
parseCombinedCount
) {
const processArray = [];
const rogs = [];
filePaths.forEach((filePath) => {
fileData = fs.readFileSync(filePath, "utf8", function (err) {
console.log("error in readFile", err);
});
const arr = [];
searchStr = 1;
const stringChunk = fileData.toString().toLowerCase();
const string = fileData.toString().toLowerCase();
for (
let pos = stringChunk.lastIndexOf(`${searchStr.toString()}.`);
pos > -1;
pos = stringChunk.indexOf(`${searchStr.toString()}.`, pos + 1)
) {
arr.push(pos);
searchStr++;
console.log("arr, pos", arr, pos);
}
const questionsArray = arr.map((item, i) => {
return string.slice(arr[i], arr[i + 1]);
});
const clean = questionsArray.map((item) => {
return item.replace(/\r?\n|\r/g, "");
});
processArray.push(...clean);
const unique = processArray.filter(function (item, pos) {
return processArray.indexOf(item) == pos;
});
unique.forEach((item) => {
let obj = {};
const requestId = uuidv4();
obj["requestId"] = requestId;
obj["text"] = item;
rogs.push(obj);
});
if (rogs.length < 3) {
} else {
makeDir(folder, determinedDocType);
let requestArray = [];
let requestObject = {};
requestObject["type"] = determinedDocType;
requestObject["requests"] = rogs;
requestArray.push(requestObject);
saveParsedRogs(requestArray, folder, determinedDocType);
}
});
return;
}
/*******************************************************************************
*
* Request for production of documents parser
*
*******************************************************************************/
async function parseProduction(
docType,
filePaths,
folder,
parseOneCount,
determinedDocType,
parseProdCount
) {
const initialHeaderString = "requests for production"; // /^request* for admission*$/;
const processArray = [];
const rogs = [];
let searchStr;
if (parseProdCount < 1) {
searchStr = "REQUEST FOR PRODUCTION";
} else if (parseProdCount === 1) {
searchStr = "REQUEST NO";
} else if (parseProdCount === 2) {
searchStr = "REQUEST NUM";
}
filePaths.forEach((filePath, mainIndex) => {
let fileData;
fileData = fs.readFileSync(filePath, "utf8");
const arr = [];
const stringChunk = fileData.toString().toLowerCase();
const string = fileData.toString().toLowerCase();
for (
let pos = stringChunk.indexOf(searchStr.toLowerCase());
pos > -1;
pos = stringChunk.indexOf(searchStr.toLowerCase(), pos + 1)
) {
arr.push(pos);
}
const questionsArray = arr.map((item, i) => {
return string.slice(arr[i], arr[i + 1]);
});
const clean = questionsArray.map((item) => {
return item.replace(/\r?\n|\r/g, "");
});
processArray.push(...clean);
});
const unique = processArray.filter(function (item, pos) {
return processArray.indexOf(item) == pos;
});
unique.forEach((item) => {
let obj = {};
const requestId = uuidv4();
obj["requestId"] = requestId;
obj["text"] = item;
rogs.push(obj);
});
if (rogs.length < 2) {
if (parseProdCount < 2) {
parseProdCount++;
parseProduction(
docType,
filePaths,
folder,
parseOneCount,
determinedDocType,
parseProdCount
);
} else {
determinedDocType = "combined-numbered";
const isRequests = true;
modelController.createArrayOfQuestions(
folder,
determinedDocType,
isRequests
);
return;
}
} else {
const docId = folder;
const reqType = "production"; //determinedDocType var value is lost by here not sure why but this hack should fix
const directionVar = "Requests";
const saveDirectory = path.join(
__dirname,
"..",
"Documents",
`${directionVar}`,
`${reqType}`,
`${docId}`
);
fs.mkdir(`${saveDirectory}`, function (err) {
if (err) {
console.log("makeDir utilities error creating directory: " + err);
}
});
let requestArray = [];
let requestObject = {};
requestObject["type"] = determinedDocType;
requestObject["requests"] = rogs;
requestArray.push(requestObject);
const fileSuffix = "-jbk-parsedRequests.json";
const data = JSON.stringify(requestArray);
fs.writeFile(
`${saveDirectory}/${docId}${fileSuffix}`,
data,
function (err) {
if (err) {
return console.log("Error in parseProd writeFile:", err);
}
}
);
}
}
/*******************************************************************************
*
* Requests for Admissions parser
*
*******************************************************************************/
async function parseAdmissions(
docType,
filePaths,
folder,
parseOneCount,
determinedDocType,
parseAdmitCount
) {
const initialHeaderString = "requests for admissions"; //^request* for admission*$/;
console.log(
"parseAdmissions called-------------------------------------------"
);
const processArray = [];
const rogs = [];
let searchStr;
if (parseAdmitCount < 1) {
searchStr = "REQUEST NO";
} else if (parseAdmitCount === 1) {
searchStr = "ADMIT THAT";
} else if (parseAdmitCount === 2) {
searchStr = "ADMIT";
} else if (parseAdmitCount === 3) {
regex = /^[1-9]?$/;
searchStr = `Request No. ${reggex}`;
} else if (parseAdmitCount === 4) {
regex = /^[1-9][0-9]?$/;
searchStr = `Request No. ${reggex}`;
} else if (parseAdmitCount === 5) {
regex = /^[1-9]?$/;
searchStr = `Request ${reggex}.`;
} else {
regex = /^[1-9][0-9]?$/;
searchStr = `Request ${reggex}.`;
}
filePaths.forEach((filePath, mainIndex) => {
let fileData;
fileData = fs.readFileSync(filePath, "utf8");
const arr = [];
const stringChunk = fileData.toString().toLowerCase();
//const string = fileData.toString().toLowerCase(); this might solve lowercase problem
const string = fileData.toString();
for (
let pos = stringChunk.indexOf(searchStr.toLowerCase());
pos > -1;
pos = stringChunk.indexOf(searchStr.toLowerCase(), pos + 1)
) {
arr.push(pos);
}
const questionsArray = arr.map((item, i) => {
return string.slice(arr[i], arr[i + 1]);
});
const clean = questionsArray.map((item) => {
let temp4;
const temp = item.replace(/\r?\n|\r/g, "");
const temp2 = temp.replace("request no.", "").trim();
const temp3 = temp2.replace("REQUEST NO.", "").trim();
const firstChar = Number(temp3[0]);
if (Number.isInteger(firstChar)) {
temp4 = temp3.substring(3);
char = temp3[2].toUpperCase();
return `${char}${temp4}`;
} else {
return temp2;
}
});
processArray.push(...clean);
});
const unique = processArray.filter(function (item, pos) {
return processArray.indexOf(item) == pos;
});
unique.forEach((item) => {
let obj = {};
const requestId = uuidv4();
obj["requestId"] = requestId;
obj["text"] = item;
rogs.push(obj);
});
if (rogs.length < 2) {
console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>rogs.length < 2 fired");
if (parseAdmitCount < 6) {
console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>parseAdmitCount < 6 fired");
let determinedDocType = "admissions";
parseAdmitCount++;
parseAdmissions(
docType,
filePaths,
folder,
parseOneCount,
determinedDocType,
parseAdmitCount
);
} else {
console.log(
"--------------------> Parsed admissions switching to LLM calling createArrayOfQuestions"
);
const isRequests = true;
determinedDocType = "combined-numbered";
updateDB(docId, determinedDocType);
modelController.createArrayOfQuestions(
folder,
determinedDocType,
isRequests
);
}
} else {
const reqType = "admissions"; //determinedDocType var value is lost by here not sure why but this hack should fix
const directionVar = "Requests";
const docId = folder;
const saveDirectory = path.join(
__dirname,
"..",
"Documents",
"Requests",
"admissions",
`${docId}`
);
fs.mkdir(`${saveDirectory}`, function (err) {
if (err) {
console.log("makeDir utilities error creating directory: " + err);
}
});
let requestArray = [];
let requestObject = {};
requestObject["type"] = determinedDocType;
requestObject["requests"] = rogs;
requestArray.push(requestObject);
parseTextFiles2SaveCount = 0;
parseAdmitCount = 0;
console.log("requestArray", requestArray);
const data = JSON.stringify(requestArray);
const fileSuffix = "-jbk-parsedRequests.json";
fs.writeFile(
`${saveDirectory}/${docId}${fileSuffix}`,
data,
function (err) {
if (err) {
return console.log("Error in parse admit writeFile:", err);
}
}
);
const reqstType = "admissions";
const isRequests = true;
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
await sleep(3000);
modelController.arrayGenAnswers(docId, reqstType, isRequests);
}
}
/*******************************************************************************
*
* Interrogatory Parser
*
*******************************************************************************/
async function parseRogs(
docType,
filePaths,
folder,
determinedDocType,
parseRogsCount
) {
let searchStr;
console.log(
"***************************************************************************** PARSE ROGS FIRED"
);
if (parseRogsCount < 1) {
searchStr = "INTERROGATORY NO";
} else {
searchStr = "INTERROGATORY NUM";
}
const processArray = [];
const rogs = [];
filePaths.forEach((filePath) => {
let fileData = fs.readFileSync(filePath, "utf8");
const arr = [];
if (fileData) {
if (!fileData.toLowerCase().includes(searchStr.toLowerCase())) return;
}
const string = fileData.toString();
for (
let pos = fileData.toLowerCase().indexOf(searchStr.toLowerCase());
pos > -1;
pos = fileData.toLowerCase().indexOf(searchStr.toLowerCase(), pos + 1)
) {
arr.push(pos);
}
const questionsArray = arr.map((item, i) => {
return string.slice(arr[i], arr[i + 1]);
});
const clean = questionsArray.map((item) => {
return item.replace(/\r?\n|\r/g, "");
});
processArray.push(...clean);
});
const unique = processArray.filter(function (item, pos) {
return processArray.indexOf(item) == pos;
});
const regex = /[A-Za-z]+ [A-Za-z]+\. [A-Za-z0-9]+:/;
const regex2 = new RegExp(/.[Pp]age\s\d{1,2}$/);
const tempArr = unique.map((item) => {
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
const scrubbed = item.replace(regex, "");
const scrubbedMore = scrubbed.replace(regex2, ".");
const caps = capitalizeFirstLetter(scrubbedMore);
return caps;
});
tempArr.forEach((item) => {
let obj = {};
const interrogatoryId = uuidv4();
obj["interrogatoryId"] = interrogatoryId;
obj["text"] = item;
rogs.push(obj);
});
if (rogs.length < 2) {
if (parseRogsCount < 2) {
parseRogsCount++;
parseRogs(docType, filePaths, folder, determinedDocType, parseRogsCount);
} else {
const _isRequests = true;
const reqType = "combined-numbered";
console.log(
"---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- parseRogs GIVING UP calling createArrayOfQuestions ---- ---- "
);
modelController.createArrayOfQuestions(folder, reqType, _isRequests);
return;
}
} else {
let requestArray = [];
let requestObject = {};
requestObject["type"] = "interrogatories";
requestObject["requests"] = rogs;
requestArray.push(requestObject);
const docId = folder;
const reqType = "interrogatories"; //determinedDocType var value is lost by here not sure why but this hack should fix
const saveDirectory = path.join(
__dirname,
"..",
"Documents",
"Requests",
"interrogatories",
`${folder}`
);
fs.mkdir(`${saveDirectory}`, function (err) {
if (err) {
console.log("makeDir utilities error creating directory: " + err);
}
});
const fileSuffix = "-jbk-parsedRequests.json";
const data = JSON.stringify(requestArray);
console.log(
"************************************************************** parseRogs updating DB"
);
updateDB(docId, reqType);
console.log(
" `${saveDirectory}/${docId}${fileSuffix}`",
`${saveDirectory}/${folder}${fileSuffix}`
);
fs.writeFileSync(
`${saveDirectory}/${folder}${fileSuffix}`,
data,
function (err) {
if (err) {
return console.log("Error in parseRogs writeFile:", err);
}
}
);
// Send it straight to LLM
const isRequests = false;
modelController.arrayGenAnswers(docId, reqType, isRequests);
}
}
/*******************************************************************************
*
* Create a directory
*
*******************************************************************************/
async function makeDir(folder, determinedDocType) {
let dir;
if (determinedDocType === "interrogatories") {
dir = path.join(
__dirname,
"..",
"Documents",
"Requests",
"interrogatories",
`${folder}`
);
} else if (determinedDocType === "production") {
dir = path.join(
__dirname,
"..",
"Documents",
"Requests",
"production",
`${folder}`
);
} else if (determinedDocType === "admissions") {
dir = path.join(
__dirname,
"..",
"Documents",
"Requests",
"admissions",
`${folder}`
);
} else if (determinedDocType === "combined-numbered") {
dir = path.join(
__dirname,
"..",
"Documents",
"Requests",
"combnined-numbered",
`${folder}`
);
} else {
dir = `../Documents/Requests/Fallback/${folder}`;
}
fs.mkdir(dir, function (err) {
if (err) {
console.log("docParser makeDir error. Error Creating Directory: " + err);
}
});
}
/*******************************************************************************
*
* Write result to a file
*
*******************************************************************************/
function saveParsedRogs(rogs, folder, determinedDocType) {
let dir;
const fdirup = path.join(__dirname, "..", "Documents", "Requests");
const data2 = JSON.stringify(rogs);
if (determinedDocType === "interrogatories") {
dir = `${fdirup}/interrogatories/${folder}/`;
} else if (determinedDocType === "production") {
dir = `${fdirup}/production/${folder}/`;
} else if (determinedDocType === "admissions") {
dir = `${fdirup}/admissions/${folder}/`;
} else if (determinedDocType === "combined-numbered") {
dir = `${fdirup}/combined-numbered/${folder}/`;
}
try {
if (folder) {
updateDB(folder, determinedDocType);
}
fs.writeFile(
dir + `${folder}-jbk-parsedRequests.json`,
data2,
function (err) {
if (err) {
return console.log("Error writing in saveParsedRogs", err);
}
}
);
} catch (err) {
console.log("docParser saveParsedRogs error. Error writing file:", err);
}
}
/*
const reqType = "admissions";
const docId = "73cf6d0d-15cd-4d12-9edc-00bfa8de8ebb";
const isRequests = true;
modelController.testSaveFunction(docId, reqType, isRequests);
*/
module.exports = {
readDir,
makeDir,
saveParsedRogs,
};