Skip to content

Commit 0216779

Browse files
committed
add: sep 16 exercise
1 parent 8d0288a commit 0216779

11 files changed

Lines changed: 985 additions & 0 deletions

File tree

F25/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
.DS_Store
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>org.example</groupId>
8+
<artifactId>queue_manager_2</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
11+
<properties>
12+
<maven.compiler.source>18</maven.compiler.source>
13+
<maven.compiler.target>18</maven.compiler.target>
14+
</properties>
15+
16+
</project>
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package edu.brown.cs32.livecode.dispatcher;
2+
3+
import edu.brown.cs32.livecode.dispatcher.utils.TABusyException;
4+
import edu.brown.cs32.livecode.dispatcher.utils.Utils;
5+
import edu.brown.cs32.livecode.records.Student;
6+
import edu.brown.cs32.livecode.records.TA;
7+
8+
import java.util.*;
9+
10+
/**
11+
* A (very incomplete) dispatcher class for TA hours.
12+
*/
13+
public class HoursDispatcher {
14+
/** Single queue that the dispatcher will get students from */
15+
private final Deque<Student> queue;
16+
/** TAs on duty */
17+
private final Map<TA, Integer> minutesLeft = new HashMap<>();
18+
/** How many students have been helped by *any* dispatcher instance. */
19+
static int studentsHelped = 0;
20+
21+
/**
22+
* @param signups an Iterator that provides Student objects
23+
*/
24+
HoursDispatcher(Deque<Student> signups) {
25+
this.queue = signups;
26+
}
27+
28+
/**
29+
* Add an on-duty TA
30+
* @param ta the TA who is arriving for hours
31+
* @param minutes the number of minutes that this TA will stay
32+
*/
33+
void addTA(TA ta, int minutes) {
34+
minutesLeft.put(ta, minutes);
35+
}
36+
37+
/**
38+
* Running this method starts the dispatcher.
39+
*/
40+
public void dispatch() {
41+
System.out.println(Utils.timestamp()+
42+
" Dispatcher: Welcome to edu.brown.cs32.livecode hours!");
43+
44+
// Loop forever: new students may arrive over time
45+
while(true) {
46+
// Is there a student waiting right now?
47+
if(queue.peek() != null) {
48+
// Who will help this student?
49+
// TODO: later, prioritize free TAs with a specialty matching the student's question.
50+
Optional<TA> maybeHelper = this.minutesLeft.keySet().stream().filter(TA::isFree).findFirst();
51+
if(maybeHelper.isEmpty()) {
52+
Utils.tryWait(); // nobody is free; wait a short time
53+
continue;
54+
}
55+
TA helper = maybeHelper.orElseThrow();
56+
57+
// Who to see next?
58+
Student nextStudent = queue.poll();
59+
60+
// Help the student
61+
System.out.println(Utils.timestamp()+" Dispatcher: Hi "+nextStudent+"; you'll be seen by "+helper);
62+
try {
63+
helper.seeStudent(nextStudent);
64+
} catch (TABusyException e) {
65+
// We hope this won't happen, but if this class had a bug in it, or a different
66+
// thread were possibly assigning students, or if we had implemented a TA timeout,
67+
// this would be possible...
68+
System.out.println("Unexpected behavior: TA became busy while assigning student! Re-adding student to queue.");
69+
queue.addFirst(nextStudent); // a Deque lets us add at the front or the back
70+
71+
}
72+
} else {
73+
System.out.println(Utils.timestamp()+" Dispatcher ("+studentsHelped+" helped so far): Nobody waiting in queue, will check again shortly.");
74+
Utils.tryWait();
75+
}
76+
}
77+
}
78+
79+
public static void helpedAStudent() {
80+
studentsHelped++;
81+
}
82+
83+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package edu.brown.cs32.livecode.dispatcher;
2+
3+
import edu.brown.cs32.livecode.records.Student;
4+
import edu.brown.cs32.livecode.records.TA;
5+
6+
import java.util.*;
7+
8+
/**
9+
* Show the (incomplete) dispatcher example
10+
*/
11+
public class Main {
12+
13+
public static void main(String[] args) {
14+
// Not all Lists implement Queue. LinkedList does, ArrayList does not.
15+
Deque<Student> queue = new LinkedList<>(Arrays.asList(
16+
new Student("Nim", "project1", 1000),
17+
new Student("Alice", "project1", 1000),
18+
new Student("Bob", "project1", 1000),
19+
new Student("Charli", "project2", 1000),
20+
new Student("Boatswain", "project2", 1000),
21+
new Student("Bucky", "project3", 1000)));
22+
HoursDispatcher dispatcher = new HoursDispatcher(queue);
23+
24+
// Random Spring '23 TA names, for demo purposes:
25+
dispatcher.addTA(new TA("Erica", "project1", queue), 110);
26+
dispatcher.addTA(new TA("Orion", "project2", queue), 50);
27+
28+
dispatcher.dispatch();
29+
}
30+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package edu.brown.cs32.livecode.dispatcher.utils;
2+
3+
public class TABusyException extends Exception {
4+
public TABusyException() {
5+
}
6+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package edu.brown.cs32.livecode.dispatcher.utils;
2+
3+
import java.time.LocalTime;
4+
import java.time.format.DateTimeFormatter;
5+
6+
public class Utils {
7+
private Utils() {} // no constructor
8+
final static private DateTimeFormatter fmt = DateTimeFormatter.ofPattern("hh:mm:ss:SSS");
9+
public static String timestamp() {
10+
return fmt.format(LocalTime.now());
11+
}
12+
13+
/** The number of milliseconds to wait if no progress can be made. */
14+
static final int SLEEP_DELAY_MS = 3000;
15+
/** Exit code: the application thread has unexpectedly terminated. */
16+
static final int ERR_THREAD_TERMINATED = 1;
17+
18+
/** The application waits before trying again. */
19+
public static void tryWait() {
20+
try {
21+
Thread.sleep(SLEEP_DELAY_MS);
22+
} catch(InterruptedException e) {
23+
// The application thread has been interrupted. Stop the app.
24+
System.out.println("Dispatcher terminated. Stopping.");
25+
System.exit(ERR_THREAD_TERMINATED); // Exit the application with error status
26+
}
27+
}
28+
29+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package edu.brown.cs32.livecode.records;
2+
3+
/** A student-at-hours record. Notice that we can customize the functionality
4+
* that the record invisibly generates for us: we're replacing toString(). */
5+
public record Student(String name, String projectID, Integer problem_needs_ms) {
6+
7+
@Override
8+
public String toString() {
9+
return this.name;
10+
}
11+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package edu.brown.cs32.livecode.records;
2+
3+
import edu.brown.cs32.livecode.dispatcher.HoursDispatcher;
4+
import edu.brown.cs32.livecode.dispatcher.utils.TABusyException;
5+
import edu.brown.cs32.livecode.dispatcher.utils.Utils;
6+
7+
import java.util.Deque;
8+
9+
/** A TA record, with some functionality. Because we need to have internal
10+
* state (at least, designed like this) we have to use a class, not a record.
11+
*/
12+
public class TA {
13+
final private String name;
14+
final private String specialty;
15+
final private Deque<Student> replaceIn;
16+
17+
public TA(String name, String specialty, Deque<Student> replaceIn) {
18+
this.name = name;
19+
this.specialty = specialty;
20+
this.replaceIn = replaceIn;
21+
}
22+
public String getName() {
23+
return name;
24+
}
25+
26+
private Student helping = null;
27+
public void seeStudent(Student student) throws TABusyException {
28+
if(this.helping != null)
29+
throw new TABusyException();
30+
this.helping = student;
31+
32+
System.out.println(Utils.timestamp()+" "+name+ " says: Hello "+helping+"!");
33+
try {
34+
// Help the student, however long they need
35+
Thread.sleep(helping.problem_needs_ms());
36+
} catch (InterruptedException e) {
37+
// Shouldn't happen, but in case it does due to OS issues etc.:
38+
System.out.println(this.name+" was interrupted; had to stop helping.");
39+
this.replaceIn.addFirst(helping);
40+
}
41+
42+
System.out.println(name+ " says: Goodbye "+helping+", I hope that helped!!");
43+
HoursDispatcher.helpedAStudent();
44+
helping = null;
45+
}
46+
47+
@Override
48+
public String toString() {
49+
return name;
50+
}
51+
52+
public boolean isFree() {
53+
return helping == null;
54+
}
55+
56+
}

0 commit comments

Comments
 (0)