new(basic.gblib): FIND can now have more than one filter with multiple datatypes.

This commit is contained in:
Rodrigo Rodriguez 2021-08-03 10:06:59 -03:00
parent 23d048c9fd
commit b6962f058b
3 changed files with 149 additions and 26 deletions

View file

@ -98,7 +98,7 @@ export class DialogKeywords {
const user = await this.min.userProfile.get(step.context, {}); const user = await this.min.userProfile.get(step.context, {});
const sec = new SecService(); const sec = new SecService();
const userFull = await sec.getUserFromSystemId(user.systemUser.userId); const userFull = await sec.getUserFromSystemId(user.systemUser.userId);
switch (userFull.locale) { switch (userFull.locale) {
case 'pt': case 'pt':
return [day, month, year].join('/'); return [day, month, year].join('/');
@ -120,6 +120,32 @@ export class DialogKeywords {
await step.endDialog(); await step.endDialog();
} }
/**
* Returns specified date week day in format 'Mon'.
*
* @example day = WEEKDAY (date)
*
*/
public getWeekFromDate(date) {
if (!(date instanceof Date)) {
date = new Date(date);
}
return date.toLocaleString('en-us', { weekday: 'short' });
}
/**
* Returns the specified time in format hh:dd.
*
* @example hour = HOUR (date)
*
*/
public getHourFromDate(date) {
if (!(date instanceof Date)) {
date = new Date(date);
}
return date.getHours() + ':' + date.getMinutes();
}
/** /**
* Returns current time in format hh:dd. * Returns current time in format hh:dd.
* *
@ -288,7 +314,7 @@ export class DialogKeywords {
return 'whatsapp'; return 'whatsapp';
} }
return 'webchat'; return 'webchat';
} }
} }

View file

@ -162,7 +162,9 @@ export class GBVMService extends GBService {
mobile = this.userMobile(step); mobile = this.userMobile(step);
from = mobile; from = mobile;
ubound = function(list){return list.length}; ubound = function(list){return list.length};
isArray = function(list){return Array.isArray(list) }; isarray = function(list){return Array.isArray(list) };
weekday = this.getWeekFromDate;
hour = this.getHourFromDate;
headers = {}; headers = {};
${code} ${code}
@ -423,8 +425,10 @@ export class GBVMService extends GBService {
parsedCode = this.handleThisAndAwait(parsedCode); parsedCode = this.handleThisAndAwait(parsedCode);
parsedCode = parsedCode.replace(/(now)(?=(?:[^"]|"[^"]*")*$)/gi, 'await this.getNow(step)'); parsedCode = parsedCode.replace(/(\bnow\b)(?=(?:[^"]|"[^"]*")*$)/gi, 'await this.getNow()');
parsedCode = parsedCode.replace(/(today)(?=(?:[^"]|"[^"]*")*$)/gi, 'await this.getToday(step)'); parsedCode = parsedCode.replace(/(\btoday\b)(?=(?:[^"]|"[^"]*")*$)/gi, 'await this.getToday(step)');
parsedCode = parsedCode.replace(/(\bweekday\b)(?=(?:[^"]|"[^"]*")*$)/gi, 'weekday');
parsedCode = parsedCode.replace(/(\bhour\b)(?=(?:[^"]|"[^"]*")*$)/gi, 'hour');
parsedCode = beautify(parsedCode, { indent_size: 2, space_in_empty_paren: true }); parsedCode = beautify(parsedCode, { indent_size: 2, space_in_empty_paren: true });
fs.writeFileSync(jsfile, parsedCode); fs.writeFileSync(jsfile, parsedCode);
@ -485,7 +489,9 @@ export class GBVMService extends GBService {
code = code.replace(/this\./gm, 'await this.'); code = code.replace(/this\./gm, 'await this.');
code = code.replace(/function/gm, 'async function'); code = code.replace(/function/gm, 'async function');
code = code.replace('ubound = async', 'ubound ='); // TODO: Improve this. code = code.replace('ubound = async', 'ubound ='); // TODO: Improve this.
code = code.replace('isArray = async', 'isArray ='); // TODO: Waiting for a real compiler. code = code.replace('hour = await', 'hour ='); // TODO: Improve this.
code = code.replace('weekday = await', 'weekday ='); // TODO: Improve this.
code = code.replace('isArray = async', 'isArray ='); // TODO: Waiting for a compiler.
return code; return code;
} }

View file

@ -270,11 +270,11 @@ export class SystemKeywords {
* *
* @example * @example
* *
* rows = FIND "file.xlsx", "A2=active" * rows = FIND "file.xlsx", "A2=active", "A2 < 12/06/2010 15:00"
* i = 1 * i = 1
* do while i < ubound(row) * do while i < ubound(row)
* row = rows[i] * row = rows[i]
* send sms to "+" + row.mobile, "Hello " + row.namee + "! " * send sms to "+" + row.mobile, "Hello " + row.name + "! "
* loop * loop
* *
*/ */
@ -285,11 +285,6 @@ export class SystemKeywords {
const path = `/${botId}.gbai/${botId}.gbdata`; const path = `/${botId}.gbai/${botId}.gbdata`;
let document = await this.internalGetDocument(client, baseUrl, path, file); let document = await this.internalGetDocument(client, baseUrl, path, file);
if (args.length > 1) {
throw `File '${file}' has a FIND call with more than 1 arguments. Check the .gbdialog associated.`;
}
let maxLines = 100; let maxLines = 100;
if (this.dk.user.basicOptions && this.dk.user.basicOptions.maxLines) { if (this.dk.user.basicOptions && this.dk.user.basicOptions.maxLines) {
if (this.dk.user.basicOptions.maxLines.toString().toLowerCase() !== "default") { if (this.dk.user.basicOptions.maxLines.toString().toLowerCase() !== "default") {
@ -299,9 +294,6 @@ export class SystemKeywords {
// Creates workbook session that will be discarded. // Creates workbook session that will be discarded.
const filter = args[0].split('=');
const columnName = filter[0];
const value = filter[1];
let sheets = await client let sheets = await client
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets`) .api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets`)
.get(); .get();
@ -310,16 +302,69 @@ export class SystemKeywords {
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A1:Z${maxLines}')`) .api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A1:Z${maxLines}')`)
.get(); .get();
let getFilter = async (text) => {
let filter;
const operators = [/\<\=/, /\>\=/, /\</, /\>/, /\bin\b/, /\bnot in\b/, /\=/];
let done = false;
await CollectionUtil.asyncForEach(operators, async op => {
var re = new RegExp(op, "g");
const parts = text.split(re);
if (parts.length === 2 && !done) {
filter = {
columnName: parts[0].trim(),
operator: op.toString().replace(/\//g, '').replace(/\\/g, '').replace(/\b/g, ''),
value: parts[1].trim()
};
done = true;
}
});
return filter;
};
function isValidDate(date) {
if (!(date instanceof Date)) {
date = new Date(date);
}
return !isNaN(date.valueOf());
}
function isValidNumber(number) {
return !isNaN(number);
}
// Increments columnIndex by looping until find a column match. // Increments columnIndex by looping until find a column match.
let columnIndex = 0; const filters = [];
const header = results.text[0]; const header = results.text[0];
for (; columnIndex < header.length; columnIndex++) { await CollectionUtil.asyncForEach(args, async arg => {
const filter = await getFilter(arg);
if (header[columnIndex].toLowerCase() === columnName.toLowerCase()) { if (!filter) {
break; throw new Error(`BASIC: FIND filter has an error: ${arg} check this and publish .gbdialog again.`);
} }
}
let columnIndex = 0;
for (; columnIndex < header.length; columnIndex++) {
if (header[columnIndex].toLowerCase() === filter.columnName.toLowerCase()) {
break;
}
}
filter.columnIndex = columnIndex;
if (isValidDate(filter.value)) {
filter.value = new Date(filter.value);
filter.dataType = 'date';
}
else if (isValidNumber(filter.value)) {
filter.value = Number.parseInt(filter.value);
filter.dataType = 'number';
} else {
filter.value = filter.value;
filter.dataType = 'string';
}
filters.push(filter);
});
// As BASIC uses arrays starting with 1 (one) as index, // As BASIC uses arrays starting with 1 (one) as index,
// a ghost element is added at 0 (zero) position. // a ghost element is added at 0 (zero) position.
@ -328,15 +373,60 @@ export class SystemKeywords {
table.push({ 'this is a hidden base 0': 'element' }); table.push({ 'this is a hidden base 0': 'element' });
let foundIndex = 0; let foundIndex = 0;
// Fills the row variable. // Fills the row variable.
for (; foundIndex < results.text.length; foundIndex++) { for (; foundIndex < results.text.length; foundIndex++) {
let filterAcceptCount = 0;
await CollectionUtil.asyncForEach(filters, async filter => {
let result = results.text[foundIndex][columnIndex]; let result = results.text[foundIndex][filter.columnIndex];
// Filter results action. switch (filter.dataType) {
case 'string':
switch (filter.operator) {
case '=':
if (result && result.toLowerCase().trim() === filter.value.toLowerCase().trim()) {
filterAcceptCount++;
}
break;
}
break;
case 'number':
switch (filter.operator) {
case '=':
if (result && result.trim() === filter.value.trim()) {
filterAcceptCount++;
}
break;
}
break;
if (result && result.toLowerCase().trim() === value.toLowerCase().trim()) { case 'date':
const resultDate = new Date(result);
switch (filter.operator) {
case '<':
if (resultDate.getTime() < filter.value.getTime())
filterAcceptCount++;
break;
case '>':
if (resultDate.getTime() > filter.value.getTime())
filterAcceptCount++;
break;
case '<=':
if (resultDate.getTime() <= filter.value.getTime())
filterAcceptCount++;
break;
case '>=':
if (resultDate.getTime() >= filter.value.getTime())
filterAcceptCount++;
break;
}
break;
}
});
if (filterAcceptCount === filters.length) {
let row = {}; let row = {};
const xlRow = results.text[foundIndex]; const xlRow = results.text[foundIndex];
for (let colIndex = 0; colIndex < xlRow.length; colIndex++) { for (let colIndex = 0; colIndex < xlRow.length; colIndex++) {
@ -346,6 +436,7 @@ export class SystemKeywords {
row['line'] = foundIndex + 1; row['line'] = foundIndex + 1;
table.push(row); table.push(row);
} }
} }
if (table.length === 1) { if (table.length === 1) {
@ -643,7 +734,7 @@ export class SystemKeywords {
const options = { const options = {
url: url, url: url,
headers: headers, headers: headers,
qs:qs, qs: qs,
}; };
let result = await request.get(options); let result = await request.get(options);