Why is my dart script is getting so slow? - dart

I am trying to add new data to keys named "translations" in my items for all files sitting in the Directory.
However, as soon as I enable the commented section in the method translateRecipeMatching and want to merge my recipes, my script gets so slow/wonky that a simple log(recipeMatchingList.length.toString()) in that method crashes my visual studio code window and I have to restart it. Without that block the script ends in around 10 seconds but with that block I can wait over 5 minutes and nothing will happen.
Every other section runs in a reasonable time bewteen 1 and 5 seconds, for reference
Why is my script becoming so slow?
The translations list has around 23434 Elements and recipeMatchingList has 1419 elements. Recipelist contains around 700 elements.
The script is this:
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:translationMatcherNorviah/languagemaps.dart';
import 'package:translationMatcherNorviah/sourcepaths.dart';
enum Mergemode { normal, recipes }
List<Map<String, dynamic>> translationList = [];
List<String> clothingCategorys = [
"Accessories",
"Bags",
"Bottoms",
"Dress-Up",
"Headwear",
"Shoes",
"Socks",
"Tops",
"Clothing Other"
];
void setJsonFileAsString(Mergemode mergemode) {
List<String> jsonPaths = getJsonDataPaths(mergemode);
//Read translations
if (translationList.isEmpty) {
List<dynamic> translationData =
json.decode(File("json/sources/translations/translationsNew.json").readAsStringSync());
for (int j = 0; j < translationData.length; j++) {
Map<String, dynamic> tempMap = translationData[j];
translationList.add(tempMap);
}
}
List<Map<String, dynamic>> recipeMatchingList = [];
if (mergemode == Mergemode.recipes) {
//Read recipeMatchingList
recipeMatchingList = loadRecipeClothMatchingList();
}
//Loop through all files in the path List
for (int i = 0; i < jsonPaths.length; i++) {
String currentPath = jsonPaths[i];
print("Extracting from Filepath: ${jsonPaths[i]}");
//open the json file
List<dynamic> data = json.decode(File(currentPath).readAsStringSync());
List<Map<String, dynamic>> categoryItemList = [];
//Make sure that the dynamic type gets converted into a Map
//Doing it not this way causes an exception
for (int j = 0; j < data.length; j++) {
Map<String, dynamic> tempMap = data[j];
categoryItemList.add(tempMap);
}
List<Map<String, dynamic>> outPutList = [];
//Merge in translations depending on the files propertys
for (int j = 0; j < categoryItemList.length; j++) {
outPutList.add(
addTranslationsToItem(categoryItemList[j], recipeMatchingList),
);
}
//Create a new file at the output path
print("Writing to File: json/output/${getFileName(currentPath)}");
File newFile = File("json/output/${getFileName(currentPath)}");
//Write data to the new File
newFile.createSync();
newFile.writeAsStringSync(json.encode(categoryItemList));
}
}
String getFileName(String filePath) {
String fileName = "";
fileName = filePath.split("/").last;
return fileName;
}
Map<String, dynamic> addTranslationsToItem(Map<String, dynamic> item, List<Map<String, dynamic>> recipeMatchingList) {
Map<String, dynamic> translation = {};
bool hasVariants = item.containsKey("variations");
bool clothGroupMatching = (clothingCategorys.contains(item["sourceSheet"]));
bool fileNameMatching = (item["sourceSheet"] == "Sheet1");
bool iconFileNameMatching = (item["sourceSheet"] == "Sheet2");
bool recipeMatching = (item["sourceSheet"] == "Recipes");
bool hasPlural = (item["sourceSheet"] == "Other");
//The method will loop through the list of translations once and collect the nessecary translations for the item
for (int i = 0; i < translationList.length; i++) {
translation = translationList[i];
//See if the item does not have any specific category and add the translations in the fitting style
if (!clothGroupMatching && !recipeMatching && !fileNameMatching && !iconFileNameMatching && !hasPlural) {
item = translateMatchInternalId(item, translation);
}
//See if the item a Recipe and add the translations in the fitting style
if (!clothGroupMatching && recipeMatching && !fileNameMatching && !iconFileNameMatching && !hasPlural) {
item = translateRecipeMatching(item, translation, recipeMatchingList);
}
}
return item;
}
Map<String, dynamic> translateMatchInternalId(Map<String, dynamic> item, Map<String, dynamic> translation) {
bool hasVariants = item.containsKey("variations");
String itemInternalId = hasVariants ? item["variations"][0]["internalId"].toString() : item["internalId"].toString();
if (translation["id"].toString() == itemInternalId) {
Map<String, dynamic> tempMap = {};
translation.forEach((key, value) {
String oldLanguageString = getOldLanguageString(key);
tempMap[oldLanguageString] = value;
});
item["translations"] = tempMap;
}
return item;
}
Map<String, dynamic> translateMatchFileName(Map<String, dynamic> item, Map<String, dynamic> translation) {
String itemFileName = item["filename"];
if (translation["id"].toString() == itemFileName) {
Map<String, dynamic> tempMap = {};
translation.forEach((key, value) {
String oldLanguageString = getOldLanguageString(key);
tempMap[oldLanguageString] = value;
});
item["translations"] = tempMap;
}
return item;
}
Map<String, dynamic> translateRecipeMatching(
Map<String, dynamic> item, Map<String, dynamic> translation, List<Map<String, dynamic>> recipeMatchingList) {
//First we need to find out if the item is a cloth type and needs GroupID Matching or Internal ID Matching
bool needsGroupIdMatching = item["category"] == "Equipment";
String craftedItemId = item["craftedItemInternalId"].toString();
if (needsGroupIdMatching) {
for (int k = 0; k < recipeMatchingList.length; k++) {
Map<String, dynamic> matchingListItem = recipeMatchingList[k];
bool matchingItemHasVariations = matchingListItem.containsKey("variations");
String matchingListItemId = "";
if (matchingItemHasVariations) {
matchingListItemId = matchingListItem["variations"][0]["internalId"].toString();
} else {
matchingListItemId = matchingListItem["internalId"].toString();
}
if (craftedItemId == matchingListItemId) {
if (matchingItemHasVariations) {
craftedItemId = matchingListItem["variations"][0]["clothGroupId"].toString();
} else {
matchingListItemId = matchingListItem["clothGroupId"].toString();
}
}
}
}
//We need to load the target item files:
if (translation["id"].toString() == craftedItemId) {
Map<String, dynamic> tempMap = {};
translation.forEach((key, value) {
String oldLanguageString = getOldLanguageString(key);
tempMap[oldLanguageString] = value;
});
item["translations"] = tempMap;
}
return item;
}
List<Map<String, dynamic>> loadRecipeClothMatchingList() {
List<dynamic> clothingData = [];
for (int i = 0; i < jsonDataPaths.length; i++) {
String filename = getFileName(jsonDataPaths[i]);
if (clothingFiles.containsValue(filename)) {
clothingData.addAll(json.decode(File(jsonDataPaths[i]).readAsStringSync()));
}
}
List<Map<String, dynamic>> clothingDataMapList = [];
for (int j = 0; j < clothingData.length; j++) {
Map<String, dynamic> tempMap = clothingData[j];
clothingDataMapList.add(tempMap);
}
print("Clothmatchinglist length is: " + clothingDataMapList.length.toString());
return clothingDataMapList;
}

Related

How to return two value from a function in dart?

here is my code
import 'dart:io';
import 'dart:math';
void main() {
bool flag = false;
for (int i = 0; i < 100; i++) {
gameCode();
if (userNumber == computerNumber) {
flag = true;
break;
}
}
}
int randomNumber(number) {
Random randNumber = Random();
int random = randNumber.nextInt(number);
return random;
}
gameCode() {
int computerNumber = randomNumber(9);
print("start guessing the number : ");
int userNumber = int.parse(stdin.readLineSync()!);
if (userNumber == computerNumber) {
print("You got it");
}
}
in this code you can see gameCode function. in that function there is two value that i need to use in main function.so how do i return those two keyword from that function ?
//userNumber // computerNumber
this is the variable that i want to return from that code
Dart not support return multiple values in function, you can return it with array, map, or you can use third lib tuple
Dart does not support returning multiple values in the current latest version. I would in your case recommend creating a class for the specific purpose of define the result from gameCode(). So something like this:
class GameCodeResult {
int userNumber;
int computerNumber;
GameCodeResult({
required this.userNumber,
required this.computerNumber,
});
}
Which we can then use like this in your program:
import 'dart:io';
import 'dart:math';
void main() {
bool flag = false;
for (int i = 0; i < 100; i++) {
GameCodeResult result = gameCode();
if (result.userNumber == result.computerNumber) {
flag = true;
break;
}
}
}
final _random = Random();
int randomNumber(int maxNumber) => _random.nextInt(maxNumber);
GameCodeResult gameCode() {
int computerNumber = randomNumber(9);
print("start guessing the number : ");
int userNumber = int.parse(stdin.readLineSync()!);
if (userNumber == computerNumber) {
print("You got it");
}
return GameCodeResult(userNumber: userNumber, computerNumber: computerNumber);
}
Note, I also fixed your randomNumber() method since it is not recommended to generate a new Random() object for each new random number you want. We should instead reuse an instance of Random in our program.
Please refer to below code
import 'dart:io';
import 'dart:math';
void main() {
bool flag = false;
for (int i = 0; i < 100; i++) {
Map<String, dynamic> res = gameCode();
print(res);
if (res['user_number'] == res['computer_number']) {
flag = true;
break;
}
}
}
int randomNumber(number) {
Random randNumber = Random();
int random = randNumber.nextInt(number);
return random;
}
Map<String, dynamic> gameCode() {
int computerNumber = randomNumber(9);
print("start guessing the number : ");
int userNumber =
int.parse(stdin.readLineSync()!);
if (userNumber == computerNumber) {
print("You got it");
}
return {
"computer_number": computerNumber,
"user_number": userNumber,
};
}

