Created
January 5, 2012 01:31
-
-
Save ciembor/1563224 to your computer and use it in GitHub Desktop.
PRIR 06
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * autor: Maciej Ciemborowicz | |
| * PRIR 2011/2012 | |
| * Uniwersytet Jagielloński | |
| * | |
| */ | |
| import java.util.Random; | |
| import java.util.concurrent.CyclicBarrier; | |
| class Autobusy implements AutobusyI { | |
| CyclicBarrier barrier; | |
| private final static Object lock = new Object(); | |
| /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| // ________________ | |
| // /.--------------.\ | |
| // // \\ | |
| // // \\ | |
| // || .-..----. .-. .--. || | |
| // ||( ( '-..-'|.-.||.-.||| | |
| // || \ \ || || ||||_|||| | |
| // ||._) ) || \'-'/||-' || | |
| // \\'-' `' `-' `' // | |
| // \\ // | |
| // \\______________// | |
| // '--------------' | |
| // |_|_ | |
| // ____ _/ _)_) | |
| // ' | (_) | |
| // .--'"\| () | |
| // | | | |
| // | | | |
| // |_| | |
| // | |
| private class Stop implements Runnable { | |
| private int passengers; | |
| private double probability; | |
| private Random generator; | |
| private int counter = 0; | |
| public Stop(int passengers, double probability) { | |
| // System.out.println("konstruuję przystanek"); | |
| this.passengers = passengers; | |
| this.probability = probability; | |
| this.generator = new Random(); | |
| } | |
| @Override public void run() { | |
| // System.out.println("startuję przystanek"); | |
| while (true) { | |
| try { | |
| // System.out.println("stop barrier: " + barrier.getNumberWaiting()); | |
| barrier.await(); | |
| } | |
| catch (Exception e) { | |
| return; | |
| } | |
| // System.out.print(counter); | |
| counter++; | |
| this.generatePassenger(); | |
| } | |
| } | |
| public int getPassengers() { | |
| return passengers; | |
| } | |
| private void generatePassenger() { | |
| if (generator.nextDouble() <= probability) { | |
| passengers += 1; | |
| } | |
| } | |
| public boolean letOut() { | |
| if (passengers > 0) { | |
| passengers -= 1; | |
| return true; | |
| } | |
| else { | |
| return false; | |
| } | |
| } | |
| } | |
| /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| // | |
| // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| // _ , | |
| // __ __ __ __ __ -- -,_/\\_~0_\ ___ __ __ __ | |
| // -- / ___ \- `___`"-, | |
| // --- `"-( @ )----( @ )---` | |
| // '-' '-' | |
| // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| // | |
| private class Road { | |
| private Stop[] positions; | |
| public Road(int length, | |
| int stops_number, | |
| int first_stop_position, | |
| int stop_passengers_number, | |
| double passenger_probability) { | |
| positions = new Stop[length]; | |
| this.addStops(first_stop_position, | |
| stops_number, | |
| stop_passengers_number, | |
| passenger_probability); | |
| } | |
| public void startStops() { | |
| for (int i=0; i<positions.length; ++i) { | |
| if (positions[i] != null) { | |
| (new Thread(positions[i])).start(); | |
| } | |
| } | |
| } | |
| private int validPosition(int position) { | |
| return Math.abs(position % positions.length); | |
| } | |
| private void addStops(int first_position, | |
| int number, | |
| int passengers, | |
| double probability) { | |
| for (int i=0; i<number; ++i) { | |
| positions[this.validPosition(first_position + (positions.length / number) * i)] = | |
| new Stop(passengers, probability); | |
| } | |
| }; | |
| public int nextPosition(int position) { | |
| return validPosition(position + 1); | |
| } | |
| public boolean isStop(int position) { | |
| if (positions[position] != null) { | |
| return true; | |
| } | |
| else { | |
| return false; | |
| } | |
| } | |
| public Stop getStop(int position) { | |
| return positions[position]; | |
| } | |
| public int getLength() { | |
| return positions.length; | |
| } | |
| } | |
| /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| // _______________________________ | |
| // / .-----..--..--..--..--..--..--\ | |
| // |)[_____][__][__][__][__][__][___\__ | |
| // | _ | -|- _ `\ | |
| // _( /.\ | | /.\ [) | |
| // `'---\_/---------------------------\_/--' | |
| // | |
| private class Bus implements Runnable { | |
| private int id, position, capacity, passengers; | |
| private Road road; | |
| private Bus previous; | |
| private Bus next; | |
| private boolean was_empty; | |
| private int counter = 0; | |
| public Bus(int id, Road road, int position, int capacity) { | |
| // System.out.println("konstruuję bus"); | |
| this.road = road; | |
| this.position = road.validPosition(position); | |
| this.capacity = capacity; | |
| this.passengers = 0; | |
| this.id = id; | |
| this.was_empty = true; | |
| } | |
| @Override public synchronized void run() { | |
| // System.out.println("startuję bus " + this.id); | |
| while (true) { | |
| try { | |
| // System.out.println("bus" + this.id + " " + "barrier: " + barrier.getNumberWaiting()); | |
| barrier.await(); | |
| } | |
| catch (Exception e) { | |
| return; | |
| } | |
| // System.out.print(counter); | |
| counter++; | |
| if (road.isStop(position)) { | |
| Stop stop = road.getStop(position); | |
| if (!this.was_empty) { | |
| if (this.passengers > 0) { | |
| this.letOut(); | |
| } | |
| if (this.passengers == 0) { | |
| this.was_empty = true; | |
| } | |
| } | |
| else if (this.capacity > this.passengers) { | |
| if (stop.letOut()) { | |
| this.letIn(); | |
| } | |
| else { | |
| this.was_empty = false; | |
| this.move(); | |
| } | |
| } | |
| else { | |
| this.was_empty = false; | |
| this.move(); | |
| } | |
| } | |
| else { | |
| this.move(); | |
| } | |
| } | |
| } | |
| private void move() { | |
| // System.out.println("move: " + this.position + " currentpos / nextpos " + road.nextPosition(position)); | |
| if (next.getPosition() != road.nextPosition(this.position)) { | |
| position = road.nextPosition(position); | |
| } | |
| } | |
| private boolean letIn() { | |
| if (passengers < capacity) { | |
| passengers += 1; | |
| return true; | |
| } | |
| else { | |
| return false; | |
| } | |
| } | |
| private void letOut() { | |
| passengers -= 1; | |
| } | |
| public void setPrevious(Bus bus) { | |
| this.previous = bus; | |
| } | |
| public void pushNext(Bus bus) { | |
| this.next = bus; | |
| bus.setPrevious(this); | |
| } | |
| public int getPosition() { | |
| return position; | |
| } | |
| public Bus getPrevious() { | |
| return previous; | |
| } | |
| public Bus getNext() { | |
| return next; | |
| } | |
| public int getPassengers() { | |
| return passengers; | |
| } | |
| public int minDistance() { | |
| int previousDistance, nextDistance; | |
| if (this.position > previous.getPosition()) { | |
| previousDistance = this.position - previous.getPosition(); | |
| } | |
| else | |
| { | |
| previousDistance = this.position + (road.getLength() - previous.getPosition()); | |
| } | |
| if (this.position < next.getPosition()) { | |
| nextDistance = next.getPosition() - this.position; | |
| } | |
| else | |
| { | |
| nextDistance = next.getPosition() + (road.getLength() - this.position); | |
| } | |
| return Math.min(previousDistance, nextDistance); | |
| } | |
| public int getId() { | |
| return this.id; | |
| } | |
| } | |
| /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| // ___ __ ___ ____ | |
| // / _ \ /_ | |__ \ |___ \ | |
| // | | | | | | ) | __) | | |
| // | | | | | | / / |__ < | |
| // | |_| | __ | | __ / /_ __ ___) | __ __ __ | |
| // \___/ (__) |_| (__) |____| (__) |____/ (__|__|__) | |
| // | |
| public class Counter implements Runnable { | |
| int value; | |
| boolean request, done; | |
| public Counter() { | |
| // System.out.println("konstruuję counter"); | |
| this.value = 0; | |
| this.done = false; | |
| this.request = false; | |
| } | |
| @Override public void run() { | |
| // System.out.println("startuję counter"); | |
| while (true) { | |
| synchronized(lock) { | |
| if (this.value > 0 && done == false) { | |
| // System.out.println("%%%%%%" + this.value + " val / done " + done); | |
| try { | |
| // System.out.println("cter barrier: " + barrier.getNumberWaiting()); | |
| barrier.await(); | |
| } | |
| catch (Exception e) { | |
| return; | |
| } | |
| this.value -= 1; | |
| // System.out.println("value" + value); | |
| } | |
| else if (this.value == 0 && this.request && done == false) { | |
| // System.out.println("#######" + this.value + " val / done " + done); | |
| this.request = false; | |
| // System.out.println("done!"); | |
| this.done = true; | |
| try { | |
| lock.wait(); | |
| } | |
| catch (Exception e) { | |
| return; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| public boolean done() { | |
| System.out.print(""); | |
| return this.done; | |
| } | |
| public void count(int value) { | |
| synchronized(lock) { | |
| this.done = false; | |
| this.request = true; | |
| this.value = value; | |
| lock.notifyAll(); | |
| // System.out.println(this.value); | |
| } | |
| } | |
| } | |
| /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| // | |
| // () | |
| // JL | |
| // || | |
| // LJ | |
| // _,--"""""""---. | |
| // ,' `. | |
| // / \ | |
| // J L | |
| // F L | |
| // J J | |
| // | J | |
| // ___L______________ J | |
| // /,---------------. "". J | |
| // JJ / \/ | J J | |
| // LL J J | L J | |
| // JJ J # J # | L | | |
| // \\__`.___,_`.____,' F | | |
| // ""-.---------....___/ | | |
| // |_T--+---+--.,._ | | |
| // |--|----\---\-`. | | |
| // |__|____J___J_ F F | |
| // _|__|____|___|_/ L | |
| // | L | |
| // |____________________M-K | |
| // | |
| private Counter counter; | |
| private Road road; | |
| private Bus first_bus; | |
| private int L, K; | |
| /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| @Override public void init(int N, int K, int L, int M, double P, int a0, int p0, int pp) { | |
| this.L = L; | |
| this.K = K; | |
| this.barrier = new CyclicBarrier(K+L+1); | |
| // initialization of all Runnable objects | |
| this.counter = new Counter(); | |
| this.road = new Road(N, L, p0, pp, P); | |
| this.first_bus = new Bus(0, road, a0, M); | |
| Bus bus = this.first_bus; | |
| for (int i=1; i<K; ++i) { | |
| bus.pushNext(new Bus(i, road, a0 + (i * (N / K)), M)); | |
| bus = bus.getNext(); | |
| } | |
| bus.pushNext(first_bus); | |
| // start of all Runnable objects | |
| (new Thread(this.counter)).start(); | |
| this.road.startStops(); | |
| bus = this.first_bus; | |
| for (int i=0; i<K; ++i) { | |
| (new Thread(bus)).start(); | |
| bus = bus.getNext(); | |
| } | |
| } | |
| /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| // uwaga! show wyświetla aktualny stan obiektów, nie czeka na zakończenie tury | |
| // takiego wymogu nie było w specyfikacji | |
| // count czeka na zakończenie tury, dlatego zaleca się uruchomić show po count | |
| @Override public void show() { | |
| int position = 0; | |
| do { | |
| System.out.print(position); | |
| if (road.isStop(position)) { | |
| Stop stop = road.getStop(position); | |
| System.out.print(" P[" + stop.getPassengers() + "]"); | |
| } | |
| Bus bus = this.first_bus; | |
| do { | |
| if (bus.getPosition() == position) { | |
| System.out.print(" A[" + bus.getId() + "," + bus.getPassengers() + "]"); | |
| } | |
| bus = bus.getNext(); | |
| } while (bus != this.first_bus); | |
| System.out.println(""); | |
| position += 1; | |
| } while (this.road.validPosition(position) != 0); | |
| } | |
| /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| // mam nadzieję, że o to chodziło (w specyfikacji jest to niejasne) | |
| @Override public double calc(int T) { | |
| this.counter.count(T); | |
| int number = 0; | |
| double sum = 0; | |
| Bus bus = this.first_bus; | |
| while (true) { | |
| if (this.counter.done()) { | |
| do { | |
| number += 1; | |
| sum += bus.minDistance(); | |
| bus = bus.getNext(); | |
| } while (bus.getId() != 0); | |
| break; | |
| } | |
| } | |
| double avg_min_distance = sum/number; | |
| return avg_min_distance; | |
| } | |
| ////////////////////////////////////////////////// | |
| public void test(int T) { | |
| for (int i=0; i<1000; ++i) { | |
| this.counter.count(1); | |
| System.out.println("liczę--------------------------------------------"); | |
| while (true) { | |
| if (this.counter.done()) { | |
| this.show(); | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| //////////////////////////////////////////////// | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment