This site requires JavaScript, please enable it in your browser!
Greenfoot back
mrunknown
mrunknown wrote ...

2014/6/5

Use var from method in act() in world class

1
2
3
danpost danpost

2014/6/7

#
I was not aware you wanted the program to allow inputting of those values to create the world size with. However you accomplish this, it will not be simple. I would create a separate world class to receive the input and create a new Plane object using the given values. Or more simple and maybe better, might be to allow changing of the values by use of the arrow keys. In your world class act method you could check for arrow keystrokes and just create and activate a new plane object upon detection (if the change in values is within a reasonable range). * if 'up' is detected, increase AReihen (if not already at maximum value) * if 'down' is detected, decrease AReihen (if not already at minimum value) * if 'left' is detected, decrease S (if not already at minimum value) * if 'right' is detected, increase S (if not already at maximum value) The code would look something like this:
String key = Greenfoot.getKey();
if (key != null)
{
    int dS = 0, dAR = 0;
    if ("up".equals(key) && AReihen<20) dAR++;
    if ("down".equals(key) && AReihen>5) dAR--;
    if ("right".equals(key) && S<5) dS++;
    if ("left".equals(key) && S>1)  dS--;
    if (dS != 0 || dAR != 0)
    {
        S += dS;
        AReihen += dAR;
        Greenfoot.setWorld(new Plane(S, AReihen));
    }
}
mrunknown mrunknown

2014/6/7

#
Ok, i think i'll stay with the static world size for now and add the size-changing functions later. More important, is there any way of delaying the creation of the passengers? By now all passengers are being created at the same time on the same field and are therefore stacked while walking down the aisle. That does not look very realistic. How can i make the second passenger wait for the first passenger to go a step further (Y+1) and so on? Using getNeighbours() or similar won't work i suspect, as all the passengers are on the same field in the beginning. So there has to be a delay in the creating of the passengers, i think. Basically, i want that every field can only be occupied by one passenger at the same time. Except for the seats, as the passengers may need to pass another passenger sitting in the aisle or middle seat or both to get to their seat.
danpost danpost

2014/6/7

#
I would not create a new passenger unless the following was true:
if (getObjectsAt(S, 0, Passenger.class).isEmpty() && getObjectsAt(S, 1, Passenger.class).isEmpty())
This will ensure that the first two aisle locations are empty. You should also only create a passenger if the following is true:
if (getObjects(Passenger.class).size() < S*2*AReihen)
which could also be determined by this:
if (getObjects(Passenger.class).size() < getObjects(Seat.class).size())
You should only create a passenger only when it is time for a new passenger to begin its trek to its seat (not before). In other words, your passengers should each be created in the act method when all conditions are met; not in the constructor all at once.
mrunknown mrunknown

2014/6/8

#
I have gone for the super-secure method you suggested above so my act method looks like this now:
public void act()
    {
        if(getObjectsAt(S, 0, Passenger.class).isEmpty() && getObjectsAt(S, 1, Passenger.class).isEmpty())
        { // check if first two aisle position are empty
            if(getObjects(Passenger.class).size() < S*2*AReihen) // check if Passengers < Seats
            {
                if(getObjects(Passenger.class).size() < getObjects(Seat.class).size()) // s.o. ...safety first!
                {
                    // create passenger
                    setPassenger(z);
                    z++;
                }
            }
            else
            {
                checkBoarding();
                if(boardingComplete == true)
                {
                    Greenfoot.stop();
                    System.out.println("________Greenfoot stopped_________");
                    System.out.println("");
                    System.out.println("* "+stepCount+" Steps");
                    System.out.println("__________________________________");
                }   
            }
        }
        stepCount++;
}
As you can see i want to count the steps of the simulation until the boarding is completed. Is the method i used (count up an integer in act) the right one or leads this to wrong results?
danpost danpost

2014/6/8

