I have over 5000 .txt files stored locally on my app each file is at least 15 lines of words
So am trying to search with multiple words all over the 5000 list
Finally i was able to search in all of them but with only one problem
The app freezes until the whole process finished
Future<List<FatwaModel>> searchFatawy(String searchText) async {
if (searchText.isEmpty) return [];
emit(SearchFatawyLoadingState());
searchFatawyTxt.clear();
RegExp regExp = RegExp(
RemoveExtinctionsAtWord()
.normalise(searchText)
.trim()
.split(' ')
.where((element) => element.length > 1)
.join('|'),
caseSensitive: false,
);
Future.forEach(fullFatawy, (FatwaModel fatwa) {
bool check = regExp.hasMatch(RemoveExtinctionsAtWord().normalise(
RegExp(r'(?<=:)(.*)(?=)').firstMatch(fatwa.fatwaBody)?.group(0) ?? '',
));
if (check) searchFatawyTxt.add(fatwa);
}).then((value) {
emit(SearchFatawySuccessState());
});
// searchFatawyTxt = fullFatawy
// .where((fatwa) => regExp.hasMatch(RemoveExtinctionsAtWord().normalise(
// RegExp(r'(?<=:)(.*)(?=)').firstMatch(fatwa.fatwaBody)?.group(0) ??
// '',
// )))
// .toList();
//Sorting the list depending on how many keywords found in a single txt file
searchFatawyTxt.sort(
(FatwaModel a, FatwaModel b) {
int aMatchCount = regExp
.allMatches(
RemoveExtinctionsAtWord().normalise(
RegExp(r'(?<=:)(.*)(?=)').firstMatch(a.fatwaBody)?.group(0) ??
'',
),
)
.length;
int bMatchCount = regExp
.allMatches(
RemoveExtinctionsAtWord().normalise(
RegExp(r'(?<=:)(.*)(?=)').firstMatch(b.fatwaBody)?.group(0) ??
'',
),
)
.length;
return bMatchCount.compareTo(aMatchCount);
},
);
return searchFatawyTxt;
}
All am trying to do is showing a progress bar while the search is being process without freezing the app.
Instead of calling that method directly on your app ( on the main thread ), you will need to call it in another isolate that doesn't share a memory with the main thread.
ad the quickest and easiest way to do it is by calling a compute() method which spawns an isolate and runs the provided callback on that isolate, passes it the provided message, and (eventually) returns the value returned by callback.
Future<List<FatwaModel>> isolatedMethod = compute(searchFatawy, searchText);
Note that I am passing your method declaration, not calling it inside the compute().
and now you can use that isolatedMethod as the Future which you will use in your app.
Related
I am implementing a testcase in cypress where I want to match a list of dateTime values with a RegEx pattern.
All of this gets done in a forEach loop. It works for the first Item and fails on the 2nd item, even though they are the same.
Here is the code for reproduction:
const array = [
"2022-05-23 14:39:43.145",
"2022-05-23 14:39:43.145",
"2022-05-23 14:39:43.120",
"2022-05-23 14:39:43.120",
"2022-05-23 14:39:43.096",
"2022-05-23 14:39:43.096",
"2022-05-23 14:39:43.074",
"2022-05-23 14:39:43.074",
];
const dateTime = new RegExp(/\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d\.\d\d\d/gm);
describe('tesst',() => {
it('should work', function() {
array.forEach((object) => {
expect(object).to.match(dateTime);
})
});
})
Edit
It seems like the bug was the global flag (/g) of the RegEx pattern. However I do not get why this is an issue here. I'd be thankful for an explanation :)
You can make the example simpler to help eliminate factors,
it('tests with regex', function() {
expect("2022-05-23 14:39:43.145").to.match(dateTime) // passes
expect("2022-05-23 14:39:43.120").to.match(dateTime) // fails
})
If you look at the chaijs library, this is how to.match() is implemented
function assertMatch(re, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object');
this.assert(
re.exec(obj)
, 'expected #{this} to match ' + re
, 'expected #{this} not to match ' + re
);
}
so the active ingredient is re.exec(obj), equivalent to dateTime.exec("2022-05-23 14:39:43.145") and if you console.log that expression, the first call succeeds and the second returns null - which chai interprets as a failure.
it('tests with regex', function() {
console.log(dateTime.exec("2022-05-23 14:39:43.145")) // ['2022-05-23 14:39:43.145', index: 0...
console.log(dateTime.exec("2022-05-23 14:39:43.120")) // null
})
The reason can be found at MDN RegExp.prototype.exec() Finding successive matches
If your regular expression uses the "g" flag, you can use the exec() method multiple times to find successive matches in the same string.
When you do so, the search starts at the substring of str specified by the regular expression's lastIndex property (test() will also advance the lastIndex property).
Note that the lastIndex property will not be reset when searching a different string, it will start its search at its existing lastIndex .
If we check the lastIndex property after each step and repeat a few times, every 2nd date fails.
But after a failure lastIndex is reset and the next test succeeds.
it('tests with regex', function() {
console.log(dateTime.exec("2022-05-23 14:39:43.145")) // ['2022-05-23 14:39:43.145', index: 0...
console.log(dateTime.lastIndex) // 23
console.log(dateTime.exec("2022-05-23 14:39:43.120")) // null
console.log(dateTime.lastIndex) // 0
console.log(dateTime.exec("2022-05-23 14:39:43.096")) // ['2022-05-23 14:39:43.096', index: 0...
console.log(dateTime.lastIndex) // 23
console.log(dateTime.exec("2022-05-23 14:39:43.074")) // null
console.log(dateTime.lastIndex) // 0
})
So you can make your loop work by manually resetting the lastIndex
it('should work', function() {
array.forEach(object => {
expect(object).to.match(dateTime); // passes every date
dateTime.lastIndex = 0;
})
})
(or removing the /g flag)
I am trying to create a LinkedHashMap and populate it with a DateTime as the key and a List as the value in my flutter app. I keep running into problems with creating this.
Here is what I am trying right now without success:
List<dynamic> _getEventsForDay(DateTime day) {
for (int i = 0; i < eventDoc.length; i++ ) {
if (day.year == eventDate.year && day.day == eventDate.day && day.month == eventDate.month) {
List<dynamic> eventList = [];
eventList.add(eventDoc[i].agencyId);
eventList.add(eventDoc[i].agentId);
eventList.add(eventDoc[i].eventDate);
eventList.add(eventDoc[i].eventDescription);
eventList.add(eventDoc[i].eventDuration);
eventList.add(eventDoc[i].eventName);
eventList.add(eventDoc[i].eventStartTime);
return kEvents.putIfAbsent(eventDateUTC, () => eventList);
}
}
}
Everything is working except the last line and the putIfAbsent call. The eventDateUTC and the eventList both have values.
I am getting this error when I try to execute the
return kEvents.putIfAbsent(eventDateUTC, () => eventList);
line. When this line executes I get this error:
The method 'putIfAbsent' was called on null.
Receiver: null
Tried calling: putIfAbsent(Instance of 'DateTime', Closure: () => List<dynamic>)
kEvents is declared like this:
LinkedHashMap<DateTime, List> kEvents;
I am sure I am missing something small but I don't have enough experience with flutter to know what it is. Please help if you can.
Code:
filter {
if ([trap_id]) {
mutate {
update => { "trap_id" => "trap_id"++ }
}
else
mutate {
add_field => { "trap_id" => 1 }
}
}
}
Scenario:
I'm trying to introduce a new field(trap_id) which needs to increment by 1 every time a trap is generated.
Error:
:ConfigurationError", :message=>"Expected one of #, {, } at line 26, column 50 (byte 1229) after filter {\n
which points to line : update => { "trap_id" => "trap_id"++ }
Question:
How do I fix the error? or Is this the right way to do for the given scenario.
You cannot increment a field using that syntax. You might be able to use the math filter (although you would need to install it, and it has not been updated for three years), or you could do it in ruby.
ruby {
init => '#trap_id = 0'
code => '
#trap_id += 1
event.set("trap_id", #trap_id)
'
}
You will need to set pipeline.workers to 1 for this to work reliably. If there are multiple pipeline worker threads then access to the instance variable will not be synchronised across them. It may work almost all of the time but it is not impossible for two threads to increment #trap_id before either of them calls event.set. If for some reason the call to event.set actually has to reference memory again (as opposed to a register) then this will get the wrong result.
I would like to add an item to a list:
void submitAll() async {
List<UserSearchItem> userSearchItems = [];
Firestore.instance
.collection('insta_users')
.snapshots()
.listen((data) =>
data.documents.forEach((doc){
print(data.documents.length);
User user = new User.fromDocument(doc);
UserSearchItem searchItem = new UserSearchItem(user);
userSearchItems.add(searchItem);
print(user.bio);
}));
print("Loaded");
print(userSearchItems.length);
}
But if I print the length of the list to the console, it always says, the list is 0 long...
print(userSearchItems.length);
Any suggegstions?
Best Regards
I will try to give an explanation of what is happing here take a look on this code:
import 'dart:async';
void main() {
List<int> userSearchItems = [];
Timer _sendTimeOutTimer;
const oneSec = Duration(seconds: 2);
_sendTimeOutTimer = Timer.periodic(oneSec, (Timer t) {
userSearchItems.add(1);
print(userSearchItems.length); // result 1 and it will be executed after 2 seconds
_sendTimeOutTimer.cancel();
});
print(userSearchItems.length); // result 0 and it will be executed first
}
The print inside asynchronous action(Timer) it will be executed after 2 seconds means after the asynchronous action ends but the one which is outside of asynchronous action(Timer) it will be executed directly without waiting 2 seconds, in your case the asynchronous action is listening to data .listen((data) =>, so if you print the length outside of your asynchronous action you will not see the deferent because the item is not added yet.
Solution: you can create function witch return Future and then wait until it's finished then print the length.
List<UserSearchItem> userSearchItems = [];
Future<String> submitAll() async {
Firestore.instance
.collection('insta_users')
.snapshots()
.listen((data) =>
data.documents.forEach((doc){
print(data.documents.length);
User user = new User.fromDocument(doc);
UserSearchItem searchItem = new UserSearchItem(user);
userSearchItems.add(searchItem);
print(user.bio);
return 'success';
}));
}
void yourFunction() async{
await submitAll();
print("Loaded");
print(userSearchItems.length);
}
Then call yourFunction().
Try to add print(userSearchItems.length); inside forEach after adding the item and you will see the real length.
There is a simple way tu add new data tu a list on Flutter.
for (var i = 0; i < list.length; i++) {
double newValue=newValue+1; //This is just an example,you should put what you'r trying to add here.
list[i]["newValueName"] = newValue; //This is how we add the new value tu the list,
}
See if it work by doing a:
print(list);//You can put a breakpoint her to see it more clearly
Hope it helps.
I programmed a custom field plugin for Virtuemart 2.6.6, which show some parameters on the product page for example "size", and that parameter is a cart variable either.
A huge help was this article:
https://www.spiralscripts.co.uk/Joomla-Tips/custom-plugin-fields-in-virtuemart-2-2.html
And of course stackoverflow forum and factory default VM custom plugins.
Everything is working (the size is displayed in product details view, and in the cart, when you added the product to it) but one thing:
after sending the order the parameter has not displayed in the order details, so I don't know what size of product was bought.
I placed following functions into my plugin, but not solved my problem:
function plgVmOnViewCart($product, $row, &$html)
{
if (empty($product->productCustom->custom_element) or $product->productCustom->custom_element != $this->_name) return '';
if (!$plgParam = $this->GetPluginInCart($product)) return false ;
$html .= '<div class="parameterek_attributes">';
foreach ($plgParam as $attributes) {
foreach ($attributes as $k => $attribute) {
if ($k =='child_id') continue;
if ($k == 'custom_param_default3') $name = 'Veľkosť'; else $name = '';
$html .='<span class="parameterek_attribute"> '.$name.': '.JText::_($attribute).' </span>';
}
}
$html.='</div>';
return true;
}
/**
*
* shopper order display BackEnd
*/
function plgVmDisplayInOrderBE($item, $row,&$html)
{
if (empty($item->productCustom->custom_element) or $item->productCustom->custom_element != $this->_name) return '';
if(!empty($productCustom)){
$item->productCustom = $productCustom;
}
$this->plgVmOnViewCart($item, $row,$html);
}
/**
*
* shopper order display FrontEnd
*/
function plgVmDisplayInOrderFE($item, $row,&$html)
{
if (empty($item->productCustom->custom_element) or $item->productCustom->custom_element != $this->_name) return '';
$this->plgVmOnViewCart($item, $row,$html);
}
Into database table called #__virtuemart_order_items were saved values: something like:
{"357":"5"}
but it should be something like:
{"357":"size M"}
I see that the key function is GetPluginInCart($product), and when I printed out the $product->param in that function I've got this output, when I go through checkout process:
Array
(
[0] => Array
(
[parameterek] => Array
(
[custom_param_default3] => L
)
)
)
but after I finish the order and go into order details the $product->param has this value:
Array
(
[357] => 5
)
So I think, before I finish the order I have to somehow handle the
chosen product parameter and transform it into the correct form, but
I don't know how.
On the following site
https://dev.virtuemart.net/projects/virtuemart/wiki/Product_Plugins
I found a function:
plgVmOnViewCartOrder($product, $param,$productCustom, $row)
handel $param before adding it in the order
return $param;
but when I searched for the string "plgVmOnViewCartOrder" in the whole virtuemart installation, it was not found, so it means it is not launched (?)
If anybody could help me or send a fair documentation would be very good. Thank you!
I think, I solved my problem, what was:
in function plgVmOnDisplayProductVariantFE I made a mistake, I didn't use layout renderer, which generates an object $viewData with variable virtuemart_customfield_id.
Then in your plugin's layout, input field name has to be as follows:
<input
class="parameterekInput"
type="radio"
id="plugin_param['.$viewData[0]->virtuemart_customfield_id.']['.$this->_name.']['.$c.']"
name="customPlugin['.$viewData[0]->virtuemart_customfield_id.']['.$this->_name.'][custom_param_default3]"
value="'.$size.'" />
so the name attribute should be always:
customPlugin['.$viewData[0]->virtuemart_customfield_id.']['.$this->_name.'][whatever]
The right usage of plgVmOnDisplayProductVariantFE function is to use expression:
$group->display .= $this->renderByLayout('default',array($field,&$idx,&$group )
Here the whole function with the right expresion:
function plgVmOnDisplayProductVariantFE ($field, &$idx, &$group) {
if ($field->custom_element != $this->_name) return '';
$this->getCustomParams($field);
$this->getPluginCustomData($field, $field->virtuemart_product_id);
$group->display .= $this->renderByLayout('default',array($field,&$idx,&$group ) );
return true;
}
Now when I print_r -ing $product->param in function GetPluginInCart($product), I get this:
Array
(
[273] => Array //previously the key was Zero, now it is 273, value of virtuemart_customfield_id
(
[parameterek] => Array
(
[custom_param_default3] => L
)
)
)
...and now I'm glad, that I can move on in my project :)