Add CT326 Programming III
38
third/semester1/CT326_Programming_III/assignments/assignment1/CT326-Assignment01/.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
3
third/semester1/CT326_Programming_III/assignments/assignment1/CT326-Assignment01/.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
13
third/semester1/CT326_Programming_III/assignments/assignment1/CT326-Assignment01/.idea/misc.xml
generated
Normal file
@ -0,0 +1,13 @@
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
124
third/semester1/CT326_Programming_III/assignments/assignment1/CT326-Assignment01/.idea/uiDesigner.xml
generated
Normal file
@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
After Width: | Height: | Size: 82 KiB |
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>CT326-Assignment01</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,6 @@
|
||||
// Andrew Hayes, ID: 21321503
|
||||
public class DateInPastException extends RuntimeException {
|
||||
public DateInPastException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
// Andrew Hayes, ID: 21321503
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class NCTBooking {
|
||||
private static final AtomicLong NEXT_ID = new AtomicLong(0);
|
||||
|
||||
private String vehicleRegistrationNumber;
|
||||
private TestCentre testCentre;
|
||||
private LocalDateTime datetime;
|
||||
private final long bookingID = NEXT_ID.getAndIncrement();
|
||||
|
||||
public NCTBooking(String vehicleRegistrationNumber, TestCentre testCentre, LocalDateTime datetime) throws DateInPastException {
|
||||
// if datetime is in the future, initialising NCTBooking, otherwise throwing DateInPastException
|
||||
if (datetime.isAfter(LocalDateTime.now())) {
|
||||
this.vehicleRegistrationNumber = vehicleRegistrationNumber;
|
||||
this.testCentre = testCentre;
|
||||
this.datetime = datetime;
|
||||
}
|
||||
else {
|
||||
throw new DateInPastException("Passed datetime is in the past!");
|
||||
}
|
||||
}
|
||||
|
||||
public NCTBooking(String vehicleRegistrationNumber, TestCentre testCentre) {
|
||||
this.vehicleRegistrationNumber = vehicleRegistrationNumber;
|
||||
this.testCentre = testCentre;
|
||||
}
|
||||
|
||||
public TestCentre getTestCentre() { return testCentre; }
|
||||
|
||||
public String getVehicleRegistrationNumber() { return vehicleRegistrationNumber; }
|
||||
|
||||
public void setVehicleRegistrationNumber(String vehicleRegistrationNumber) { this.vehicleRegistrationNumber = vehicleRegistrationNumber; }
|
||||
|
||||
public long getBookingID() { return bookingID; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("EEEE, d MMMM yyyy");
|
||||
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
|
||||
|
||||
return "Booking ID Number: " + bookingID + "\n" +
|
||||
"Registration Number: " + vehicleRegistrationNumber + "\n" +
|
||||
"Centre: " + testCentre.getName() + "\n" +
|
||||
"Address: " + testCentre.getAddress() + "\n" +
|
||||
"Date & Time: On " + datetime.format(dateFormatter) + " at " + datetime.format(timeFormatter);
|
||||
}
|
||||
|
||||
public void setDatetime(LocalDateTime datetime) throws DateInPastException {
|
||||
// if datetime is in the future, setting datetime, otherwise throwing exception
|
||||
if (datetime.isAfter(LocalDateTime.now())) {
|
||||
this.datetime = datetime;
|
||||
}
|
||||
else {
|
||||
throw new DateInPastException(datetime.toString() + "is in the past!");
|
||||
}
|
||||
}
|
||||
|
||||
public LocalDateTime getDatetime() { return datetime; }
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
// Andrew Hayes, ID: 21321503
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public interface NCTBookingSlotWebservice {
|
||||
public LocalDateTime getBookingDateTime(TestCentre testCentre);
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
// Andrew Hayes, ID: 21321503
|
||||
public class TestCentre {
|
||||
private String name;
|
||||
private String address;
|
||||
|
||||
public TestCentre(String name, String address) {
|
||||
this.name = name;
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getName() { return name; }
|
||||
public String getAddress() { return address; }
|
||||
}
|
@ -0,0 +1,165 @@
|
||||
// Andrew Hayes, ID: 21321503
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
class NCTBookingTest {
|
||||
// tests ability to instantiate an NCTBooking
|
||||
@Test
|
||||
void testCreateNCTBooking() {
|
||||
TestCentre testCentre = new TestCentre("Test Centre 1", "10 Downing Street");
|
||||
NCTBooking booking = new NCTBooking("221-RN-1234", testCentre, LocalDateTime.of(2024, 1, 1, 9, 0, 0));
|
||||
assertNotNull(booking);
|
||||
}
|
||||
|
||||
// tests ability to query the test centre of a booking
|
||||
@Test
|
||||
void testGetTestCentre() {
|
||||
TestCentre testCentre = new TestCentre("Test Centre 1", "10 Downing Street");
|
||||
NCTBooking booking = new NCTBooking("221-RN-1234", testCentre, LocalDateTime.of(2024, 1, 1, 9, 0, 0));
|
||||
|
||||
// value returned by getTestCentre() should be the value set when the booking was created
|
||||
assertEquals(testCentre, booking.getTestCentre());
|
||||
}
|
||||
|
||||
// tests ability to query the vehicle registration for a booking
|
||||
@Test
|
||||
void testGetVehicleRegistrationNumber() {
|
||||
String vehicleRegistrationNumber = "221-RN-1234";
|
||||
TestCentre testCentre = new TestCentre("Test Centre 1", "10 Downing Street");
|
||||
NCTBooking booking = new NCTBooking(vehicleRegistrationNumber, testCentre, LocalDateTime.of(2024, 1, 1, 9, 0, 0));
|
||||
|
||||
// value returned by getVehicleRegistrationNumber() should be the value that was set when the booking was created (in this case)
|
||||
assertEquals(vehicleRegistrationNumber, booking.getVehicleRegistrationNumber());
|
||||
}
|
||||
|
||||
// tests ability to edit the vehicle registration number of a booking
|
||||
@Test
|
||||
void testSetVehicleRegistrationNumber() {
|
||||
String vehicleRegistrationNumber = "221-RN-1234";
|
||||
TestCentre testCentre = new TestCentre("Test Centre 1", "10 Downing Street");
|
||||
NCTBooking booking = new NCTBooking(vehicleRegistrationNumber, testCentre, LocalDateTime.of(2024, 1, 1, 9, 0, 0));
|
||||
|
||||
// changing the value of vehicleRegistrationNumber and testing that the value returned by getVehicleRegistrationNumber is equal to the updated value
|
||||
String newVehicleRegistrationNumber = "00-D-4321";
|
||||
booking.setVehicleRegistrationNumber(newVehicleRegistrationNumber);
|
||||
|
||||
// value returned by getVehicleRegistrationNumber() should be the value that was set in the last edit
|
||||
assertEquals(newVehicleRegistrationNumber, booking.getVehicleRegistrationNumber());
|
||||
}
|
||||
|
||||
// tests ability to instantiate an NCTBooking without specifying a date
|
||||
@Test
|
||||
void testCreateNCTBookingWithoutDate() {
|
||||
TestCentre testCentre = new TestCentre("Test Centre 1", "10 Downing Street");
|
||||
NCTBooking booking = new NCTBooking("221-RN-123", testCentre);
|
||||
assertNotNull(booking);
|
||||
}
|
||||
|
||||
// tests ability to query the date and time of a booking
|
||||
@Test
|
||||
void testGetDatetime() {
|
||||
TestCentre testCentre = new TestCentre("Test Centre 1", "10 Downing Street");
|
||||
LocalDateTime datetime = LocalDateTime.of(2024, 1, 1, 9, 0, 0);
|
||||
NCTBooking booking = new NCTBooking("221-RN-1234", testCentre, datetime);
|
||||
|
||||
// queried datetime should be equal to the datetime set on initialisation
|
||||
assertEquals(datetime, booking.getDatetime());
|
||||
}
|
||||
|
||||
// tests ability to set the date and time of a booking via an external API
|
||||
@Test
|
||||
void testSetDatetime() {
|
||||
// stub implementation of the NCTBookingSlotWebservice for testing purposes
|
||||
NCTBookingSlotWebservice testService = new NCTBookingSlotWebservice() {
|
||||
@Override
|
||||
public LocalDateTime getBookingDateTime(TestCentre testCentre) {
|
||||
return LocalDateTime.of(2024, 1, 1, 9, 0, 0);
|
||||
}
|
||||
};
|
||||
|
||||
TestCentre testCentre = new TestCentre("Test Centre 1", "10 Downing Street");
|
||||
NCTBooking booking = new NCTBooking("221-RN-123", testCentre);
|
||||
LocalDateTime datetime = testService.getBookingDateTime(testCentre);
|
||||
booking.setDatetime(datetime);
|
||||
|
||||
assertEquals(datetime, booking.getDatetime());
|
||||
}
|
||||
|
||||
// tests that bookings with a date and time in the past throw a user-defined exception
|
||||
@Test
|
||||
void testCreateNCTBookingWithDataInThePast() {
|
||||
TestCentre testCentre = new TestCentre("Test Centre 1", "10 Downing Street");
|
||||
assertThrows(
|
||||
DateInPastException.class,
|
||||
() -> new NCTBooking("221-RN-123", testCentre, LocalDateTime.of(1970, 1, 1, 9, 0, 0))
|
||||
);
|
||||
}
|
||||
|
||||
// tests that attempting to set the datetime of a booking to a time in the past throws a user-defined exception
|
||||
@Test
|
||||
void testSetDatetimeInPast() {
|
||||
// stub implementation of the NCTBookingSlotWebservice for testing purposes
|
||||
NCTBookingSlotWebservice testService = new NCTBookingSlotWebservice() {
|
||||
@Override
|
||||
public LocalDateTime getBookingDateTime(TestCentre testCentre) {
|
||||
return LocalDateTime.of(1970, 1, 1, 9, 0, 0);
|
||||
}
|
||||
};
|
||||
|
||||
TestCentre testCentre = new TestCentre("Test Centre 1", "10 Downing Street");
|
||||
NCTBooking booking = new NCTBooking("221-RN-123", testCentre);
|
||||
LocalDateTime datetime = testService.getBookingDateTime(testCentre);
|
||||
|
||||
assertThrows(
|
||||
DateInPastException.class,
|
||||
() -> booking.setDatetime(datetime)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
// tests that bookings have a unique booking ID number generated when they're created
|
||||
@Test
|
||||
void testUniqueIDGenerated() {
|
||||
TestCentre testCentre = new TestCentre("Test Centre 1", "10 Downing Street");
|
||||
NCTBooking booking = new NCTBooking("221-RN-123", testCentre, LocalDateTime.of(2024, 1, 1, 9, 0, 0));
|
||||
assertNotNull(booking.getBookingID());
|
||||
}
|
||||
|
||||
// attempts to test if booking IDs are not unique by comparing 10,000 of them (note that this does not prove uniqueness, just will disprove it in certain situations)
|
||||
@Test
|
||||
void testBookingIDsUnique() {
|
||||
TestCentre testCentre = new TestCentre("Test Centre 1", "10 Downing Street");
|
||||
|
||||
NCTBooking[] bookings = new NCTBooking[10_000];
|
||||
for (int i = 0; i < 10_000; i ++) {
|
||||
bookings[i] = new NCTBooking("221-RN-123", testCentre, LocalDateTime.of(2024, 1, 1, 9, 0, 0));
|
||||
}
|
||||
|
||||
// looping over the bookings and comparing each one to every other one
|
||||
for (int i = 0; i < 10_000; i ++) {
|
||||
for (int j = 0; j < 10_000; j ++) {
|
||||
if (i != j) {
|
||||
assertNotEquals(bookings[i].getBookingID(), bookings[j].getBookingID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tests that output from toString() method matches a regex for the expected output
|
||||
@Test
|
||||
void testToString() {
|
||||
TestCentre testCentre = new TestCentre("Test Centre 1", "10 Downing Street");
|
||||
NCTBooking booking = new NCTBooking("221-RN-123", testCentre, LocalDateTime.of(2024, 1, 1, 9, 0, 0));
|
||||
|
||||
// the only "regular-expressiony" part of the below regex is "[0-9]+" which just matches one or more decimal digits
|
||||
assertTrue(booking.toString().matches(
|
||||
"""
|
||||
Booking ID Number: [0-9]+
|
||||
Registration Number: 221-RN-123
|
||||
Centre: Test Centre 1
|
||||
Address: 10 Downing Street
|
||||
Date & Time: On Monday, 1 January 2024 at 09:00"""
|
||||
));
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
// Andrew Hayes, ID: 21321503
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
class TestCentreTest {
|
||||
// tests ability to instantiate a TestCentre
|
||||
@Test
|
||||
void testCreateTestCentre() {
|
||||
TestCentre testCentre = new TestCentre("Test Centre 1", "10 Downing Street");
|
||||
assertNotNull(testCentre);
|
||||
}
|
||||
|
||||
// tests the getter for "name" in TestCentre class
|
||||
@Test
|
||||
void testGetName() {
|
||||
TestCentre testCentre = new TestCentre("Test Centre 1", "10 Downing Street");
|
||||
assertEquals("Test Centre 1", testCentre.getName());
|
||||
}
|
||||
|
||||
// tests the getter for "address" in TestCentre class
|
||||
@Test
|
||||
void testGetAddress() {
|
||||
TestCentre testCentre = new TestCentre("Test Centre 1", "10 Downing Street");
|
||||
assertEquals("10 Downing Street", testCentre.getAddress());
|
||||
}
|
||||
}
|
38
third/semester1/CT326_Programming_III/assignments/assignment2/assignment2/.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
3
third/semester1/CT326_Programming_III/assignments/assignment2/assignment2/.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
1
third/semester1/CT326_Programming_III/assignments/assignment2/assignment2/.idea/.name
generated
Normal file
@ -0,0 +1 @@
|
||||
assignment2
|
7
third/semester1/CT326_Programming_III/assignments/assignment2/assignment2/.idea/encodings.xml
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
13
third/semester1/CT326_Programming_III/assignments/assignment2/assignment2/.idea/misc.xml
generated
Normal file
@ -0,0 +1,13 @@
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
After Width: | Height: | Size: 85 KiB |
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>assignment2</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -0,0 +1,138 @@
|
||||
// Name: Andrew Hayes
|
||||
// ID Number: 21321503
|
||||
import java.time.LocalDate;
|
||||
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.joda.money.Money;
|
||||
|
||||
public class Expense {
|
||||
private LocalDate date;
|
||||
private String description;
|
||||
private ExpenseCategory category;
|
||||
private Money amount;
|
||||
private boolean approved; // defaults to false
|
||||
|
||||
/**
|
||||
* constructor that does not take the boolean "approved" - this should be set later
|
||||
* @param date
|
||||
* @param description
|
||||
* @param category
|
||||
* @param amount
|
||||
*/
|
||||
public Expense(LocalDate date, String description, ExpenseCategory category, Money amount) {
|
||||
this.date = date;
|
||||
this.description = description;
|
||||
this.category = category;
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* constructor that takes the boolean "approved" in case you want to override it defaulting to false
|
||||
* @param date
|
||||
* @param description
|
||||
* @param category
|
||||
* @param amount
|
||||
* @param approved
|
||||
*/
|
||||
public Expense(LocalDate date, String description, ExpenseCategory category, Money amount, boolean approved) {
|
||||
this.date = date;
|
||||
this.description = description;
|
||||
this.category = category;
|
||||
this.amount = amount;
|
||||
this.approved = approved;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return date
|
||||
*/
|
||||
public LocalDate getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param date
|
||||
*/
|
||||
public void setDate(LocalDate date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param description
|
||||
*/
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return category
|
||||
*/
|
||||
public ExpenseCategory getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param category
|
||||
*/
|
||||
public void setCategory(ExpenseCategory category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return amount
|
||||
*/
|
||||
public Money getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param amount
|
||||
*/
|
||||
public void setAmount(Money amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* method to return the currency unit of the amount
|
||||
* @return the CurrencyUnit of the amount
|
||||
*/
|
||||
public CurrencyUnit getAmountCurrency() { return amount.getCurrencyUnit(); }
|
||||
|
||||
/**
|
||||
*
|
||||
* @return isApproved
|
||||
*/
|
||||
public boolean isApproved() {
|
||||
return approved;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param approved
|
||||
*/
|
||||
public void setApproved(boolean approved) {
|
||||
this.approved = approved;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"%s: %s - %s - %s %.2f", date.toString(), description, category, amount.getCurrencyUnit(), amount.getAmount().doubleValue()
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
// Name: Andrew Hayes
|
||||
// ID Number: 21321503
|
||||
public enum ExpenseCategory {
|
||||
TRAVEL_AND_SUBSISTENCE,
|
||||
SUPPLIES,
|
||||
ENTERTAINMENT,
|
||||
EQUIPMENT,
|
||||
OTHER
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
// Name: Andrew Hayes
|
||||
// ID Number: 21321503
|
||||
import java.util.ArrayList;
|
||||
|
||||
public interface ExpensePrinter {
|
||||
|
||||
/**
|
||||
* method to print the expenses
|
||||
* @param expenses
|
||||
*/
|
||||
public void print(ArrayList<Expense> expenses);
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
// Name: Andrew Hayes
|
||||
// ID Number: 21321503
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.joda.money.IllegalCurrencyException;
|
||||
import org.joda.money.Money;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ExpensesPortal {
|
||||
private ArrayList<Expense> expenses = new ArrayList<Expense>();
|
||||
|
||||
/**
|
||||
* main method
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
ExpensesPortal ep = new ExpensesPortal();
|
||||
|
||||
// create sample expenses
|
||||
ep.addExpense(new Expense(LocalDate.of(2022, 9, 23), "FLight to Glasgow", ExpenseCategory.TRAVEL_AND_SUBSISTENCE, Money.parse("EUR 270.59")));
|
||||
ep.addExpense(new Expense(LocalDate.of(2022, 9, 23), "FLight to Dublin", ExpenseCategory.TRAVEL_AND_SUBSISTENCE, Money.parse("EUR 271.59")));
|
||||
ep.addExpense(new Expense(LocalDate.of(2022, 9, 20), "Dell 17-inch monitor", ExpenseCategory.EQUIPMENT, Money.parse("USD 540.00")));
|
||||
ep.addExpense(new Expense(LocalDate.of(2022, 9, 20), "Logitech Mouse", ExpenseCategory.EQUIPMENT, Money.parse("USD 40.00")));
|
||||
ep.addExpense(new Expense(LocalDate.of(2022, 9, 21), "Java for Dummies", ExpenseCategory.OTHER, Money.parse("EUR 17.99")));
|
||||
ep.addExpense(new Expense(LocalDate.of(2022, 9, 21), "Dinner", ExpenseCategory.OTHER, Money.parse("EUR 20.99")));
|
||||
ep.addExpense(new Expense(LocalDate.of(2022, 9, 21), "Whiteboard Marker", ExpenseCategory.SUPPLIES, Money.parse("EUR 4.99")));
|
||||
|
||||
// call the printExpenses method using a lambda expression to implement the ExpensePrinter parameter
|
||||
ep.printExpenses(expenses -> {
|
||||
for (Expense expense : expenses) {
|
||||
System.out.println(expense);
|
||||
}
|
||||
});
|
||||
System.out.printf("%n");
|
||||
|
||||
// call the printExpenses method using an anonymous inner class to implement the ExpensePrinter parameter
|
||||
ep.printExpenses(new ExpensePrinter() {
|
||||
/**
|
||||
* method to print a summary of the expenses
|
||||
* @param expenses
|
||||
*/
|
||||
@Override
|
||||
public void print(ArrayList<Expense> expenses) {
|
||||
System.out.println("There are " + expenses.toArray().length + " expenses in the system totalling to a value of " + sumExpenses(expenses));
|
||||
}
|
||||
});
|
||||
System.out.printf("%n");
|
||||
|
||||
// call the printExpense method using a PrinterByLabel instance as a parameter
|
||||
ep.printExpenses(new PrinterByLabel());
|
||||
}
|
||||
|
||||
/**
|
||||
* method to submit a new expense
|
||||
* @param expense
|
||||
*/
|
||||
public void addExpense(Expense expense) {
|
||||
expenses.add(expense);
|
||||
}
|
||||
|
||||
/**
|
||||
* method to print expenses
|
||||
* @param printer
|
||||
*/
|
||||
public void printExpenses(ExpensePrinter printer) {
|
||||
printer.print(expenses);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* method for summing the expenses that supports both EUR & USD
|
||||
* @param expenses
|
||||
* @return
|
||||
* @throws IllegalCurrencyException
|
||||
*/
|
||||
public static Money sumExpenses(ArrayList<Expense> expenses) throws IllegalCurrencyException {
|
||||
Money total = Money.parse("EUR 0");
|
||||
BigDecimal USDToEURConversionRate = BigDecimal.valueOf(0.95); // hardcoded conversion rate as of 2023-10-04 - clearly not ideal, but as a proof of concept
|
||||
|
||||
for (Expense expense : expenses) {
|
||||
// if currency is usd, converting to euro and adding to total
|
||||
if (expense.getAmountCurrency().equals(CurrencyUnit.of("USD"))) {
|
||||
total = total.plus(expense.getAmount().convertedTo(CurrencyUnit.EUR, USDToEURConversionRate, RoundingMode.HALF_UP));
|
||||
}
|
||||
// checking that the currency is of type euro before adding to total
|
||||
else if (expense.getAmountCurrency().equals(CurrencyUnit.of("EUR"))) {
|
||||
total = total.plus(expense.getAmount());
|
||||
}
|
||||
else {
|
||||
throw new IllegalCurrencyException("CurrencyUnity " + expense.getAmountCurrency() + " is not supported! USD or EUR only");
|
||||
}
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
// Name: Andrew Hayes
|
||||
// ID Number: 21321503
|
||||
import java.util.ArrayList;
|
||||
//import java.util.Collections; // for use in commented out algorithm -- see below
|
||||
//import java.util.Comparator;
|
||||
|
||||
public class PrinterByLabel implements ExpensePrinter {
|
||||
/**
|
||||
* method to print all the expenses, grouped by category
|
||||
* @param expenses
|
||||
*/
|
||||
@Override
|
||||
public void print(ArrayList<Expense> expenses) {
|
||||
ExpenseCategory[] categories = ExpenseCategory.values();
|
||||
|
||||
for (ExpenseCategory category : categories) {
|
||||
System.out.println(category + ":");
|
||||
|
||||
for (Expense expense : expenses) {
|
||||
// printing out expense only if it's in the current category
|
||||
if (expense.getCategory().equals(category)) {
|
||||
System.out.println(expense);
|
||||
}
|
||||
}
|
||||
System.out.printf("%n");
|
||||
}
|
||||
|
||||
// below is a commented-out alternative to the above algorithm that doesn't match the output in the design spec
|
||||
// it doesn't print out every expense category as a title, just the ones that have an existing expense in the system
|
||||
// this allows the sorting to be done nicely using the enum, and allows the enum to be expanded or contracted without changing other code
|
||||
// this allows for slightly nicer sorting and does not print out categories which do not have extant expenses in them, which may or may not be desirable
|
||||
|
||||
// // sorting the ArrayList by category
|
||||
// Collections.sort(expenses, Comparator.comparing(Expense::getCategory));
|
||||
//
|
||||
// // variable to keep track of what category the last printed expense was so that a heading can be printed once and only once for each category
|
||||
// ExpenseCategory lastCategory = null;
|
||||
//
|
||||
// for (Expense expense : expenses) {
|
||||
// // if the current expense's category is different to the last, print it out as a heading
|
||||
// if (expense.getCategory() != lastCategory) {
|
||||
// System.out.println(expense.getCategory());
|
||||
// lastCategory = expense.getCategory();
|
||||
// }
|
||||
// System.out.println(expense);
|
||||
// }
|
||||
}
|
||||
}
|
38
third/semester1/CT326_Programming_III/assignments/assignment3/CT326-Assignment3/.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
3
third/semester1/CT326_Programming_III/assignments/assignment3/CT326-Assignment3/.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
14
third/semester1/CT326_Programming_III/assignments/assignment3/CT326-Assignment3/.idea/misc.xml
generated
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
124
third/semester1/CT326_Programming_III/assignments/assignment3/CT326-Assignment3/.idea/uiDesigner.xml
generated
Normal file
@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>CT326-Assignment3</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.10.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,81 @@
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* class representing a player's achievement
|
||||
*/
|
||||
public class Achievement {
|
||||
private String achievementName;
|
||||
private String description;
|
||||
private LocalDate dateOfAward;
|
||||
|
||||
/**
|
||||
* constructor for the Achievement class
|
||||
* @param achievementName a String representation of the name of the Achievement
|
||||
* @param description a String describing the Achievement
|
||||
* @param dateOfAward a LocalDate representing the date that the Achievement was awarded
|
||||
*/
|
||||
public Achievement(String achievementName, String description, LocalDate dateOfAward) {
|
||||
this.achievementName = achievementName;
|
||||
this.description = description;
|
||||
this.dateOfAward = dateOfAward;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Achievement) {
|
||||
Achievement toCompare = (Achievement) obj;
|
||||
|
||||
if (!achievementName.equals(toCompare.achievementName)) {
|
||||
return false;
|
||||
}
|
||||
if (!description.equals(toCompare.description)) {
|
||||
return false;
|
||||
}
|
||||
if (!dateOfAward.equals(toCompare.dateOfAward)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else { return false; }
|
||||
}
|
||||
|
||||
/**
|
||||
* getter method for the achievementName field
|
||||
* @return a String representation of the name of the Achievement
|
||||
*/
|
||||
public String getAchievementName() { return achievementName; }
|
||||
|
||||
/**
|
||||
* setter method for the achievementName field
|
||||
* @param achievementName a String representation of the name of the Achievement
|
||||
*/
|
||||
public void setAchievementName(String achievementName) { this.achievementName = achievementName; }
|
||||
|
||||
/**
|
||||
* getter method for the description field
|
||||
* @return a String describing the Achievement
|
||||
*/
|
||||
public String getDescription() { return description; }
|
||||
|
||||
/**
|
||||
* setter method for the description field
|
||||
* @param description a String describing the Achievement
|
||||
*/
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
|
||||
/**
|
||||
* getter method for the dateOfAward field
|
||||
* @return a LocalDate representing the date that the Achievement was awarded
|
||||
*/
|
||||
public LocalDate getDateOfAward() { return dateOfAward; }
|
||||
|
||||
/**
|
||||
* setter method for the dateOfAward field
|
||||
* @param dateOfAward a LocalDate representing the date that the Achievement was awarded
|
||||
*/
|
||||
public void setDateOfAward(LocalDate dateOfAward) { this.dateOfAward = dateOfAward; }
|
||||
}
|
@ -0,0 +1,260 @@
|
||||
/**
|
||||
* enum for each ISO 3166 Alpha-2 country Code
|
||||
*/
|
||||
public enum Country {
|
||||
// Explanation of how this data was sourced:
|
||||
// the following ISO 3166 Alpha-2 Codes were taken from the CSV file found here: https://pkgstore.datahub.io/core/country-list/data_csv/data/d7c9d7cfb42cb69f4422dec222dbbaa8/data_csv.csv
|
||||
// the CSV file was cleaned to have UNIX line endings (as it had Windows line endings, and I am on GNU/Linux) with the command `tr -d '\r' < data_csv.csv > clean_data.csv `
|
||||
// they were then parsed & read into this Java source file with the Vim / GNU AWK command `:read !awk -F',' '{gsub(/\"/, ""); print $NF ",\t// " $1}' clean_data.csv`
|
||||
// finally, the block was indented in Vim and a `;` appended to the last value
|
||||
|
||||
AF, // Afghanistan
|
||||
AX, // Åland Islands
|
||||
AL, // Albania
|
||||
DZ, // Algeria
|
||||
AS, // American Samoa
|
||||
AD, // Andorra
|
||||
AO, // Angola
|
||||
AI, // Anguilla
|
||||
AQ, // Antarctica
|
||||
AG, // Antigua and Barbuda
|
||||
AR, // Argentina
|
||||
AM, // Armenia
|
||||
AW, // Aruba
|
||||
AU, // Australia
|
||||
AT, // Austria
|
||||
AZ, // Azerbaijan
|
||||
BS, // Bahamas
|
||||
BH, // Bahrain
|
||||
BD, // Bangladesh
|
||||
BB, // Barbados
|
||||
BY, // Belarus
|
||||
BE, // Belgium
|
||||
BZ, // Belize
|
||||
BJ, // Benin
|
||||
BM, // Bermuda
|
||||
BT, // Bhutan
|
||||
BO, // Bolivia
|
||||
BQ, // Bonaire
|
||||
BA, // Bosnia and Herzegovina
|
||||
BW, // Botswana
|
||||
BV, // Bouvet Island
|
||||
BR, // Brazil
|
||||
IO, // British Indian Ocean Territory
|
||||
BN, // Brunei Darussalam
|
||||
BG, // Bulgaria
|
||||
BF, // Burkina Faso
|
||||
BI, // Burundi
|
||||
KH, // Cambodia
|
||||
CM, // Cameroon
|
||||
CA, // Canada
|
||||
CV, // Cape Verde
|
||||
KY, // Cayman Islands
|
||||
CF, // Central African Republic
|
||||
TD, // Chad
|
||||
CL, // Chile
|
||||
CN, // China
|
||||
CX, // Christmas Island
|
||||
CC, // Cocos (Keeling) Islands
|
||||
CO, // Colombia
|
||||
KM, // Comoros
|
||||
CG, // Congo
|
||||
CD, // Congo
|
||||
CK, // Cook Islands
|
||||
CR, // Costa Rica
|
||||
CI, // Côte d'Ivoire
|
||||
HR, // Croatia
|
||||
CU, // Cuba
|
||||
CW, // Curaçao
|
||||
CY, // Cyprus
|
||||
CZ, // Czech Republic
|
||||
DK, // Denmark
|
||||
DJ, // Djibouti
|
||||
DM, // Dominica
|
||||
DO, // Dominican Republic
|
||||
EC, // Ecuador
|
||||
EG, // Egypt
|
||||
SV, // El Salvador
|
||||
GQ, // Equatorial Guinea
|
||||
ER, // Eritrea
|
||||
EE, // Estonia
|
||||
ET, // Ethiopia
|
||||
FK, // Falkland Islands (Malvinas)
|
||||
FO, // Faroe Islands
|
||||
FJ, // Fiji
|
||||
FI, // Finland
|
||||
FR, // France
|
||||
GF, // French Guiana
|
||||
PF, // French Polynesia
|
||||
TF, // French Southern Territories
|
||||
GA, // Gabon
|
||||
GM, // Gambia
|
||||
GE, // Georgia
|
||||
DE, // Germany
|
||||
GH, // Ghana
|
||||
GI, // Gibraltar
|
||||
GR, // Greece
|
||||
GL, // Greenland
|
||||
GD, // Grenada
|
||||
GP, // Guadeloupe
|
||||
GU, // Guam
|
||||
GT, // Guatemala
|
||||
GG, // Guernsey
|
||||
GN, // Guinea
|
||||
GW, // Guinea-Bissau
|
||||
GY, // Guyana
|
||||
HT, // Haiti
|
||||
HM, // Heard Island and McDonald Islands
|
||||
VA, // Holy See (Vatican City State)
|
||||
HN, // Honduras
|
||||
HK, // Hong Kong
|
||||
HU, // Hungary
|
||||
IS, // Iceland
|
||||
IN, // India
|
||||
ID, // Indonesia
|
||||
IR, // Iran
|
||||
IQ, // Iraq
|
||||
IE, // Ireland
|
||||
IM, // Isle of Man
|
||||
IL, // Israel
|
||||
IT, // Italy
|
||||
JM, // Jamaica
|
||||
JP, // Japan
|
||||
JE, // Jersey
|
||||
JO, // Jordan
|
||||
KZ, // Kazakhstan
|
||||
KE, // Kenya
|
||||
KI, // Kiribati
|
||||
KP, // Korea
|
||||
KR, // Korea
|
||||
KW, // Kuwait
|
||||
KG, // Kyrgyzstan
|
||||
LA, // Lao People's Democratic Republic
|
||||
LV, // Latvia
|
||||
LB, // Lebanon
|
||||
LS, // Lesotho
|
||||
LR, // Liberia
|
||||
LY, // Libya
|
||||
LI, // Liechtenstein
|
||||
LT, // Lithuania
|
||||
LU, // Luxembourg
|
||||
MO, // Macao
|
||||
MK, // Macedonia
|
||||
MG, // Madagascar
|
||||
MW, // Malawi
|
||||
MY, // Malaysia
|
||||
MV, // Maldives
|
||||
ML, // Mali
|
||||
MT, // Malta
|
||||
MH, // Marshall Islands
|
||||
MQ, // Martinique
|
||||
MR, // Mauritania
|
||||
MU, // Mauritius
|
||||
YT, // Mayotte
|
||||
MX, // Mexico
|
||||
FM, // Micronesia
|
||||
MD, // Moldova
|
||||
MC, // Monaco
|
||||
MN, // Mongolia
|
||||
ME, // Montenegro
|
||||
MS, // Montserrat
|
||||
MA, // Morocco
|
||||
MZ, // Mozambique
|
||||
MM, // Myanmar
|
||||
NA, // Namibia
|
||||
NR, // Nauru
|
||||
NP, // Nepal
|
||||
NL, // Netherlands
|
||||
NC, // New Caledonia
|
||||
NZ, // New Zealand
|
||||
NI, // Nicaragua
|
||||
NE, // Niger
|
||||
NG, // Nigeria
|
||||
NU, // Niue
|
||||
NF, // Norfolk Island
|
||||
MP, // Northern Mariana Islands
|
||||
NO, // Norway
|
||||
OM, // Oman
|
||||
PK, // Pakistan
|
||||
PW, // Palau
|
||||
PS, // Palestine
|
||||
PA, // Panama
|
||||
PG, // Papua New Guinea
|
||||
PY, // Paraguay
|
||||
PE, // Peru
|
||||
PH, // Philippines
|
||||
PN, // Pitcairn
|
||||
PL, // Poland
|
||||
PT, // Portugal
|
||||
PR, // Puerto Rico
|
||||
QA, // Qatar
|
||||
RE, // Réunion
|
||||
RO, // Romania
|
||||
RU, // Russian Federation
|
||||
RW, // Rwanda
|
||||
BL, // Saint Barthélemy
|
||||
SH, // Saint Helena
|
||||
KN, // Saint Kitts and Nevis
|
||||
LC, // Saint Lucia
|
||||
MF, // Saint Martin (French part)
|
||||
PM, // Saint Pierre and Miquelon
|
||||
VC, // Saint Vincent and the Grenadines
|
||||
WS, // Samoa
|
||||
SM, // San Marino
|
||||
ST, // Sao Tome and Principe
|
||||
SA, // Saudi Arabia
|
||||
SN, // Senegal
|
||||
RS, // Serbia
|
||||
SC, // Seychelles
|
||||
SL, // Sierra Leone
|
||||
SG, // Singapore
|
||||
SX, // Sint Maarten (Dutch part)
|
||||
SK, // Slovakia
|
||||
SI, // Slovenia
|
||||
SB, // Solomon Islands
|
||||
SO, // Somalia
|
||||
ZA, // South Africa
|
||||
GS, // South Georgia and the South Sandwich Islands
|
||||
SS, // South Sudan
|
||||
ES, // Spain
|
||||
LK, // Sri Lanka
|
||||
SD, // Sudan
|
||||
SR, // Suriname
|
||||
SJ, // Svalbard and Jan Mayen
|
||||
SZ, // Swaziland
|
||||
SE, // Sweden
|
||||
CH, // Switzerland
|
||||
SY, // Syrian Arab Republic
|
||||
TW, // Taiwan
|
||||
TJ, // Tajikistan
|
||||
TZ, // Tanzania
|
||||
TH, // Thailand
|
||||
TL, // Timor-Leste
|
||||
TG, // Togo
|
||||
TK, // Tokelau
|
||||
TO, // Tonga
|
||||
TT, // Trinidad and Tobago
|
||||
TN, // Tunisia
|
||||
TR, // Turkey
|
||||
TM, // Turkmenistan
|
||||
TC, // Turks and Caicos Islands
|
||||
TV, // Tuvalu
|
||||
UG, // Uganda
|
||||
UA, // Ukraine
|
||||
AE, // United Arab Emirates
|
||||
GB, // United Kingdom
|
||||
US, // United States
|
||||
UM, // United States Minor Outlying Islands
|
||||
UY, // Uruguay
|
||||
UZ, // Uzbekistan
|
||||
VU, // Vanuatu
|
||||
VE, // Venezuela
|
||||
VN, // Viet Nam
|
||||
VG, // Virgin Islands
|
||||
VI, // Virgin Islands
|
||||
WF, // Wallis and Futuna
|
||||
EH, // Western Sahara
|
||||
YE, // Yemen
|
||||
ZM, // Zambia
|
||||
ZW; // Zimbabwe
|
||||
}
|
@ -0,0 +1,184 @@
|
||||
import java.io.*;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* class to represent a player
|
||||
*/
|
||||
public class Player implements Serializable {
|
||||
private String id;
|
||||
private String username;
|
||||
private Country country;
|
||||
private LocalDate joinDate;
|
||||
private List<Achievement> achievements;
|
||||
private static final String serializeAchievementsTo = "achievements.csv";
|
||||
|
||||
/**
|
||||
* constructor for the Player class
|
||||
* @param id a String representing the player's ID
|
||||
* @param username a String representing the player's username
|
||||
* @param country a Country object representing the country to which the player belongs
|
||||
* @param joinDate a LocalDate object representing the date that the player joined the team
|
||||
* @param achievements a List of Achievement objects awarded to the player
|
||||
*/
|
||||
public Player(String id, String username, Country country, LocalDate joinDate, List<Achievement> achievements) {
|
||||
this.id = id;
|
||||
this.username = username;
|
||||
this.country = country;
|
||||
this.joinDate = joinDate;
|
||||
this.achievements = achievements;
|
||||
}
|
||||
|
||||
/**
|
||||
* overridden method to compare two objects for equality
|
||||
* @param obj the object to be compared
|
||||
* @return boolean - true if the objects have all the same fields equals, false otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Player) {
|
||||
Player toCompare = (Player) obj;
|
||||
|
||||
if (!id.equals(toCompare.id)) {
|
||||
return false;
|
||||
}
|
||||
if (!username.equals(toCompare.username)) {
|
||||
return false;
|
||||
}
|
||||
if (!country.equals(toCompare.country)) {
|
||||
return false;
|
||||
}
|
||||
if (!joinDate.equals(toCompare.joinDate)) {
|
||||
return false;
|
||||
}
|
||||
if (!achievements.equals(toCompare.achievements)) {
|
||||
return false;
|
||||
} // note that if the lists are in different orders, this will return false
|
||||
|
||||
return true;
|
||||
}
|
||||
else { return false; }
|
||||
}
|
||||
|
||||
/**
|
||||
* method to deserialize the Player object and to read in its achievements from a CSV file
|
||||
* @param out ObjectOutputStream
|
||||
* @throws IOException
|
||||
*/
|
||||
@Serial
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
// would be inappropriate to catch IOExceptions here - should be caught in the code attempting to serialize the object
|
||||
out.writeObject(id);
|
||||
out.writeObject(username);
|
||||
out.writeObject(country);
|
||||
out.writeObject(joinDate);
|
||||
|
||||
// deliberate design choice here to not use the writeObject method of the Achievement class
|
||||
// serializing Achievements in the context of a Player's list of Achievements should be treated differently to serializing, say, a single, isolated Achievement
|
||||
// there may be times when we want to serialize an Achievement without reference to a Player, without a CSV file
|
||||
|
||||
// writing out Achievements to CSV file
|
||||
FileWriter writer = new FileWriter(serializeAchievementsTo, true); // append set to true
|
||||
for (Achievement achievement : achievements) {
|
||||
writer.write(id + "," + achievement.getAchievementName() + "," + achievement.getDescription() + "," + achievement.getDateOfAward().toString() + "\n");
|
||||
}
|
||||
writer.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* method to serialize the Player object and to write out its achievements to a CSV file
|
||||
* @param in ObjectInputStream
|
||||
* @throws IOException
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
@Serial
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
// would be inappropriate to catch exceptions here - should be caught in the code attempting to de-serialize the object
|
||||
id = (String) in.readObject();
|
||||
username = (String) in.readObject();
|
||||
country = (Country) in.readObject();
|
||||
joinDate = (LocalDate) in.readObject();
|
||||
|
||||
achievements = new ArrayList<>();
|
||||
|
||||
FileReader fileReader = new FileReader(serializeAchievementsTo);
|
||||
BufferedReader bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
String line;
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
String[] cols = line.split(",");
|
||||
|
||||
// only adding to list of achievements if the player ids match
|
||||
if (cols[0].equals(id)) {
|
||||
achievements.add(new Achievement(cols[1], cols[2], LocalDate.parse(cols[3], DateTimeFormatter.ofPattern("yyyy-MM-dd"))));
|
||||
}
|
||||
}
|
||||
bufferedReader.close();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* getter method for the ID field
|
||||
* @return a String representing the player's ID
|
||||
*/
|
||||
public String getId() { return id; }
|
||||
|
||||
/**
|
||||
* setter method for the id field
|
||||
* @param id String representing the player's ID
|
||||
*/
|
||||
public void setId(String id) { this.id = id; }
|
||||
|
||||
|
||||
/**
|
||||
* getter method for the username field
|
||||
* @return a String representing the player's username
|
||||
*/
|
||||
public String getUsername() { return username; }
|
||||
|
||||
/**
|
||||
* setter method for the username field
|
||||
* @param username String representing the player's username
|
||||
*/
|
||||
public void setUsername(String username) { this.username = username; }
|
||||
|
||||
/**
|
||||
* getter method for the country field
|
||||
* @return a Country object
|
||||
*/
|
||||
public Country getCountry() { return country; }
|
||||
|
||||
/**
|
||||
* setter method for the country field
|
||||
* @param country a Country object
|
||||
*/
|
||||
public void setCountry(Country country) { this.country = country; }
|
||||
|
||||
/**
|
||||
* getter method for the joinDate field
|
||||
* @return a LocalDate representing the date when the player joined the team
|
||||
*/
|
||||
public LocalDate getJoinDate() { return joinDate; }
|
||||
|
||||
/**
|
||||
* setter method for the joinDate field
|
||||
* @param joinDate LocalDate representing the date when the player joined the team
|
||||
*/
|
||||
public void setJoinDate(LocalDate joinDate) { this.joinDate = joinDate; }
|
||||
|
||||
/**
|
||||
* getter method for the achievements field
|
||||
* @return a list of Achievement objects
|
||||
*/
|
||||
public List<Achievement> getAchievements() { return achievements; }
|
||||
|
||||
/**
|
||||
* setter method for the achievements field
|
||||
* @param achievements a list of Achievement objects
|
||||
*/
|
||||
public void setAchievements(List<Achievement> achievements) { this.achievements = achievements; }
|
||||
}
|
@ -0,0 +1,155 @@
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.*;
|
||||
import java.io.*;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* JUnit tests to test the serialization ability of the Player class
|
||||
*/
|
||||
public class TestSerialization {
|
||||
// assuming that the instruction "Use a test-driven development approach to implement the serialization of Player objects" only applies to the serialization, and not the other functionality
|
||||
|
||||
/**
|
||||
* method that runs after each test and deletes the achievements.csv and players.ser files
|
||||
*/
|
||||
@AfterEach
|
||||
void deleteFiles() {
|
||||
File achievementsFile = new File("achievements.csv");
|
||||
achievementsFile.delete();
|
||||
|
||||
File playersFile = new File("player.ser");
|
||||
playersFile.delete();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* test that creates 5 player objects, serializes them, and compares them to the deserialized objects
|
||||
* @throws IOException
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
@Test
|
||||
void serializeFivePlayers() throws IOException, ClassNotFoundException {
|
||||
// deliberately not catching potential IOExceptions - we want the tests to fail if these are thrown
|
||||
FileOutputStream players_file = new FileOutputStream("players.ser");
|
||||
ObjectOutputStream players_out = new ObjectOutputStream(players_file);
|
||||
ObjectInputStream players_in = new ObjectInputStream(new FileInputStream("players.ser"));
|
||||
|
||||
ArrayList<Player> players = new ArrayList<>(); // array of players to be serialized
|
||||
|
||||
// creating some unique players
|
||||
// player 0
|
||||
players.add(new Player("0", "player0", Country.IE, LocalDate.now(),
|
||||
new ArrayList<>() {{
|
||||
add(new Achievement("Something Award", "An award for something that was especially something", LocalDate.of(2004, 7, 6)));
|
||||
}}
|
||||
));
|
||||
|
||||
// player 1
|
||||
players.add(new Player("1", "player1", Country.JP, LocalDate.now(),
|
||||
new ArrayList<>() {{
|
||||
add(new Achievement("Something Award", "An award for something that was especially something", LocalDate.of(2004, 7, 6)));
|
||||
add(new Achievement("Another Award", "An award for something else", LocalDate.of(1996, 7, 6)));
|
||||
}}
|
||||
));
|
||||
|
||||
// player 2
|
||||
players.add(new Player("2", "player2", Country.UA, LocalDate.now(),
|
||||
new ArrayList<>() {{
|
||||
add(new Achievement("Something Award", "An award for something that was especially something", LocalDate.of(2004, 7, 6)));
|
||||
add(new Achievement("Another Award", "An award for something else", LocalDate.of(1996, 7, 6)));
|
||||
add(new Achievement("Yet Another Award", "An award for something else entirely", LocalDate.of(2023, 8, 6)));
|
||||
}}
|
||||
));
|
||||
|
||||
// player 3
|
||||
players.add(new Player("3", "player3", Country.AD, LocalDate.now(),
|
||||
new ArrayList<>() {{
|
||||
add(new Achievement("Something Award", "An award for something that was especially something", LocalDate.of(2004, 7, 6)));
|
||||
add(new Achievement("Another Award", "An award for something else", LocalDate.of(1996, 7, 6)));
|
||||
add(new Achievement("Yet Another Award", "An award for something else entirely", LocalDate.of(2023, 8, 6)));
|
||||
add(new Achievement("A fourth award", "An award that comes after three previous awards", LocalDate.of(2022, 8, 3)));
|
||||
}}
|
||||
));
|
||||
|
||||
// player 4
|
||||
players.add(new Player("4", "player4", Country.DE, LocalDate.now(),
|
||||
new ArrayList<>() {{
|
||||
add(new Achievement("Something Award", "An award for something that was especially something", LocalDate.of(2004, 7, 6)));
|
||||
add(new Achievement("Another Award", "An award for something else", LocalDate.of(1996, 7, 6)));
|
||||
add(new Achievement("Yet Another Award", "An award for something else entirely", LocalDate.of(2023, 8, 6)));
|
||||
add(new Achievement("A fourth award", "An award that comes after three previous awards", LocalDate.of(2022, 8, 3)));
|
||||
add(new Achievement("The final award", "The last award anyone will ever get", LocalDate.of(2030, 12, 25)));
|
||||
}}
|
||||
));
|
||||
|
||||
for (Player player : players) {
|
||||
players_out.writeObject(player);
|
||||
}
|
||||
|
||||
// looping over each player and comparing it to the de-serialized player
|
||||
// doing this in a separate loop to separate writing and reading
|
||||
for (Player player : players) {
|
||||
// deliberately not catching exceptions here - we want the test to fail if exceptions are thrown
|
||||
Player dplayer = (Player) players_in.readObject();
|
||||
assertEquals(player, dplayer);
|
||||
}
|
||||
|
||||
players_out.close();
|
||||
players_file.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* test the equals() method of the Player class
|
||||
*/
|
||||
@Test
|
||||
void testPlayerDotEquals() {
|
||||
// creating two identical players
|
||||
Player player1 = new Player("0", "player0", Country.IE, LocalDate.now(),
|
||||
new ArrayList<>(){{ add(new Achievement("Something Award", "An award for something that was especially something", LocalDate.of(2004, 7, 6))); }}
|
||||
);
|
||||
Player player2 = new Player("0", "player0", Country.IE, LocalDate.now(),
|
||||
new ArrayList<>(){{ add(new Achievement("Something Award", "An award for something that was especially something", LocalDate.of(2004, 7, 6))); }}
|
||||
);
|
||||
|
||||
// assertEquals uses the objects equals() method, so it suffices for this test
|
||||
assertEquals(player1, player2);
|
||||
}
|
||||
|
||||
/**
|
||||
* test the equals() method of the Achievement class
|
||||
*/
|
||||
@Test
|
||||
void testAchievementDotEquals() {
|
||||
Achievement achievement1 = new Achievement("Something Award", "An award for something that was especially something", LocalDate.of(2004, 7, 6));
|
||||
Achievement achievement2 = new Achievement("Something Award", "An award for something that was especially something", LocalDate.of(2004, 7, 6));
|
||||
|
||||
assertEquals(achievement1, achievement2);
|
||||
}
|
||||
|
||||
/**
|
||||
* test serializing & de-serializing just one player
|
||||
* @throws IOException
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
@Test
|
||||
void testSerializePlayer() throws IOException, ClassNotFoundException {
|
||||
// deliberately not catching potential IOExceptions - we want the tests to fail if these are thrown
|
||||
FileOutputStream players_file = new FileOutputStream("players.ser");
|
||||
ObjectOutputStream players_out = new ObjectOutputStream(players_file);
|
||||
ObjectInputStream players_in = new ObjectInputStream(new FileInputStream("players.ser"));
|
||||
|
||||
Player player = new Player("0", "player0", Country.IE, LocalDate.now(),
|
||||
new ArrayList<>(){{ add(new Achievement("Something Award", "An award for something that was especially something", LocalDate.of(2004, 7, 6))); }}
|
||||
);
|
||||
|
||||
// serializing player object, de-serializing it, and comparing them
|
||||
players_out.writeObject(player);
|
||||
Player dplayer = (Player) players_in.readObject();
|
||||
players_out.close();
|
||||
players_file.close();
|
||||
|
||||
assertEquals(player, dplayer);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,250 @@
|
||||
Name,Code
|
||||
Afghanistan,AF
|
||||
Åland Islands,AX
|
||||
Albania,AL
|
||||
Algeria,DZ
|
||||
American Samoa,AS
|
||||
Andorra,AD
|
||||
Angola,AO
|
||||
Anguilla,AI
|
||||
Antarctica,AQ
|
||||
Antigua and Barbuda,AG
|
||||
Argentina,AR
|
||||
Armenia,AM
|
||||
Aruba,AW
|
||||
Australia,AU
|
||||
Austria,AT
|
||||
Azerbaijan,AZ
|
||||
Bahamas,BS
|
||||
Bahrain,BH
|
||||
Bangladesh,BD
|
||||
Barbados,BB
|
||||
Belarus,BY
|
||||
Belgium,BE
|
||||
Belize,BZ
|
||||
Benin,BJ
|
||||
Bermuda,BM
|
||||
Bhutan,BT
|
||||
"Bolivia, Plurinational State of",BO
|
||||
"Bonaire, Sint Eustatius and Saba",BQ
|
||||
Bosnia and Herzegovina,BA
|
||||
Botswana,BW
|
||||
Bouvet Island,BV
|
||||
Brazil,BR
|
||||
British Indian Ocean Territory,IO
|
||||
Brunei Darussalam,BN
|
||||
Bulgaria,BG
|
||||
Burkina Faso,BF
|
||||
Burundi,BI
|
||||
Cambodia,KH
|
||||
Cameroon,CM
|
||||
Canada,CA
|
||||
Cape Verde,CV
|
||||
Cayman Islands,KY
|
||||
Central African Republic,CF
|
||||
Chad,TD
|
||||
Chile,CL
|
||||
China,CN
|
||||
Christmas Island,CX
|
||||
Cocos (Keeling) Islands,CC
|
||||
Colombia,CO
|
||||
Comoros,KM
|
||||
Congo,CG
|
||||
"Congo, the Democratic Republic of the",CD
|
||||
Cook Islands,CK
|
||||
Costa Rica,CR
|
||||
Côte d'Ivoire,CI
|
||||
Croatia,HR
|
||||
Cuba,CU
|
||||
Curaçao,CW
|
||||
Cyprus,CY
|
||||
Czech Republic,CZ
|
||||
Denmark,DK
|
||||
Djibouti,DJ
|
||||
Dominica,DM
|
||||
Dominican Republic,DO
|
||||
Ecuador,EC
|
||||
Egypt,EG
|
||||
El Salvador,SV
|
||||
Equatorial Guinea,GQ
|
||||
Eritrea,ER
|
||||
Estonia,EE
|
||||
Ethiopia,ET
|
||||
Falkland Islands (Malvinas),FK
|
||||
Faroe Islands,FO
|
||||
Fiji,FJ
|
||||
Finland,FI
|
||||
France,FR
|
||||
French Guiana,GF
|
||||
French Polynesia,PF
|
||||
French Southern Territories,TF
|
||||
Gabon,GA
|
||||
Gambia,GM
|
||||
Georgia,GE
|
||||
Germany,DE
|
||||
Ghana,GH
|
||||
Gibraltar,GI
|
||||
Greece,GR
|
||||
Greenland,GL
|
||||
Grenada,GD
|
||||
Guadeloupe,GP
|
||||
Guam,GU
|
||||
Guatemala,GT
|
||||
Guernsey,GG
|
||||
Guinea,GN
|
||||
Guinea-Bissau,GW
|
||||
Guyana,GY
|
||||
Haiti,HT
|
||||
Heard Island and McDonald Islands,HM
|
||||
Holy See (Vatican City State),VA
|
||||
Honduras,HN
|
||||
Hong Kong,HK
|
||||
Hungary,HU
|
||||
Iceland,IS
|
||||
India,IN
|
||||
Indonesia,ID
|
||||
"Iran, Islamic Republic of",IR
|
||||
Iraq,IQ
|
||||
Ireland,IE
|
||||
Isle of Man,IM
|
||||
Israel,IL
|
||||
Italy,IT
|
||||
Jamaica,JM
|
||||
Japan,JP
|
||||
Jersey,JE
|
||||
Jordan,JO
|
||||
Kazakhstan,KZ
|
||||
Kenya,KE
|
||||
Kiribati,KI
|
||||
"Korea, Democratic People's Republic of",KP
|
||||
"Korea, Republic of",KR
|
||||
Kuwait,KW
|
||||
Kyrgyzstan,KG
|
||||
Lao People's Democratic Republic,LA
|
||||
Latvia,LV
|
||||
Lebanon,LB
|
||||
Lesotho,LS
|
||||
Liberia,LR
|
||||
Libya,LY
|
||||
Liechtenstein,LI
|
||||
Lithuania,LT
|
||||
Luxembourg,LU
|
||||
Macao,MO
|
||||
"Macedonia, the Former Yugoslav Republic of",MK
|
||||
Madagascar,MG
|
||||
Malawi,MW
|
||||
Malaysia,MY
|
||||
Maldives,MV
|
||||
Mali,ML
|
||||
Malta,MT
|
||||
Marshall Islands,MH
|
||||
Martinique,MQ
|
||||
Mauritania,MR
|
||||
Mauritius,MU
|
||||
Mayotte,YT
|
||||
Mexico,MX
|
||||
"Micronesia, Federated States of",FM
|
||||
"Moldova, Republic of",MD
|
||||
Monaco,MC
|
||||
Mongolia,MN
|
||||
Montenegro,ME
|
||||
Montserrat,MS
|
||||
Morocco,MA
|
||||
Mozambique,MZ
|
||||
Myanmar,MM
|
||||
Namibia,NA
|
||||
Nauru,NR
|
||||
Nepal,NP
|
||||
Netherlands,NL
|
||||
New Caledonia,NC
|
||||
New Zealand,NZ
|
||||
Nicaragua,NI
|
||||
Niger,NE
|
||||
Nigeria,NG
|
||||
Niue,NU
|
||||
Norfolk Island,NF
|
||||
Northern Mariana Islands,MP
|
||||
Norway,NO
|
||||
Oman,OM
|
||||
Pakistan,PK
|
||||
Palau,PW
|
||||
"Palestine, State of",PS
|
||||
Panama,PA
|
||||
Papua New Guinea,PG
|
||||
Paraguay,PY
|
||||
Peru,PE
|
||||
Philippines,PH
|
||||
Pitcairn,PN
|
||||
Poland,PL
|
||||
Portugal,PT
|
||||
Puerto Rico,PR
|
||||
Qatar,QA
|
||||
Réunion,RE
|
||||
Romania,RO
|
||||
Russian Federation,RU
|
||||
Rwanda,RW
|
||||
Saint Barthélemy,BL
|
||||
"Saint Helena, Ascension and Tristan da Cunha",SH
|
||||
Saint Kitts and Nevis,KN
|
||||
Saint Lucia,LC
|
||||
Saint Martin (French part),MF
|
||||
Saint Pierre and Miquelon,PM
|
||||
Saint Vincent and the Grenadines,VC
|
||||
Samoa,WS
|
||||
San Marino,SM
|
||||
Sao Tome and Principe,ST
|
||||
Saudi Arabia,SA
|
||||
Senegal,SN
|
||||
Serbia,RS
|
||||
Seychelles,SC
|
||||
Sierra Leone,SL
|
||||
Singapore,SG
|
||||
Sint Maarten (Dutch part),SX
|
||||
Slovakia,SK
|
||||
Slovenia,SI
|
||||
Solomon Islands,SB
|
||||
Somalia,SO
|
||||
South Africa,ZA
|
||||
South Georgia and the South Sandwich Islands,GS
|
||||
South Sudan,SS
|
||||
Spain,ES
|
||||
Sri Lanka,LK
|
||||
Sudan,SD
|
||||
Suriname,SR
|
||||
Svalbard and Jan Mayen,SJ
|
||||
Swaziland,SZ
|
||||
Sweden,SE
|
||||
Switzerland,CH
|
||||
Syrian Arab Republic,SY
|
||||
"Taiwan, Province of China",TW
|
||||
Tajikistan,TJ
|
||||
"Tanzania, United Republic of",TZ
|
||||
Thailand,TH
|
||||
Timor-Leste,TL
|
||||
Togo,TG
|
||||
Tokelau,TK
|
||||
Tonga,TO
|
||||
Trinidad and Tobago,TT
|
||||
Tunisia,TN
|
||||
Turkey,TR
|
||||
Turkmenistan,TM
|
||||
Turks and Caicos Islands,TC
|
||||
Tuvalu,TV
|
||||
Uganda,UG
|
||||
Ukraine,UA
|
||||
United Arab Emirates,AE
|
||||
United Kingdom,GB
|
||||
United States,US
|
||||
United States Minor Outlying Islands,UM
|
||||
Uruguay,UY
|
||||
Uzbekistan,UZ
|
||||
Vanuatu,VU
|
||||
"Venezuela, Bolivarian Republic of",VE
|
||||
Viet Nam,VN
|
||||
"Virgin Islands, British",VG
|
||||
"Virgin Islands, U.S.",VI
|
||||
Wallis and Futuna,WF
|
||||
Western Sahara,EH
|
||||
Yemen,YE
|
||||
Zambia,ZM
|
||||
Zimbabwe,ZW
|
|
@ -0,0 +1,250 @@
|
||||
Name,Code
|
||||
Afghanistan,AF
|
||||
Åland Islands,AX
|
||||
Albania,AL
|
||||
Algeria,DZ
|
||||
American Samoa,AS
|
||||
Andorra,AD
|
||||
Angola,AO
|
||||
Anguilla,AI
|
||||
Antarctica,AQ
|
||||
Antigua and Barbuda,AG
|
||||
Argentina,AR
|
||||
Armenia,AM
|
||||
Aruba,AW
|
||||
Australia,AU
|
||||
Austria,AT
|
||||
Azerbaijan,AZ
|
||||
Bahamas,BS
|
||||
Bahrain,BH
|
||||
Bangladesh,BD
|
||||
Barbados,BB
|
||||
Belarus,BY
|
||||
Belgium,BE
|
||||
Belize,BZ
|
||||
Benin,BJ
|
||||
Bermuda,BM
|
||||
Bhutan,BT
|
||||
"Bolivia, Plurinational State of",BO
|
||||
"Bonaire, Sint Eustatius and Saba",BQ
|
||||
Bosnia and Herzegovina,BA
|
||||
Botswana,BW
|
||||
Bouvet Island,BV
|
||||
Brazil,BR
|
||||
British Indian Ocean Territory,IO
|
||||
Brunei Darussalam,BN
|
||||
Bulgaria,BG
|
||||
Burkina Faso,BF
|
||||
Burundi,BI
|
||||
Cambodia,KH
|
||||
Cameroon,CM
|
||||
Canada,CA
|
||||
Cape Verde,CV
|
||||
Cayman Islands,KY
|
||||
Central African Republic,CF
|
||||
Chad,TD
|
||||
Chile,CL
|
||||
China,CN
|
||||
Christmas Island,CX
|
||||
Cocos (Keeling) Islands,CC
|
||||
Colombia,CO
|
||||
Comoros,KM
|
||||
Congo,CG
|
||||
"Congo, the Democratic Republic of the",CD
|
||||
Cook Islands,CK
|
||||
Costa Rica,CR
|
||||
Côte d'Ivoire,CI
|
||||
Croatia,HR
|
||||
Cuba,CU
|
||||
Curaçao,CW
|
||||
Cyprus,CY
|
||||
Czech Republic,CZ
|
||||
Denmark,DK
|
||||
Djibouti,DJ
|
||||
Dominica,DM
|
||||
Dominican Republic,DO
|
||||
Ecuador,EC
|
||||
Egypt,EG
|
||||
El Salvador,SV
|
||||
Equatorial Guinea,GQ
|
||||
Eritrea,ER
|
||||
Estonia,EE
|
||||
Ethiopia,ET
|
||||
Falkland Islands (Malvinas),FK
|
||||
Faroe Islands,FO
|
||||
Fiji,FJ
|
||||
Finland,FI
|
||||
France,FR
|
||||
French Guiana,GF
|
||||
French Polynesia,PF
|
||||
French Southern Territories,TF
|
||||
Gabon,GA
|
||||
Gambia,GM
|
||||
Georgia,GE
|
||||
Germany,DE
|
||||
Ghana,GH
|
||||
Gibraltar,GI
|
||||
Greece,GR
|
||||
Greenland,GL
|
||||
Grenada,GD
|
||||
Guadeloupe,GP
|
||||
Guam,GU
|
||||
Guatemala,GT
|
||||
Guernsey,GG
|
||||
Guinea,GN
|
||||
Guinea-Bissau,GW
|
||||
Guyana,GY
|
||||
Haiti,HT
|
||||
Heard Island and McDonald Islands,HM
|
||||
Holy See (Vatican City State),VA
|
||||
Honduras,HN
|
||||
Hong Kong,HK
|
||||
Hungary,HU
|
||||
Iceland,IS
|
||||
India,IN
|
||||
Indonesia,ID
|
||||
"Iran, Islamic Republic of",IR
|
||||
Iraq,IQ
|
||||
Ireland,IE
|
||||
Isle of Man,IM
|
||||
Israel,IL
|
||||
Italy,IT
|
||||
Jamaica,JM
|
||||
Japan,JP
|
||||
Jersey,JE
|
||||
Jordan,JO
|
||||
Kazakhstan,KZ
|
||||
Kenya,KE
|
||||
Kiribati,KI
|
||||
"Korea, Democratic People's Republic of",KP
|
||||
"Korea, Republic of",KR
|
||||
Kuwait,KW
|
||||
Kyrgyzstan,KG
|
||||
Lao People's Democratic Republic,LA
|
||||
Latvia,LV
|
||||
Lebanon,LB
|
||||
Lesotho,LS
|
||||
Liberia,LR
|
||||
Libya,LY
|
||||
Liechtenstein,LI
|
||||
Lithuania,LT
|
||||
Luxembourg,LU
|
||||
Macao,MO
|
||||
"Macedonia, the Former Yugoslav Republic of",MK
|
||||
Madagascar,MG
|
||||
Malawi,MW
|
||||
Malaysia,MY
|
||||
Maldives,MV
|
||||
Mali,ML
|
||||
Malta,MT
|
||||
Marshall Islands,MH
|
||||
Martinique,MQ
|
||||
Mauritania,MR
|
||||
Mauritius,MU
|
||||
Mayotte,YT
|
||||
Mexico,MX
|
||||
"Micronesia, Federated States of",FM
|
||||
"Moldova, Republic of",MD
|
||||
Monaco,MC
|
||||
Mongolia,MN
|
||||
Montenegro,ME
|
||||
Montserrat,MS
|
||||
Morocco,MA
|
||||
Mozambique,MZ
|
||||
Myanmar,MM
|
||||
Namibia,NA
|
||||
Nauru,NR
|
||||
Nepal,NP
|
||||
Netherlands,NL
|
||||
New Caledonia,NC
|
||||
New Zealand,NZ
|
||||
Nicaragua,NI
|
||||
Niger,NE
|
||||
Nigeria,NG
|
||||
Niue,NU
|
||||
Norfolk Island,NF
|
||||
Northern Mariana Islands,MP
|
||||
Norway,NO
|
||||
Oman,OM
|
||||
Pakistan,PK
|
||||
Palau,PW
|
||||
"Palestine, State of",PS
|
||||
Panama,PA
|
||||
Papua New Guinea,PG
|
||||
Paraguay,PY
|
||||
Peru,PE
|
||||
Philippines,PH
|
||||
Pitcairn,PN
|
||||
Poland,PL
|
||||
Portugal,PT
|
||||
Puerto Rico,PR
|
||||
Qatar,QA
|
||||
Réunion,RE
|
||||
Romania,RO
|
||||
Russian Federation,RU
|
||||
Rwanda,RW
|
||||
Saint Barthélemy,BL
|
||||
"Saint Helena, Ascension and Tristan da Cunha",SH
|
||||
Saint Kitts and Nevis,KN
|
||||
Saint Lucia,LC
|
||||
Saint Martin (French part),MF
|
||||
Saint Pierre and Miquelon,PM
|
||||
Saint Vincent and the Grenadines,VC
|
||||
Samoa,WS
|
||||
San Marino,SM
|
||||
Sao Tome and Principe,ST
|
||||
Saudi Arabia,SA
|
||||
Senegal,SN
|
||||
Serbia,RS
|
||||
Seychelles,SC
|
||||
Sierra Leone,SL
|
||||
Singapore,SG
|
||||
Sint Maarten (Dutch part),SX
|
||||
Slovakia,SK
|
||||
Slovenia,SI
|
||||
Solomon Islands,SB
|
||||
Somalia,SO
|
||||
South Africa,ZA
|
||||
South Georgia and the South Sandwich Islands,GS
|
||||
South Sudan,SS
|
||||
Spain,ES
|
||||
Sri Lanka,LK
|
||||
Sudan,SD
|
||||
Suriname,SR
|
||||
Svalbard and Jan Mayen,SJ
|
||||
Swaziland,SZ
|
||||
Sweden,SE
|
||||
Switzerland,CH
|
||||
Syrian Arab Republic,SY
|
||||
"Taiwan, Province of China",TW
|
||||
Tajikistan,TJ
|
||||
"Tanzania, United Republic of",TZ
|
||||
Thailand,TH
|
||||
Timor-Leste,TL
|
||||
Togo,TG
|
||||
Tokelau,TK
|
||||
Tonga,TO
|
||||
Trinidad and Tobago,TT
|
||||
Tunisia,TN
|
||||
Turkey,TR
|
||||
Turkmenistan,TM
|
||||
Turks and Caicos Islands,TC
|
||||
Tuvalu,TV
|
||||
Uganda,UG
|
||||
Ukraine,UA
|
||||
United Arab Emirates,AE
|
||||
United Kingdom,GB
|
||||
United States,US
|
||||
United States Minor Outlying Islands,UM
|
||||
Uruguay,UY
|
||||
Uzbekistan,UZ
|
||||
Vanuatu,VU
|
||||
"Venezuela, Bolivarian Republic of",VE
|
||||
Viet Nam,VN
|
||||
"Virgin Islands, British",VG
|
||||
"Virgin Islands, U.S.",VI
|
||||
Wallis and Futuna,WF
|
||||
Western Sahara,EH
|
||||
Yemen,YE
|
||||
Zambia,ZM
|
||||
Zimbabwe,ZW
|
|
38
third/semester1/CT326_Programming_III/assignments/assignment4/assignment4/.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
3
third/semester1/CT326_Programming_III/assignments/assignment4/assignment4/.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
7
third/semester1/CT326_Programming_III/assignments/assignment4/assignment4/.idea/encodings.xml
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
14
third/semester1/CT326_Programming_III/assignments/assignment4/assignment4/.idea/misc.xml
generated
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
After Width: | Height: | Size: 431 KiB |
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>assignment4</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
</project>
|
After Width: | Height: | Size: 112 KiB |
After Width: | Height: | Size: 8.0 KiB |
After Width: | Height: | Size: 280 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 150 KiB |
@ -0,0 +1,13 @@
|
||||
1., "Personal Holloway", 3:23
|
||||
2., "Greedy Fly", 4:30
|
||||
3., "Swallowed", 4:51
|
||||
4., "Insect Kin", 4:27
|
||||
5., "Cold Contagious", 6:00
|
||||
6., "A Tendency to Start Fires", 4:04
|
||||
7., "Mouth", 5:45
|
||||
8., "Straight No Chaser", 4:02
|
||||
9., "History", 4:17
|
||||
10., "Synapse", 4:52
|
||||
11., "Communicator", 4:25
|
||||
12., "Bonedriven", 4:32
|
||||
13., "Distant Voices", 6:39
|
@ -0,0 +1,11 @@
|
||||
1., "Negative Vibes", 4:44
|
||||
2., "Ghosts of Overdoses", 4:41
|
||||
3., "It's All Good", 4:21
|
||||
4., "Factories", 5:17
|
||||
5., "Jar Song", 5:03
|
||||
6., "Celtic Tiger", 5:13
|
||||
7., "Apple of My Eye", 3:43
|
||||
8., "Industrial School", 5:27
|
||||
9., "Great Gaels of Ireland", 5:21
|
||||
10., "Marching Season Siege", 3:24
|
||||
11., "Seize the Day" (hidden track), 4:12
|
@ -0,0 +1,11 @@
|
||||
1., "Babooshka", 3:20
|
||||
2., "Delius (Song of Summer)", 2:51
|
||||
3., "Blow Away (For Bill)", 3:33
|
||||
4., "All We Ever Look For", 3:47
|
||||
5., "Egypt", 4:10
|
||||
6., "The Wedding List", 4:15
|
||||
7., "Violin", 3:15
|
||||
8., "The Infant Kiss", 2:50
|
||||
9., "Night Scented Stock", 0:51
|
||||
10., "Army Dreamers", 2:55
|
||||
11., "Breathing", 5:29
|
@ -0,0 +1,10 @@
|
||||
1, Nasty, 4:40
|
||||
2, O.D., 3:22
|
||||
3, Death Note, 3:40
|
||||
4, Bad, 3:55
|
||||
5, Drown, 3:54
|
||||
6, Saucy, 3:04
|
||||
7, Yas, 3:22
|
||||
8, So Strange, 4:00
|
||||
9, Rich Kids, 3:21
|
||||
10, G.O.A.T., 3:35
|
@ -0,0 +1,11 @@
|
||||
1., "Here Comes the Sun", 3:05
|
||||
2., "Because", 2:45
|
||||
3., "You Never Give Me Your Money", 4:03
|
||||
4., "Sun King", 2:26
|
||||
5., "Mean Mr. Mustard", 1:06
|
||||
6., "Polythene Pam", 1:13
|
||||
7., "She Came In Through the Bathroom Window", 1:58
|
||||
8., "Golden Slumbers", 1:31
|
||||
9., "Carry That Weight", 1:36
|
||||
10., "The End", 2:05
|
||||
11., "Her Majesty", 0:23
|
@ -0,0 +1,5 @@
|
||||
Bush, Razorblade Suitcase, covers/Razorblade_suitcase.jpg, library/bush_razorblade_suitcase.txt
|
||||
Kate Bush, Never for Ever, covers/Katebushneverforever.png, library/kate_bush_never_for_ever.txt
|
||||
Damien Dempsey, Seize the Day, covers/Damien_Dempsey_-_Seize_the_Day.jpg, library/damien_dempsey_seize_the_day.txt
|
||||
Beatles, Abbey Road, covers/Beatles_-_Abbey_Road.jpg, library/the_beatles_abbey_road.txt
|
||||
Polyphia, New Levels New Devils, covers/polyphia_new_levels_new_devils.jpeg, library/new_levels_new_devils.txt
|
@ -0,0 +1,120 @@
|
||||
// Name: Andrew Hayes
|
||||
// Student ID: 21321503
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* class to represent an Album object and its tracks
|
||||
*/
|
||||
public class Album {
|
||||
private String artist; // the name of the artist
|
||||
private String title; // the title of the album
|
||||
private String pathToCover; // the path to the cover image of the album
|
||||
private String pathToTrackList; // the path to the track list text file for the album
|
||||
private ArrayList<Track> tracks = new ArrayList<>(); // arraylist of all the tracks on the album
|
||||
|
||||
/**
|
||||
* constructor for Album objects
|
||||
* @param artist String of the artist's name
|
||||
* @param title String of the title of the album
|
||||
* @param pathToCover String of the filepath to the cover image
|
||||
* @param pathToTrackList String of the filepath to the list of tracks on the album
|
||||
*/
|
||||
public Album(String artist, String title, String pathToCover, String pathToTrackList) throws IOException {
|
||||
this.artist = artist;
|
||||
this.title = title;
|
||||
this.pathToCover = pathToCover;
|
||||
this.pathToTrackList = pathToTrackList;
|
||||
|
||||
// reading the trackList file and adding a Track object to the ArrayList for each line in the file
|
||||
BufferedReader reader = new BufferedReader(new FileReader(pathToTrackList)); // not catching FileNotFoundException as entire method should fail if the trackList file is not accessible
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
String[] columns = line.split(",");
|
||||
tracks.add(new Track(columns[0].strip(), columns[1].strip(), columns[2].strip())); // trimming whitespace from the ends of each column read in
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* getter for the artist's name
|
||||
* @return String artist
|
||||
*/
|
||||
public String getArtist() {
|
||||
return artist;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for the artist's name
|
||||
* @param artist String of the artist's name
|
||||
*/
|
||||
public void setArtist(String artist) {
|
||||
this.artist = artist;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter for the title
|
||||
* @return String title of the album
|
||||
*/
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for the title
|
||||
* @param title String title of the album
|
||||
*/
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter for pathToCover
|
||||
* @return String path to the cover image
|
||||
*/
|
||||
public String getPathToCover() {
|
||||
return pathToCover;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for pathToCover
|
||||
* @param pathToCover String of the filepath to the cover image
|
||||
*/
|
||||
public void setPathToCover(String pathToCover) {
|
||||
this.pathToCover = pathToCover;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter for trackList
|
||||
* @return String of the filepath to the trackList
|
||||
*/
|
||||
public String getPathToTrackList() {
|
||||
return pathToTrackList;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for trackList
|
||||
* @param pathToTrackList String of the filepath to the trackLists
|
||||
*/
|
||||
public void setPathToTrackList(String pathToTrackList) {
|
||||
this.pathToTrackList = pathToTrackList;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter for tracks
|
||||
* @return Array of Track objects
|
||||
*/
|
||||
public ArrayList<Track> getTracks() {
|
||||
return tracks;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for tracks
|
||||
* @param tracks array of Track objects
|
||||
*/
|
||||
public void setTracks(ArrayList<Track> tracks) {
|
||||
this.tracks = tracks;
|
||||
}
|
||||
}
|
@ -0,0 +1,181 @@
|
||||
// Name: Andrew Hayes
|
||||
// Student ID: 21321503
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Application class for the Music Library application
|
||||
*/
|
||||
public class MusicLibrary extends JFrame {
|
||||
private String libraryDirectory = "resources/"; // directory that the library files are in
|
||||
private String libraryFileName = "music_library.txt"; // name of the music libary file
|
||||
private ArrayList<Album> albums = new ArrayList<>();
|
||||
private ActionListener actionListener; // action listener for the buttons in this application
|
||||
|
||||
/**
|
||||
* constructor for the Music Library application
|
||||
*/
|
||||
public MusicLibrary() {
|
||||
super("Music Library"); // set window title
|
||||
|
||||
// make JFrame fill the screen
|
||||
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
setSize(screenSize.width, screenSize.height);
|
||||
|
||||
// using border layout to position JPanels easily
|
||||
Container container = getContentPane();
|
||||
container.setLayout(new BorderLayout());
|
||||
|
||||
// panel to show the list of albums
|
||||
JPanel albumPanel = new JPanel();
|
||||
|
||||
// action listener to handle what happens when buttons are clicked
|
||||
actionListener = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
// if the actionCommand was to show the albumPanel (i.e., "back" button was pressed on the trackPanel)
|
||||
if (event.getActionCommand().equals("showAlbumPanel")) {
|
||||
// removing everything from the container
|
||||
container.removeAll();
|
||||
|
||||
// cleaning screen
|
||||
container.revalidate();
|
||||
container.repaint();
|
||||
|
||||
// adding albumPanel to container
|
||||
container.add(albumPanel, BorderLayout.CENTER);
|
||||
}
|
||||
// else if the actionCommand was anything other than showAlbumPanel, i.e. it was an album being clicked, hide it and display the tracklist of the selected album
|
||||
else {
|
||||
// hiding the albumPanel
|
||||
container.remove(albumPanel);
|
||||
|
||||
// cleaning screen
|
||||
container.revalidate();
|
||||
container.repaint();
|
||||
|
||||
// displaying album contents (trackPanel)
|
||||
container.add(generateTrackPanel(albums.get(Integer.parseInt(event.getActionCommand()))), BorderLayout.CENTER);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// loading the albums into the arraylist
|
||||
try {
|
||||
albums = loadAlbums(libraryDirectory + libraryFileName);
|
||||
}
|
||||
// display error message if the music library file could not be read successfully
|
||||
catch (IOException e) {
|
||||
albumPanel.add(new JLabel("The music library file could not be read successfully!!!"));
|
||||
}
|
||||
|
||||
// iterating over each album and adding it to the GUI interface as a button
|
||||
for (int i = 0; i < albums.size(); i++) { // using iteration instead of for-each so that we can set the actionCommand of the button to the value of i
|
||||
Album album = albums.get(i);
|
||||
|
||||
// attempting to create a button with the album cover as the icon
|
||||
try {
|
||||
// reading in image, scaling it, turning it into an icond, and adding it to the album button
|
||||
Image coverImage = ImageIO.read(new File(libraryDirectory + album.getPathToCover())).getScaledInstance(200, 200, Image.SCALE_SMOOTH);
|
||||
ImageIcon icon = new ImageIcon(coverImage);
|
||||
JButton button = new JButton(album.getTitle(), icon); // including album title in button to make it easier to use
|
||||
// JButton button = new JButton(icon); // would give same appearancec as in assignment spec
|
||||
|
||||
// make clicking the button use an action command that references the album's position in the arraylist
|
||||
button.setActionCommand(String.valueOf(i));
|
||||
button.addActionListener(actionListener);
|
||||
|
||||
albumPanel.add(button);
|
||||
}
|
||||
// if the album cover cannot be found, just put a text button in its place
|
||||
catch (IOException e) {
|
||||
JButton button = new JButton(album.getTitle());
|
||||
|
||||
// make clicking the button use an action command that references the album's position in the arraylist
|
||||
button.setActionCommand(String.valueOf(i));
|
||||
button.addActionListener(actionListener);
|
||||
|
||||
albumPanel.add(button);
|
||||
}
|
||||
}
|
||||
|
||||
// display the album panel
|
||||
container.add(albumPanel, BorderLayout.CENTER);
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* method to load all the Albums into memory as an ArrayList of Albums
|
||||
* @param libraryPath String representing the file path to the music_library.txt file
|
||||
* @throws IOException if reading the albums in from the library file and/or instantiating them fails
|
||||
*/
|
||||
public ArrayList<Album> loadAlbums(String libraryPath) throws IOException {
|
||||
// it's not really necessary that libraryPath be passed to this method from a design perspective, as they are both members of the MusicLibrary object class
|
||||
// however, this makes the method more re-usable if we ever want to load albums from outside of this class
|
||||
|
||||
ArrayList<Album> albums = new ArrayList<>(); // ArrayList of Album objects to be returned
|
||||
|
||||
// instantiating an Album object for each line in the library file
|
||||
BufferedReader reader = new BufferedReader(new FileReader(libraryPath)); // not catching FileNotFoundException as entire method should fail if the library file is not accessible
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
String[] columns = line.split(",");
|
||||
|
||||
// creating the album object and adding it to the ArrayList
|
||||
albums.add(new Album(columns[0].trim(), columns[1].trim(), columns[2].trim(), libraryDirectory + columns[3].trim())); // trimming whitespace from the ends of each column read in
|
||||
}
|
||||
|
||||
return albums;
|
||||
}
|
||||
|
||||
/**
|
||||
* method to generate a JPanel containing a JTable of all the tracks for a given Album
|
||||
* @param album the Album for which we are generating a JTable of tracks
|
||||
* @return a JPanel containing a JTable of all the tracks for a given Album
|
||||
*/
|
||||
public JPanel generateTrackPanel(Album album) {
|
||||
JPanel trackPanel = new JPanel(new BorderLayout()); // using border layout so the table can be easily aligned above the "back" button
|
||||
|
||||
ArrayList<Track> tracks = album.getTracks();
|
||||
|
||||
// columns to be displayed in JTable
|
||||
String[][] data = new String[tracks.size()][3];
|
||||
|
||||
// filling up columns to be displayed in JTable
|
||||
for (int i = 0; i < tracks.size(); i++) {
|
||||
// track number, track title, and track duration
|
||||
data[i] = new String[]{tracks.get(i).getTrackNumber(), tracks.get(i).getTitle(), tracks.get(i).getDuration()};
|
||||
}
|
||||
|
||||
// adding the JTable of tracks to the center of the panel
|
||||
String[] columnNames = {"No.", "Track Title", "Length"};
|
||||
JTable table = new JTable(data, columnNames);
|
||||
table.setEnabled(false); // disable user interaction with the table so they can't edit it
|
||||
trackPanel.add(new JScrollPane(table), BorderLayout.CENTER);
|
||||
|
||||
JButton button = new JButton("Back");
|
||||
|
||||
// make clicking the button use an action command that references the album's position in the arraylist
|
||||
button.addActionListener(actionListener);
|
||||
button.setActionCommand("showAlbumPanel");
|
||||
|
||||
// adding the back button to the bottom of the panel, underneath the table
|
||||
trackPanel.add(button, BorderLayout.SOUTH);
|
||||
|
||||
return trackPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* main method
|
||||
* @param args (none)
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
MusicLibrary application = new MusicLibrary();
|
||||
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
// Name: Andrew Hayes
|
||||
// Student ID: 21321503
|
||||
|
||||
/**
|
||||
* class to represent a Track on an Album
|
||||
* not really necessary for this assignmenet, could've just stored tracks as Strings or something, but i feel that this is a more "correct" OOP-like approach
|
||||
*/
|
||||
public class Track {
|
||||
private String trackNumber; // storing as String as we never manipulate it arithmetically, and allows non-integer numberings such as A1 and B1 for A-sides and B-sides
|
||||
private String title; // title of track
|
||||
private String duration; // duration can also be stored as String as we never manipulate it. if manipulation was being done, java.time.Duration would be a better choice
|
||||
|
||||
/**
|
||||
* constructor for Track objects
|
||||
* @param trackNumber the number of the track as a String
|
||||
* @param title the name of the track/song
|
||||
* @param duration the length of the song as a String
|
||||
*/
|
||||
public Track(String trackNumber, String title, String duration) {
|
||||
this.trackNumber = trackNumber;
|
||||
this.title = title;
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter method for the number of the track
|
||||
* @return the number of the track as a String
|
||||
*/
|
||||
public String getTrackNumber() {
|
||||
return trackNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter method for the number of the track
|
||||
* @param trackNumber a String representing the number of the track
|
||||
*/
|
||||
public void setTrackNumber(String trackNumber) {
|
||||
this.trackNumber = trackNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter method for the title of the track
|
||||
* @return the name of the track, as a String
|
||||
*/
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter method for the title of the track
|
||||
* @param title a String object representing the name of the track
|
||||
*/
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter method for the duration of the track
|
||||
* @return the duration of the track, as a String object
|
||||
*/
|
||||
public String getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter method for the duration of the track
|
||||
* @param duration a String object representing the duration of the track
|
||||
*/
|
||||
public void setDuration(String duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 17 KiB |
38
third/semester1/CT326_Programming_III/assignments/assignment5/CT326-Assignment-5/.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
3
third/semester1/CT326_Programming_III/assignments/assignment5/CT326-Assignment-5/.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
13
third/semester1/CT326_Programming_III/assignments/assignment5/CT326-Assignment-5/.idea/misc.xml
generated
Normal file
@ -0,0 +1,13 @@
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
After Width: | Height: | Size: 122 KiB |
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>CT326-Assignment-5</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.joda</groupId>
|
||||
<artifactId>joda-money</artifactId>
|
||||
<version>1.0.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,117 @@
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.joda.money.Money;
|
||||
|
||||
/**
|
||||
* Account class for CT326 Assignment 5 (23/24)
|
||||
* @author Adrian Clear
|
||||
*/
|
||||
public class Account implements Serializable {
|
||||
|
||||
// Define serialVersionUID which is used during object deserialization to verify that the sender and receiver of a serialized
|
||||
// object have loaded classes for that object that are compatible - will throw InvalidClassException if not compatible
|
||||
// IDEs will often auto generate this value for you when creating new Java classes
|
||||
|
||||
private static final long serialVersionUID = 202010191519L;
|
||||
|
||||
private int accnum;
|
||||
private Money balance;
|
||||
|
||||
// Date and Time account object was first created or loaded from storage
|
||||
private LocalDateTime activated;
|
||||
|
||||
/**
|
||||
* Creates an account with a given account number and balance.
|
||||
* @param accnum the account number
|
||||
* @param balance the initial balance of the account
|
||||
* @throws NegativeBalanceException if the initial balance is negative
|
||||
*/
|
||||
public Account (int accnum, Money balance) throws NegativeBalanceException {
|
||||
setBalance(balance);
|
||||
this.accnum = accnum;
|
||||
activated = LocalDateTime.now();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a deposit to the account of the given amount
|
||||
* @param amount the amount to deposit
|
||||
*/
|
||||
public synchronized void makeDeposit(Money amount) throws NegativeBalanceException { // should never throw this Exception, only attempt to setBalance if amount is greater than 0
|
||||
if(amount.isGreaterThan(Money.of(CurrencyUnit.EUR, 0)) ) {
|
||||
setBalance(balance.plus(amount));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a withdrawal from the account of the given amount
|
||||
* @param amount the amount to withdraw
|
||||
* @throws InsufficientFundsException if the amount to withdraw is greater than the current balance
|
||||
*/
|
||||
public synchronized void makeWithdrawal(Money amount) throws InsufficientFundsException {
|
||||
try {
|
||||
setBalance(balance.minus(amount));
|
||||
} catch (NegativeBalanceException e) {
|
||||
throw new InsufficientFundsException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the balance of the account to the given amount.
|
||||
* @param balance the new balance of the account
|
||||
* @throws NegativeBalanceException if the balance is negative
|
||||
*/
|
||||
private synchronized void setBalance(Money balance) throws NegativeBalanceException {
|
||||
if (balance.isLessThan(Money.of(CurrencyUnit.EUR, 0))) throw new NegativeBalanceException("Negative Balance Not Allowed!");
|
||||
this.balance = balance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the balance of the account
|
||||
* @return the balance of the account
|
||||
*/
|
||||
public Money getBalance() {
|
||||
return balance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the account number of the account
|
||||
* @return the account number of the account
|
||||
*/
|
||||
public int getAccountNumber() {
|
||||
return accnum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the activation date of the account
|
||||
* @return the activation date of the account
|
||||
*/
|
||||
public LocalDateTime getActivated() {
|
||||
return activated;
|
||||
}
|
||||
|
||||
// This method is called when we are deserializing an instance of an Account object
|
||||
private void readObject(ObjectInputStream aInputStream) throws ClassNotFoundException,IOException {
|
||||
balance = (Money) aInputStream.readObject();
|
||||
accnum = aInputStream.readInt();
|
||||
// Reinitialise value for the LocalDateTime activated variable
|
||||
activated = LocalDateTime.now();
|
||||
}
|
||||
|
||||
// This method is called when we serialize an instance of an Account object
|
||||
private void writeObject(ObjectOutputStream aOutputStream) throws IOException {
|
||||
aOutputStream.writeObject(balance);
|
||||
aOutputStream.writeInt(accnum);
|
||||
// We don't write value for the LocalDateTime activated variable as we will reinitialise this when reloading the object
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("Account %d has a balance of %s.", accnum, balance);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,116 @@
|
||||
// Name: Andrew Hayes
|
||||
// ID: 21321503
|
||||
import org.joda.money.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* Class to represent a Bank and its Accounts
|
||||
* @author andrew
|
||||
*/
|
||||
public class Bank {
|
||||
private static Map<Integer, Account> accounts = new HashMap<>(); // key is the account's number
|
||||
private LinkedBlockingQueue<Transaction> transactions = new LinkedBlockingQueue<>();
|
||||
|
||||
/**
|
||||
* method to add an Account to the Bank
|
||||
* @param account the Account object to be added to the Bank
|
||||
*/
|
||||
public void addAccount(Account account) {
|
||||
accounts.put(account.getAccountNumber(), account);
|
||||
}
|
||||
|
||||
/**
|
||||
* method to return the Account identified by the supplied account number
|
||||
* @param accountNumber the number of the account to be returned
|
||||
* @return the account with the supplied accountNumber
|
||||
*/
|
||||
public Account getAccountByNumber(int accountNumber) {
|
||||
return accounts.get(accountNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* method to submit a Transaction to the queue to be processed
|
||||
* @param transaction the Transaction to be submitted to the queue
|
||||
*/
|
||||
public void submitTransaction(Transaction transaction) {
|
||||
try {
|
||||
transactions.put(transaction);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt(); // restore interrupted status
|
||||
e.printStackTrace(); // if a transaction fails to be submitted, fail gracefully so that the transaction can be tried again later
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* method to get the next Transaction from the queue for processing
|
||||
* @return the next Transaction in the queue
|
||||
*/
|
||||
public Transaction getNextTransaction() throws InterruptedException {
|
||||
// retrieve the head of the queue, waiting up to 5 seconds for an element to become available, otherwise returning null
|
||||
return transactions.poll(5, TimeUnit.SECONDS); // not catching InterruptedExceptions here, should be caught in the calling method
|
||||
}
|
||||
|
||||
/**
|
||||
* method to print out the details of each account in the bank (account number and balance)
|
||||
*/
|
||||
public static void printAccountsDetails() {
|
||||
for (Account account : accounts.values()) {
|
||||
System.out.println(account); // using given toString() method of the Account class
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* method to return a collection of all the Account numbers in the Bank
|
||||
* @return a Set of all the Integer account numbers in the Bank
|
||||
*/
|
||||
public ArrayList<Integer> getAccountNumbers() {
|
||||
return new ArrayList<>(accounts.keySet());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* main method of the Bank class
|
||||
* @param args No arguments used
|
||||
*/
|
||||
public static void main(String[] args) throws NegativeBalanceException {
|
||||
// declare and instantiate a bank object
|
||||
Bank bank = new Bank();
|
||||
|
||||
// create and add three account instances to the bank with different starting balances
|
||||
bank.addAccount(new Account(1, Money.of(CurrencyUnit.EUR, 20_000.00)));
|
||||
bank.addAccount(new Account(2, Money.of(CurrencyUnit.EUR, 25_000.00)));
|
||||
bank.addAccount(new Account(3, Money.of(CurrencyUnit.EUR, 33_333.33)));
|
||||
|
||||
// declare and instantiate two TransactionProcessors
|
||||
TransactionProcessor TP1 = new TransactionProcessor("TP1", bank);
|
||||
TransactionProcessor TP2 = new TransactionProcessor("TP2", bank);
|
||||
|
||||
// declare and instantiate one RandomTransactionGenerator
|
||||
RandomTransactionGenerator rtg = new RandomTransactionGenerator(bank);
|
||||
|
||||
// execute the threads using a thread pool
|
||||
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(4);
|
||||
executorService.execute(rtg);
|
||||
executorService.execute(TP1);
|
||||
executorService.execute(TP2);
|
||||
|
||||
// shut down the transaction generator after 10 seconds
|
||||
executorService.schedule(
|
||||
() -> {
|
||||
rtg.stopGenerating();
|
||||
executorService.shutdown();
|
||||
}, 10, TimeUnit.SECONDS
|
||||
);
|
||||
|
||||
// waiting until all threads have finished to print account details
|
||||
try {
|
||||
if (executorService.awaitTermination(10, TimeUnit.MINUTES)) { // giving some arbitrarily long timeout to wait for threads to finish
|
||||
printAccountsDetails();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
// just printing stacktrace if exception thrown, no handling to be done
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* An exception representing the fact that an account has insufficient funds
|
||||
* for a given transaction.
|
||||
* @author Adrian Clear
|
||||
*/
|
||||
public class InsufficientFundsException extends Exception {
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
/**
|
||||
* An exception representing an instance where a negative balance is set to an account
|
||||
* @author Adrian Clear
|
||||
*/
|
||||
public class NegativeBalanceException extends Exception {
|
||||
public NegativeBalanceException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
// Name: Andrew Hayes
|
||||
// ID: 21321503
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Thread to randomly generate deposit and withdrawal transactions for random accounts
|
||||
* @author andrew
|
||||
*/
|
||||
public class RandomTransactionGenerator extends Thread {
|
||||
private Bank bank;
|
||||
private ArrayList<Integer> accountNumbers;
|
||||
public static final Transaction poisonPill = new Transaction(-1, 0);
|
||||
private boolean keepGenerating = true; // flag used to stop the thread
|
||||
|
||||
/**
|
||||
* Constructor for RandomTransactionGenerator objects
|
||||
* @param bank the Bank object with which the RandomTransactionGenerator is associated
|
||||
*/
|
||||
public RandomTransactionGenerator(Bank bank) {
|
||||
this.bank = bank;
|
||||
accountNumbers = bank.getAccountNumbers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread's run() method
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
// loop until stopped
|
||||
while (keepGenerating) {
|
||||
// sleep for a random amount of time between 0 and 1 seconds
|
||||
try {
|
||||
sleep((long) (Math.random() * 1000));
|
||||
} catch (InterruptedException e) {
|
||||
// if thread is interrupted, just break out of loop
|
||||
break;
|
||||
}
|
||||
|
||||
// pick account and transaction amount randomly
|
||||
int accountNumber = accountNumbers.get((int) (Math.random() * accountNumbers.size()));
|
||||
float amount = (float) ((Math.random() * 20_000) - 10_000);
|
||||
|
||||
// submit random transaction
|
||||
bank.submitTransaction(new Transaction(accountNumber, amount));
|
||||
}
|
||||
|
||||
// submit poison pill before exiting
|
||||
bank.submitTransaction(poisonPill);
|
||||
System.out.println("Transaction generator terminated");
|
||||
}
|
||||
|
||||
/**
|
||||
* method to stop the thread
|
||||
*/
|
||||
public void stopGenerating() {
|
||||
keepGenerating = false;
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* A class representing an account transaction for the CT326 Assignment 5 (23/24)
|
||||
* @author Adrian Clear
|
||||
*/
|
||||
public class Transaction {
|
||||
private float amount;
|
||||
private int accountNumber;
|
||||
|
||||
/**
|
||||
* Create a transaction for the Account with the given account number, of the given amount.
|
||||
* @param accNumber the account number of the transaction account
|
||||
* @param amount the amount to withdraw/deposit. A positive value represents a deposit, a negative value represents a withdrawal
|
||||
*/
|
||||
public Transaction(int accNumber, float amount) {
|
||||
this.accountNumber = accNumber;
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount of this transaction
|
||||
* @return the amount of the transaction
|
||||
*/
|
||||
public float getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the account number of the transaction
|
||||
* @return the account number of the transaction
|
||||
*/
|
||||
public int getAccountNumber() {
|
||||
return accountNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if(amount >= 0)
|
||||
return String.format("a deposit of %f to %d", amount, accountNumber);
|
||||
else
|
||||
return String.format("a withdrawal of %f from %d", amount, accountNumber);
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
// Name: Andrew Hayes
|
||||
// ID: 21321503
|
||||
import org.joda.money.Money;
|
||||
|
||||
/**
|
||||
* Thread class to process Transactions of a Bank
|
||||
* @author andrew
|
||||
*/
|
||||
public class TransactionProcessor extends Thread {
|
||||
private String name;
|
||||
private Bank bank;
|
||||
|
||||
// explicitly setting these values to 0 for readability, although they would default to 0 regardless
|
||||
// variables to keep a tally of how many withdrawals and deposits the object has made
|
||||
private int numWithdrawals = 0;
|
||||
private int numDeposits = 0;
|
||||
|
||||
/**
|
||||
* TransactionProcessor Constructor
|
||||
* @param name
|
||||
* @param bank
|
||||
*/
|
||||
public TransactionProcessor(String name, Bank bank) {
|
||||
this.name = name;
|
||||
this.bank = bank;
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread's run() method
|
||||
*/
|
||||
public void run() {
|
||||
// loop infinitely
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
try {
|
||||
// sleep for a random amount of time between 0 and 1 seconds before processing the next transaction
|
||||
sleep((long) (Math.random() * 1000));
|
||||
|
||||
// get transaction to process
|
||||
Transaction transaction = bank.getNextTransaction();
|
||||
|
||||
// finish executing if the thread has been closed (poison pill received) or 5 seconds has elapsed without a new transaction being received
|
||||
// if the transaction is `null` this is because bank.getNextTransaction() waited for 5 seconds without receiving a new transaction
|
||||
if (transaction == null || transaction.equals(RandomTransactionGenerator.poisonPill)) {
|
||||
break;
|
||||
}
|
||||
// otherwise, process the transaction
|
||||
else {
|
||||
Account account = bank.getAccountByNumber(transaction.getAccountNumber());
|
||||
float amount = transaction.getAmount();
|
||||
|
||||
// if the amount is positive, then it is a deposit
|
||||
// made the design choice to treat a transaction of amount 0 as a deposit because it still needs to be processed and 0 is a positive number
|
||||
if (amount >= 0) {
|
||||
System.out.printf("%s is processing a deposit of EUR %.2f to %d\n", name, amount, transaction.getAccountNumber());
|
||||
// only dealing in euros as specified
|
||||
account.makeDeposit(Money.parse(String.format("EUR %.2f", amount))); // ignoring decimals after the second place
|
||||
numDeposits++;
|
||||
}
|
||||
// if the amount is negative, then it is a deposit
|
||||
else {
|
||||
try {
|
||||
System.out.printf("%s is processing a withdrawal of EUR %.2f from %d\n", name, amount, transaction.getAccountNumber());
|
||||
account.makeWithdrawal(Money.parse(String.format("EUR %.2f", -amount)));
|
||||
|
||||
// if the above line fails due to an exception, the control flow will jump to the catch block and the following line will not be executed, and the failed withdrawal will not be counted
|
||||
numWithdrawals++;
|
||||
}
|
||||
catch (InsufficientFundsException e) { // abort transaction if funds are insufficient
|
||||
System.out.println("Transaction could not be processed due to insufficient funds");
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
// if the thread has been interrupted, just exit loop and return
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// print the TransactionProcessor's name and number of deposits and withdrawals processed
|
||||
System.out.printf("%s finished processing %d transactions, including %d deposits, and %d withdrawals\n", name, numWithdrawals + numDeposits, numDeposits, numWithdrawals);
|
||||
}
|
||||
}
|
45
third/semester1/CT326_Programming_III/exam_notes.txt
Normal file
@ -0,0 +1,45 @@
|
||||
- most code for gui questions
|
||||
- not expected to include @Override annotations in code
|
||||
- static imports are necessary
|
||||
- imports are not necessary
|
||||
- unless asked to use floats, just use ints even for stuff like Salaries because it's simpler
|
||||
- talked a lot about comparators
|
||||
|
||||
|
||||
|
||||
Intbuffer question answer:
|
||||
|
||||
public class IntBufferImp {
|
||||
private int values;
|
||||
private boolean available = false;
|
||||
|
||||
public int consume() {
|
||||
if (!available) {
|
||||
try {
|
||||
wait();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
available = false;
|
||||
notifyAll();
|
||||
return value;
|
||||
}
|
||||
|
||||
public void produce(int i) {
|
||||
if (available) {
|
||||
try {
|
||||
wait();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
value = i;
|
||||
notifyAll();
|
||||
available = true;
|
||||
}
|
||||
}
|
BIN
third/semester1/CT326_Programming_III/notes/CT326-Notes.pdf
Normal file
1344
third/semester1/CT326_Programming_III/notes/CT326-Notes.tex
Normal file
@ -0,0 +1,3 @@
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\PYG{k+kt}{int}\PYG{+w}{ }\PYG{n+nf}{compareTo}\PYG{p}{(}\PYG{n}{String}\PYG{+w}{ }\PYG{n}{anotherString}\PYG{p}{)}
|
||||
\end{Verbatim}
|
@ -0,0 +1,5 @@
|
||||
\begin{Verbatim}[commandchars=\\\{\},codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8\relax}]
|
||||
\PYG{k+kd}{public}\PYG{+w}{ }\PYG{k+kd}{interface} \PYG{n+nc}{Runnable}\PYG{+w}{ }\PYG{p}{\PYGZob{}}
|
||||
\PYG{+w}{ }\PYG{k+kd}{public}\PYG{+w}{ }\PYG{k+kt}{void}\PYG{+w}{ }\PYG{n+nf}{run}\PYG{p}{();}
|
||||
\PYG{p}{\PYGZcb{}}
|
||||
\end{Verbatim}
|
@ -0,0 +1,6 @@
|
||||
\begin{Verbatim}[commandchars=\\\{\},codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8\relax}]
|
||||
\PYG{n}{ptivate}\PYG{+w}{ }\PYG{k+kt}{void}\PYG{+w}{ }\PYG{n+nf}{writeObject}\PYG{p}{(}\PYG{n}{ObjectOutputStream}\PYG{+w}{ }\PYG{n}{s}\PYG{p}{)}\PYG{+w}{ }\PYG{k+kd}{throws}\PYG{+w}{ }\PYG{n}{IOException}\PYG{+w}{ }\PYG{p}{\PYGZob{}}
|
||||
\PYG{+w}{ }\PYG{n}{s}\PYG{p}{.}\PYG{n+na}{defaultWriteObject}\PYG{p}{();}
|
||||
\PYG{+w}{ }\PYG{c+c1}{// customised serialization code}
|
||||
\PYG{p}{\PYGZcb{}}
|
||||
\end{Verbatim}
|
@ -0,0 +1,7 @@
|
||||
\begin{Verbatim}[commandchars=\\\{\},codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8\relax}]
|
||||
\PYG{k+kn}{package}\PYG{+w}{ }\PYG{n+nn}{java.io}\PYG{p}{;}
|
||||
|
||||
\PYG{k+kd}{public}\PYG{+w}{ }\PYG{k+kd}{interface} \PYG{n+nc}{Serializable}\PYG{+w}{ }\PYG{p}{\PYGZob{}}
|
||||
\PYG{+w}{ }\PYG{c+c1}{// there's nothing in here!}
|
||||
\PYG{p}{\PYGZcb{};}
|
||||
\end{Verbatim}
|
@ -0,0 +1,8 @@
|
||||
\begin{Verbatim}[commandchars=\\\{\},codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8\relax}]
|
||||
\PYG{n}{String}\PYG{+w}{ }\PYG{n}{myString}\PYG{+w}{ }\PYG{o}{=}\PYG{+w}{ }\PYG{l+s}{\PYGZdq{}Hello world!\PYGZdq{}}\PYG{p}{;}
|
||||
\PYG{n}{String}\PYG{+w}{ }\PYG{n}{myString}\PYG{+w}{ }\PYG{o}{=}\PYG{+w}{ }\PYG{k}{new}\PYG{+w}{ }\PYG{n}{String}\PYG{p}{();}
|
||||
\PYG{k+kt}{char}\PYG{+w}{ }\PYG{o}{[]}\PYG{+w}{ }\PYG{n}{ct326Array}\PYG{+w}{ }\PYG{o}{=}\PYG{+w}{ }\PYG{p}{\PYGZob{}}\PYG{+w}{ }\PYG{err}{‘}\PYG{n}{C}\PYG{err}{\PYGZsq{}}\PYG{p}{,}\PYG{+w}{ }\PYG{err}{‘}\PYG{n}{T}\PYG{err}{\PYGZsq{}}\PYG{p}{,}\PYG{+w}{ }\PYG{err}{‘}\PYG{l+m+mi}{3}\PYG{err}{\PYGZsq{}}\PYG{p}{,}\PYG{+w}{ }\PYG{err}{‘}\PYG{l+m+mi}{2}\PYG{err}{\PYGZsq{}}\PYG{p}{,}\PYG{+w}{ }\PYG{err}{‘}\PYG{l+m+mi}{6}\PYG{err}{\PYGZsq{}}\PYG{+w}{ }\PYG{p}{\PYGZcb{};}
|
||||
\PYG{n}{String}\PYG{+w}{ }\PYG{n}{ct326String}\PYG{+w}{ }\PYG{o}{=}\PYG{+w}{ }\PYG{k}{new}\PYG{+w}{ }\PYG{n}{String}\PYG{p}{(}\PYG{n}{ct326Array}\PYG{p}{);}
|
||||
|
||||
\PYG{n}{String}\PYG{+w}{ }\PYG{n}{fs}\PYG{+w}{ }\PYG{o}{=}\PYG{+w}{ }\PYG{n}{tring}\PYG{p}{.}\PYG{n+na}{format}\PYG{p}{(}\PYG{l+s}{\PYGZdq{}The value of the float variable is \PYGZpc{}f, while the value of the integer variable is \PYGZpc{}d, and the string is \PYGZpc{}s\PYGZdq{}}\PYG{p}{,}\PYG{+w}{ }\PYG{n}{floatVar}\PYG{p}{,}\PYG{+w}{ }\PYG{n}{intVar}\PYG{p}{,}\PYG{+w}{ }\PYG{n}{stringVar}\PYG{p}{);}
|
||||
\end{Verbatim}
|
@ -0,0 +1,3 @@
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\PYG{n}{run}\PYG{p}{()}
|
||||
\end{Verbatim}
|
@ -0,0 +1,8 @@
|
||||
\begin{Verbatim}[commandchars=\\\{\},codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8\relax}]
|
||||
\PYG{k+kd}{class} \PYG{n+nc}{EnclosingClass}\PYG{+w}{ }\PYG{p}{\PYGZob{}}
|
||||
\PYG{+w}{ }\PYG{p}{...}
|
||||
\PYG{+w}{ }\PYG{k+kd}{class} \PYG{n+nc}{ANestedClass}\PYG{+w}{ }\PYG{p}{\PYGZob{}}
|
||||
\PYG{+w}{ }\PYG{p}{...}
|
||||
\PYG{+w}{ }\PYG{p}{\PYGZcb{}}
|
||||
\PYG{p}{\PYGZcb{}}
|
||||
\end{Verbatim}
|
@ -0,0 +1,12 @@
|
||||
\begin{Verbatim}[commandchars=\\\{\},codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8\relax}]
|
||||
\PYGZdl{} java Planet 175
|
||||
Your weight on MERCURY is 66.107583
|
||||
Your weight on VENUS is 158.374842
|
||||
Your weight on EARTH is 175.000000
|
||||
Your weight on MARS is 66.279007
|
||||
Your weight on JUPITER is 442.847567
|
||||
Your weight on SATURN is 186.552719
|
||||
Your weight on URANUS is 158.397260
|
||||
Your weight on NEPTUNE is 199.207413
|
||||
Your weight on PLUTO is 11.703031
|
||||
\end{Verbatim}
|
@ -0,0 +1,7 @@
|
||||
\begin{Verbatim}[commandchars=\\\{\},codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8\relax}]
|
||||
\PYG{k+kd}{private}\PYG{+w}{ }\PYG{k+kt}{void}\PYG{+w}{ }\PYG{n+nf}{readObject}\PYG{p}{(}\PYG{n}{ObjectInputStream}\PYG{+w}{ }\PYG{n}{s}\PYG{p}{)}\PYG{+w}{ }\PYG{k+kd}{throws}\PYG{+w}{ }\PYG{n}{IOException}\PYG{+w}{ }\PYG{p}{\PYGZob{}}
|
||||
\PYG{+w}{ }\PYG{n}{s}\PYG{p}{.}\PYG{n+na}{defaultReadObject}\PYG{p}{();}
|
||||
\PYG{+w}{ }\PYG{c+c1}{// customised deserialization code}
|
||||
\PYG{+w}{ }\PYG{c+c1}{// followed by code to update the object if necessary}
|
||||
\PYG{p}{\PYGZcb{}}
|
||||
\end{Verbatim}
|
@ -0,0 +1,3 @@
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\PYG{n}{String}\PYG{+w}{ }\PYG{n+nf}{concat}\PYG{p}{(}\PYG{n}{String}\PYG{+w}{ }\PYG{n}{str}\PYG{p}{)}
|
||||
\end{Verbatim}
|
@ -0,0 +1,9 @@
|
||||
\begin{Verbatim}[commandchars=\\\{\},codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8\relax}]
|
||||
\PYG{k+kd}{public}\PYG{+w}{ }\PYG{k+kd}{static}\PYG{+w}{ }\PYG{k+kt}{void}\PYG{+w}{ }\PYG{n+nf}{main}\PYG{p}{(}\PYG{n}{String}\PYG{o}{[]}\PYG{+w}{ }\PYG{n}{args}\PYG{p}{)}\PYG{+w}{ }\PYG{p}{\PYGZob{}}
|
||||
\PYG{+w}{ }\PYG{k+kt}{double}\PYG{+w}{ }\PYG{n}{earthWeight}\PYG{+w}{ }\PYG{o}{=}\PYG{+w}{ }\PYG{n}{Double}\PYG{p}{.}\PYG{n+na}{parseDouble}\PYG{p}{(}\PYG{n}{args}\PYG{o}{[}\PYG{l+m+mi}{0}\PYG{o}{]}\PYG{p}{);}
|
||||
\PYG{+w}{ }\PYG{k+kt}{double}\PYG{+w}{ }\PYG{n}{mass}\PYG{+w}{ }\PYG{o}{=}\PYG{+w}{ }\PYG{n}{earthWeight}\PYG{o}{/}\PYG{n}{EARTH}\PYG{p}{.}\PYG{n+na}{surfaceGravity}\PYG{p}{();}
|
||||
|
||||
\PYG{+w}{ }\PYG{k}{for}\PYG{+w}{ }\PYG{p}{(}\PYG{n}{Planet}\PYG{+w}{ }\PYG{n}{p}\PYG{+w}{ }\PYG{p}{:}\PYG{+w}{ }\PYG{n}{Planet}\PYG{p}{.}\PYG{n+na}{values}\PYG{p}{())}\PYG{+w}{ }\PYG{p}{\PYGZob{}}
|
||||
\PYG{+w}{ }\PYG{n}{System}\PYG{p}{.}\PYG{n+na}{out}\PYG{p}{.}\PYG{n+na}{printf}\PYG{p}{(}\PYG{l+s}{\PYGZdq{}Your weight on \PYGZpc{}s is \PYGZpc{}f\PYGZpc{}n\PYGZdq{}}\PYG{p}{,}\PYG{+w}{ }\PYG{n}{p}\PYG{p}{,}\PYG{+w}{ }\PYG{n}{p}\PYG{p}{.}\PYG{n+na}{surfaceWeight}\PYG{p}{(}\PYG{n}{mass}\PYG{p}{));}
|
||||
\PYG{+w}{ }\PYG{p}{\PYGZcb{}}
|
||||
\end{Verbatim}
|
@ -0,0 +1,3 @@
|
||||
\begin{Verbatim}[commandchars=\\\{\},codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8\relax}]
|
||||
\PYG{n}{elements}\PYG{p}{.}\PYG{n+na}{forEach}\PYG{p}{(}\PYG{n}{e}\PYG{+w}{ }\PYG{o}{\PYGZhy{}\PYGZgt{}}\PYG{+w}{ }\PYG{n}{System}\PYG{p}{.}\PYG{n+na}{out}\PYG{p}{.}\PYG{n+na}{println}\PYG{p}{(}\PYG{n}{e}\PYG{p}{));}
|
||||
\end{Verbatim}
|
@ -0,0 +1,14 @@
|
||||
\begin{Verbatim}[commandchars=\\\{\},codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8\relax}]
|
||||
\PYG{n}{ArrayList}\PYG{o}{\PYGZlt{}}\PYG{n}{Integer}\PYG{o}{\PYGZgt{}}\PYG{+w}{ }\PYG{n}{list}\PYG{+w}{ }\PYG{o}{=}\PYG{+w}{ }\PYG{k}{new}\PYG{+w}{ }\PYG{n}{ArrayList}\PYG{o}{\PYGZlt{}}\PYG{n}{Integer}\PYG{o}{\PYGZgt{}}\PYG{p}{();}
|
||||
|
||||
\PYG{c+c1}{// looping though an ArrayList using the Iterator class}
|
||||
\PYG{k}{for}\PYG{+w}{ }\PYG{p}{(}\PYG{n}{Iterator}\PYG{+w}{ }\PYG{n}{i}\PYG{+w}{ }\PYG{o}{=}\PYG{+w}{ }\PYG{n}{list}\PYG{p}{.}\PYG{n+na}{iterator}\PYG{p}{();}\PYG{+w}{ }\PYG{n}{i}\PYG{p}{.}\PYG{n+na}{hasNext}\PYG{p}{();)}\PYG{+w}{ }\PYG{p}{\PYGZob{}}
|
||||
\PYG{+w}{ }\PYG{n}{Integer}\PYG{+w}{ }\PYG{n}{value}\PYG{+w}{ }\PYG{o}{=}\PYG{+w}{ }\PYG{p}{(}\PYG{n}{Integer}\PYG{p}{)}\PYG{+w}{ }\PYG{n}{i}\PYG{p}{.}\PYG{n+na}{next}\PYG{p}{();}
|
||||
\PYG{+w}{ }\PYG{c+c1}{// do some stuff}
|
||||
\PYG{p}{\PYGZcb{}}
|
||||
|
||||
\PYG{c+c1}{// looping though an ArrayList using a For-Each loop}
|
||||
\PYG{k}{for}\PYG{+w}{ }\PYG{p}{(}\PYG{n}{Integer}\PYG{+w}{ }\PYG{n}{i}\PYG{+w}{ }\PYG{p}{:}\PYG{+w}{ }\PYG{n}{list}\PYG{p}{)}\PYG{+w}{ }\PYG{p}{\PYGZob{}}
|
||||
\PYG{+w}{ }\PYG{c+c1}{// do some stuff}
|
||||
\PYG{p}{\PYGZcb{}}
|
||||
\end{Verbatim}
|
@ -0,0 +1,13 @@
|
||||
\begin{Verbatim}[commandchars=\\\{\},codes={\catcode`\$=3\catcode`\^=7\catcode`\_=8\relax}]
|
||||
\PYG{k+kd}{class} \PYG{n+nc}{Fred}\PYG{+w}{ }\PYG{k+kd}{implements}\PYG{+w}{ }\PYG{n}{Runnable}\PYG{+w}{ }\PYG{p}{\PYGZob{}}
|
||||
\PYG{+w}{ }\PYG{k+kd}{public}\PYG{+w}{ }\PYG{k+kt}{void}\PYG{+w}{ }\PYG{n+nf}{run}\PYG{p}{()}\PYG{+w}{ }\PYG{p}{\PYGZob{}}
|
||||
\PYG{+w}{ }\PYG{c+c1}{// insert code to be ran here}
|
||||
\PYG{+w}{ }\PYG{p}{\PYGZcb{}}
|
||||
|
||||
\PYG{+w}{ }\PYG{k+kd}{public}\PYG{+w}{ }\PYG{k+kd}{static}\PYG{+w}{ }\PYG{k+kt}{void}\PYG{+w}{ }\PYG{n+nf}{main}\PYG{p}{(}\PYG{n}{String}\PYG{+w}{ }\PYG{n}{args}\PYG{o}{[]}\PYG{p}{)}\PYG{+w}{ }\PYG{p}{\PYGZob{}}
|
||||
\PYG{+w}{ }\PYG{n}{Thread}\PYG{+w}{ }\PYG{n}{t}\PYG{+w}{ }\PYG{o}{=}\PYG{+w}{ }\PYG{k}{new}\PYG{+w}{ }\PYG{n}{Thread}\PYG{p}{(}\PYG{k}{new}\PYG{+w}{ }\PYG{n}{Fred}\PYG{p}{())}\PYG{+w}{ }\PYG{p}{\PYGZob{}}
|
||||
\PYG{+w}{ }\PYG{n}{t}\PYG{p}{.}\PYG{n+na}{start}\PYG{p}{();}
|
||||
\PYG{+w}{ }\PYG{p}{\PYGZcb{}}
|
||||
\PYG{+w}{ }\PYG{p}{\PYGZcb{}}
|
||||
\PYG{p}{\PYGZcb{}}
|
||||
\end{Verbatim}
|