#
In the act method, you do not need to use both conditions of line 5 and line 7; they both do essentially the same thing. You do not need to count the passengers. If you are trying to give then some type of identification, their seat 'id' is sufficient. All you need to do is assign a seat to a new Passenger and add the passenger into the world, which I presume is done in the 'setPassenger' method (I would like to view that method, if you do not mind). The 'stepCount' field, as you have it, will count the act cycles that have been executed and the terminal should print out the proper value.
mrunknown mrunknown

2014/6/8

#
I know its unnessesary to use both conditions but i just thought it might be a goof safety feature. The passenger count is just in case that i need to use the Id of each passenger later, by now i'm using it to check if passenger specific methods are working (e.g. stopping if someone blocks the aisle or the aisle seat). setPassenger looks like this:
public void setPassenger(int num) // int num = generated ID from act()
    {
        List<Seat> seats = new ArrayList<Seat>(getObjects(Seat.class)); // get all seats
        List<Seat> available = new ArrayList<Seat>(seats); // copy list
        for(Seat seat : seats)
        {
            if(seat.isOccupied())
            {
                available.remove(seat); // remove occupied seats
            }
        }
        Seat seat = available.get(Greenfoot.getRandomNumber(available.size())); // choose random available seat
        boolean l = randomBoolean();  // 50/50 chance if luggage or not
        Passenger passenger = new Passenger(seat, num, l);
        seat.setOccupant(passenger);
        addObject(passenger, S, 0);
    }
At the moment i'm experimenting with different boarding strategies, e.g. back-to-front or outside-in. Therefore, i need to implement a feature in 'setPassenger' that puts the seats e.g. from row 20 to 15 in a list and the seats from row 15 to 10 and so on. Same with the outside-in boarding where i first need to put all window-seats in a list, then middle seats and so on... I think i go for something like this
public void outsidein(int num)
    {
        List<Seat> seats = new ArrayList<Seat>(getObjects(Seat.class)); // get all seats
        List<Seat> available = new ArrayList<Seat>(seats); // copy list
        for(Seat seat : seats)
        {
            if(seat.isOccupied())
            {
                available.remove(seat); // remove occupied seats
            }
        }
        List<Seat> priority1 = new ArrayList<Seat>(available); // copy list
        for(Seat seat : available)
        {
            if(seat.getX() != 0 || seat.getX() != 6)
            {
                priority1.remove(seat);
            }
        }
        Seat seat = priority1.get(Greenfoot.getRandomNumber(priority.size())); // choose random seat
        boolean l = randomBoolean(); // 50/50 chance if luggage or not
        Passenger passenger = new Passenger(seat, num, l);
        seat.setOccupant(passenger);
        addObject(passenger, S, 0);
    }
// check if list 'priority 1' is empty
// create list 'priority 2' and so on...
But i get the 'java.lang.IllegalArgumentException: n must be positive' error for line 20. And there needs to be added an 'if(priority1 == is empty) then create priority2' or similiar... maybe it can be simplified but i don't really know how to do that. The same principle can be used then for the back-to-front boarding.
danpost danpost

2014/6/8

#
There is also this: outside-in where you allow any seat to be occupied provided it is a window seat OR the outer seat is already occupied :?- This would allow some non-window seats to be occupied before all window seats are occupied.
mrunknown mrunknown

2014/6/9

#
That would be simpler in terms of programming, i think. But i have to do this very realistic so the window seats on both sides have to be occupied before the passengers for the middle seats are created. I have solved this now and it works fine. At the moment i'm working on a way to store the 'stepCount' variable in a text file and then restart the whole simulation. It works fine except that it always overwrites the complete text file. I can't work out how it can just add another line to it instead of overwriting the file. In addition, it would be nice to have an option to set that the simulation runs e.g. 50 times and then stops automatically. I think that can be realized by counting the number of lines in the textfile that have been written so far. But then again, i don't know how Greenfoot can read the existing file (and count the lines) and then add another line to it.
BufferedWriter file = null;
                    try 
                    {
                        file = new BufferedWriter(new FileWriter("results.txt"));
                        file.write("Steps_"+stepCount);
                        file.close();
                    }
                    catch (IOException ioe) 
                    {
                        ioe.printStackTrace();
                    }
                    finally 
                    {
                        try {
                            file.close();
                        }
                        catch (IOException ioe) {
                            ioe.printStackTrace();
                        }
                    }
                    Greenfoot.setWorld(new Plane());
danpost danpost

2014/6/9

#
Actually, it would not be simpler in terms of programming. I did manage to use a switch statement, that depending on the method used, would do the following for each case:
for (Seat seat : seats) if (/* conditions */) available.remove(seat);
break;
I used five different loading methods, named by what seats are taken first: ANY (any order), BACK (back to front), FRONT (front to back), WINDOW (window to aisle), and OUTER (outer to inner). The last one is where a seat can be occupied provided it is a window seat OR the seat next to it (toward the window) is already assigned. I created a separate world as a title/set-up world where the RUN and ROWS (your S and AReihen) and the method can be set. It uses up and down arrow actors to click on to change the current number settings and a drop-down for the method setting. Either clicking the start button or pressing enter will start the Plane world and clicking or pressing escape will return to the title/set-up screen.
danpost danpost

2014/6/9

#
Did you try 'file.append' instead of 'file.write'? ('append' is inherited from the Writer class which BufferedWriter extends)
mrunknown mrunknown

2014/6/9

#
'file.append' also just overwrites the file... i have tried it with a file reader demo from the scenario-page that looks like this:
InputStream is = getClass().getClassLoader().getResourceAsStream("results.txt");
        BufferedReader r = new BufferedReader(new InputStreamReader(is));
        
        String[] lines = new String[5];
        
        for (int i = 0; i < 5; i++) {
            lines[i] = r.readLine();
        }
        
        return lines;
But that doesn't work either, writes an awkward "@Array86138" in the file.
mrunknown mrunknown

2014/6/9

#
I got that working now, but i really struggle to put the content of the file in the 'file.write()' or 'file.append()' method. When I'm changing the code a bit Greenfoot always tells me that i need to use 'try ... catch'. In addition, I don't know how i can count the lines in the text file. Do you know how to do that properly?
BufferedWriter file = null;
                    try 
                    {
                        try
                        {
                            String [] lines = readText();
                            for (int i = 0; i < 5; i++) {
                                System.out.println(lines[i]);
                            }
                        }
                        catch (IOException ioe) 
                        {
                            ioe.printStackTrace();
                        }
                        file = new BufferedWriter(new FileWriter("results.txt"));
                        file.append("Steps_"+stepCount);
                        file.close();
                    }
                    catch (IOException ioe) 
                    {
                        ioe.printStackTrace();
                    }
                    finally 
                    {
                        try {
                            file.close();
                        }
                        catch (IOException ioe) {
                            ioe.printStackTrace();
                        }
                    }
danpost danpost

2014/6/10

#
Will you be publishing your scenario on the site? or are you doing this for you own application? or is this a school project? FYI, you will not be able to write to files on the site to save the best times.
mrunknown mrunknown

2014/6/10

#
At the moment it's just for school but i think I'll publish it on this site, too. I'm trying to store the results from the simulation in an Array in another World, so it basically looks like this WORLD -Main --Plane
public class Main extends World
{
    private int runs = 100;
    private int[] results;
    
    public Main()
    {
        super(1, 1, 1);
        Greenfoot.setWorld(new Plane(3, 30, 0.8));
    }
and the Plane class
public class Plane extends Main
{ 
    public Plane(int seats, int rows, double lugg)
    {    
        super(2*seats + 1, rows, 24);
        S = seats;
        AReihen = rows;
        luggage = lugg;
        setBackground("tile.png");
        createSeats();
        ID = 0;
        //Greenfoot.start();
    }
But every time when compiling it marks "super(2*seats + 1, rows, 24);" and says "constructor Main in class Main cannot be applied to given types; required: no arguments; found: int,int,int; reason: actual and formal argument lists differ in length" Any suggestions why this error occurs?
danpost danpost

2014/6/10

#
You have Plane extending Main. It needs to extend World.
There are more replies on the next page.
1
2
3