Dart why my code not work with negative value

I try a small code but I have a strange behavior that I can't explain.
I want according to a value to return the "keyvalue" of a map which is based on the key.
My code works with positive value.
If the value is not in the array then it returns null.
It also works with negative values ​​only if the value is included in my array.
If I put a negative value lower than my array then it returns not null but zero which is false!
Keys in my map must be String.
My code that you can test on dartPad :
import 'dart:collection';
void main() {
int myVar = -360;
Map<String, dynamic> values = {
"-200" : 42,
"-100" : 21,
"0" : 0,
"100" : -22,
"150" : -30,
"200" : -43,
"300" : -64
};
Map<String, dynamic> filter(int myVar, Map<String, dynamic> values) {
SplayTreeMap<String, dynamic> newval = SplayTreeMap.of(values);
String convertString = myVar.toString();
if (values.containsKey(convertString)) {
return {convertString: values[convertString]};
}
String lowerKey;
String upperKey;
if(myVar > 0){
lowerKey = newval.lastKeyBefore(convertString);
upperKey = newval.firstKeyAfter(convertString);
}
else{
lowerKey = newval.firstKeyAfter(convertString);
upperKey = newval.lastKeyBefore(convertString);
}
print(lowerKey);
print(upperKey);
return {
if (lowerKey != null) lowerKey: values[lowerKey],
if (upperKey != null) upperKey: values[upperKey],
};
}
var result = filter(myVar, values);
print('============================');
print(result);
}
First I want to give a minor complain about the use of dynamic in the code. It is totally fine to use dynamic in cases where the type cannot be determined on runtime like JSON parsing. But in this case, all the types can be determined and the use of dynamic is not necessary. So I have fixed the code to remove the usage of dynamic and also removed unnecessary typing:
import 'dart:collection';
void main() {
const myVar = -360;
final values = {
"-200": 42,
"-100": 21,
"0": 0,
"100": -22,
"150": -30,
"200": -43,
"300": -64
};
Map<String, int> filter(int myVar, Map<String, int> values) {
final newVal = SplayTreeMap.of(values);
final convertString = myVar.toString();
if (values.containsKey(convertString)) {
return {convertString: values[convertString]};
}
String lowerKey;
String upperKey;
if (myVar > 0) {
lowerKey = newVal.lastKeyBefore(convertString);
upperKey = newVal.firstKeyAfter(convertString);
} else {
lowerKey = newVal.firstKeyAfter(convertString);
upperKey = newVal.lastKeyBefore(convertString);
}
print(lowerKey);
print(upperKey);
return {
if (lowerKey != null) lowerKey: values[lowerKey],
if (upperKey != null) upperKey: values[upperKey],
};
}
final result = filter(myVar, values);
print('============================');
print(result);
}
Your problem is that you are using SplayTreeMap to sort your keys in values but you have used Strings to represent your numbers. This is rather confusing since numbers is valid keys. But this also means that your sorting in your SplayTreeMap is alphabetical and not by number. This is properly the reason why your code does not work as expected.
You can either change the type of your keys to int or provide a compare method to your SplayTreeMap which changes how the sorting are done.
I have made the following example where I have changed the type of keys into int which makes your code work:
import 'dart:collection';
void main() {
const myVar = -360;
final values = {
-200: 42,
-100: 21,
0: 0,
100: -22,
150: -30,
200: -43,
300: -64
};
Map<int, int> filter(int myVar, Map<int, int> values) {
final newVal = SplayTreeMap.of(values);
if (values.containsKey(myVar)) {
return {myVar: values[myVar]};
}
int lowerKey;
int upperKey;
if (myVar > 0) {
lowerKey = newVal.lastKeyBefore(myVar);
upperKey = newVal.firstKeyAfter(myVar);
} else {
lowerKey = newVal.firstKeyAfter(myVar);
upperKey = newVal.lastKeyBefore(myVar);
}
print(lowerKey);
print(upperKey);
return {
if (lowerKey != null) lowerKey: values[lowerKey],
if (upperKey != null) upperKey: values[upperKey],
};
}
final result = filter(myVar, values);
print('============================');
print(result);
}
Output
-200
null
============================
{-200: 42}

