Newer
Older
Rafi Zereselasie (raz070)
committed
import java.text.SimpleDateFormat;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
Rafi Zereselasie (raz070)
committed
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
protected Map<Integer, Shift> shifts;
protected Map<Integer, Employee> employees;
protected Map<Integer, TimeOff> timeOff;
Rafi Zereselasie (raz070)
committed
protected Map<String, Float> positions;
ArktikHunter
committed
private boolean isManager;
private int thisEmployee;
private int selectedEmployee;
ArktikHunter
committed
isManager = false; // changes if manager logs in
Rafi Zereselasie (raz070)
committed
this.shifts = new HashMap<>();
this.employees = new HashMap<>();
this.timeOff = new HashMap<>();
Rafi Zereselasie (raz070)
committed
this.positions = new HashMap<>();
try {
InetAddress ip = InetAddress.getByName(hostname);
this.socket = new Socket(ip, port);
System.out.println("Connected to the scheduling server");
new ReceiveThread(this.socket, this).start();
OutputStream output = this.socket.getOutputStream();
this.writer = new PrintWriter(output, true);
} catch (UnknownHostException error) {
System.out.println("Server not found: " + error.getMessage());
} catch (IOException error) {
System.out.println("I/O Error: " + error.getMessage());
}
ArktikHunter
committed
public void setIsManager(boolean aBool){
isManager = aBool;
}
public boolean getIsManager(){
return isManager;
}
public void setThisEmployee(int id){
thisEmployee = selectedEmployee = id;
}
public int getThisEmployee(){
return thisEmployee;
}
//for manager only, allows viewing of weekly schedule by employee
public void setSelectedEmployee(int id){
selectedEmployee = id;
ArktikHunter
committed
}
public int getSelectedEmployee(){
return selectedEmployee;
}
public void dateNext(){
date = date.plusDays(1);
ArktikHunter
committed
}
public void weekNext(){
date = date.plusDays(7);
notifySubscribers();
}
ArktikHunter
committed
public void datePrev(){
date = date.minusDays(1);
ArktikHunter
committed
}
public void weekPrev(){
date = date.minusDays(7);
notifySubscribers();
}
ArktikHunter
committed
//todo: add calender to fill jump field
public void dateJump(LocalDate date){
//this.date = date;
ArktikHunter
committed
}
/*
Name: addEmployee
Parameters:
String firstName: The new employees first name.
String lastName: The new employees last name.
Description: Adds an employee to the database.
Return: String indicating the result
*/
String addEmployee(String firstName, String lastName) {
if (firstName.contains("/") || lastName.contains("/") || firstName.contains(",") || lastName.contains(",")){
return "Illegal character(s)";
}
else {
writer.println("addEmployee/" + firstName + "/" + lastName + "/" + false + "/" + "empty" + "/" + "empty" + "/" + 0.0f);
return "Employee added";
}
void addEmployee(String firstName, String lastName, boolean isManager, String email, String phoneNumber, float wage) {
writer.println("addEmployee/" + firstName + "/" + lastName + "/" + isManager + "/" + email + "/" + phoneNumber +
"/" + wage);
}
String editEmployee(int employeeID, String firstName, String lastName, boolean isManager, String email, String phoneNumber, float wage) {
if (employeeID <= 0){
return "Invalid ID";
}
if (firstName.contains("/") || lastName.contains("/") || firstName.contains(",") || lastName.contains(",")){
return "Name contains illegal character(s)";
}
if(email.contains("/") || email.contains(",")){
return "Email contains illegal character(s)";
}
if(phoneNumber.contains("/") || phoneNumber.contains(",")){
return "phoneNumber contains illegal character(s)";
}
if (wage < 0){
return "Invalid wage";
}
if (this.employees.containsKey(employeeID)) {
writer.println("editEmployee/" + employeeID + "/" + firstName + "/" + lastName + "/" + isManager + "/" + email + "/" + phoneNumber +
"/" + wage);
return "Employee edited";
}
return "Employee does not exist";
/*
Name: removeEmployee
Parameters:
String ID: The employees unique ID.
Description: Removes an employee with the given ID if it exists.
Return: String indicating the result
*/
String removeEmployee(String employeeID) {
if (Integer.parseInt(employeeID) <= 0){
return "Invalid ID";
}
if (this.employees.size() < Integer.parseInt(employeeID)){
return "Employee does not exist";
}
if (this.employees.containsKey(Integer.parseInt(employeeID))) {
writer.println("removeEmployee/" + employeeID);
return "Employee removed";
}
return "Employee does not exist";
/*
Name: getEmployee
Parameters:
int ID: The employees unique ID.
Description: Gets an employee with the given ID if it exists.
Return: The employee object if it exists, null if not
*/
Employee getEmployee(int employeeID) {
return employees.getOrDefault(employeeID, null);
}
/*
Sorry if this breaks anything.
*/
if (employeeSize() == 0){
ArktikHunter
committed
System.out.println("No employees");
}
ArrayList<String> employeeList = new ArrayList<>();
for (Employee employee : this.employees.values()) {
employeeList.add(employee.getFullName());
}
System.out.println(employeeList);
}
/*
Name: employeeSize
Description: Gets the number of employees in the database.
Return: The total number of employees.
*/
int employeeSize(){
return this.employees.size();
/*
Name: getEmployeeByID
Parameters:
int ID: The employees unique ID.
Description: Gets an employee's name with the given ID if it exists.
Return: A string containing the employees full name
*/
if (id <= 0){
return "Invalid ID";
}
if (this.employees.containsKey(id)) {
Employee employee = this.employees.get(id);
return employee.getFullName();
return "No Employee with that ID";
public ArrayList<Employee> getAllEmployees(){
return new ArrayList<Employee>(employees.values());
}
/*
Name: addShift
Parameters:
int ID: The employees unique ID.
String date: The date in yyyy-mm-dd format.
int start: The start time in 24 hour time.
int end: The end time in 24 hour time.
Description: Adds a new shift on the given date.
Return: String indicating the result
*/
String addShift(int id, String date, int start, int end) {
if (id <= 0) {
return "Invalid ID";
}
if (start < 0 || end < 0 || end > 2359 || start >= end) {
return "Invalid start or end time";
}
Rafi Zereselasie (raz070)
committed
//todo: fix this, broke when moved from int to localtime
/*
DateTimeFormatter dbTimeFormat = DateTimeFormatter.ofPattern("kkmm");
LocalTime startTime = LocalTime.parse(String.valueOf(start), dbTimeFormat);
LocalTime endTime = LocalTime.parse(String.valueOf(end), dbTimeFormat);
if (this.employees.containsKey(id)) {
LocalTime[] dayOfTheWeekAvailability = this.employees.get(id).getAvailabilityForDay(LocalDate.parse(date)
.getDayOfWeek().getValue() % 7);
if (dayOfTheWeekAvailability[0].isAfter(startTime) || dayOfTheWeekAvailability[1].isBefore(startTime) || dayOfTheWeekAvailability[1].isBefore(endTime)) {
return "Shift time conflicts with employees availability";
}
Rafi Zereselasie (raz070)
committed
}
for (Shift shift : getShiftsByDay(date)) {
if (shift.getEmployeeID() == id) {
/* Commented out split shift just in case
int otherShiftStart = Integer.parseInt(shift.getStart().toLocalTime().toString().replace(":", ""));
int otherShiftEnd = Integer.parseInt(shift.getEnd().toLocalTime().toString().replace(":", ""));
if (start <= otherShiftEnd && !(end <= otherShiftStart)){
return "Shift time conflict with existing shift";
}
*/
//return "Shift time conflict for employee";
}
} else {
return "No Employee with that ID";
writer.println("addShift/" + id + "/" + date + "/" + start + "/" + end + "/" + " ");
notifySubscribers();
return "New shift added";
boolean hasEmployee(int id){
Rafi Zereselasie (raz070)
committed
//
void addShift(int id, String date, int start, int end, String position){
writer.println("addShift/"+id+"/"+date+"/"+start+"/"+end+"/"+position);
notifySubscribers();
}
/*
Name: removeShift
Parameters:
String shiftID: The unique ID for the shift.
Description: Removes the shift with the given ID if it exists.
Return: String indicating the result
*/
String removeShift(int shiftID){
if (shiftID <= 0){
return "Invalid ID";
}
if (this.shifts.containsKey(shiftID)) {
writer.println("removeShift/" + shiftID);
notifySubscribers();
return "Shift removed";
}
return "Shift does not exist";
String editShift(int shiftID, String day, int start, int end, Boolean availability, int employeeID) {
if (shiftID <= 0){
return "Invalid shift ID";
}
if (employeeID <= 0){
return "Invalid employee ID";
}
return "Invalid start or end time";
}
if (this.shifts.containsKey(shiftID)) {
writer.println("editShift/" + shiftID + "/" + day + "/" + start + "/" + end + "/" + availability + "/" + employeeID);
notifySubscribers();
return "Shift successfully edited";
}
return "Shift does not exist";
/*
Name: getShift
Parameters:
int shiftID: The unique shift ID
Description: Gets the shift with the given ID if it exists.
Return: The shift object if it exists, null if not
*/
Rafi Zereselasie (raz070)
committed
Shift getShift(int shiftID) {
return shifts.getOrDefault(shiftID, null);
Rafi Zereselasie (raz070)
committed
}
/*
Parameters:
- String date in format 2022-03-10.
Return: ArrayList<String> where each string is a shift of format id.yyyy-mm-dd.start.end
*/
ArrayList<Shift> getShiftsByDay(String date){
ArrayList<Shift> shifts = new ArrayList<>();
for (Shift shift : this.shifts.values()) {
if (shift.getDate().equals(date)) {
shifts.add(shift);
return shifts;
/*
Parameters:
startOfWeek - The first day of the week in "yyyy-mm-dd" format
endOfWeek - The last day of the week in "yyyy-mm-dd" format
Return: ArrayList<String>
*/
ArrayList<Shift> getShiftsByWeek(LocalDateTime startOfWeek, LocalDateTime endOfWeek){
ArrayList<Shift> shifts = new ArrayList<>();
for (Shift shift : this.shifts.values()) {
LocalDateTime start = shift.getStart();
LocalDateTime end = shift.getEnd();
if ((start.isAfter(startOfWeek) || start.isEqual(startOfWeek)) && (end.isBefore(endOfWeek)) ||
end.isEqual(endOfWeek)) {
shifts.add(shift);
return shifts;
//for view
public ArrayList<Shift> getWeeklySchedule(){
LocalDateTime start;
LocalDateTime end;
// get start and end dates to pass along
int today = date.getDayOfWeek().getValue(); // Mon is 1, Sun is 7
if (today == 7) { //this is the start date
start = date.atTime(0, 0);
end = date.plusDays(6).atTime(0,0);
start = date.minusDays(today).atTime(0, 0);
end = date.plusDays(6 - today).atTime(0, 0);
return getEmployeeShiftsByWeek(selectedEmployee, start, end);
}
//for view
public ArrayList<Shift> getDailySchedule(){
return getShiftsByDay(date.toString());
ArrayList<Shift> getEmployeeShifts(String id) {
int intID = -1;
try {
intID = Integer.parseInt(id);
} catch (NumberFormatException exception) {
exception.printStackTrace();
}
ArrayList<Shift> shifts = new ArrayList<>();
for (Shift shift: this.shifts.values()) {
if (shift.getEmployeeID() == intID) {
shifts.add(shift);
return shifts;
}
ArrayList<Shift> getEmployeeShiftsByWeek(int employeeID, LocalDateTime startOfWeek, LocalDateTime endOfWeek){
ArrayList<Shift> shifts = new ArrayList<>();
for (Shift shift : this.shifts.values()) {
LocalDateTime start = shift.getStart();
LocalDateTime end = shift.getEnd();
if ((shift.getEmployeeID() == employeeID) && (start.isAfter(startOfWeek) || start.isEqual(startOfWeek)) &&
(end.isBefore(endOfWeek)) || end.isEqual(endOfWeek)) {
shifts.add(shift);
return shifts;
String editShiftAvailability(int shiftID, boolean available) {
if (shiftID <= 0){
return "Invalid shift ID";
}
if (this.shifts.containsKey(shiftID)) {
writer.println("editShiftAvailability/" + shiftID + "/" + available);
return "Shift edited";
}
return "Shift does not exist";
Rafi Zereselasie (raz070)
committed
}
Rafi Zereselasie (raz070)
committed
// adds a position if its one of the possible positions in the position table.
String addEmployeePosition(int employeeID, String position) {
if (employeeID <= 0){
return "Invalid employee ID";
}
if (!this.positions.containsKey(position)){
return "Position does not exist";
}
if (this.employees.containsKey(employeeID)) {
writer.println("addEmployeePosition/" + employeeID + "/" + position);
return "Position added to employee";
}
return "Employee does not exist";
}
String removeEmployeePosition(int employeeID, String position) {
if (employeeID <= 0){
return "Invalid employee ID";
}
if (!this.positions.containsKey(position)){
return "Position does not exist";
}
if (this.employees.containsKey(employeeID)) {
writer.println("removeEmployeePosition/" + employeeID + "/" + position);
return "Position removed from employee";
}
return "Employee does not exist";
}
String editAvailability(int employeeID, int dayOfTheWeek, int start, int end) {
if (employeeID <= 0){
return "Invalid employee ID";
}
if (dayOfTheWeek < 0 || dayOfTheWeek > 8){
return "Invalid day";
}
if (end < start){
return "End must be after start";
}
if (start < 0 || end < 0 || start > 2400 || end > 2400){
return "Invalid start or end time";
}
if (this.employees.containsKey(employeeID)) {
writer.println("editAvailability/" + employeeID + "/" + dayOfTheWeek + "/" + start + "/" + end);
editLocalAvailability(employeeID, dayOfTheWeek, start, end);
notifySubscribers();
return "Availability changed successfully";
}
return "Employee does not exist";
}
private void editLocalAvailability(int employeeID, int dayOfTheWeek, int start, int end){
employees.get(employeeID).updateAvailability(dayOfTheWeek, intToLocalTime(start), intToLocalTime(end));
}
public LocalTime intToLocalTime(int time){
String resultString;
String sub = "0000";
String timeString = String.valueOf(time);
if (timeString.length() < 4){
resultString = sub.substring(0, 4-timeString.length()) + timeString;
} else {
resultString = timeString;
}
DateTimeFormatter dbTimeFormat = DateTimeFormatter.ofPattern("kkmm");
LocalTime result = LocalTime.parse(resultString, dbTimeFormat);
return result;
}
//"YYYY-MM-DD"
String addTimeOff(int employeeID, String startDate, String endDate, String reason) {
if (employeeID <= 0){
return "Invalid employee ID";
}
if (reason.contains("/") || reason.contains(",")){
return "Illegal character(s)";
}
if (this.employees.containsKey(employeeID)) {
writer.println("addTimeOff/" + employeeID + "/" + startDate + "/" + endDate + "/" + reason);
return "Time off added";
}
return "Employee does not exist";
}
String setTimeOffApproval(int timeOffID, boolean approval) {
if (timeOffID <= 0){
return "Invalid employee ID";
}
if(this.timeOff.containsKey(timeOffID)) {
writer.println("setTimeOffApproval/" + timeOffID + "/" + approval);
return "Time off approved";
}
return "Time off request doesn't exist";
}
String removeTimeOff(int timeOffID) {
if (timeOffID <= 0){
return "Invalid employee ID";
}
if(this.timeOff.containsKey(timeOffID)) {
writer.println("removeTimeOff/" + timeOffID);
return "Time off removed";
}
return "Time off request does not exist";
}
String addPosition(String position, float wage) {
if (position.contains("/") || position.contains(",")){
return "Illegal character(s)";
}
if (wage <= 0){
return "Invalid wage";
}
writer.println("addPosition/" + position + "/" + wage);
return "Position added";
Rafi Zereselasie (raz070)
committed
}
String editPositionWage(String position, float wage) {
if (position.contains("/") || position.contains(",")){
return "Illegal character(s)";
}
if (wage <= 0){
return "Invalid wage";
}
if(this.positions.containsKey(position)) {
writer.println("editPosition/" + position + "/" + wage);
return "Position edited";
}
return "Position does not exist";
Rafi Zereselasie (raz070)
committed
}
String removePosition(String position, float wage) {
if (position.contains("/") || position.contains(",")){
return "Illegal character(s)";
}
if (wage <= 0){
return "Invalid wage";
}
if(this.positions.containsKey(position)) {
writer.println("removePosition/"+ position + "/" + wage);
return "Position removed";
}
return "Position does not exist";
Rafi Zereselasie (raz070)
committed
}
Rafi Zereselasie (raz070)
committed
//How this works is if you start within 5 minutes of your shift than you can "signed-in" and
//assumes you work the whole shift, if you leave early of come in late the shift manager
//must change it in the schedule.
void checkIn(int shiftID) {
LocalDateTime nMinutesAfter = this.shifts.get(shiftID).getStart().plusMinutes(5);
LocalDateTime nMinutesBefore = this.shifts.get(shiftID).getStart().minusMinutes(5);
LocalDateTime now = LocalDateTime.now();
if (nMinutesBefore.isBefore(now) && nMinutesAfter.plusMinutes(5).isAfter(now)) {
writer.println("checkIn/" + shiftID);
}
Rafi Zereselasie (raz070)
committed
}
//This allows the manager to mark any shift as checked-in.
void managerCheckIn(int shiftID) {
writer.println("checkIn/" + shiftID);
}
Rafi Zereselasie (raz070)
committed
//The dates need to be in form "yyyy-mm-dd"
//Also the start and end are inclusive.
float getHoursWorked(int employeeID, String start, String end) {
float hoursWorked = 0.0f;
try {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date startDate = formatter.parse(start);
Date endDate = formatter.parse(end);
for (Shift shift : this.shifts.values()) {
if (shift.getEmployeeID() == employeeID) {
Date shiftDate = formatter.parse(shift.getDate());
if (!startDate.after(shiftDate) && !endDate.before(shiftDate)){
if (shift.isCheckedIn()) {
hoursWorked = (hoursWorked + shift.getEnd().getHour() - shift.getStart().getHour()) + ((shift.getEnd().getMinute() - shift.getStart().getMinute())/60f);
}
}
}
}
} catch (Exception exception) {
exception.printStackTrace();
return -1f;
}
return hoursWorked;
Rafi Zereselasie (raz070)
committed
}
void logOut() {
writer.println("logout");
try {
this.socket.close();
} catch (IOException ex){
System.out.println("Error: Failed to close socket");
}
}
public static void main(String[] args) {
String hostname = "localhost";
int port = 8989;
Model client = new Model(hostname, port);
System.out.print("Retrieving Data");
while(client.employees.isEmpty()){
System.out.print(".");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
System.out.println("Error: ScheduleClient main. Interrupted while retrieving data ");
}
}
System.out.println();
System.out.println("Data retrieved.");
System.out.println("ScheduleClient is ready to use!");
}
public ArrayList<String> returnFormattedEmployeeNames(){
ArrayList<String> result = new ArrayList<>();
for (Employee employee: this.employees.values()) {
result.add(employee.getFullName());
//System.out.println(result);
return result;
}
public ArrayList<String> returnPositions(){
ArrayList<String> result = new ArrayList<>();
for (String position: this.positions.keySet()) {
result.add(position);
}
//System.out.println(result);
Employee[] employeeList = this.employees.values().toArray(new Employee[0]);
return employeeList[index].getEmployeeID();
//for publish/subscribe
public void addSubscriber(ModelSubscriber sub){
subscribers.add(sub);
}
public void notifySubscribers(){
for (ModelSubscriber sub : subscribers){
sub.modelChanged();
}
}