OOP2

Add the source code from the last Challenge

I postponed this for a while, then forgot about it, then Windows decided to fuck my GNU/Linux partitioning... Better late than never I guess.

Author
Maarten 'Vngngdn' Vangeneugden
Date
Jan. 6, 2017, 10:07 p.m.
Hash
631637c5cbe33241bcb4deaac0ae7defb568906e
Parent
cd8fef3ba559bf2ebfdb75e4d6dcedfbb6805718
Modified files
Challenge 6/Walk.java
Challenge 6/WalkController.java
Challenge 6/WalkReservation.java
Challenge 6/WalkSearchView.java
Challenge 6/WalkView.java
Challenge 6/ontwerpkeuzes2.md → Challenge 6/ontwerpkeuzes.md
Challenge 6/ontwerpkeuzes.txt

Challenge 6/Walk.java

54 additions and 0 deletions.

View changes Hide changes
+
1
import java.util.ArrayList;
+
2
+
3
/**
+
4
 * Represents a guided walk, in which a series of attractions are visited.
+
5
 * Walks behave quite a lot like Rooms; they  TODO
+
6
 * @author Maarten Vangeneugden - 1438256
+
7
 */
+
8
public class Walk {
+
9
+
10
	private String name;
+
11
	private int duration;
+
12
	private List<String> attractions;
+
13
+
14
	public Walk(String name, int duration, List<String> attractions) {
+
15
		this.name = name;
+
16
		this.duration = duration;
+
17
		this.attractions = attractions;
+
18
	}
+
19
+
20
	/**
+
21
	 * Construct a blank Walk for future editing.
+
22
	 */
+
23
	public Walk() {
+
24
		this.name = "";
+
25
		this.duration = 0;
+
26
		this.attractions = new ArrayList<>();
+
27
	}
+
28
+
29
	public void setName(String name) {
+
30
		this.name = name;
+
31
	}
+
32
+
33
	public String getName() {
+
34
		return name;
+
35
	}
+
36
+
37
	public void setDuration(int duration) {
+
38
		this.duration = duration;
+
39
	}
+
40
+
41
	public int getDuration() {
+
42
		return duration;
+
43
	}
+
44
+
45
	public void setAttractions(List<String> attractions) {
+
46
		this.attractions = attractions;
+
47
	}
+
48
+
49
	public List<String> getAttractions() {
+
50
		return attractions;
+
51
	}
+
52
+
53
}
+
54

Challenge 6/WalkController.java

131 additions and 0 deletions.

View changes Hide changes
+
1
import java.util.HashSet;
+
2
+
3
/**
+
4
 * Controller class for everything related to the guided walks.
+
5
 * This class contains the links between other controllers, but also holds the
+
6
 * information related to the walks, such as reservations, possible walks, ...
+
7
 * @author Maarten Vangeneugden - 1438256
+
8
 */
