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 sec = new SecService();
const userFull = await sec.getUserFromSystemId(user.systemUser.userId);
switch (userFull.locale) {
case 'pt':
return [day, month, year].join('/');
@ -120,6 +120,32 @@ export class DialogKeywords {
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.
*
@ -288,7 +314,7 @@ export class DialogKeywords {
return 'whatsapp';
}
return 'webchat';
}
}
}

View file

@ -162,7 +162,9 @@ export class GBVMService extends GBService {
mobile = this.userMobile(step);
from = mobile;
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 = {};
${code}
@ -423,8 +425,10 @@ export class GBVMService extends GBService {
parsedCode = this.handleThisAndAwait(parsedCode);
parsedCode = parsedCode.replace(/(now)(?=(?:[^"]|"[^"]*")*$)/gi, 'await this.getNow(step)');
parsedCode = parsedCode.replace(/(today)(?=(?:[^"]|"[^"]*")*$)/gi, 'await this.getToday(step)');
parsedCode = parsedCode.replace(/(\bnow\b)(?=(?:[^"]|"[^"]*")*$)/gi, 'await this.getNow()');
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 });
fs.writeFileSync(jsfile, parsedCode);
@ -485,7 +489,9 @@ export class GBVMService extends GBService {
code = code.replace(/this\./gm, 'await this.');
code = code.replace(/function/gm, 'async function');
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;
}

View file

@ -270,11 +270,11 @@ export class SystemKeywords {
*
* @example
*
* rows = FIND "file.xlsx", "A2=active"
* rows = FIND "file.xlsx", "A2=active", "A2 < 12/06/2010 15:00"
* i = 1
* do while i < ubound(row)
* row = rows[i]
* send sms to "+" + row.mobile, "Hello " + row.namee + "! "
* send sms to "+" + row.mobile, "Hello " + row.name + "! "
* loop
*
*/
@ -285,11 +285,6 @@ export class SystemKeywords {
const path = `/${botId}.gbai/${botId}.gbdata`;
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;
if (this.dk.user.basicOptions && this.dk.user.basicOptions.maxLines) {
if (this.dk.user.basicOptions.maxLines.toString().toLowerCase() !== "default") {
@ -299,9 +294,6 @@ export class SystemKeywords {
// Creates workbook session that will be discarded.
const filter = args[0].split('=');
const columnName = filter[0];
const value = filter[1];
let sheets = await client
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets`)
.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}')`)
.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.
let columnIndex = 0;
const filters = [];
const header = results.text[0];
for (; columnIndex < header.length; columnIndex++) {
if (header[columnIndex].toLowerCase() === columnName.toLowerCase()) {
break;
await CollectionUtil.asyncForEach(args, async arg => {
const filter = await getFilter(arg);
if (!filter) {
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,
// 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' });
let foundIndex = 0;
// Fills the row variable.
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 = {};
const xlRow = results.text[foundIndex];
for (let colIndex = 0; colIndex < xlRow.length; colIndex++) {
@ -346,6 +436,7 @@ export class SystemKeywords {
row['line'] = foundIndex + 1;
table.push(row);
}
}
if (table.length === 1) {
@ -643,7 +734,7 @@ export class SystemKeywords {
const options = {
url: url,
headers: headers,
qs:qs,
qs: qs,
};
let result = await request.get(options);