I'm writing a simple music database and ATM I'm trying to create a playlist class which will let the user organise their music (4 tracks previously entered into the database class) into a playlist of 3 songs.
After the user selects a song to be put into the playlist, the method is meant to search for the closest free slot in the newplaylist and place the Song variables (artist, name, duration & filesize) inside.
At the moment i am receiving this;
Entering the playlist tool...
Hello, welcome to the playlist builder!
Please select a track to add to the new playlist from the database below(using keys 1-4)
Slot 1:Trees:Breeze:2.34:128
1
Error: there is no free space in the database
Slot A : Song#3a1ec6
Slot B : Song#1ba6076
Slot C : Song#112e7f7
MENU
0 EXIT
1 IMPORT TRACK
2 SHOW ALL
3 Build a playlist(requires atleast 1 track in database)
Am I right in guessing that what is being returned is the reference to the location of the variables and not the variables themselves?
The code for Playlist.class is;
public class Playlist {
Song songDataPlay = new Song();
static UserInterface UI = new UserInterface();
static Song playlisttrackA = new Song();
static Song playlisttrackB = new Song();
static Song playlisttrackC = new Song();
private int MAX_TIME;
private double totalSize;
private double totalTIme;
String playlistClassArtist, playlistClassName;
double playlistClassDuration;
int playlistClassFileSize;
static String playlistArtist;
static String playlistName;
static double playlistDuration;
static int playlistFileSize;
static Song newplaySong;
static Song newSong;
static Song carryfromuserintoplaylist = UI.newPlaylistSongIN;
public void playlistObject(Song a, Song b, Song c) {
this.playlisttrackA = a;
this.playlisttrackB = b;
this.playlisttrackC = c;
}
public static void playlistAllocation() {
newSong = UI.newPlaylistSongIN;
Playlist plu = new Playlist();
SongDatabase SD = new SongDatabase();
Song newSong = carryfromuserintoplaylist;
if (playlisttrackA.songfileSize == 0) {
setSongA(newplaySong);
System.out.println("Slot A : " + playlisttrackA);
System.out.println("Slot B : " + playlisttrackB);
System.out.println("Slot C : " + playlisttrackC);
newplaySong = newSong;
} else if (playlisttrackB.songfileSize == 0) {
setSongB(newplaySong);
System.out.println("Slot A : " + playlisttrackA);
System.out.println("Slot B : " + playlisttrackB);
System.out.println("Slot C : " + playlisttrackC);
newplaySong = newSong;
} else if (playlisttrackC.songfileSize == 0) {
setSongC(newplaySong);
System.out.println("Slot A : " + playlisttrackA);
System.out.println("Slot B : " + playlisttrackB);
System.out.println("Slot C : " + playlisttrackC);
newplaySong = newSong;
} else {
System.out.println("Error: there is no free space in the database");
System.out.println("Slot A : " + playlisttrackA);
System.out.println("Slot B : " + playlisttrackB);
System.out.println("Slot C : " + playlisttrackC);
}
}
public static void setSongA(Song newSong) {
playlisttrackA = newplaySong;
playlisttrackA.songartist = newplaySong.songartist;
playlisttrackA.songname = newplaySong.songname;
playlisttrackA.songduration = newplaySong.songduration;
playlisttrackA.songfileSize = newplaySong.songfileSize;
}
public Song getSongA() {
return (playlisttrackA);
}
public static void setSongB(Song newSong) {
playlisttrackB = newplaySong;
playlisttrackB.songartist = newplaySong.songartist;
playlisttrackB.songname = newplaySong.songname;
playlisttrackB.songduration = newplaySong.songduration;
playlisttrackB.songfileSize = newplaySong.songfileSize;
}
public Song getSongB() {
return (playlisttrackB);
}
public static void setSongC(Song newSongC) {
playlisttrackC = newplaySong;
playlisttrackC.songartist = newplaySong.songartist;
playlisttrackC.songname = newplaySong.songname;
playlisttrackC.songduration = newplaySong.songduration;
playlisttrackC.songfileSize = newplaySong.songfileSize;
}
public Song getSongC() {
return (playlisttrackC);
}
public String returnPlaylist() {
if (playlisttrackA.songfileSize == 0 && playlisttrackB.songfileSize == 0 && playlisttrackC.songfileSize == 0) {
return ("Error ; No new playlists have been added.");
} else if (playlisttrackB.songfileSize == 0 && playlisttrackC.songfileSize == 0) {
return ("You have imported:" + newplaySong.songname + " By " + newplaySong.songartist + " to slot A in the new playlist");
} else if (newplaySong.songfileSize == 0) {
return ("You have imported:" + newplaySong.songname + " By " + newplaySong.songartist + " to slot B in the new playlist");
} else {
return ("You have imported:" + newplaySong.songname + " By " + newplaySong.songartist + " to slot C in the new playlist");
}
}
}
Any help would be great thanks,
System.out.println("Slot A : "+playlisttrackA); this calls the toString() method of Song (which is derived from Object). By default it prints the hash code of an object.
You should better print playlisttrackA.songname if I understand your code right.
Related
In my program, I am trying to create a method that will Edit any property inside of a BaseContact. BaseContact is an abstract class that is extended within a PersonContact and BusinessContact classes. I want to create an edit method that asks the user what property they want to edit, shows them the old value, and then updates with the new value they want. I reuse a lot of code so I was thinking of trying to make another method that will help recycle code, but I'm unsure how that would work with the need of unique getters and setters.
public void editQuery() {
}
// Edit BaseContact
public void edit(int id) {
try {
contacts.contains(contacts.get(id - 1));
} catch (IndexOutOfBoundsException e) {
System.out.println("Contact does not exist\n--- EXIT ---");
return;
}
Boolean active = true;
// While Statement for Edit
while (active) {
System.out.println(
"What property would you like to edit?\n1. Name\n2. Phone Number\n3. Date of Birth\n4. Hobby\n5. Description"
+ "\n6. Website URL\n7. Hours of Operation\n8. Street\n9. City\n10. State\n11. Zip Code\n12. Location"
+ "\n13. Relatives" + "\n14. Photos\n15. Exit");
String choice = sc.nextLine();
switch (choice.toUpperCase()) {
case "1":
case "NAME":
for (BaseContact contact : contacts) {
if (contact.getId() == id) {
System.out.println("Contact Name: " + contact.getName() + "\n");
System.out.print("New Name: ");
String name = sc.nextLine();
contact.setName(name);
System.out.println("Contact Name Set To: " + contact.getName());
}
}
break;
case "3":
case "DATE OF BIRTH":
for (BaseContact contact : contacts) {
if (contact.getId() == id) {
if (contact.getType().equals("personContact")) {
PersonContact temp = (PersonContact) contact;
System.out.println("Contact Date of Birth (ex. January 01, 1999): " + temp.getDob() + "\n");
System.out.print("New Date of Birth: ");
String dob = sc.nextLine();
temp.setDob(dob);
System.out.println("Contact Date of Birth Set To: " + temp.getDob());
}
}
}
break;
case "10":
case "STATE":
for (BaseContact contact : contacts) {
if (contact.getId() == id) {
System.out.println("Contact State: " + contact.getLocation().getState());
System.out.print("New State: ");
String state = sc.nextLine();
contact.getLocation().setState(state);
System.out.println("Contact State Set To: " + contact.getLocation().getState());
}
}
break;
case "12":
case "LOCATION":
for (BaseContact contact : contacts) {
if (contact.getId() == id) {
// Location
Location location = createLocation();
contact.getLocation().setStreet(location.getStreet());
contact.getLocation().setCity(location.getCity());
contact.getLocation().setState(location.getState());
contact.getLocation().setZipCode(location.getZipCode());
System.out.println("Contact Location Set To: " + contact.getLocation());
}
}
break;
case "13":
case "RELATIVES":
for (BaseContact contact : contacts) {
if (contact.getId() == id) {
if (contact.getType().equals("personContact")) {
PersonContact temp = (PersonContact) contact;
System.out.println("List of Relatives");
System.out.print("Contact Relatives: ");
for (int i = 0; i < temp.getRelatives().size(); i++) {
System.out.println(temp.getRelatives().get(i).getName());
}
System.out.println("Would you like to 1. Add or 2. Remove relatives?");
String rChoice = sc.nextLine();
// Adding Relative
if (rChoice.equalsIgnoreCase("1") || rChoice.equalsIgnoreCase("ADD")) {
System.out.println("--- Add Relatives ---");
System.out.println("List of Available Contacts\n");
for (BaseContact rcontact : contacts) {
if (rcontact.getType().equals("personContact")) {
PersonContact rtemp = (PersonContact) rcontact;
System.out.print(rtemp.getName() + " | ");
}
}
System.out.println();
System.out.println("How many relatives would you like to add?");
int numOfRelatives = sc.nextInt();
sc.nextLine();
for (int i = 0; i < numOfRelatives; i++) {
System.out.println("--- Add Relative ---");
System.out.print("Relative Name: ");
String rname = sc.nextLine();
for (BaseContact r2contact : contacts) {
if (r2contact.getType().equals("personContact")) {
PersonContact r2temp = (PersonContact) r2contact;
if (rname.equalsIgnoreCase(r2temp.getName())) {
temp.getRelatives().add(r2temp);
}
}
}
}
// Removing Relative
} else if (rChoice.equals("2") || rChoice.equalsIgnoreCase("REMOVE")) {
System.out.println("--- Remove Relatives ---");
System.out.println("List of Relatives");
for (int i = 0; i < temp.getRelatives().size(); i++) {
System.out.println(temp.getRelatives().get(i).getName());
}
System.out.println();
System.out.println("How many relatives would you like to remove?");
int numOfRelatives = sc.nextInt();
sc.nextLine();
if (numOfRelatives > temp.getRelatives().size()
|| numOfRelatives == temp.getRelatives().size()) {
temp.getRelatives().clear();
System.out.println("All Relatives Removed");
} else {
for (int i = 0; i < numOfRelatives; i++) {
System.out.println("--- Remove Relative ---");
System.out.print("Relative Name: ");
String rName = sc.nextLine();
for (BaseContact r2contact : contacts) {
if (r2contact.getType().equals("personContact")) {
PersonContact r2temp = (PersonContact) r2contact;
if (rName.equalsIgnoreCase(r2temp.getName())) {
temp.getRelatives().remove(r2temp);
}
}
}
}
}
} else {
System.out.println("Invalid Option");
}
}
}
}
break;
Well ask and thou shall receive. I have looked mainly at the humongous switch statement you have going on. For a starter, that should be condensed. A more functional style of programming can help here.
I had to deduce a lot of the classes you have used based on the methods which were called in the code. Furthermore, I have picked a couple of switch expressions and converted them in something more dynamic. See this as a starting point to build on for the rest of your application.
Start of with creating an action class for the simple edits:
public class ActionHolder {
private final String actionText;
private final BiConsumer<String, PersonContact> action;
private final Function<PersonContact, String> originalValFunc;
public ActionHolder(String actionText, BiConsumer<String, PersonContact> action,
Function<PersonContact, String> originalValFunc) {
this.actionText = actionText;
this.action = action;
this.originalValFunc = originalValFunc;
}
public String getActionText() {
return actionText;
}
public BiConsumer<String, PersonContact> getAction() {
return action;
}
public Function<PersonContact, String> getOriginalValFunc() {
return originalValFunc;
}
}
The action class relies heavily on functional interfaces, make sure you read up on them thoroughly as they provide a powerful way of programming. (https://www.baeldung.com/java-8-functional-interfaces)
actionText: Is used to label the attribute which is edited.
action: A function which accepts two arguments and returns nothing.
In this case we will use this to set the respective value on the
PersonContact
originalValFunc: A function to retrieve the origional value from the
PersonContact, it is a function with one parameter (PersonContact)
and it returns a string.
The edit method can then be build up as follows:
class TestInputProgram {
public static void main(String[] args) {
TestInputProgram inputProgram = new TestInputProgram();
inputProgram.edit(1);
}
private final Scanner sc = new Scanner(System.in);
//Initialize with temp data
private final ArrayList<PersonContact> contacts = new ArrayList<PersonContact>() {{
add(new PersonContact(1));
}};
private static final Map<String, ActionHolder> actionMap = new HashMap<String, ActionHolder>() {{
put("1", new ActionHolder("Contact Name",
(input, contact) -> contact.setName(input), BaseContact::getName));
put("NAME", new ActionHolder("Contact Name",
(input, contact) -> contact.setName(input), BaseContact::getName));
put("3", new ActionHolder("Date of Birth",
(input, contact) -> contact.setDob(input), PersonContact::getDob));
put("DATE OF BIRTH", new ActionHolder("Date of Birth",
(input, contact) -> contact.setDob(input), PersonContact::getDob));
put("10", new ActionHolder("State",
(input, contact) -> contact.getLocation().setState(input),
(contact -> contact.getLocation().getState())));
put("STATE", new ActionHolder("State",
(input, contact) -> contact.getLocation().setState(input),
(contact -> contact.getLocation().getState())));
}};
// Edit BaseContact
public void edit(int id) {
while (true) {
System.out.println(
"What property would you like to edit?\n" +
"1. Name\n" +
"2. Phone Number\n" +
"3. Date of Birth\n" +
"15. Exit");
String choice = sc.nextLine();
if (Objects.equals(choice, "15")) {
break;
}
PersonContact pContact = contacts.stream()
.filter(contact -> contact.id == id)
.findFirst()
.orElseThrow(
() -> new IllegalArgumentException("Contact with id: " + id + " does not exist!")
);
Optional.ofNullable(actionMap.get(choice.toUpperCase())).ifPresent(actionHolder -> {
System.out.println(actionHolder.getActionText() + " current value: "
+ actionHolder.getOriginalValFunc().apply(pContact) + "\n");
System.out.println("Please provide the new value:");
String newValue = sc.nextLine();
actionHolder.getAction().accept(newValue, pContact);
System.out.println(actionHolder.getActionText() + " set to: "
+ actionHolder.getOriginalValFunc().apply(pContact));
System.out.println("############################# \n");
});
}
}
}
Some brief info about the variables and whats going on:
The actionMap holds all the possible edit options we currently provide. Notice the implementation of the action holder arguments. We implement the actions using both lamda's and static method references. Inside the edit method the map is queried and the actionHolder retrieved. The respective input action info is then printed to the user and asked for input. The input is processed using the (BiConsumer) from the actionHolder.
I hope this will provide some reference for future programming optimization.
I'm trying to model a normal PDDL case ,as the logistics example, into a different programming language(java). I'm doing this to understand what are the advantages or disvantages in using PDDL.
This is the PDDL original example
https://github.com/pellierd/pddl4j/wiki/Logistics:-a-simple-running-example
My result is an easy sequential program, shown in the code. My target is to automatize the calculation to obtain a real combinatorial calculation, not a sequential one.
public class logistics {
private static boolean airplaneInUse = false;
private static boolean truckInUse = false;
private static String airport;
private static String place;
private static String city;
private static String pack1;
private static String pack2;
static int state = 0;
public static void main(String args[]) {
if(state == 0) {
start();
System.out.println("The city in the initial state is " + city + "\n");
System.out.println("The airport in the initial state is " + airport + "\n");
}
if(city == "London") {
load_plane();
System.out.println("pk1 and pk2 are on the plane" +"\n");
pack1 = "On Board";
pack2 = "On Board";
}
if(pack1 == "On Board" && pack2 == "On Board") {
fly();
System.out.println("The city after the flight is " + city + "\n");
System.out.println("The airport after the flight is " + airport + "\n");
}
if (city == "Paris") {
unload_plane();
System.out.println("pk1 and pk2 are unloaded from the plane " + "\n");
pack1 = "Unloaded";
pack2 = "Unloaded";
}
if (pack1 == "Unloaded" && pack2 == "Unloaded") {
load_truck();
System.out.println(pack1 + "\n");
System.out.println(pack2 + "\n");
}
if(pack1 == "pk1 On the truck" || pack2 == "pk2 On the truck") {
drive_truck();
System.out.println("Driving to the first place " + "\n");
System.out.println("Driving to the second place " + "\n");
}
if (truckInUse == true) {
unload_truck1();
System.out.println("pk1 delivered in the " + place + "\n");
unload_truck2();
System.out.println("pk2 delivered in the " + place + "\n");
}
}
public static void start() {
city = "London";
airport = "lhr";
return;
}
public static void load_plane() {
city = "London";
pack1 = " pk1 On board";
pack2 = " pk2 On board";
return;
}
public static void fly() {
city = "Paris";
airport = "cdg";
airplaneInUse = true;
return;
}
public static void unload_plane() {
pack1 = "Arrived in Paris";
pack2 = "Arrived in Paris";
airplaneInUse = false;
return;
}
public static void load_truck() {
pack1 = "pk1 On the truck";
pack2 = "pk2 On the truck";
return;
}
public static void drive_truck() {
truckInUse = true;
return;
}
public static void unload_truck1() {
truckInUse = false;
pack1 = "Arrived in South";
place = "South";
return;
}
public static void unload_truck2() {
truckInUse = false;
pack1 = "Arrived in North";
place = "North";
return;
}
}
How can I reach my target? How can I obtain a combinatorial calculation to solve the problem?
I think you are getting at it the wrong way around. Do not try to implement any if/else imperative logic. Declare your actions (aka operators), domain, problem and call a planner to solve it. If you do want to create the domain and problem without encoding it into PDDL and letting the planner (e.g. pddl4j) parse it, you can code it out in Java and hand it over as a coded domain and coded problem.
The structure of your code will be very similar as what you would have put into PDDL, so besides shaving off the parsing time and speeding up the solution time, I do not see much point doing it this way. If you do, keep reading...
See a code example how you call the planner via the pddl4j APIs: https://github.com/pellierd/pddl4j/wiki/A-tutorial-to-develop-your-own-planner#step-6-searching-for-a-solution-plan
Now, normally, you would let the PDDL parser do the job: https://github.com/pellierd/pddl4j/wiki/A-tutorial-to-develop-your-own-planner#step-5-parse-and-encode-the-pddl-domain-and-problem-files
...but if you want to code it out, you will need to declare your actions, domain and problem using the Op, Domain and Problem classes.
Then you call encode the Problem and call one of the planners in pddl4j as indicated in one of the tutorials (links I pasted above). Does this help?
We have a program that compares thousands of pairs of Students by checking each field of the Student and counting the diffs:
class Student{
String name;
String address;
String biologyCourse;
.....
// about 100 other fields
}
And the counter POJO class:
class Counters{
long bothStudentsHaveName;
long onlyLeftHasName;
long onlyRightHasName;
......
// number of fields in Student * 3 (both, only left, only right)
}
Our compare function accepts 2 students plus the counters object and needs to scan the fields and update the relevant counters:
public void compareStudents(Student left, Student right, Counters counters){
if (!StringUtils.isEmpty(left.name) && !StringUtils.isEmpty(right.name) ){
counters.bothStudentsHaveName++;
} else if (StringUtils.isEmpty(left.name) && !StringUtils.isEmpty(right.name)){
counters.onlyRightHasName++;
} else if (!StringUtils.isEmpty(left.name) && StringUtils.isEmpty(right.name))){
counters.onlyLeftHasName++;
}
/// and now??
}
At this point, we can add 100s more triplets of if/else like the above - but we believe there should be a much easier way to do that.
Reflection can be an option or maybe X dimensions arrays, but can we somehow write the code so the comparison and counting will be much more generic?
I have solved your problem with one single loop. But here I'm assuming that naming convention for all the fields will be the same as described in your question. Here I am dynamically accessing the Student fields and updating Counter fields accordingly. Here is the complete solution:
Solution Class:
public class Solution {
public void compareStudents(Student left, Student right, Counter counter) throws Exception {
for (Field field : Student.class.getDeclaredFields()) {
Object leftValue = field.get(left);
Object rightValue = field.get(right);
String fieldName = field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
if(leftValue != null && rightValue != null) {
Field counterField = Counter.class.getDeclaredField("bothStudentsHave" + fieldName);
counterField.set(counter, (long) counterField.get(counter) + 1);
} else if (leftValue != null) {
Field counterField = Counter.class.getDeclaredField("onlyLeftHas" + fieldName);
counterField.set(counter, (long) counterField.get(counter) + 1);
} else if (rightValue != null) {
Field counterField = Counter.class.getDeclaredField("onlyRightHas" + fieldName);
counterField.set(counter, (long) counterField.get(counter) + 1);
}
}
}
}
Student Class:
class Student {
String name;
String address;
String biologyCourse;
}
Counter Class:
class Counter {
// name
long bothStudentsHaveName;
long onlyLeftHasName;
long onlyRightHasName;
// address
long bothStudentsHaveAddress;
long onlyLeftHasAddress;
long onlyRightHasAddress;
// biologyCourse
long bothStudentsHaveBiologyCourse;
long onlyLeftHasBiologyCourse;
long onlyRightHasBiologyCourse;
// ... and so on
#Override
public String toString() {
return "Counter{" + "\n" +
"\tbothStudentsHaveName = " + bothStudentsHaveName + "\n" +
"\t, onlyLeftHasName = " + onlyLeftHasName + "\n" +
"\t, onlyRightHasName = " + onlyRightHasName + "\n" +
"\t, bothStudentsHaveAddress = " + bothStudentsHaveAddress + "\n" +
"\t, onlyLeftHasAddress = " + onlyLeftHasAddress + "\n" +
"\t, onlyRightHasAddress = " + onlyRightHasAddress + "\n" +
"\t, bothStudentsHaveBiologyCourse = " + bothStudentsHaveBiologyCourse + "\n" +
"\t, onlyLeftHasBiologyCourse = " + onlyLeftHasBiologyCourse + "\n" +
"\t, onlyRightHasBiologyCourse = " + onlyRightHasBiologyCourse + "\n" +
'}';
}
}
Tester Class:
public class Tester {
public static void main(String[] args) throws Exception {
// Creating Dummy Variables
Student student1 = new Student();
student1.name = "Test";
student1.biologyCourse = "Yes";
Student student2 = new Student();
student2.name = "Test1";
student2.address = "abc street";
Counter counter = new Counter();
// Comparing Students
Solution solution = new Solution();
solution.compareStudents(student1, student2, counter);
// Printing Counter
System.out.println(counter);
}
}
Output:
Counter{
bothStudentsHaveName = 1
, onlyLeftHasName = 0
, onlyRightHasName = 0
, bothStudentsHaveAddress = 0
, onlyLeftHasAddress = 0
, onlyRightHasAddress = 1
, bothStudentsHaveBiologyCourse = 0
, onlyLeftHasBiologyCourse = 1
, onlyRightHasBiologyCourse = 0
}
If you keep repreating the same basic pattern of fields, then consider extracting that into a class. For example introduce a FieldComparison class that looks a little like this:
public class FieldComparisonCounter {
public int bothHave;
public int onlyLeftHas;
public int onlyRightHas;
// constructor, getters, setters left as an exercise for the reader
}
Then have a Map<String,FieldComparisonCounter> counters somewhere and a method like this:
public void compareField(String fieldName, String leftValue, String rightValue) {
FieldComparisonCounter counter = counters.get(fieldName);
if (counter == null) {
counter = new FieldComparisonCounter();
counters.put(fieldName, counter);
}
boolean leftHas = !StringUtils.isEmpty(leftValue);
boolean rightHas = !StringUtils.isEmpty(rightValue);
if (leftHas && rightHas) {
counter.bothHave++;
} else if (leftHas) {
counter.onlyLeftHas++;
} else if (rightHas) {
counter.onlyRightHas++;
}
}
Then adding a new field comparison is as simple as calling
compareField("name", left.name, right.name);
I'm trying to get the hang of queues by making a very simple program that simulates a checkout line. For some reason my custom dequeue function (using a linkedlist's removeFirst()) wont actually delete stuff in the queue.
Heres the CustomerQueue Class
public class CustomerQueue<E> {
private LinkedList<E> list = new LinkedList<>();
public void enqueue(E e) { list.addLast(e); }
public E dequeue() { return list.removeFirst(); }
public int size() { return list.size(); }
public E element() { return list.getFirst(); }
#Override
public String toString() { return "Queue: " + list.toString(); }
}
Here is my main:
public static void main(String[] args) {
CustomerQueue<Customer> queue = new CustomerQueue<>();
final int totalTime = 720;
int totalServiced = 0;
int totalQueued = 0;
int totalArrived = 1;
int maxQueuedAtOnce = 0;
Customer next = new Customer();
queue.enqueue(next);
System.out.println(next.getATime() + " <-- ATIME STIME --> " + next.getSTime());
for (int minute = 0; minute < totalTime; minute++) {
System.out.println("-- Minute " + (minute + 1) + " ---------");
if (queue.element().getSTime() == 0) {
totalServiced++;
System.out.println("Current customer (" + queue.dequeue() + ") finished being serviced. (Removed)");
//queue.dequeue();
}
if (next.getATime() == 0) {
System.out.println("Customer ID=" + next.getID() + " has arrived.");
queue.enqueue(next);
System.out.println("Customer ID=" + next.getID() + " in queue.");
next = new Customer();
System.out.println("New Customer generated. ID=" + next.getID() + " ATIME: " + next.getATime() + " STIME: " + next.getSTime());
totalArrived++;
totalQueued++;
}
System.out.println("Customer ID=" + next.getID() + " arrival ticked down.");
next.tickArrivalDown();
queue.element().tickServiceDown();
System.out.println("Current queue customer ID=" + next.getID() + " ticked down.");
if (queue.size() > maxQueuedAtOnce)
maxQueuedAtOnce = queue.size();
}
System.out.println("Total Customers Generated " + next.getNumCustomers());
System.out.println("Total Customers Serviced: " + totalServiced);
System.out.println("Total Customers Arrived: " + totalArrived);
System.out.println("Maximum Customers Queued: " + maxQueuedAtOnce);
System.out.println(queue.element());
}
And of course the Customer Class:
public class Customer {
private int serviceTime;
private int arrivalTime;
private static int numCustomers = 0;
private int ID;
public int getSTime() { return serviceTime; }
public void setSTime(int t) { serviceTime = t; }
public int getATime() { return arrivalTime; }
public void setATime(int t) { arrivalTime = t; }
public int getID() { return ID; }
public static int getNumCustomers() { return numCustomers; }
Customer() {
serviceTime = (int) (Math.random()*3 + 1);
arrivalTime = (int) (Math.random()*3 + 1);
ID = ++numCustomers;
}
public void tickServiceDown() { serviceTime--; }
public void tickServiceUp() { serviceTime++; }
public void tickArrivalDown() { arrivalTime--; }
public void tickArrivalUp() { arrivalTime++; }
#Override
public String toString() {
return "ID: " + ID + " ArrivalTime: " + arrivalTime + " ServiceTime: " + serviceTime;
}
}
The Customer class I have setup generates its own arrival time and completion time when a Customer is instantiated. Basically at the end of the loop, the next customer's arrival time ticks down and the current customer's service time ticks down. When the current customer's service time hits 0, it should dequeue/remove the first element in the LinkedList. For some reason it isnt removing it. Here is the post-loop output:
Total Customers Generated 358
Total Customers Serviced: 1
Total Customers Arrived: 358
Maximum Customers Queued: 357
ID: 1 ArrivalTime: 0 ServiceTime: -717
I'm totally stumped, no amount of googling has helped.
Looking at your output
ID: 1 ArrivalTime: 0 ServiceTime: -717
and ServiceTime being what is being returned in getSTime()
then as 0 != -717 I think the below will be fine
How about if (queue.element().getSTime() <= 0) {
I figured out the answer. The initial if statement:
if (queue.element().getSTime() == 0) needed to become if (queue.size() > 0 && queue.element().getSTime() == 0)
Also needed to make the queue.element().tickServiceDown(); enclosed with the following if-statement if (queue.size() > 0)
I've got some problems with the topological sorting. It can find lops, but it counts some of the tasks (or "nodes" if you want to call it) several times. I think the problem is something with how I read or the Edge class, but I just can't see where it goes wrong. Any help would be really appreciated :)
enter code here
import java.util.*;
import java.io.*;
import java.lang.*;
class Task {
int id, time, staff;
int depA, depB;
String name;
int eStart, lStart;
Edge outEdge;
int cntPredecessors;
boolean visited;
Task(int id, String name, int time, int staff) {
this.id = id;
this.name = name;
this.time = time;
this.staff = staff;
visited = false;
}
public String getName() {
return name;
}
public String toString() {
return name;
}
}
class Edge {
Task id, name, time, staff;
Edge neste;
Task fra, til;
Edge(Task id) {
this.id = id;
}
}
class Input {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("enter a filename!");
System.exit(1);
} else if (args.length == 1) {
String fil = args[0]+".txt";
LesFraFil(fil);
// skrivUt();
topSort();
} else {
System.out.println("too many parameters, try again...");
}
}
static int antTask;
static Task[] ids;
static int tTid;
static void LesFraFil(String fil) {
int i = 0;
int j;
try {
String lest;
Scanner in = new Scanner(new FileReader(fil));
Edge til;
int counter = 0;
antTask = in.nextInt();
ids = new Task[antTask];
System.out.println(antTask);
while (in.hasNextLine()) {
lest = in.nextLine();
// hvis tom linje, så hopper den over
if(lest.trim().length() == 0) continue;
String split[] = lest.split("\\s+");
int id = Integer.parseInt(split[0]);
String act = split[1];
int tid = Integer.parseInt(split[2]);
int staff = Integer.parseInt(split[3]);
int depA = Integer.parseInt(split[4]);
tTid += tid;
ids[i] = new Task(id, act, tid, staff);
j = 4;
/*
* Lesingen av inputen skal avbrytes når den leser 0.
* j er den som holder på hvor langt vi er i split arrayet
* når den møter på 0
*/
while(split[j].compareTo("0") != 0) {
int tmp = Integer.parseInt(split[j])-1;
// System.out.println(tmp+1 + " Aktivitetens navn : " + act); //+ " tiden aktiviteten tar tid: " + tid + " avhengihet: " + split[j]);
j++;
if (ids[tmp] == null) {
ids[tmp] = new Task(id, act, tid, staff);
ids[tmp].visited = true;
}
ids[i].cntPredecessors++;
if(ids[tmp].outEdge == null) {
ids[tmp].outEdge = new Edge(ids[i]);
} else {
til = ids[tmp].outEdge;
while(til.neste != null) {
til = til.neste;
}
til.neste = new Edge(ids[i]);
}
}
counter++;
i++;
}
if (antTask == counter) {
System.out.println("Lesinga gikk som planlagt av fil: " + fil);
System.out.println("Total arbeidstid: " + tTid);// + antTask + " == " + counter );
} else {
System.out.println("Noe gikk galt avslutter!");
System.out.println(antTask + " || " + counter);
System.exit(2);
}
in.close();
} catch (Exception e) {
System.err.println("ERROR!" + e.getMessage());
}
}
static void skrivUt() {
for (Task sort : ids) {
System.out.print(sort.id + " " + sort.name);
Edge til = sort.outEdge;
while (til != null) {
System.out.print(" " + til.id.id);
til = til.neste;
}
System.out.println();
}
}
static void topSort() {
LinkedList<Task> list = new LinkedList<Task>();
ArrayList<Task> array = new ArrayList<Task>();
Task temp;
int count = 0;
int totalTime = 0;
// Legger taskene i lista
for (Task t : ids) {
if(t.cntPredecessors == 0) {
list.add(t);
totalTime += t.time;
// System.out.println(t);
t.visited = true;
}
}
for (Task t : ids) {
if(t.cntPredecessors == 1) {
list.add(t);
totalTime += t.time;
// System.out.println(t);
t.visited = true;
}
}
// går i evig løkke til lista er tom.
while (!list.isEmpty()) {
temp = list.pop(); // fjerner elementet fra lista
array.add(temp); // legger inn i arraylisten
count++;
// System.out.println(temp);
for(Edge til = temp.outEdge; til!=null;til=til.neste) {
til.id.cntPredecessors--;
if(til.id.cntPredecessors==0) {
list.add(til.id);
}
}
}
if(count < antTask) {
System.out.println("A loop has been found. Terminating...");
System.exit(0);
}
System.out.println("Topological sort: " + Arrays.toString(array.toArray()));// den sorterte "arraylisten"
System.out.println("Total time spend: " + totalTime);
}
} // End class Input
Here is an example of an input file
8
1 Build-walls 4 2 5 0
2 Build-roofs 6 4 1 0
3 Put-on-wallpapers 1 2 1 2 0
4 Put-on-tiles 1 3 2 0
5 Build-foundation 4 2 0
6 Make-floor 2 2 5 0
7 Put-carpet-floor 4 2 6 2 0
8 Move-in 4 4 3 7 0
The problem is with this loop (inside topSort()):
for (Task t : ids) {
if(t.cntPredecessors == 1) {
list.add(t);
totalTime += t.time;
// System.out.println(t);
t.visited = true;
}
}
You just need to remove it.
Reason: this loop adds to list nodes that have 1 incoming edge. Later (in the while loop), it is possible that for these nodes the cntPredecessors field will be decreased to 0 which will make them being pushed back onto list, thus counted twice.
In the future, please try to narrow down your code to something that contains less "noise", that is: the smallset (or nearly smallest) code that illustrates the problem. This will ease the understanding on potential answerers (not to mention that it may help you see the problem yourself).