+
9
public class WalkController {
+
10
+
11
	private ReservationController reservationController;
+
12
	private HashSet<Walk> walks;
+
13
	private HashSet<WalkReservation> walkReservations;
+
14
+
15
	public WalkController(ReservationController reservationController) {
+
16
		this.reservationController = reservationController;
+
17
		this.walks = new HashSet<>();
+
18
		this.walkReservations = new HashSet<>();
+
19
	}
+
20
+
21
	public void setReservationController(ReservationController reservationController) {
+
22
		this.reservationController = reservationController;
+
23
	}
+
24
+
25
	public ReservationController getReservationController() {
+
26
		return reservationController;
+
27
	}
+
28
+
29
	/**
+
30
	 * Returns a copy of all Walk Reservations.
+
31
	 * Emphasis on "copy"; There is no setWalkReservations() for a reason, using
+
32
	 * this to edit the pointer variable would omit the use of 'private'.
+
33
	 * @return A verbatim copy of all Walk Reservations.
+
34
	 */
+
35
	@SuppressWarnings("unchecked")
+
36
	public Set<WalkReservation> getWalkReservations() {
+
37
		return (HashSet<WalkReservation>)this.walkReservations.clone();
+
38
	}
+
39
+
40
	/**
+
41
	 * Add a Walk Reservation to the system.
+
42
	 * Calling this method adds the Walk Reservation to the system, allowing it
+
43
	 * to be queried through the search menu, and allowing other parts of the
+
44
	 * program to interact with it.
+
45
	 * @param walkReservation The WalkReservation you wish to add.
+
46
	 * @pre walkReservation mustn't be null.
+
47
	 * @pre walkReservation mustn't already exist in the system.
+
48
	 * @throws IllegalArgumentException if walkReservation is already in the
+
49
	 * system.
+
50
	 * @throws NullPointerException if walkReservation is a null pointer.
+
51
	 * @post walkReservation is added to the set of active Walk Reservations.
+
52
	 */
+
53
	public void addWalkReservation(WalkReservation walkReservation) {
+
54
		if(this.getWalkReservations().contains(walkReservation)) {
+
55
			throw new IllegalArgumentException("walkReservation already exists in the system.");
+
56
		}
+
57
		// Contract validated
+
58
		this.walkReservations.add(walkReservation);
+
59
	}
+
60
+
61
	/**
+
62
	 * Cancels and removes the given WalkReservation.
+
63
	 * If you want to remove a WalkReservation, use this method, and provide the
+
64
	 * WalkReservation up for removal.
+
65
	 * This method will take care of related actions, such as releasing Beds.
+
66
	 * @param walkReservation The WalkReservation to be removed.
+
67
	 * @pre reservation mustn't be null.
+
68
	 * @pre reservation must be contained in the active WalkReservations.
+
69
	 * @post The WalkReservation is removed from the active WalkReservations.
+
70
	 * @throws NullPointerException if reservation is a null pointer.
+
71
	 * @throws IllegalArgumentException if reservation is not contained in the
+
72
	 * active WalkReservations.
+
73
	 */
+
74
	public void cancelWalkReservation(WalkReservation walkReservation) {
+
75
		// Contract validation
+
76
		if(!this.getWalkReservations().contains(walkReservation)) {
+
77
			throw new IllegalArgumentException("The given WalkReservation was not contained in the active WalkReservations.");
+
78
		}
+
79
		if(walkReservation == null) {
+
80
			throw new NullPointerException();
+
81
		}
+
82
		// Contract validated, execute method
+
83
		this.walkReservations.remove(walkReservation);
+
84
	}
+
85
	
+
86
	/**
+
87
	 * Add Walk to the system.
+
88
	 * @pre walk must have a unique name compared to the already stored Walks.
+
89
	 */
+
90
	public void addWalk(Walk walk) {
+
91
		this.walks.add(walk);
+
92
		// FIXME Contract!
+
93
	}
+
94
+
95
	/**
+
96
	 * Returns a copy of all Walks.
+
97
	 * @return A verbatim copy of all Walk Reservations.
+
98
	 */
+
99
	@SuppressWarnings("unchecked")
+
100
	public Set<Walk> getWalks() {
+
101
		return (HashSet<Walk>)this.walks.clone();
+
102
	}
+
103
+
104
	/**
+
105
	 * Returns a Walk based on the given name.
+
106
	 * Every walk has its own name. This can be as simple as "Walk 1", "Walk2",
+
107
	 * ... to cultural names in the native language like "Twaalfkroegentocht",
+
108
	 * "Bloedprocessie", ...
+
109
	 * Because of this uniqueness, it's possible to retrieve a walk by giving
+
110
	 * its name to this method.
+
111
	 * @param walkName The name of the Walk you want to find.
+
112
	 * @pre walkName mustn't be blank or null.
+
113
	 * @throws IllegalArgumentException if walkName is an empty String.
+
114
	 * @throws NullPointerException if walkName is a null pointer.
+
115
	 * @return The Walk with the given name, or null if there isn't a Walk with
+
116
	 * that name in the system.
+
117
	 */
+
118
	public Walk getWalkFromName(String walkName) {
+
119
		// Contract validation
+
120
		if(walkName.isEmpty())
+
121
			throw new IllegalArgumentException("walkName mustn't be an empty String.");
+
122
		// Contract validated
+
123
		for(Walk walk: this.getWalks()) {
+
124
			if(walk.getName() == walkName) {
+
125
				return walk;
+
126
			}
+
127
		}
+
128
		return null; // No walk was found with that name.
+
129
	}
+
130
}
+
131