how to edit node using Analyser in dart

How to edit a source file in dart using analyser.
This is what i tried
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/scanner.dart';
String src = """
Dynamism d = new Dynamism(expert:true);
main(){
var o = new Object();
d.on(o).hi = 'bye';
}
""";
main() {
var ast = parseCompilationUnit(src, parseFunctionBodies: true);
print('initial value: ');
print(ast.toSource());
var v = new Visitor();
ast.visitChildren(v);
print('After modification:');
print(ast.toSource());
}
class Visitor extends RecursiveAstVisitor {
#override
visitAssignmentExpression(AssignmentExpression node) {
//filter
var p = new RegExp(r'.*\.on\(\w\)');
if (!p.hasMatch(node.toString())) return;
//replace
SimpleStringLiteral ssl = _create_SimpleStringLiteral(node);
node.parent.accept(new NodeReplacer(node, ssl));
}
}
SimpleStringLiteral _create_SimpleStringLiteral(AstNode node) {
String new_string = modify(node.toString());
int line_num = node.offset;
//holds the position and type
StringToken st = new StringToken(TokenType.STRING, new_string,
line_num);
return new SimpleStringLiteral(st, new_string);
}
String modify(String s) {
List parts = s.split('=');
var value = parts[1];
List l = parts[0].split('.');
String dynamism = l.sublist(0, l.length - 1).join('.');
String propertyName = l.last.trim();
return '${dynamism}.set("${propertyName}",${value})';
}
but it's throwing error on SimpleStringLiteral, saying it is an Abstract Class. Please help me to edit 'bye' to 'goodbye'.i think previous version of dart has its implementation but now its abstract.
Instead of using
return new SimpleStringLiteral(st, new_string) try
return astFactory.simpleStringLiteral(st, new_string);
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/scanner.dart';
String src = """
Dynamism d = new Dynamism(expert:true);
main(){
var o = new Object();
d.on(o).hi = 'bye';
}
""";
main() {
var ast = parseCompilationUnit(src, parseFunctionBodies: true);
print('initial value: ');
print(ast.toSource());
var v = new Visitor();
ast.visitChildren(v);
print('After modification:');
print(ast.toSource());
}
class Visitor extends RecursiveAstVisitor {
#override
visitAssignmentExpression(AssignmentExpression node) {
//filter
var p = new RegExp(r'.*\.on\(\w\)');
if (!p.hasMatch(node.toString())) return;
//replace
SimpleStringLiteral ssl = _create_SimpleStringLiteral(node);
node.parent.accept(new NodeReplacer(node, ssl));
}
}
SimpleStringLiteral _create_SimpleStringLiteral(AstNode node) {
String new_string = modify(node.toString());
int line_num = node.offset;
//holds the position and type
StringToken st = new StringToken(TokenType.STRING, new_string,
line_num);
return astFactory.simpleStringLiteral(st, new_string);
}
String modify(String s) {
List parts = s.split('=');
var value = parts[1];
List l = parts[0].split('.');
String dynamism = l.sublist(0, l.length - 1).join('.');
String propertyName = l.last.trim();
return '${dynamism}.set("${propertyName}",${value})';
}

keeping track of a series of simple multiple choice web form answers

This is the code I'm trying to use, which seems logical. But doesn't seem to be working.
MyAsFileName.prototype.getTotalScore = function() {
var totalScore = 0;
for (var i = 0; i < allQuestions.length; i++) {
totalScore += allQuestions[i].getCalculatedScore();
if (currentModule.allQuestions[i].parent.questionCorrect == true) {
knowledgePoints++;
} else {
knowledgePoints--;
}
}
debugLog("Total score: " + totalScore);
debugLog(knowledgePoints);
return totalScore;
}
I have allQuestions defined as below:
var allQuestions = Array();
I have knowledgePoints defined as:
this.knowledgePoints = 10;
I have questionCorrect defined as:
this.questionCorrect = false;
Second fresh attempt made with new class as answer below suggested (commented out for now until I figure out how to get working):
// package
// {
/*public class Quiz {
//public
var knowledgePoints: int = 10;
//public
var allQuestions: Array = new Array;
//public
var questionCorrect: Boolean = false;
//public
function getTotalScore(): int {
var totalScore: int = 0;
for (var i = 0; i < allQuestions.length; i++) {
totalScore += allQuestions[i].getCalculatedScore();
if (currentModule.allQuestions[i].parent.questionCorrect) {
knowledgePoints++;
} else {
knowledgePoints--;
}
}
debugLog("Total score: " + totalScore);
debugLog(knowledgePoints);
return totalScore;
}
}*/
//}
This code above outputs two errors in flash console:
Error 1. Attribute used outside of class.
Error 2. 'Int' could not be loaded.
It's a weird (and actually non-AS3 way) way to do this. Instead of creating a unnamed closure which refers weird variables from who-knows where, you should make it a normal AS3 class, something like that (in a file named Quiz.as):
package
{
public class Quiz
{
public var knowledgePoints:int = 10;
public var allQuestions:Array = new Array;
public var questionCorrect:Boolean = false;
public function getTotalScore():int
{
var totalScore:int = 0;
// Your code does not explain how you will that Array.
// It is initially an empty Array of length 0.
for (var i = 0; i < allQuestions.length; i++)
{
totalScore += allQuestions[i].getCalculatedScore();
if (currentModule.allQuestions[i].parent.questionCorrect)
{
knowledgePoints++;
}
else
{
knowledgePoints--;
}
}
// Not sure what it is.
debugLog("Total score: " + totalScore);
debugLog(knowledgePoints);
return totalScore;
}
}
}

Sorting an array of String in BlackBerry

I need to sort an array of String like the following, in ascending order.
String str[] = {"ASE", "LSM", "BSE", "LKCSE", "DFM"};
How to do that? I need help.
This answer is based on Signare and HeartBeat's suggestion. Explore this link for details. Also this link, Sorting using java.util.Array might be helpful.
// Initialization of String array
String strs[] = {"One", "Two", "Threee", "Four", "Five", "Six", "Seven"};
// implementation of Comparator
Comparator strComparator = new Comparator() {
public int compare(Object o1, Object o2) {
return o1.toString().compareTo(o2.toString());
}
};
// Sort
Arrays.sort(strs, strComparator);
Try this -
import java.util.*;
import java.io.*;
public class TestSort1 {
String [] words = { "Réal", "Real", "Raoul", "Rico" };
public static void main(String args[]) throws Exception {
try {
Writer w = getWriter();
w.write("Before :\n");
for (String s : words) {
w.write(s + " ");
}
java.util.Arrays.sort(words);
w.write("\nAfter :\n");
for (String s : words) {
w.write(s + " ");
}
w.flush();
w.close();
}
catch(Exception e){
e.printStackTrace();
}
}
// useful to output accentued characters to the console
public static Writer getWriter() throws UnsupportedEncodingException {
if (System.console() == null) {
Writer w =
new BufferedWriter
(new OutputStreamWriter(System.out, "Cp850"));
return w;
}
else {
return System.console().writer();
}
}
}
Here is my solution:-
String str[]={"ASE","LSM","BSE","LKCSE","DFM"};
for(int j = 0; j < str.length; j++){
for(int i = j + 1; i < str.length; i++) {
if(str[i].compareTo(str[j]) < 0) {
String t = str[j];
str[j] = str[i];
str[i] = t;
}
}
}

Resources