The code below is taking 27 seconds to load 51 images each image is about 22 KB (timed between the starting and ending alerts I inserted). Is it possible to make it a lot more efficient (I would like to get it to under 3 seconds)?
At first I thought it was the database so I put the alerts in to make sure and found it was this code.
Regards,
Glyn
public void renderYMAwardsTable(List<YouthMemberAwards> ymAwardsList) {
if (!ymAwardsList.isEmpty()) {
flexTableLink.clear();
int linkRow = 0;
int linkCol = 0;
flexTableLeadership.clear();
int leadershipRow = 0;
int leadershipCol = 0;
flexTableBoomerang.clear();
int boomerangRow = 0;
int boomerangCol = 0;
flexTableAchievement.clear();
int achievementRow = 0;
int achievementCol = 0;
flexTableSpecialInterest.clear();
int specialInterestRow = 0;
int specialInterestCol = 0;
totalAwards = 0;
Window.alert("Start populating page.");
for (final YouthMemberAwards ymAwards : ymAwardsList) {
// Display awards and, if applicable, date awarded
if (((ymAwards.getCaAwardedDate() != null)
|| (ymAwards.getAwArchivedDate() == null)
|| (ymAwards.getCaAwardStarted().equals("Y"))
) && (ymAwards.getAwStartedDate().before(ymEndDate))) {
//Display each award in the correct area with:
// the date awarded, if applicable, and
// the date box shaded if the award has been started but not awarded
String imageDataString = ymAwards.getAwAwardPicture();
Image image = new Image(imageDataString);
image.setWidth("75px");
image.setHeight("75px");
image.setStyleName("gwt-Selectable");
final DateBox awardedDate = new DateBox();
awardedDate.setFormat(new DefaultFormat(DateTimeFormat.getFormat("dd/MM/yyyy")));
awardedDate.setValue(ymAwards.getCaAwardedDate());
awardedDate.setWidth("75px");
awardedDate.setFireNullValues(true);
//Check if the Youth Member has started the Award,
//if they have then colour the date box Green.
if (ymAwards.getCaAwardStarted()!= null){
if ((ymAwards.getCaAwardedDate() == null)
&& (ymAwards.getCaAwardStarted().equals("Y"))){
awardedDate.setStyleName("gwt-Green-Background");
}else{
awardedDate.setStyleName("gwt-Label-Login");
}
}else{
awardedDate.setStyleName("gwt-Label-Login");
}
//Tally the number of Awards the Youth Member has been awarded.
if (ymAwards.getCaAwardedDate() != null){
totalAwards = totalAwards + 1;
}
//Display each Award in the appropriate category.
if (ymAwards.getAwAwardType().equals("Link")){
flexTableLink.setWidget(linkRow, linkCol, image);
flexTableLink.setWidget(linkRow + 1, linkCol, awardedDate);
if (linkCol < 10){
linkCol = linkCol + 1;
}else{
linkCol = 0;
linkRow = linkRow + 2;
}
}else{
if (ymAwards.getAwAwardType().equals("Leadership")){
flexTableLeadership.setWidget(leadershipRow, leadershipCol, image);
flexTableLeadership.setWidget(leadershipRow + 1, leadershipCol, awardedDate);
if (leadershipCol < 10){
leadershipCol = leadershipCol + 1;
}else{
leadershipCol = 0;
leadershipRow = leadershipRow + 2;
}
}else{
if (ymAwards.getAwAwardType().equals("Boomerang")){
flexTableBoomerang.setWidget(boomerangRow, boomerangCol, image);
flexTableBoomerang.setWidget(boomerangRow + 1, boomerangCol, awardedDate);
if (boomerangCol < 10){
boomerangCol = boomerangCol + 1;
}else{
boomerangCol = 0;
boomerangRow = boomerangRow + 2;
}
}else{
if (ymAwards.getAwAwardType().equals("Achievement")){
flexTableAchievement.setWidget(achievementRow, achievementCol, image);
flexTableAchievement.setWidget(achievementRow + 1, achievementCol, awardedDate);
if (achievementCol < 10){
achievementCol = achievementCol + 1;
}else{
achievementCol = 0;
achievementRow = achievementRow + 2;
}
}else{
if (ymAwards.getAwAwardType().equals("Special Interest")){
flexTableSpecialInterest.setWidget(specialInterestRow, specialInterestCol, image);
flexTableSpecialInterest.setWidget(specialInterestRow + 1, specialInterestCol, awardedDate);
if (specialInterestCol < 10){
specialInterestCol = specialInterestCol + 1;
}else{
specialInterestCol = 0;
specialInterestRow = specialInterestRow + 2;
}
}else{
//If not found then default to Special Interest.
flexTableSpecialInterest.setWidget(specialInterestRow, specialInterestCol, image);
flexTableSpecialInterest.setWidget(specialInterestRow + 1, specialInterestCol, awardedDate);
if (specialInterestCol < 10){
specialInterestCol = specialInterestCol + 1;
}else{
specialInterestCol = 0;
specialInterestRow = specialInterestRow + 2;
}
}
}
}
}
}
//Add a click handler to the image
image.addClickHandler(new ClickHandler(){
public void onClick(ClickEvent event){
//Store the data from this view for use in subsequent Views (ScoutAwardView).
AsyncCallback<ViewData> callback = new ViewDataStoreHandler<ViewData>();
rpc.setViewData(accountId, accountLevel, youthMemberID, ymAwards.getAwId(), "0", callback);
//If the Award has sub groups then display the Groups and allow one the
//be selected to display the details. Otherwise, display the details.
if (ymAwards.getAwGrouped().equals("Y")) {
//Go to the AwardGroupView
navHandler2.go("AwardGroup");
}else{
//Go to the ScoutAwardView
navHandler2.go("ScoutAward");
}
}
});
//Add change handler for the awarded date.
//Only a Leader or Administrator can update the date
if (accountLevel.equals("Leader") || accountLevel.equals("Administrator")) {
awardedDate.addValueChangeHandler(new ValueChangeHandler<java.util.Date>() {
public void onValueChange(ValueChangeEvent<java.util.Date> event) {
//Check for a null date and handle it for dateBoxArchived and dateBoxPackOut
java.sql.Date sqlDateAwarded = awardedDate.getValue() == null ? null : new java.sql.Date(awardedDate.getValue().getTime());
AsyncCallback<Void> callback = new YMAwardedDateHandler<Void>();
rpc.updateYMAwarded(youthMemberID, ymAwards.getAwId(), sqlDateAwarded, callback);
#SuppressWarnings("unused")
AdjustAwardStock adjustAwardStock = new AdjustAwardStock(sqlDateAwarded, ymAwards.getAwId());
}
});
}
}
}
}
Window.alert("Finish populating page.");
//Hide "Loading please wait" popup.
popup.hide();
//Display the number of Awards earned.
String totalAwardsString = Integer.toString(totalAwards);
textBoxTotalAwards.setText(totalAwardsString);
}
First of all, an image with 75x75 pixels size should not be 22kB. Even a PNG-24 image of this size is about 3kB, let alone GIF. Store your images in the correct sizes and the appropriate file format (use PNG or GIF). For 51 images that means a difference between 1MB and 150kB. This is the first big improvement.
Second, if you use a limited number of images, combine them into a single sprite. This will reduce the number of round-trip server calls from 51 (in your example) to 1. That's another huge improvement.
You don't need to make this sprite manually (unless you want to). You can use GWT's ImageResource ClientBundle. Note that this sprite can be cached, so a browser won't need to load it every time a user visits this page.
The other suggestions (like using switch statements) are good for code readability and maintenance, but they won't give you a significant performance boost because your Java code is compiled into JavaScript, and the compiler is pretty smart.
For combining the images and other JS files, you can always use gzip functionality supported by browser so that all the files can b zipped and send to the browser to unzip. It will lot of network time and transferred data size will b much reduced.
Related
Hello all for the second time,
Initially I was looking for a broad answer, but this thread got blocked for being "too broad"... so I've got no choice, but to go into detail. My apologies if asking the question again is against the forum guidelines, I'm new to stackoverflow so please be kind.
I’ve got data coming into a serial port at 250Hz and I’d like to save it all to a .csv file. Of course draw() is not going to be able to keep up with that rate of data...
At the moment I am using the serialEvent(port) to collect and parse the data. Once parsed out, I'm calling a function in draw to add the data to a new line in a table and then saving that table every 5 seconds...
Yes, I see the obvious flaw that if I'm saving the current data in draw then of course it's not going to be able to save all the data coming in, but rather just the data that happens to be present when the data saving function is called... but I'm not sure of the best way to solve that. A buffer scheme? Or can I have a separate thread that just adds ALL data coming in to a table?
which lead to my initial (broad) question...
Is there a way to save all incoming data to a file without polling?
Thanks to all in advance.. code below:
Twain
import processing.serial.*;
import static javax.swing.JOptionPane.*;
Table table;
String Path = "PathProvidedHere.csv";
String message;
//Some time keeping variables
int hours, minutes, seconds, milliseconds;
float SaveTime;
//Serial port selection
Serial myPort;
String COMx, COMlist = "";
final boolean debug = true;
String portName;
// Data variables
float yaw = 0.0; float pitch = 0.0; float roll = 0.0;
float A1, A2, A3, A4;
float E1, E2, E3, E4;
void setup()
{
//Set up GIU box
size(1024, 768, P3D);
frameRate(250);
smooth();
//Some other setups like fonts, graphs, etc.
//Set up the logging table
table = new Table();
table.addColumn("A1"); table.addColumn("A2"); table.addColumn("A3"); table.addColumn("A4");
table.addColumn(""); table.addColumn("E1"); table.addColumn("E3"); table.addColumn("E4");
table.addColumn(" "); table.addColumn("min"); table.addColumn("sec"); table.addColumn("milli");
portName = chooseCOM();
delay(1000);
}
void draw()
{
SavetoCSV();
//serialEvent(myPort); // read and parse incoming serial message
ACouple();
Unrelated();
FunctionsHere();
if(millis() - SaveTime > 5000)
{
saveTable(table, Path);
SaveTime=millis();
}
}
String chooseCOM()
{
setupP2 = true;
try
{
if (debug) printArray(Serial.list());
int i = Serial.list().length;
if (i != 0)
{
if (i >= 2)
{
// need to check which port the inst uses -
// for now we'll just let the user decide
for (int j = 0; j < i; )
{
COMlist += char(j+'a') + " = " + Serial.list()[j];
if (++j < i) COMlist += ", ";
}
COMx = showInputDialog("Which COM port is correct? (a,b,..):\n"+COMlist);
if (COMx == null) exit();
if (COMx.isEmpty()) exit();
i = int(COMx.toLowerCase().charAt(0) - 'a') + 1;
}
String portName = Serial.list()[i-1];
if (debug) //println(portName + " Selected");
myPort = new Serial(this, portName, 115200); // change baud rate to your liking
myPort.bufferUntil(13); // buffer until CR/LF appears, but not required..
return portName;
}
else
{
showMessageDialog(frame, "Device is not connected to the PC");
exit();
}
}
catch (Exception e)
{ //Print the type of error
showMessageDialog(frame, "COM port is not available (may\nbe in use by another program)");
//println("Error:", e);
exit();
}
return "noPort";
}
void serialEvent(Serial myPort)
{
int newLine = 13; // new line character in ASCII
do
{
message = myPort.readStringUntil(newLine); // read from port until new line
if (message != null)
{
String[] list = split(trim(message), " ");
if (list.length == 4 && list[0].equals("i"))
{
yaw = float(list[1]); // convert to float yaw
pitch = float(list[2]); // convert to float pitch
roll = float(list[3]); // convert to float roll
}
else if (list.length == 5 && list[0].equals("s"))
{
A1 = float(list[1]);
A2 = float(list[2]);
A3 = float(list[3]);
A4 = float(list[4]);
}
else if (list.length >=2 && list[0].equals("b"))
{
Battery = int(list[1]);
}
else if (list.length >= 2 && list[0].equals("m"))
{
MACid = int(list[1]);
}
else
{
//print anything extra to console
//println(message);
}
}
} while (message != null);
}
void SavetoCSV()
{
if (A1 != 0)
{
TableRow newRow = table.addRow();
newRow.setFloat("A1", (A1));
newRow.setFloat("A2", (A2));
newRow.setFloat("A3", (A3));
newRow.setFloat("A4", (A4));
//saveTable(table, Path);
}
}
Additional info:
- Processing P3
- For the record, with the rest of my script I can get draw up to 80hz or so
- I'd be okay with saving all the data and parsing it later
Went the buffer route.... I think I'm getting close now. Unsure if I'm saving the data in the right order or if the saving process will halt the rest of the processes...
Code:
import processing.serial.*;
import static javax.swing.JOptionPane.*;
//Arrays to save the data
LinkedList<Integer> A1c = new LinkedList<Integer>();
LinkedList<Integer> A2c = new LinkedList<Integer>();
LinkedList<Integer> A3c = new LinkedList<Integer>();
LinkedList<Integer> A4c = new LinkedList<Integer>();
int bufferLength = 500;
int bufflen = 0;
//Serial port selection
Serial myPort;
String COMx, COMlist = "";
final boolean debug = true;
String portName;
// Data variables
float yaw = 0.0; float pitch = 0.0; float roll = 0.0;
float A1, A2, A3, A4;
//Data log variables
Table table;
String Path = "PathtoFile.csv";
void setup() {
//Set up GIU box
size(1024, 768, P3D);
frameRate(250);
strokeWeight(50);
smooth();
//Set up the logging table
table = new Table();
table.addColumn("A1"); table.addColumn("A2"); table.addColumn("A3"); table.addColumn("A4");
portName = chooseCOM();
}
void draw() {
//SavetoCSV now called within SerialEvent()
//SavetoCSV();
//serialEvent(myPort); // read and parse incoming serial message
Some();
Unrelated();
FunctionsHere();
}
void serialEvent(Serial myPort) {
int newLine = 13; // new line character in ASCII
do {
message = myPort.readStringUntil(newLine); // read from port until new line
if (message != null) {
String[] list = split(trim(message), " ");
if (list.length == 4 && list[0].equals("i")) {
yaw = float(list[1]); // convert to float yaw
pitch = float(list[2]); // convert to float pitch
roll = float(list[3]); // convert to float roll
} else if (list.length == 5 && list[0].equals("s")) {
A1 = float(list[1]);
A2 = float(list[2]);
A3 = float(list[3]);
A4 = float(list[4]);
if (bufflen < bufferLength) {
A1c.push(int(A1));
A2c.push(int(A2));
A3c.push(int(A3));
A4c.push(int(A4));
bufflen++;
}
else{
bufflen = 0;
SavetoCSV();
}
} else if (list.length >=2 && list[0].equals("b")) {
Battery = int(list[1]);
} else if (list.length >= 2 && list[0].equals("m")) {
MACid = int(list[1]);
} else {
//print anything extra to console
//println(message);
}
}
} while (message != null);
}
void SavetoCSV() {
if (A1 != 0) {
for (int i = bufferLength - 1; i >= 0; i--){
if (i < bufferLength){
TableRow newRow = table.addRow();
newRow.setFloat("A1", (A1c.get(i)));
newRow.setFloat("A2", (A2c.get(i)));
newRow.setFloat("A3", (A3c.get(i)));
newRow.setFloat("A4", (A4c.get(i)));
} else saveTable(table, Path);
}
}
}
String chooseCOM() {
setupP2 = true;
try {
if (debug) printArray(Serial.list());
int i = Serial.list().length;
if (i != 0) {
if (i >= 2) {
// need to check which port the inst uses -
// for now we'll just let the user decide
for (int j = 0; j < i; ) {
COMlist += char(j+'a') + " = " + Serial.list()[j];
if (++j < i) COMlist += ", ";
}
COMx = showInputDialog("Which COM port is correct? (a,b,..):\n"+COMlist);
if (COMx == null) exit();
if (COMx.isEmpty()) exit();
i = int(COMx.toLowerCase().charAt(0) - 'a') + 1;
}
String portName = Serial.list()[i-1];
if (debug) //println(portName + " Selected");
myPort = new Serial(this, portName, 115200); // change baud rate to your liking
myPort.bufferUntil(13); // buffer until CR/LF appears, but not required..
return portName;
} else {
showMessageDialog(frame, "Device is not connected to the PC");
exit();
}
}
catch (Exception e)
{ //Print the type of error
showMessageDialog(frame, "COM port is not available (may\nbe in use by another program)");
//println("Error:", e);
exit();
}
return "noPort";
}
I am writing an app that plays 4 mp3 files simultaneously using 4 MediaPlayer objects. I have added 3 custom knobs to control bass, mid, and treble using 4 equalizers, each attached to its specific MediaPlayer. I have verified that I am passing the correct values (in Millibels) to setBandLevel for each as specified, but I don't hear any difference in sound when spinning the controls. I have added the relevant code below.
One thing I noticed that seems really odd is that the Equalizer method I am calling expects a short, but the frequency range upper limits come back as high as 6,000,000 millibels. I may be missing something here, but a short in android is 2^16 which should mean an upper limit of 64k.
public void setBandLevel(short band, short level)
The code runs without hitting exceptions and I have traces all values to verify each frequency is within its band's range, but I get no variance in sound when I spin the control knobs. I have tested this on K, L and M with the same results.
I appreciate any insight into this.
public void onResume() {
super.onResume();
// Load an ad into the AdMob banner view.
AdView adView = (AdView) getView().findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder()
.setRequestAgent("android_studio:ad_template").build();
adView.loadAd(adRequest);
//initialize views
initializeViews();
setInstrumentNames();
mediaPlayer1.start();
mediaPlayer2.start();
mediaPlayer3.start();
mediaPlayer4.start();
// Start the songtime thread and remember its object so it can be stopped legally
play();
setEqualizer();
setupKnobButtons();
}
public void setEqualizer() {
eq1 = new Equalizer(0, mediaPlayer1.getAudioSessionId());
eq2 = new Equalizer(0, mediaPlayer2.getAudioSessionId());
eq3 = new Equalizer(0, mediaPlayer3.getAudioSessionId());
eq4 = new Equalizer(0, mediaPlayer4.getAudioSessionId());
if (eq1 != null && eq2 != null && eq3 != null && eq4 != null) {
int z = eq1.setEnabled(true);
int c = eq2.setEnabled(true);
int d = eq3.setEnabled(true);
int e = eq4.setEnabled(true);
// The number of bands is usually 5 but could be up to 13
num_bands = eq1.getNumberOfBands();
// The band range will always return the min and max
// Gets the level range for use by setBandLevel(short,short)}. The level is expressed in
// milliBel. Return the band level range in an array of short integers. The first element is the lower
// limit of the range, the second element the upper limit.
// --- THIS IS FOR THE FULL RANGE OF ALL BANDS ---///
range = eq1.getBandLevelRange();
min_level = range[0];
max_level = range[1];
Log.d(TAG_BANDLEVELS, "min level = " + min_level + " max level = " + max_level);
// Loop through all the bands ( usually 5 ) and create 2 arrays
// ( one for lower limit of each band and one for the upper )
for (int i = 0; i < num_bands; i++) {
freq_range = eq1.getBandFreqRange((short) i);
freqRangeLowerLimit.add(freq_range[0]);
freqRangeUpperLimit.add(freq_range[1]);
Log.d(TAG_BANDLEVELS, "freqRangeLowerLimit = " + freq_range[0] +
" freqRangeUpperLimit = " + freq_range[1] + " band = " + i);
}
}
}
private void setBandLevels(int percentage, int new_level1, int new_level2, int nBand) {
if (eq1.hasControl()) {
eq1.setBandLevel((short) nBand, (short) new_level1);
}
else
Log.d(TAG_BANDLEVELS, "EQ 1 DOES NOT HAVE CONTROL");
if (eq2.hasControl()) {
eq2.setBandLevel((short) nBand, (short) new_level1);
}
else
Log.d(TAG_BANDLEVELS, "EQ 2 DOES NOT HAVE CONTROL");
if (eq3.hasControl()) {
eq3.setBandLevel((short) nBand, (short) new_level1);
}
else
Log.d(TAG_BANDLEVELS, "EQ 3 DOES NOT HAVE CONTROL");
if (eq4.hasControl()) {
eq4.setBandLevel((short) nBand, (short) new_level1);
}
else
Log.d(TAG_BANDLEVELS, "EQ 4 DOES NOT HAVE CONTROL");
// Mid and Treble use 2 bands (Mid = 2nd and 3rd Treble = 4th and 5th
if (nBand == PlayFragment.BAND_BASS || nBand == PlayFragment.BAND_TREBLE) {
try {
eq1.setBandLevel((short) (nBand+1), (short) new_level2);
eq2.setBandLevel((short) (nBand+1), (short) new_level2);
eq3.setBandLevel((short) (nBand+1), (short) new_level2);
eq4.setBandLevel((short) (nBand+1), (short) new_level2);
} catch (Throwable ex2) {
ex2.printStackTrace();
}
}
}
public void setupKnobButtons() {
RoundKnobButton rnbBass = (RoundKnobButton) getView().findViewById(R.id.btRoundBass);
rnbBass.SetListener(new RoundKnobButtonListener() {
TextView tvEQBass = (TextView) getView().findViewById(R.id.tvEQBass);
public void onStateChange(boolean newstate) {
Toast.makeText(getActivity(), "New state:" + newstate, Toast.LENGTH_SHORT).show();
}
public void onRotate(final int percentage) {
tvEQBass.post(new Runnable() {
public void run() {
tvEQBass.setText("\n" + percentage + "%\n");
// Bass only uses the first band
int lower1 = freqRangeLowerLimit.get(0);
int upper1 = freqRangeUpperLimit.get(0);
int new_level1 = lower1 + ((upper1 - lower1) * percentage/100);
// new_level1 /= 1000;
// int new_level1 = calc1/100;
int lower2 = freqRangeLowerLimit.get(1);
int upper2 = freqRangeUpperLimit.get(1);
int new_level2 = lower1 + ((upper2 - lower2) * percentage/100);
// new_level2 /= 1000;
// int new_level2 = calc2/100;
setBandLevels(percentage, new_level1, new_level2, BAND_BASS);
Log.d(TAG_BANDLEVELS, "Band = Bass " + "New Level1 = " + new_level1 + "New Level2 = " + new_level2 + " Percentage = " + percentage);
}
});
}
});
I have to use an algorithm to find a path for a school project. I have a sequence of 12 goals on the map, which must be reached before the end of the path. The map is a 70x70 array. What I already did:
I find all the goals and add in a list
The goals are marked by numbers 10 to 21, and i put on a list 0 to 12. (21 IS THE last goal)
private casa[] acharCasas(){
casa[] casas = new casa[12];
for (int linha = 0; linha < jogo.getMapa().length; linha++) {
for (int coluna = 0; coluna < jogo.getMapa()[0].length; coluna++) {
if(jogo.getMapa()[linha][coluna] >= 10 && jogo.getMapa()[linha][coluna] <= 21){
casas[jogo.getMapa()[linha][coluna]-10] = new casa (linha,coluna);
}
}
}
return casas;
}
I make heuristics total cost + distance from other houses unvisited
casas_visitadas are the number of visited goals, and posL = row, posC = Col. What I wanted to do is calculate the distance from where you are to the next uncompleted objective, + distance from this objective to the next objective... to the final goal.
public double distanciaDasOutrasCasas(){
double somaTotal = 0;
int posL = linha,posC = coluna;
for (int i = casas_visitadas; i < 12; i++) {
somaTotal += Math.sqrt(
Math.pow( (double) (casas[i].linha - posL),2) +
Math.pow( (double) (casas[i].coluna - posC),2)
);
posL = casas[i].linha;
posC = casas[i].coluna;
}
return somaTotal;
}
I check all possible movements
And I add them to the ArrayList. Here are the constructors:
public ArrayList<Direcao> movimentosPossiveis(){
ArrayList<Direcao> movimentos = new ArrayList<>();
if (linha > 0) movimentos.add(Direcao.CIMA); // if isnt the first row add UP
if (coluna > 0) movimentos.add(Direcao.ESQUERDA);//if inst the first col add LEFT
if (linha < jogo.getMapa().length) movimentos.add(Direcao.BAIXO); // last row add down
if (coluna < jogo.getMapa()[linha].length) movimentos.add(Direcao.DIREITA); // add right
return movimentos;
}
public ArrayList<cell> permutaCelula(){
ArrayList<Direcao> movimentos = movimentosPossiveis();
ArrayList<cell> novasCelulas = new ArrayList<>();
for (Iterator<Direcao> iterator = movimentos.iterator(); iterator.hasNext();) {
Direcao D = iterator.next();
switch (D){
case CIMA:
novasCelulas.add(
new cell(this /*father*/, Direcao.CIMA /*direction from father */, custo_total /*total cost*/, linha-1/*row-1*/, coluna/*col*/, casas_visitadas/*goals visiteds*/)
);
break;
case BAIXO:
novasCelulas.add(
new cell(this, Direcao.CIMA, custo_total, linha+1, coluna, casas_visitadas)
);
break;
case ESQUERDA:
novasCelulas.add(
new cell(this, Direcao.CIMA, custo_total, linha, coluna-1, casas_visitadas)
);
break;
case DIREITA:
novasCelulas.add(
new cell(this, Direcao.CIMA, custo_total, linha, coluna+1, casas_visitadas)
);
break;
}
}
return novasCelulas;
}
public double convertePesoDoChao(){
System.out.println(" L " + this.linha + " Coluna "+ coluna);
int chao = jogo.getMapa()[this.linha][this.coluna];
switch (chao) {
case 0:
return 200; //rock field, slowest field
case 1:
return 1;
case 2:
return 3.5;
case 3:
return 5;
case 22:
if(quantidadeDeCavaleirosVivos() != 0) return Double.MAX_VALUE; // cant go to master without find all goals
finalizado = true; // found
caminhoFinal = converteCelulaParaMovimentos(); // converts cells movements
return 0;
default:
casas_visitadas++;
return 0;
}
}
public cell(cell pai, Direcao oPaiMexeuPraQualDirecao, double custo_total, int linha, int coluna, int casas_visitadas) {
this.pai = pai; // father
this.oPaiMexeuPraQualDirecao = oPaiMexeuPraQualDirecao; // direction from father
this.linha = linha; //row
this.coluna = coluna; // col
this.casas_visitadas = casas_visitadas; //goals visited
this.custo_total = custo_total + convertePesoDoChao(); // fathers total cost + field cost
}
public cell(int linha, int coluna) { //starter cell
this.linha = linha;
this.coluna = coluna;
this.custo_total = 0;
this.pai = null;
}
The heuristic
my heuristic is total cost + distancefromgoals
public double heuristica(){
return custo_total *10 + distanciaDasOutrasCasas();
}
Primary loop
if(!finalizado){
this.jogo = jogo;
colunaInicial = jogo.getColuna();
linhaInicial = jogo.getLinha();
casas = acharCasas();
ArrayList<cell> franja = new ArrayList<>();
franja.add(new cell(linhaInicial,colunaInicial));
while(!finalizado){
Collections.sort(franja);
franja.addAll(franja.get(0).permutaCelula());
franja.remove(0);
}
}
The problem
It's taking too long, over three hours total, to find the way... any tips? I checked on the Netbeans profiler, and the problem is sorting the array.
My full code is here
obs: on full code, a game call the action move, and on the first call I need to find the best way, and save it, later I just pop the stack of movements
obs2: sorry my bad english, i used google translator on some parts
I got a really annoying problem with my realtime graph. It works really pretty with MpAndroidChart library, but I guess I'm running out of memory. Because my realtime lineChart-graph become slower the longer it's running, until it get stuck. I didn't find any solution that works.
This is my linecharts screenshot
This is my code to enter values into charts,
( test01 - test04 are possible solution from other posts, I tried )
private void addEntry(double[][] pts) {
// System.out.println("######### addEntry #########");
if (mLineChartObj != null) {
int anzLineChartObj = mLineChartObj.size();
// System.out.println("######### Anzahl LineChartObj: " + anzLineChartObj);
for (int i = 0; i < anzLineChartObj; i++) {
LineChartObject ob = mLineChartObj.get(i);
LineData data = ob.lineChart.getData();
if (data != null) {
data.addXValue((ob.set).getEntryCount() + "");
data.addEntry(new Entry((float) pts[ob.rootNodePos][0], (ob.set).getEntryCount()), 0);
// data.addEntry(new Entry((float) (Math.random() * 9) + 0.45f, (ob.set).getEntryCount()), 0);
}
// °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
if (data.getXValCount() > 1400) {
System.out.println("X-ValueCount: " + ob.lineChart.getXValCount() + " EntryValueCount: " + ob.set.getEntryCount() + " ###############################");
// Test 01 °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
// for (int j = 0; j < 400; j++) {
// data.removeXValue(0);
// ob.set.removeEntry(0);
// }
// Test 02 °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
// runOnUiThread(new Runnable() {
// #Override
// public void run() {
// ob.lineChart.clearValues();
// }
// });
// Test 03 °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
// for (int j = 400; j > 0; j--) {
// data.removeXValue(j + 999);
// ob.set.removeEntry(j + 999);
// }
// Test 04 °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
// data.removeXValue(0);
// ob.set.removeEntry(0);
System.out.println("X-ValueCount: " + ob.lineChart.getXValCount() + " EntryValueCount: " + ob.set.getEntryCount() + " ###############################");
}
// °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
// notify chart data have changed
ob.lineChart.notifyDataSetChanged();
// limit number of visible entries
float range = 200f;
// ob.lineChart.setVisibleXRange(0f, range);
ob.lineChart.setVisibleXRangeMaximum(range);
// scroll the last entry
ob.lineChart.moveViewToX(data.getXValCount() - (range + 1f));
}
}
}
If I remove x-values from data or entries from set, several strange things happens. Sometimes the app gets crash, or the line of the charts begin to repeat itself, or sometimes I get more than one line per chart. I'm looking forward of a solution to remove old values from the chart.
EDIT 2: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
The output of my linechart is like the following picture...It moves like a realtime graph, until xValues an amount of reach 1400, now my programm begins to remove entries and my linechart get stuck. After a while, the line begin to dissapear from the left side. At picture 1 it get stuck, at the next three pictures you can see how it dissapears.
I've been stuck with exactly the same problem today as I'm writing an app that visualizes sensor data. I just came up with the following makeshift solution that works for me:
// (following code snippet is from an event listener)
final ArrayList<Float> values = event.getValues();
final LineData data = mChart.getData();
// add data entry
if (mIndex < MAX_PLOT_SIZE) {
maxValue = 0f;
data.addXValue("" + mIndex);
for (int i = 0; i < values.size(); i++) {
final Float val = values.get(i);
final LineDataSet set = data.getDataSetByIndex(i);
set.addEntry(new Entry(val, mIndex));
}
mIndex++;
} else {
// shift values down
for (int i = 0; i < values.size(); i++) {
final LineDataSet set = data.getDataSetByIndex(i);
final List<Entry> yVals = set.getYVals();
final int size = yVals.size();
for (int j = 0; j < size - 1; j++) {
yVals.get(j).setVal(yVals.get(j + 1).getVal());
}
// add new value
final Float val = values.get(i);
yVals.get(size - 1).setVal(val);
}
}
It's admittedly a hack and there should be an easier way to do it, but at least it gets the job done. I guess you could try and adjust the xVal-Strings in the same manner ...
Recently I got an opportunity to work with Image Processing Technologies as a part of one of my projects and my task was to find matching images from an image store when a new image is given. I started my project with googling "How to compare images using java" and I got some good articles on finding the similarity of two images. Almost all of them were based on four basic steps, they are:
1.Locating the Region of Interest (Where the Objects appear in the given image),
2.Re-sizing the ROIs in to a common size,
3.Substracting ROIs,
4.Calculating the Black and White Ratio of the resultant image after subtraction.
Though this sounds as a good algorithm to compare images, it takes a considerable amount of time after implementing it using JAI in my project. Therefore I have to find an alternate method of doing it.
Any suggestions?
**// This API will compare two image file //
// return true if both image files are equal else return false//**
public static boolean compareImage(File fileA, File fileB) {
try {
// take buffer data from botm image files //
BufferedImage biA = ImageIO.read(fileA);
DataBuffer dbA = biA.getData().getDataBuffer();
int sizeA = dbA.getSize();
BufferedImage biB = ImageIO.read(fileB);
DataBuffer dbB = biB.getData().getDataBuffer();
int sizeB = dbB.getSize();
// compare data-buffer objects //
if(sizeA == sizeB) {
for(int i=0; i<sizeA; i++) {
if(dbA.getElem(i) != dbB.getElem(i)) {
return false;
}
}
return true;
}
else {
return false;
}
}
catch (Exception e) {
System.out.println("Failed to compare image files ...");
return false;
}
}
Depending on how different the images are, you could do something like this (pseudocode). It's very primitive, but should be pretty efficient. You could speed it up by taking random or patterned pixels instead of every one.
for x = 0 to image.size:
for y = 0 to image.size:
diff += abs(image1.get(x,y).red - image2.get(x,y).red)
diff += abs(image1.get(x,y).blue - image2.get(x,y).blue)
diff += abs(image1.get(x,y).green - image2.get(x,y).green)
end
end
return ((float)(diff)) / ( x * y * 3)
This API will compare two image file and return the percentage of similarity
public float compareImage(File fileA, File fileB) {
float percentage = 0;
try {
// take buffer data from both image files //
BufferedImage biA = ImageIO.read(fileA);
DataBuffer dbA = biA.getData().getDataBuffer();
int sizeA = dbA.getSize();
BufferedImage biB = ImageIO.read(fileB);
DataBuffer dbB = biB.getData().getDataBuffer();
int sizeB = dbB.getSize();
int count = 0;
// compare data-buffer objects //
if (sizeA == sizeB) {
for (int i = 0; i < sizeA; i++) {
if (dbA.getElem(i) == dbB.getElem(i)) {
count = count + 1;
}
}
percentage = (count * 100) / sizeA;
} else {
System.out.println("Both the images are not of same size");
}
} catch (Exception e) {
System.out.println("Failed to compare image files ...");
}
return percentage;
}