Challenge 6/WalkReservation.java

108 additions and 0 deletions.

View changes Hide changes
+
1
+
2
/**
+
3
 * Represents a Reservation for a guided walk.
+
4
 * A guided walk is closely connected to a Reservation, but too different to put
+
5
 * them together.
+
6
 * 
+
7
 * To consider whether a guided walk was reserved by people who are doing a
+
8
 * Reservation, the group names in both Reservations are compared. Equal names
+
9
 * indicate the same people.
+
10
 *
+
11
 * If the guided walk overlaps with their reservation period, the price does not
+
12
 * get doubled, and vice versa.
+
13
 * @author Maarten Vangeneugden - 1438256
+
14
 */
+
15
public class WalkReservation {
+
16
+
17
	private String groupName;
+
18
	private Walk walk;
+
19
	private Date beginDate;
+
20
	private int people;
+
21
+
22
	public WalkReservation(String groupName, Walk walk, Date beginDate, int people) {
+
23
		this.groupName = groupName;
+
24
		this.walk = walk;
+
25
		this.beginDate = beginDate;
+
26
		this.people = people;
+
27
	}
+
28
+
29
	public WalkReservation() {
+
30
		this.groupName = "blank name";
+
31
		this.walk = null; // XXX
+
32
		this.beginDate = new Date();
+
33
		this.people = 1;
+
34
	}
+
35
+
36
	public void setGroupName(String groupName) {
+
37
		this.groupName = groupName;
+
38
	}
+
39
+
40
	public String getGroupName() {
+
41
		return groupName;
+
42
	}
+
43
+
44
	public void setWalk(Walk walk) {
+
45
		this.walk = walk;
+
46
	}
+
47
+
48
	public Walk getWalk() {
+
49
		return walk;
+
50
	}
+
51
+
52
	public void setBeginDate(Date beginDate) {
+
53
		this.beginDate = beginDate;
+
54
	}
+
55
+
56
	public Date getBeginDate() {
+
57
		return beginDate;
+
58
	}
+
59
+
60
	/**
+
61
	 * Set a new amount of people for this Walk.
+
62
	 * A Walk can take 10 people at most.
+
63
	 * @param people The new amount of people.
+
64
	 * @pre people must be in range [1, 10].
+
65
	 * @throws IllegalArgumentException if people does not meet the
+
66
	 * preconditions.
+
67
	 * @post The amount of people is updated to the given value.
+
68
	 */
+
69
	public void setPeople(int people) {
+
70
		this.people = people;
+
71
	}
+
72
+
73
	public int getPeople() {
+
74
		return people;
+
75
	}
+
76
+
77
	/**
+
78
	 * Determines the price for this guided walk.
+
79
	 * Price is determined based on the following factors:
+
80
	 * - 5/person/attraction
+
81
	 * - This, multiplied with the duration of the guided walk
+
82
	 * - If the group has no Reservation in the hostel during the walk, double
+
83
	 *   the price.
+
84
	 *
+
85
	 * For calculation of said price, the ReservationController is required.
+
86
	 * @param rc The ReservationController.
+
87
	 * @pre rc mustn't be null.
+
88
	 * @throws NullPointerException if rc is a null pointer.
+
89
	 * @return The total price of this guided Walk Reservation.
+
90
	 */
+
91
	public int getPrice(ReservationController rc) {
+
92
		int totalPrice = 0;
+
93
		totalPrice +=  (5 * this.getWalk().getAttractions().size());
+
94
		totalPrice *= this.getPeople();
+
95
		// Searching for an overlapping Reservation:
+
96
		for(Reservation reservation: rc.getReservations()) {
+
97
			if(reservation.getGroupName() == this.getGroupName() &&
+
98
			   this.getBeginDate().after(reservation.getBeginDate()) &&
+
99
			   this.getBeginDate().before(reservation.getEndDate())) {
+
100
				// An overlapping Reservation was found, so no extra pay
+
101
				return totalPrice;
+
102
			}
+
103
		}
+
104
		// At this point, no overlapping Reservation was found.
+
105
		return totalPrice * 2;
+
106
	}
+
107
}
+
108

Challenge 6/WalkSearchView.java

80 additions and 0 deletions.

View changes Hide changes
+
1
import java.util.Date;
+
2
+
3
import javax.swing.*;
+
4
+
5
/**
+
6
 * @author Maarten Vangeneugden - 1438256
+
7
 */
+
8
public class WalkSearchView {
+
9
+
10
	private ReservationController rc;
+
11
	private WalkController wc;
+
12
+
13
	private Window window;
+
14
	private JTextField groupNameField;
+
15
	private JTextField walkNameField;
+
16
	private JTextField walkDateField;
+
17
+
18
	public WalkSearchView(ReservationController rc, WalkController wc) {
+
19
		this.rc = rc;
+
20
		this.wc = wc;
+
21
		this.window = new Window("Search screen");
+
22
		this.addFields();
+
23
	}
+
24
+
25
	private void addFields() {
+
26
		// Reservations querying
+
27
		this.window.createLabel("Search walk reservations:");
+
28
		this.groupNameField = this.window.createTextField("Search by group name");
+
29
		this.walkNameField = this.window.createTextField("Search by walk name");
+
30
		this.walkDateField = this.window.createTextField(new Date().toGMTString());
+
31
		this.window.createButton("Search walk reservation", "", "queryWalkReservations", this);
+
32
		this.window.createButton("Query walk day", "", "queryWalkDay", this);
+
33
	}
+
34
+
35
	public void queryWalkReservations() {
+
36
		ArrayList<WalkReservation> foundWalkReservations = new ArrayList<>();
+
37
		String groupNameQuery = this.groupNameField.getText();
+
38
		String walkNameQuery = this.walkNameField.getText();
+
39
		for(WalkReservation activeWalkReservation : this.wc.getWalkReservations()) {
+
40
			if(activeWalkReservation.getGroupName().contains(groupNameQuery) &&
+
41
					activeWalkReservation.getWalk().getName().contains(walkNameQuery)) {
+
42
				foundWalkReservations.add(activeWalkReservation);
+
43
				}
+
44
		}
+
45
		// After collecting all results, offer the user the choice about which
+
46
		// one to take:
+
47
		String[] walkReservationNames = new String[foundWalkReservations.size()];
+
48
		for(int i=0; i<foundWalkReservations.size(); i++) {
+
49
			String text = foundWalkReservations.get(i).getGroupName() +" ("+
+
50
				foundWalkReservations.get(i).getWalk().getName() +")";
+
51
			walkReservationNames[i] = text;
+
52
		}
+
53
		int choice = this.window.choiceDialog("Multiple results were found. Specify which one you want to view:", walkReservationNames);
+
54
		if(choice == -1) { // No result found
+
55
			this.window.messageDialog("No walk reservations matched the given details.");
+
56
		}
+
57
		else {
+
58
			new WalkView(foundWalkReservations.get(choice), this.rc, this.wc);
+
59
		}
+
60
	}
+
61
+
62
+
63
	public void setRc(ReservationController rc) {
+
64
		this.rc = rc;
+
65
	}
+
66
+
67
	public ReservationController getRc() {
+
68
		return rc;
+
69
	}
+
70
+
71
	public void setWc(WalkController wc) {
+
72
		this.wc = wc;
+
73
	}
+
74
+
75
	public WalkController getWc() {
+
76
		return wc;
+
77
	}
+
78
+
79
}
+
80

Challenge 6/WalkView.java

106 additions and 0 deletions.

View changes Hide changes
+
1
+
2
import java.util.Set;
+
3
import java.util.HashSet;
+
4
import java.util.Date;
+
5
+
6
/**
+
7
 * GUI class that handles the GUI part of walks.
+
8
 * @author Maarten Vangeneugden - 1438256
+
9
 */
+
10
public class WalkView {
+
11
	private JTextField groupNameField;
+
12
	private JComboBox<String> possibleWalksField;
+
13
	private JTextField dateField;
+
14
	private JSpinner peopleField;
+
15
+
16
	private WalkReservation walkReservation;
+
17
	private ReservationController rc;
+
18
	private WalkController wc;
+
19
	private Window window;
+
20
+
21
	public WalkView(WalkReservation walkReservation, ReservationController rc, WalkController wc) {
+
22
		if(walkReservation == null || rc == null || wc == null) {
+
23
			throw new NullPointerException("One or more of the given parameters is a null pointer.");
+
24
		}
+
25
		// Contract validated
+
26
		this.walkReservation = walkReservation;
+
27
		this.rc = rc;
+
28
		this.wc = wc;
+
29
+
30
		this.window = new Window("Walk reservation screen");
+
31
		this.addFields();
+
32
	}
+
33
+
34
	private void addFields() {
+
35
		this.groupNameField = this.window.createTextField(this.walkReservation.getGroupName());
+
36
+
37
		// Getting list of all walks
+
38
		Set<String> walkNames = new HashSet<>();
+
39
		for(Walk walk: this.wc.getWalks()) {
+
40
			System.out.println("YAY A WALKK");
+
41
			walkNames.add(walk.getName());
+
42
		}
+
43
		this.possibleWalksField = this.window.addComboBox(walkNames.toArray(new String[1]));
+
44
		this.dateField = this.window.createTextField(walkReservation.getBeginDate().toGMTString());
+
45
		this.peopleField = this.window.createSpinner(1, 10, this.walkReservation.getPeople(), 1);
+
46
+
47
		this.window.createButton("Add/Update walk reservation", "", "addWalkReservation", this);
+
48
		this.window.createButton("Remove walk reservation", "", "removeWalkReservation", this);
+
49
	}
+
50
+
51
+
52
	public void setWalkReservation(WalkReservation walkReservation) {
+
53
		this.walkReservation = walkReservation;
+
54
	}
+
55
+
56
	public WalkReservation getWalkReservation() {
+
57
		return walkReservation;
+
58
	}
+
59
+
60
	public void setRc(ReservationController rc) {
+
61
		this.rc = rc;
+
62
	}
+
63
+
64
	public ReservationController getRc() {
+
65
		return rc;
+
66
	}
+
67
+
68
	public void setWc(WalkController wc) {
+
69
		this.wc = wc;
+
70
	}
+
71
+
72
	public WalkController getWc() {
+
73
		return wc;
+
74
	}
+
75
+
76
	public void addWalkReservation() {
+
77
		// First, we collect the relevant data
+
78
		final String groupName = this.groupNameField.getText();
+
79
		final Date date = new Date(this.dateField.getText());
+
80
		final int people = (Integer)this.peopleField.getValue();
+
81
		final String stringWalk = (String)this.possibleWalksField.getSelectedItem();
+
82
		final Walk walk = this.wc.getWalkFromName(stringWalk);
+
83
		// Now create a WalkReservation with this data, and send that to the
+
84
		// Controller.
+
85
		this.walkReservation.setGroupName(groupName);
+
86
		this.walkReservation.setBeginDate(date);
+
87
		this.walkReservation.setPeople(people);
+
88
		this.walkReservation.setWalk(walk);
+
89
		// Add new/updated Walk reservation to the system
+
90
		if(!this.wc.getWalkReservations().contains(this.walkReservation)) {
+
91
			this.wc.addWalkReservation(this.walkReservation);
+
92
		}
+
93
		// Display confirmation screen to user
+
94
		int price = this.walkReservation.getPrice(this.rc);
+
95
		this.window.messageDialog("Guided walk reserved! Price: "+ price);
+
96
		this.window.close();
+
97
	}
+
98
	
+
99
	public void removeWalkReservation() {
+
100
		if(this.wc.getWalkReservations().contains(this.walkReservation)) {
+
101
			this.wc.cancelWalkReservation(this.walkReservation);
+
102
		}
+
103
		this.window.close();
+
104
	}
+
105
}
+
106

Challenge 6/ontwerpkeuzes2.md → Challenge 6/ontwerpkeuzes.md

0 additions and 0 deletions.

View changes Hide changes

Challenge 6/ontwerpkeuzes.txt

0 additions and 68 deletions.

