Skip to content

Instantly share code, notes, and snippets.

@trikitrok
Last active March 22, 2026 00:03
Show Gist options
  • Select an option

  • Save trikitrok/a7ab4f9c195bff9de05a2306c6a0e1b9 to your computer and use it in GitHub Desktop.

Select an option

Save trikitrok/a7ab4f9c195bff9de05a2306c6a0e1b9 to your computer and use it in GitHub Desktop.
Final state machine using copilot
package course_duration.domain;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
public abstract class CourseState {
private static final Duration MAX_MINUTES_SHORT_COURSES = Duration.ofMinutes(10);
private final String name;
private final Configuration configuration;
private final Clock clock;
private final CourseView courseView;
private final Duration durationInMinutes;
protected CourseState(String name, Configuration configuration, Clock clock, CourseView courseView, Duration durationInMinutes) {
this.name = name;
this.configuration = configuration;
this.clock = clock;
this.courseView = courseView;
this.durationInMinutes = durationInMinutes;
}
public void showDetails() {
courseView.displayLine("Title: " + getTitle());
courseView.displayLine("Duration: " + durationInMinutes.toMinutes() + " minutes");
courseView.displayLine("Type: " + (isShort() ? "short" : "long"));
}
public abstract CourseState start();
public abstract CourseState end();
protected CourseState transitionToOnGoing() {
return new OnGoingCourseState(name, clock.now(), clock, configuration, courseView);
}
protected CourseState transitionToFinished(Instant startTime) {
var endTime = clock.now();
var duration = Duration.ofMinutes(ChronoUnit.MINUTES.between(startTime, endTime));
return new FinishedCourseState(name, duration, clock, configuration, courseView);
}
private boolean isShort() {
return durationInMinutes.compareTo(MAX_MINUTES_SHORT_COURSES) < 0;
}
private String getTitle() {
String college = configuration.getValue("COLLEGE");
return name + " course in " + (college != null ? college : "not found") + " college";
}
}
package course_duration.domain;
import java.time.Duration;
public class FinishedCourseState extends CourseState {
public FinishedCourseState(String name, Duration durationInMinutes, Clock clock, Configuration configuration, CourseView courseView) {
super(name, configuration, clock, courseView, durationInMinutes);
}
@Override
public CourseState start() {
return this;
}
@Override
public CourseState end() {
return this;
}
}
package course_duration.domain;
import java.time.Duration;
import java.time.Instant;
public class OnGoingCourseState extends CourseState {
private final Instant startTime;
public OnGoingCourseState(String name, Instant startTime, Clock clock, Configuration configuration, CourseView courseView) {
super(name, configuration, clock, courseView, Duration.ZERO);
this.startTime = startTime;
}
@Override
public CourseState start() {
return this;
}
@Override
public CourseState end() {
return transitionToFinished(startTime);
}
}
package course_duration.domain;
import java.time.Duration;
public class YetToStartCourseState extends CourseState {
public YetToStartCourseState(String name, Configuration configuration, Clock clock, CourseView courseView) {
super(name, configuration, clock, courseView, Duration.ZERO);
}
@Override
public CourseState start() {
return transitionToOnGoing();
}
@Override
public CourseState end() {
return this;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment