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.ClockInput.UserInput;
|
||||||
import clock.io.ClockOutput;
|
import clock.io.ClockOutput;
|
||||||
|
|
||||||
|
// Semaphore
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
|
|
||||||
public class ClockMain {
|
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 {
|
public static void main(String[] args) throws InterruptedException {
|
||||||
AlarmClockEmulator emulator = new AlarmClockEmulator();
|
Thread clockThread = new Thread(new ClockThread(monitor, out));
|
||||||
|
|
||||||
ClockInput in = emulator.getInput();
|
|
||||||
ClockOutput out = emulator.getOutput();
|
|
||||||
|
|
||||||
out.displayTime(15, 2, 37); // arbitrary time: just an example
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
sem.acquire();
|
||||||
|
|
||||||
UserInput userInput = in.getUserInput();
|
UserInput userInput = in.getUserInput();
|
||||||
Choice c = userInput.choice();
|
Choice choice = userInput.choice();
|
||||||
|
|
||||||
int h = userInput.hours();
|
int h = userInput.hours();
|
||||||
int m = userInput.minutes();
|
int m = userInput.minutes();
|
||||||
int s = userInput.seconds();
|
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