View changes Hide changes
1
-
==============================
2
-
3
-
Toepassing types/classes
4
-
------------------------
5
-
Doorheen het programma heb ik getracht zoveel mogelijk gebruik te maken van
6
-
types/classes die
7
-
- Veelvoorkomend zijn in de Java STL (Zoals String, Set, List, ...)
8
-
- primitief zijn (ints, ...), omdat deze operatoren hebben en de code
9
-
  leesbaarder maken
10
-
11
-
Een goed voorbeeld hiervan zijn bv. de faciliteiten:
12
-
I.p.v. een aparte "Facility"-class te maken, heb ik de verschillende
13
-
faciliteiten voorgesteld door een simpele String. De voordelen van deze aanpak
14
-
zijn ook direct duidelijk:
15
-
- Betekenis is direct duidelijk; de faciliteit letterlijk in de code vernoemd
16
-
- Makkelijke interactie met GUI, die sowieso Strings vraagt voor bv. JLabel
17
-
- Uitbreidbaarheid wordt bekomen door simpelweg een nieuwe String te
18
-
  introduceren
19
-
20
-
View en GUI
21
-
-----------
22
-
Werken met GUI's is vaak tijdrovend en veroorzaakt snel errors, zeker met bv.
23
-
anonieme methods, exceptions, ...
24
-
Alhoewel mijn programma grotendeels in een MVC-stijl is geschreven, maken de
25
-
view-classes (RegistrationView, SearchView, ...) achterliggend gebruik van een
26
-
zelfgemaakt framework om makkelijk vensters te maken.
27
-
Dit kleine framework is een persoonlijk hobbyproject dat ik JSugar noem.
28
-
Het biedt een heleboel voordelen, vergeleken met elk GUI-venster zelf opstellen:
29
-
- Vaak gebruikte GUI-widgets (zoals een label, textfield) worden aangemaakt en
30
-
  toegevoegd door slechts 1 method op te roepen
31
-
- JSugar maakt gebruik van reflectie om op een leesbare en uitbreidbare manier
32
-
  knoppen te activeren:
33
-
  public JButton createButton(String text, String action, String methodName, Object triggerObject)
34
-
  'methodName' is een simpele String, en 'triggerObject' is het object waar deze
35
-
  method moet worden opgeroepen.
36
-
- Automatische uitlijning van widgets
37
-
Voor meer informatie kunt u JSugar-readme.md raadplegen.
38
-
39
-
java.util.Date
40
-
--------------
41
-
42
-
Doorheen het programma maak ik vaak gebruik van de Date-class uit de Java STL,
43
-
om de volgende redenen:
44
-
- Uitbreidbaarheid: Door overal eenzelfde type te gebruiken, is het gemakkelijk
45
-
  om nieuwe modules toe te voegen, zonder dat daarvoor abstractielagen etc.
46
-
  nodig zijn.
47
-
- Uniformiteit: Eenzelfde type uit de STL laat de ontwikkelaar toe om door het
48
-
  hele programma heen hetzelfde denkpatroon aan te houden; een
49
-
  Stringvoorstelling hier, een integer daar, ... veroorzaken problemen en bugs,
50
-
  die met deze class voorkomen worden.
51
-
52
-
Bedden
53
-
------
54
-
55
-
Ik heb voor bedden een aparte class aangemaakt, omdat deze een bepaalde state
56
-
bijhouden, nml. wanneer ze gereserveerd zijn.
57
-
58
-
59
-
Reservation
60
-
-----------
61
-
Voor de reservaties heb ik besloten om enkel die data bij te houden die inherent
62
-
gerelateerd is aan die reservatie:
63
-
- Enkel gereserveerde bedden i.p.v. gereserveerde kamers. Qua uitbreidbaarheid
64
-
  heeft dit tot gevolg dat men gemakkelijk kan uitbreiden naar reservaties,
65
-
  gespreid over verschillende kamers.
66
-
67
-
68
-
ReservationView
69
-
---------------
70
-
Merk op hoe in ReservationView de data van de Reservation direct in de GUI wordt
71
-
geplaatst.
72
-
Dit staat toe om zeer gemakkelijk deze class te hergebruiken voor zowel het
73
-
**aanmaken** als het **updaten** van de reservatie.
74
-