Lab1
This commit is contained in:
parent
3aca31de74
commit
af85296ddb
4 changed files with 255 additions and 8 deletions
|
@ -4,23 +4,50 @@ import clock.io.ClockInput;
|
|||
import clock.io.ClockInput.UserInput;
|
||||
import clock.io.ClockOutput;
|
||||
|
||||
// Semaphore
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
public class ClockMain {
|
||||
|
||||
private static AlarmClockEmulator emulator = new AlarmClockEmulator();
|
||||
private static ClockInput in = emulator.getInput();
|
||||
private static ClockOutput out = emulator.getOutput();
|
||||
|
||||
static Semaphore sem = in.getSemaphore();
|
||||
static Monitor monitor = new Monitor(00, 00, 00, out);
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
AlarmClockEmulator emulator = new AlarmClockEmulator();
|
||||
|
||||
ClockInput in = emulator.getInput();
|
||||
ClockOutput out = emulator.getOutput();
|
||||
|
||||
out.displayTime(15, 2, 37); // arbitrary time: just an example
|
||||
Thread clockThread = new Thread(new ClockThread(monitor, out));
|
||||
|
||||
while (true) {
|
||||
sem.acquire();
|
||||
|
||||
UserInput userInput = in.getUserInput();
|
||||
Choice c = userInput.choice();
|
||||
Choice choice = userInput.choice();
|
||||
|
||||
int h = userInput.hours();
|
||||
int m = userInput.minutes();
|
||||
int s = userInput.seconds();
|
||||
|
||||
System.out.println("choice=" + c + " h=" + h + " m=" + m + " s=" + s);
|
||||
switch (choice) {
|
||||
case SET_TIME -> {
|
||||
monitor.setTime(h, m, s);
|
||||
out.displayTime(h, m, s);
|
||||
|
||||
// Kick off the clock thread if it's not already running
|
||||
if (!clockThread.isAlive())
|
||||
clockThread.start();
|
||||
}
|
||||
case SET_ALARM -> {
|
||||
monitor.setAlarm(h, m, s);
|
||||
}
|
||||
case TOGGLE_ALARM -> {
|
||||
monitor.toggleAlarm();
|
||||
out.setAlarmIndicator(monitor.getAlarmStatus());
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("choice=" + choice + " h=" + h + " m=" + m + " s=" + s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
41
clock/src/ClockThread.java
Normal file
41
clock/src/ClockThread.java
Normal file
|
@ -0,0 +1,41 @@
|
|||
import clock.io.ClockOutput;
|
||||
|
||||
public class ClockThread implements Runnable {
|
||||
long t;
|
||||
long diff;
|
||||
private ClockOutput out;
|
||||
private Monitor monitor;
|
||||
|
||||
public ClockThread(Monitor monitor, ClockOutput out) {
|
||||
this.out = out;
|
||||
this.monitor = monitor;
|
||||
t = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("ClockThread started");
|
||||
|
||||
while (true) {
|
||||
t += 1000;
|
||||
diff = t - System.currentTimeMillis();
|
||||
|
||||
if (diff > 0) {
|
||||
try {
|
||||
Thread.sleep(diff);
|
||||
monitor.tick();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
NaiveTime time = monitor.getTime();
|
||||
|
||||
out.displayTime(time.hour(), time.min(), time.sec());
|
||||
|
||||
if (monitor.getAlarmStatus()) {
|
||||
out.alarm();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
82
clock/src/Monitor.java
Normal file
82
clock/src/Monitor.java
Normal file
|
@ -0,0 +1,82 @@
|
|||
import clock.io.ClockOutput;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
class Monitor {
|
||||
private NaiveTime currentTime = new NaiveTime();
|
||||
private NaiveTime alarmTime = new NaiveTime();
|
||||
|
||||
private boolean alarm = false;
|
||||
private int beepCount = 0;
|
||||
|
||||
private Semaphore sema = new Semaphore(1);
|
||||
private ClockOutput out;
|
||||
|
||||
Monitor(ClockOutput out) {
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
Monitor(int h, int m, int s, ClockOutput out) {
|
||||
currentTime = new NaiveTime(h, m, s);
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
void setTime(int h, int m, int s) throws InterruptedException {
|
||||
sema.acquire();
|
||||
currentTime.set(h, m, s);
|
||||
sema.release();
|
||||
}
|
||||
|
||||
void setAlarm(int h, int m, int s) throws InterruptedException {
|
||||
sema.acquire();
|
||||
alarmTime = new NaiveTime(h, m, s);
|
||||
sema.release();
|
||||
}
|
||||
|
||||
void setAlarm(boolean on) {
|
||||
alarm = on;
|
||||
}
|
||||
|
||||
boolean getAlarmStatus() {
|
||||
return this.alarm;
|
||||
}
|
||||
|
||||
void toggleAlarm() {
|
||||
alarm = !alarm;
|
||||
}
|
||||
|
||||
NaiveTime getTime() {
|
||||
return currentTime;
|
||||
}
|
||||
|
||||
void tick() throws InterruptedException {
|
||||
sema.acquire();
|
||||
currentTime.tick();
|
||||
|
||||
if (currentTime.equals(alarmTime) && beepCount == 0) {
|
||||
triggerAlarm();
|
||||
}
|
||||
|
||||
// Decrement beep count each tick
|
||||
if (beepCount > 0)
|
||||
beepCount--;
|
||||
|
||||
// Stop alarm when count hits zero
|
||||
if (beepCount == 0 && alarm)
|
||||
stopAlarm();
|
||||
|
||||
sema.release();
|
||||
}
|
||||
|
||||
void triggerAlarm() {
|
||||
System.out.println("Alarm triggered!");
|
||||
beepCount = 5;
|
||||
this.setAlarm(true);
|
||||
out.setAlarmIndicator(true);
|
||||
}
|
||||
|
||||
void stopAlarm() {
|
||||
System.out.println("Alarm stopped after 5 beeps.");
|
||||
this.setAlarm(false);
|
||||
out.setAlarmIndicator(false);
|
||||
}
|
||||
}
|
97
clock/src/NaiveTime.java
Normal file
97
clock/src/NaiveTime.java
Normal file
|
@ -0,0 +1,97 @@
|
|||
/**
|
||||
* A simple class to represent time in hours, minutes, and seconds.
|
||||
* This is not time zone aware, and does not account for leap seconds.
|
||||
*/
|
||||
public final class NaiveTime {
|
||||
final static int SECONDS_IN_DAY = 60 * 60 * 24;
|
||||
private int unix; // Not actually unix time
|
||||
|
||||
/**
|
||||
* Create a new NaiveTime object with the given time
|
||||
*/
|
||||
public NaiveTime(int h, int m, int s) {
|
||||
this.unix = h * 3600 + m * 60 + s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new NaiveTime object with the given time in seconds
|
||||
*
|
||||
* @param unix the time in seconds since midnight
|
||||
*/
|
||||
public NaiveTime(int unix) {
|
||||
this.unix = unix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new NaiveTime object with the time set to midnight
|
||||
*/
|
||||
public NaiveTime() {
|
||||
this(0, 0, 0);
|
||||
}
|
||||
|
||||
/** Advance the NaiveTime by one second */
|
||||
public void tick() {
|
||||
this.unix = (this.unix + 1) % SECONDS_IN_DAY;
|
||||
}
|
||||
|
||||
/** Set the time */
|
||||
public void set(int h, int m, int s) {
|
||||
// This sanity check will do for now
|
||||
assert h >= 0 && h < 24;
|
||||
assert m >= 0 && m < 60;
|
||||
assert s >= 0 && s < 60;
|
||||
|
||||
// Wrap around at midnight, if for some reason above assertions fail
|
||||
this.unix = (h * 3600 + m * 60 + s) % SECONDS_IN_DAY;
|
||||
}
|
||||
|
||||
/** Returns the hour portion */
|
||||
public int hour() {
|
||||
return this.unix / 3600;
|
||||
}
|
||||
|
||||
/** Set the hour */
|
||||
public void setHour(int h) {
|
||||
this.unix = (h * 3600) + (this.unix % 3600);
|
||||
}
|
||||
|
||||
/** Returns the minute portion */
|
||||
public int min() {
|
||||
return (this.unix % 3600) / 60;
|
||||
}
|
||||
|
||||
/** Set minute */
|
||||
public void setMin(int m) {
|
||||
this.unix = (this.unix / 3600) * 3600 + (m * 60) + (this.unix % 60);
|
||||
}
|
||||
|
||||
/** Returns the current second */
|
||||
public int sec() {
|
||||
return this.unix % 60;
|
||||
}
|
||||
|
||||
/** Set second */
|
||||
public void setSec(int s) {
|
||||
this.unix = (this.unix / 60) * 60 + s;
|
||||
}
|
||||
|
||||
/** Equality */
|
||||
public boolean equals(NaiveTime other) {
|
||||
return this.unix == other.unix;
|
||||
}
|
||||
|
||||
/** Comparison */
|
||||
public boolean isBefore(NaiveTime other) {
|
||||
return this.unix < other.unix;
|
||||
}
|
||||
|
||||
/** Comparison */
|
||||
public boolean isAfter(NaiveTime other) {
|
||||
return this.unix > other.unix;
|
||||
}
|
||||
|
||||
/** Returns the current time in seconds */
|
||||
public int unix() {
|
||||
return this.unix;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue