Java NullPointerException in agent based model - java

I am using the MASON library to run a simple agent-based model.
As per specifications, I meant to access an agent's inspector by double-clicking on such agent in the Portrayal.
However, when I do so I get the following console error:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at sim.display.Display2D.createInspectors(Display2D.java:1737)
at sim.display.Display2D$8.mouseClicked(Display2D.java:1392)
I went to Display2D.java:1737 to find:
public void createInspectors( final Rectangle2D.Double rect, final GUIState simulation )
{
Bag inspectors = new Bag();
Bag names = new Bag();
Bag[] hitObjects = objectsHitBy(rect);
for(int x=0;x<hitObjects.length;x++)
{
FieldPortrayal2DHolder p = (FieldPortrayal2DHolder)(portrayals.get(x));
for( int i = 0 ; i < hitObjects[x].numObjs ; i++ )
{
LocationWrapper wrapper = (LocationWrapper) (hitObjects[x].objs[i]);
inspectors.add(p.portrayal.getInspector(wrapper,simulation));
names.add(p.portrayal.getName(wrapper));
}
}
simulation.controller.setInspectors(inspectors,names); //1737
}
However, this is a library file so I'm not familiar with it.
Any advice?
Library: cs.gmu.edu/~eclab/projects/mason/
Update:
Ok, it gets interesting...
I did an echo on the toString method of inspectors and names, returning:
insepectors sim.util.Bag#1b2202a names sim.util.Bag#16b334d
Ok so they're bags, a type of collection. Time to get their sizes...
insepectors 1 names 1
Good, they're not empty.
Let's follow the error stack
Next bit:
at sim.display.Display2D$8.mouseClicked(Display2D.java:1392)
// add mouse listener for the inspectors
insideDisplay.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
if (handleMouseEvent(e)) { repaint(); return; }
else
{
// we only care about mouse button 1. Perhaps in the future we may eliminate some key modifiers as well
int modifiers = e.getModifiers();
if ((modifiers & e.BUTTON1_MASK) == e.BUTTON1_MASK)
{
final Point point = e.getPoint();
if( e.getClickCount() == 2 )
1392-> createInspectors( new Rectangle2D.Double( point.x, point.y, 1, 1 ),
Display2D.this.simulation );
if (e.getClickCount() == 1 || e.getClickCount() == 2) // in both situations
performSelection( new Rectangle2D.Double( point.x, point.y, 1, 1 ));
repaint();
}
}
}
Ok, the error is clearly in the CreateInspectors method:
public void createInspectors( final Rectangle2D.Double rect, final GUIState simulation )
{
Bag inspectors = new Bag();
Bag names = new Bag();
Bag[] hitObjects = objectsHitBy(rect);
for(int x=0;x<hitObjects.length;x++)
{
FieldPortrayal2DHolder p = (FieldPortrayal2DHolder)(portrayals.get(x));
for( int i = 0 ; i < hitObjects[x].numObjs ; i++ )
{
LocationWrapper wrapper = (LocationWrapper) (hitObjects[x].objs[i]);
inspectors.add(p.portrayal.getInspector(wrapper,simulation));
names.add(p.portrayal.getName(wrapper));
}
}
System.out.println("insepectors " + inspectors.size() + " names " + names.size());
simulation.controller.setInspectors(inspectors,names);
}
First thing I do:
System.out.println(rect.getCenterX() + " " + rect.getCenterY());
Which gives me 646.5 659.5. Seem to make sense as coordinates.
So next thing I want to look at hitObjects:
System.out.println(hitObjects.length);
Returns 2. So I had two agents at that coordinates.
I assume the NPE is somewhere here:
for(int x=0;x<hitObjects.length;x++)
{
FieldPortrayal2DHolder p = (FieldPortrayal2DHolder)(portrayals.get(x));
for( int i = 0 ; i < hitObjects[x].numObjs ; i++ )
{
LocationWrapper wrapper = (LocationWrapper) (hitObjects[x].objs[i]);
inspectors.add(p.portrayal.getInspector(wrapper,simulation));
names.add(p.portrayal.getName(wrapper));
}
}
The outer loop looks fine, but I'm having issues with the inner one. Advice?

I'm actually going to write how to reason through the library code given as far as you've come since you sound capable.
You found the code. That's a good start. You've also found the line that it's on:
simulation.controller.setInspectors(inspectors,names); //1737
And given what you know about NPEs you can reason that simulation or controller is null.
Do you know which? Can you reason about your code which you may have failed to set, or passed incorrectly? Can you put a debugger breakpoint or simple println statements in your code to determine which?
If not and you're using an IDE (you probably are), then from the source you just opened up, put a breakpoint before line 1737. When that line is reached, use the debugger to inspect the variable simulation then simulation.controller to see which is null. Exactly how to do this will depend on your IDE but it shouldn't be hard to find using XKCD's tech support cheat sheet.
Then you will probably know the cause. If not, continue reading source code, e.g. look a level up to line 1737.

Related

Wolfram Elementary Cellular Automata Using Processing

I'm using a piece of code taken from the website The Nature of Code - https://natureofcode.com/book/chapter-7-cellular-automata/ - the portion I used was from example 7.1. I'm trying to create a one-dimensional cellular automaton using the Processing IDE, but I keep getting an error saying that brackets are missing from particular locations.
Errors:
-Missing curlry bracket "}", line 32
-Syntax error on "}", delete this, line 40
I've gone over it multiple times, but I can't see how this is wrong. Though I did try changing them as it says, only to get more errors. I thought maybe they were just in the wrong place, but I also can't see how that's the case. They seem to be correct as far as I can tell, but maybe I'm missing something. This is my first time using Processing, and it's been a long time since I last used Java. So maybe I'm mistaken.
class CA {
int[] cells;
int[] ruleset;
int w = 10;
// The CA should keep track of how
// many generations.
int generation = 0;
CA() {
cells = new int[width/w];
ruleset = new int[]{0,1,0,1,1,0,1,0};
cells[cells.length/2] = 1;
}
// Function to compute the next generation
void generate() {
int[] nextgen = new int[cells.length];
for (int i = 1; i < cells.length-1; i++) {
int left = cells[i-1];
int me = cells[i];
int right = cells[i+1];
nextgen[i] = rules(left, me, right);
}
cells = nextgen;
// Increment the generation counter.
generation++;
}
int rules(int a, int b, int c) {
String s = "" + a + b + c;
int index = Integer.parseInt(s,2);
return ruleset[index];
}
for (int i = 0; i < cells.length; i++) {
if (cells[i] == 1) fill(0);
else fill(255);
// Set the y-location according to the generation.
rect(i*w, generation*w, w, w);
}
}
The program is supposed to print each generation of the one-dimensional CA on top of the next.
The for-loop in the end of the CA class is not supposed to be there. That is why you get the error: the parser expects either a method declaration or the end of the class, hence a curly bracket.
It looks like this loop is actually drawing the CA state, so you can try to wrap it in a void draw(){} method. Then it should be syntactically correct, not sure though whether it works as expected. Alternatively move the for-loop outside of the class and call fill based on the the cells state of an instance of the CA class.
In any case, will need some additional code that creates the CA instance and invokes the generate function.

checking if my array elements meet requirements

I need to create a method which checks each element in my array to see if it is true or false, each element holds several values such as mass, formula, area etc for one compound, and in total there are 30 compounds (so the array has 30 elements). I need an algorithm to ask if mass < 50 and area > 5 = true .
My properties class looks like:
public void addProperty (Properties pro )
{
if (listSize >=listlength)
{
listlength = 2 * listlength;
TheProperties [] newList = new TheProperties [listlength];
System.arraycopy (proList, 0, newList, 0, proList.length);
proList = newList;
}
//add new property object in the next position
proList[listSize] = pro;
listSize++;
}
public int getSize()
{
return listSize;
}
//returns properties at a paticular position in list numbered from 0
public TheProperties getProperties (int pos)
{
return proList[pos];
}
}
and after using my getters/setters from TheProperties I put all the information in the array using the following;
TheProperties tp = new properties();
string i = tp.getMass();
String y = tp.getArea();
//etc
theList.addProperty(tp);
I then used the following to save an output of the file;
StringBuilder builder = new StringBuilder();
for (int i=0; i<theList.getSize(); i++)
{
if(theList.getProperties(i).getFormatted() != null)
{
builder.append(theList.getProperties(i).getFormatted());
builder.append("\n");
}
}
SaveFile sf = new SaveFile(this, builder.toString());
I just cant work out how to interrogate each compound individually for whether they reach the value or not, reading a file in and having a value for each one which then gets saved has worked, and I can write an if statement for the requirements to check against, but how to actually check the elements for each compound match the requirements? I am trying to word this best I can, I am still working on my fairly poor java skills.
Not entirely sure what you are after, I found your description quite hard to understand, but if you want to see if the mass is less than 50 and the area is greater than 5, a simple if statement, like so, will do.
if (tp.getMass() < 50 && tp.getArea() > 5) {}
Although, you will again, have to instantiate tp and ensure it has been given its attributes through some sort of constructor.
Lots of ways to do this, which makes it hard to answer.
You could check at creation time, and just not even add the invalid ones to the list. That would mean you only have to loop once.
If you just want to save the output to the file, and not do anything else, I suggest you combine the reading and writing into one function.
Open up the read and the write file
while(read from file){
check value is ok
write to file
}
close both files
The advantage of doing it this way are:
You only loop through once, not three times, so it is faster
You never have to store the whole list in memory, so you can handle really large files, with thousands of elements.
In case the requirements changes, you can write method that uses Predicate<T>, which is a FunctionalInterface designed for such cases (functionalInterfaces was introduced in Java 8):
// check each element of the list by custom condition (predicate)
public static void checkProperties(TheList list, Predicate<TheProperties> criteria) {
for (int i=0; i < list.getSize(); i++) {
TheProperties tp = list.get(i);
if (!criteria.apply(tp)) {
throw new IllegalArgumentException(
"TheProperty at index " + i + " does not meet the specified criteria");
}
}
}
If you want to check if mass < 50 and area > 5, you would write:
checkProperties(theList, new Predicate<TheProperties> () {
#Override
public boolean apply(TheProperties tp) {
return tp.getMass() < 50 && tp.getArea() > 5;
}
}
This can be shortened by using lambda expression:
checkProperties(theList, (TheProperties tp) -> {
return tp.getMass() < 50 && tp.getArea() > 5;
});

Getting an"index:0" and "size:0" error from ArrayList.size()

I have been working on this program for hours, and have worked out nearly all of the errors that have cropped up in every other class. This one, however, I can's seem to fix the receive method. The receive method should first check (by comparing SKUs) whether or not the incoming product is already in myCatalog. If not, add the product (via its SKU) to the catalog. After that, in any case -- as long as there is still some of the incoming product not yet been placed in a bin -- I want to locate which bin contains the least total quantity. (If all the bins are full, add a new, empty bin to use)I'd add that specific product to that bin until the bin is either full -- at which point I'd repeat -- or I run out of the product. This repeats until no more incoming product is left.
public class Warehouse
{
private int myBinMax;
private ArrayList<MusicMedia> myCatalog;
private ArrayList<Bin> myBins;
public Warehouse( int binMax )
{
myBinMax = binMax;
myCatalog = new ArrayList<MusicMedia>();
myBins = new ArrayList<Bin>( 5 );
}
public String toString()
{
return Tester.detailedInventory(myCatalog,myBins);
}
public void addBin()
{
myBins.add( new Bin( "B" + myBins.size() ) );
}
public void receive( MusicMedia product, int quantity )
{
boolean contained = false;
int lowestAmount = myBinMax,
leastFullBinIndex,
i,
insertQuantity;
for(MusicMedia entry : myCatalog)
{
if(entry.getSKU().equals(product.getSKU()))
{
contained = true;
}
}
if(!contained)
{
myCatalog.add(product);
}
while(quantity > 0)
{
lowestAmount = myBinMax;
for(i = 0; i < myBins.size(); i++)
{
if(myBins.get(i).totalQuantity() < lowestAmount)
{
lowestAmount = myBins.get(i).totalQuantity();
leastFullBinIndex = i;
}
if((i == myBins.size() - 1 && lowestAmount == myBinMax)||(myBins.size() == 0))
{
myBins.add(new Bin("bin" + Integer.toString(i)));
}
}
if(quantity >= myBinMax - lowestAmount)
{
insertQuantity = myBinMax - lowestAmount;
}
else
{
insertQuantity = quantity;
}
quantity -= insertQuantity;
myBins.get(i).add(new BinItem(product.getSKU(), insertQuantity));
}
}
}
Before my last edit, nothing would print -- just a blank console -- but in an attempt to fix that, I added this (also contained within the code above):
if((i == myBins.size() - 1 && lowestAmount == myBinMax)||(myBins.size() == 0))
{
myBins.add(new Bin("bin" + Integer.toString(i)));
}
Now, it won't run without giving me an error:
java.lang.IndexOutOfBoundsException
Index: 0, Size 0 (in java.util.ArrayList)
As well as highlighting the following line:
myBins.get(i).add(new BinItem(product.getSKU(), insertQuantity));
Here's a breakdown on the various classes that have been created for this colossal program:
MusicMedia has three private variables, but the only one that has any bearing here is the String mySKU, obtained by getSKU()
Bin has a private String, name, which is also its only argument, as well as a private ArrayList of class BinItem. In order to access this ArrayList of BinItems from another class, you would use getContents(). It also has method totalQuantity(), which returns the total quantity of objects already in a bin.
BinItem has private variables mySKU (String) and myQuantity (int) and methods getSKU() and getQuantity(), both being its arguments in that order
So to start with you have no bins.
Your "for" block is skipped because size is zero;
So we get to the final line of the "while" loop, and we execute myBins.get(i)...
This is where we get the error because we can't get the bin at index 0, because we got no bins at all.
The problem is we reached this line of code without adding any bins...
I'm not sure if you realized, the line below doesn't start your program with 5 bins.
myBins = new ArrayList<Bin>( 5 );
The 5 in this code sets the internal buffer for the array to hold 5 items. If we supplied no number it would start with 10. But the numbers are just there to give programmers control over how much memmory is initalized.
If your goal was to start with 5 bins, you should do something as follows:
myBins = new ArrayList<Bin>( 5 );
for(int i=0; i<5; i++){
myBins.add(new myBin());
}

Checking Left/Right in an int array for Tetris, Android/Java

I'm trying to make a tetris game for android to help learn game programming for android. My goLeft/Rights break right when the button is pressed, the code for going left is in a class separate of the fields int array, and the list parts array. The fields array is accessed by a referenced variable (TetrisWorld tetrisworld;). While part list array is public so accessed through a variable(part) code for which is in the goLeft() code. It breaks at: if(tetrisworld.fields[x][part.y] != 0) Code for left:
public void goLeft() {
int x = 0;
for(int i = 0; i < 4; i++) {
TetrisParts part = parts.get(i);
x = part.x - 1;
if(tetrisworld.fields[x][part.y] != 0) {
noleft = true;
break;
}
}
if(noleft == false) {
for(int i = 0; i < 4; i++) {
TetrisParts part = parts.get(i);
part.x--;
}
}
}
The code for the fields int array:
int fields[][] = new int[WORLD_WIDTH][WORLD_HEIGHT];
WORLD_WIDTH and WORLD_HEIGHT are both static final ints, width being 9 and height being 19
I've tried putting if(tetrisworld.fields[0][0] == 0) and it still crashes so I don't think it has to do with the variables. Also It doesn't go out of bound even if I haven't added the code to check for that yet because I have the teroid spawning around x = 5 and since I can't go left/right once there's not a chance of that happening
I've tried moving the goLeft/Right methods to the gamescreen class which has a "world = TetrisWorld();" and it still bugs out at the same spot
UPDATE:
Ok just adding:
tetrisworld != null
to the first if statement fixed it, my question now is, why did it fix it? Why can't I move without this check? It clearly isn't null cause as far as I know; it's fully responsive now.
But an easier way to have solved this which is SOOOO easy is changing fields to static... then access it lika so: TetrisWorld.fields so my updated code is:
public void goLeft()
{
noleft = false;
for (int i = 0; i < 4; i++)
{
part = parts.get(i);
if (part.x - 1 < 0 || TetrisWorld.fields[part.x - 1][part.y] != 0)
{
noleft = true;
break;
}
}
if (noleft == false)
{
for (int i = 0; i < 4; i++)
{
part = parts.get(i);
part.x--;
}
}
}
Looks like you are hitting IndexOutOfBoundsException.
When you are doing x = part.x - 1;, your x variable can become lesser tan zero, thus your code will act like if(tetrisworld.fields[-1][part.y] != 0
It looks like you're getting a java.lang.NullPointerException when trying to access the array in tetrisworld. In the line you mention there are several ways that this could occur:
if(tetrisworld.fields[x][part.y] != 0) {
tetrisworld could be null.
The fields member of tetrisworld could be null.
The second array that you're looking up by using tetrisworld.fields[x].
The value of part could be null.
Having a quick look through your source code it looks to me like you never initialise tetrisworld, either at declaration using:
TetrisWorld tetrisworld = new TetrisWorld();
Or at some other point which is certain to have happened before your goLeft() method is called.
Ok I believe I found the answer, referencing: http://en.wikipedia.org/wiki/Null_Object_pattern
Apparently java will throw an NPE if you don't check for it first if you have a null reference? Is there any way to initialize it without doing a TetrisWorld tetrisworld = new TetrisWorld(); because it's already created in a different class so i get a thousand errors, an actual stack overflow! lul... Still not 100% positive. Please comment to verify and possibly suggest a better way to go about this.

java mouseadapter source not found

I have an array of JPanels and I'm trying to add a mouseadapter to each one so it will be possible to identify which one was clicked and then change its background colour. Everything seems to work fine except when I run it from eclipse when a page will appear that says EventDispatchThread.run() line: not available, Source not found, and in the debug window it says:
Thread [AWT-Shutdown] (Running)
Daemon Thread [AWT-Windows] (Running)
Thread [AWT-EventQueue-0] (Suspended (exception ArrayIndexOutOfBoundsException))
EventDispatchThread.run() line: not available
Thread [DestroyJavaVM] (Running)
Thread [AWT-EventQueue-0] (Running)
This is the code:
private void drawBoard() {
LayoutManager layout = new GridLayout(NUMBER_OF_ROWS, NUMBER_OF_COLS);
boardPanel.setLayout(layout);
boardPanel.setPreferredSize(new Dimension(200, 400));
chessBoard = new JPanel[NUMBER_OF_ROWS][NUMBER_OF_COLS];
MoveArrays move = new MoveArrays();
move.initialisePieceMoves();
for (int i = 0; i < NUMBER_OF_ROWS; i++) {
for (int j = 0; j < NUMBER_OF_COLS; j++) {
int index = i * 4 + j;
chessBoard[i][j] = new JPanel();
chessBoard[i][j].addMouseListener(clickSquare(j, i, index, move));
chessBoard[i][j].setBackground(getColor(i,j));
if (!(boardArray.chessBoard[index].square.isEmpty())) {
Piece piece = (Piece) boardArray.chessBoard[index].square.firstElement();
JLabel pieceString = new JLabel(piece.toString());
chessBoard[i][j].add(pieceString);
}
boardPanel.add(chessBoard[i][j]);
}
}
} // drawBoard()
private MouseAdapter clickSquare(final int xCo, final int yCo, final int index, final MoveArrays move) {
return new MouseAdapter() {
public void mousePressed(MouseEvent me) {
resetColors();
JPanel selectedSquare = (JPanel) me.getSource();
selectedSquare.setBackground(selectedColor());
System.out.println("xCo: " + xCo + " yCo: " + yCo);
Vector validMoves = move.DroneMovesNorth[index].Moves;
int totalMoves = move.DroneTotalMovesNorth[index];
if (!validMoves.isEmpty()) {
for (int n = 0; n <= totalMoves; n++) {
String stringMove = validMoves.elementAt(n).toString();
int intMove = Integer.parseInt(stringMove);
System.out.println("intMove: " + intMove);
}
}
}
};
}
I think it might be the fact that I cast the me.getSource to a JPanel but shouldn't it be one anyway? If I don't put the cast it says that it cannot bind an 'Object' to a JPanel, when I do System.out.print(me.getSource()) it prints a line saying that it's a JPanel so I don't get what the problem is. Any help would be much appreciated!
It appears the problem is not to do with the source of the mouse event. Indeed I think there's two different things being called "source" here, and you're mixing them together. I think the message:
EventDispatchThread.run() line: not available, Source not found
Is Eclipse telling you that the library does not have the source code attached to it, so it cannot find line numbers or show you the source code. The problem does not appear to be with me.getSource().
The problem is that you are trying to reference an index within an array that is outwith the bounds of the array (hence the ArrayIndexOutOfBoundsException in the stack trace).
Since the stack trace is on the AWT Event Queue thread, it is likely the exception is stemming from within the mousePressed() method of your MouseAdapter. Since you're already using Eclipse, I suggest you get to know the Debugger, which is extremely useful. Put a breakpoint at these lines:
Vector validMoves = move.DroneMovesNorth[index].Moves;
int totalMoves = move.DroneTotalMovesNorth[index];
And check that both the array fields of move are large enough to reference an element at the index. If you don't want to use the debugger (I'd really recommend that way), then you could wrap those two lines with an exception catch, like this:
try {
Vector validMoves = move.DroneMovesNorth[index].Moves;
int totalMoves = move.DroneTotalMovesNorth[index];
catch(ArrayIndexOutOfBoundsException e) {
System.out.println("Exception thrown: index = " + index +
"Array lengths: " + move.DroneMovesNorth.length + ", " +
move.DroneTotalMovesNorth.length);
}
When/if the exception is caught, you want to find out why the index is larger than the size of each of these arrays. That's left as an exercise ;-)
Edit: there's some other code in there which looks suspicious.
First you declare the array for the chessboard:
chessBoard = new JPanel[NUMBER_OF_ROWS][NUMBER_OF_COLS];
Then you begin to iterate for every square in the board:
for (int i = 0; i < NUMBER_OF_ROWS; i++) {
for (int j = 0; j < NUMBER_OF_COLS; j++) {
Note that i will run up to the value NUMBER_OF_ROWS, which is the length of the chessboard array. Then for some reason I don't understand, you change the value of index to something that could be 4x as large as the length of the array:
int index = i * 4 + j;
And later try to reference that position in the chessboard array:
if (!(boardArray.chessBoard[index].square.isEmpty())) {
This means it's possible for index to be a value higher than NUMBER_OF_ROWS, and if you try to access the element at that index of the array, it will throw the ArrayIndexOutOfBoundsException.
So, my second suggestion would be to take another look at the logic involved in:
int index = i * 4 + j;
... as that may also be the problem.
P.S. the debugger in Eclipse is awesome, you should use it ;-)

Categories