From 88c9964a55a2e7934dee8131748dbd2789863259 Mon Sep 17 00:00:00 2001
From: DallinFromEarth <112426674+DallinFromEarth@users.noreply.github.com>
Date: Wed, 13 Nov 2024 15:28:06 -0700
Subject: [PATCH 01/17] make frontend component
---
.../frontend/src/views/AdminView/ConfigView.vue | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/src/main/resources/frontend/src/views/AdminView/ConfigView.vue b/src/main/resources/frontend/src/views/AdminView/ConfigView.vue
index 5252c1d2..5f4db841 100644
--- a/src/main/resources/frontend/src/views/AdminView/ConfigView.vue
+++ b/src/main/resources/frontend/src/views/AdminView/ConfigView.vue
@@ -48,6 +48,17 @@ onMounted( async () => {
+
+
+
+
+
+ Daily Late Penalty: 10%
+ Max Days Penalized: 5
+ Git Commit Penalty: 10%
+
+
+
From 3c9843d5d7baa0ae9ed362e4698f297ae6dca5b3 Mon Sep 17 00:00:00 2001
From: DallinFromEarth <112426674+DallinFromEarth@users.noreply.github.com>
Date: Wed, 13 Nov 2024 15:28:25 -0700
Subject: [PATCH 02/17] add setters and getters for config
---
.../byu/cs/dataAccess/ConfigurationDao.java | 5 +++-
.../edu/byu/cs/service/ConfigService.java | 30 +++++++++++++++++++
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/src/main/java/edu/byu/cs/dataAccess/ConfigurationDao.java b/src/main/java/edu/byu/cs/dataAccess/ConfigurationDao.java
index b2b338cd..367c7861 100644
--- a/src/main/java/edu/byu/cs/dataAccess/ConfigurationDao.java
+++ b/src/main/java/edu/byu/cs/dataAccess/ConfigurationDao.java
@@ -17,6 +17,9 @@ enum Configuration {
PHASE4_ASSIGNMENT_NUMBER,
PHASE5_ASSIGNMENT_NUMBER,
PHASE6_ASSIGNMENT_NUMBER,
- COURSE_NUMBER
+ COURSE_NUMBER,
+ MAX_LATE_DAYS_TO_PENALIZE,
+ PER_DAY_LATE_PENALTY,
+ GIT_COMMIT_PENALTY
}
}
diff --git a/src/main/java/edu/byu/cs/service/ConfigService.java b/src/main/java/edu/byu/cs/service/ConfigService.java
index 876b39c7..52e015cb 100644
--- a/src/main/java/edu/byu/cs/service/ConfigService.java
+++ b/src/main/java/edu/byu/cs/service/ConfigService.java
@@ -211,4 +211,34 @@ public static void updateCourseIdsUsingCanvas(User user) throws CanvasException,
user.netId()
);
}
+
+ public static void setMaxLateDays(User user, Integer maxDays) throws DataAccessException {
+ ConfigurationDao dao = DaoService.getConfigurationDao();
+ dao.setConfiguration(ConfigurationDao.Configuration.MAX_LATE_DAYS_TO_PENALIZE, maxDays, Integer.class);
+ logConfigChange("set maximum late days penalized to %s".formatted(maxDays), user.netId());
+ }
+
+ /**
+ *
+ * @param user the user making the change
+ * @param perDayPenalty the penalty per day that should be applied. For example, a 10% penalty per day should be
+ * passed in as 0.1
+ */
+ public static void setPerDayLatePenalty(User user, Float perDayPenalty) throws DataAccessException {
+ ConfigurationDao dao = DaoService.getConfigurationDao();
+ dao.setConfiguration(ConfigurationDao.Configuration.PER_DAY_LATE_PENALTY, perDayPenalty, Float.class);
+ logConfigChange("set the per day late penalty to %s".formatted(perDayPenalty), user.netId());
+ }
+
+ /**
+ *
+ * @param user the user making the change
+ * @param gitCommitPenalty the penalty should be applied for not having enough commits. For example, a 10%
+ * penalty per day should be passed in as 0.1
+ */
+ public static void setGitCommitPenalty(User user, Float gitCommitPenalty) throws DataAccessException {
+ ConfigurationDao dao = DaoService.getConfigurationDao();
+ dao.setConfiguration(ConfigurationDao.Configuration.GIT_COMMIT_PENALTY, gitCommitPenalty, Float.class);
+ logConfigChange("set the git commit penalty to %s".formatted(gitCommitPenalty), user.netId());
+ }
}
From 69be0350ee4d7be8c0d4febcf1aefb8eabd009fe Mon Sep 17 00:00:00 2001
From: DallinFromEarth <112426674+DallinFromEarth@users.noreply.github.com>
Date: Thu, 14 Nov 2024 00:47:16 -0700
Subject: [PATCH 03/17] read penalty values on frontend from backend
---
.../byu/cs/controller/ConfigController.java | 16 ++++++++++++++++
.../dataAccess/sql/ConfigurationSqlDao.java | 10 +++++++---
src/main/java/edu/byu/cs/server/Server.java | 2 ++
.../edu/byu/cs/service/ConfigService.java | 10 ++++++++++
.../frontend/src/stores/appConfig.ts | 19 ++++++++++++++++++-
.../src/views/AdminView/ConfigView.vue | 6 +++---
6 files changed, 56 insertions(+), 7 deletions(-)
diff --git a/src/main/java/edu/byu/cs/controller/ConfigController.java b/src/main/java/edu/byu/cs/controller/ConfigController.java
index c111a7fc..896285c7 100644
--- a/src/main/java/edu/byu/cs/controller/ConfigController.java
+++ b/src/main/java/edu/byu/cs/controller/ConfigController.java
@@ -90,4 +90,20 @@ public class ConfigController {
res.status(200);
return "";
};
+
+ public static final Route updatePenalties = (req, res) -> {
+ User user = req.session().attribute("user");
+
+ Gson gson = new Gson();
+ JsonObject jsonObject = gson.fromJson(req.body(), JsonObject.class);
+ Float perDayLatePenalty = gson.fromJson(jsonObject.get("perDayLatePenalty"), Float.class);
+ Float gitCommitPenalty = gson.fromJson(jsonObject.get("gitCommitPenalty"), Float.class);
+ Integer maxLateDaysPenalized = gson.fromJson(jsonObject.get("maxLateDaysPenalized"), Integer.class);
+
+ ConfigService.setMaxLateDays(user, maxLateDaysPenalized);
+ ConfigService.setGitCommitPenalty(user, gitCommitPenalty);
+ ConfigService.setPerDayLatePenalty(user, perDayLatePenalty);
+
+ return "";
+ };
}
diff --git a/src/main/java/edu/byu/cs/dataAccess/sql/ConfigurationSqlDao.java b/src/main/java/edu/byu/cs/dataAccess/sql/ConfigurationSqlDao.java
index 822bced4..c7865405 100644
--- a/src/main/java/edu/byu/cs/dataAccess/sql/ConfigurationSqlDao.java
+++ b/src/main/java/edu/byu/cs/dataAccess/sql/ConfigurationSqlDao.java
@@ -50,7 +50,7 @@ public T getConfiguration(Configuration key, Class type) throws DataAcces
statement.setString(1, key.toString());
var rs = statement.executeQuery();
if (rs.next()) {
- return getValue(rs.getString("value"), type);
+ return getValue(key, rs.getString("value"), type);
}
throw new DataAccessException("Configuration not found: " + key);
} catch (Exception e) {
@@ -58,9 +58,9 @@ public T getConfiguration(Configuration key, Class type) throws DataAcces
}
}
- private T getValue(String value, Class type) {
+ private T getValue(Configuration key, String value, Class type) {
if (value.equals(DEFAULT_VALUE)) {
- LOGGER.warn("Using default configuration value for key: {}", type);
+ LOGGER.warn("Using default configuration value for key: {} of type {}", key, type);
if (type == String.class) {
return type.cast("");
@@ -68,6 +68,8 @@ private T getValue(String value, Class type) {
return type.cast(0);
} else if (type == Boolean.class) {
return type.cast(false);
+ } else if (type == Float.class) {
+ return type.cast(0f);
} else {
throw new IllegalArgumentException("Unsupported configuration type: " + type);
}
@@ -81,6 +83,8 @@ private T getValue(String value, Class type) {
return type.cast(Boolean.parseBoolean(value));
} else if (type == Instant.class) {
return type.cast(Instant.parse(value));
+ } else if (type == Float.class) {
+ return type.cast(Float.parseFloat(value));
} else {
throw new IllegalArgumentException("Unsupported configuration type: " + type);
}
diff --git a/src/main/java/edu/byu/cs/server/Server.java b/src/main/java/edu/byu/cs/server/Server.java
index eee8d25a..9adb3165 100644
--- a/src/main/java/edu/byu/cs/server/Server.java
+++ b/src/main/java/edu/byu/cs/server/Server.java
@@ -116,6 +116,8 @@ public static int setupEndpoints(int port) {
post("/courseIds", updateCourseIdsPost);
get("/courseIds", updateCourseIdsUsingCanvasGet);
+
+ post("/penalties", updatePenalties);
});
});
});
diff --git a/src/main/java/edu/byu/cs/service/ConfigService.java b/src/main/java/edu/byu/cs/service/ConfigService.java
index 52e015cb..742b7df0 100644
--- a/src/main/java/edu/byu/cs/service/ConfigService.java
+++ b/src/main/java/edu/byu/cs/service/ConfigService.java
@@ -55,6 +55,14 @@ private static void addBannerConfig(JsonObject response) throws DataAccessExcept
response.addProperty("bannerExpiration", bannerExpiration.toString());
}
+ private static void addPenaltyConfig(JsonObject response) throws DataAccessException {
+ ConfigurationDao dao = DaoService.getConfigurationDao();
+
+ response.addProperty("perDayLatePenalty", dao.getConfiguration(ConfigurationDao.Configuration.PER_DAY_LATE_PENALTY, Float.class));
+ response.addProperty("gitCommitPenalty", dao.getConfiguration(ConfigurationDao.Configuration.GIT_COMMIT_PENALTY, Float.class));
+ response.addProperty("maxLateDaysPenalized", dao.getConfiguration(ConfigurationDao.Configuration.MAX_LATE_DAYS_TO_PENALIZE, Integer.class));
+ }
+
private static void clearBannerConfig() throws DataAccessException {
ConfigurationDao dao = DaoService.getConfigurationDao();
@@ -100,6 +108,8 @@ public static JsonObject getPrivateConfig() throws DataAccessException {
}
JsonObject response = getPublicConfig();
+ addPenaltyConfig(response);
+
int courseNumber = DaoService.getConfigurationDao().getConfiguration(
ConfigurationDao.Configuration.COURSE_NUMBER,
Integer.class
diff --git a/src/main/resources/frontend/src/stores/appConfig.ts b/src/main/resources/frontend/src/stores/appConfig.ts
index 5e8a17fe..5750d3c9 100644
--- a/src/main/resources/frontend/src/stores/appConfig.ts
+++ b/src/main/resources/frontend/src/stores/appConfig.ts
@@ -12,6 +12,11 @@ export type Config = {
bannerLink: string
bannerColor: string
bannerExpiration: string
+
+ perDayLatePenalty: number,
+ gitCommitPenalty: number,
+ maxLateDaysPenalized: number,
+
phases: Array
courseNumber?: number
assignmentIds?: string // Map
@@ -49,6 +54,10 @@ export const useAppConfigStore = defineStore('appConfig', () => {
bannerColor.value = "#4fa0ff"
}
+ perDayLatePenalty.value = latestConfig.perDayLatePenalty
+ gitCommitPenalty.value = latestConfig.gitCommitPenalty
+ maxLateDaysPenalized.value = latestConfig.maxLateDaysPenalized
+
for (const phase of listOfPhases() as Phase[]) {
activePhaseList.value[phase] = latestConfig.phases.includes(phase);
}
@@ -68,6 +77,11 @@ export const useAppConfigStore = defineStore('appConfig', () => {
const bannerLink: Ref = ref("");
const bannerColor: Ref = ref("");
const bannerExpiration: Ref = ref("");
+
+ const perDayLatePenalty = ref(0)
+ const gitCommitPenalty = ref(0)
+ const maxLateDaysPenalized = ref(0)
+
// using the enum, if phaseActivationList[phase] == true, then that phase is active
const activePhaseList: Ref = ref>([]);
const assignmentIds: Ref> = ref>(new Map);
@@ -85,6 +99,9 @@ export const useAppConfigStore = defineStore('appConfig', () => {
phaseActivationList: activePhaseList,
rubricInfo,
assignmentIds,
- courseNumber
+ courseNumber,
+ perDayLatePenalty,
+ gitCommitPenalty,
+ maxLateDaysPenalized
};
})
diff --git a/src/main/resources/frontend/src/views/AdminView/ConfigView.vue b/src/main/resources/frontend/src/views/AdminView/ConfigView.vue
index 5f4db841..24f4c430 100644
--- a/src/main/resources/frontend/src/views/AdminView/ConfigView.vue
+++ b/src/main/resources/frontend/src/views/AdminView/ConfigView.vue
@@ -53,9 +53,9 @@ onMounted( async () => {
- Daily Late Penalty: 10%
- Max Days Penalized: 5
- Git Commit Penalty: 10%
+ Daily Late Penalty: {{appConfigStore.perDayLatePenalty * 100}}%
+ Max Days Penalized: {{appConfigStore.maxLateDaysPenalized}} days
+ Git Commit Penalty: {{appConfigStore.gitCommitPenalty * 100}}%
From 4c3bde49d9cdd4da672ca10918880a29e4941bca Mon Sep 17 00:00:00 2001
From: DallinFromEarth <112426674+DallinFromEarth@users.noreply.github.com>
Date: Thu, 14 Nov 2024 01:31:48 -0700
Subject: [PATCH 04/17] fix floating point math error on front end
---
.../components/config/BannerConfigEditor.vue | 7 ++-
.../config/LivePhaseConfigEditor.vue | 5 +-
.../components/config/PenaltyConfigEditor.vue | 63 +++++++++++++++++++
.../frontend/src/services/configService.ts | 8 +++
.../src/views/AdminView/ConfigView.vue | 7 ++-
5 files changed, 82 insertions(+), 8 deletions(-)
create mode 100644 src/main/resources/frontend/src/components/config/PenaltyConfigEditor.vue
diff --git a/src/main/resources/frontend/src/components/config/BannerConfigEditor.vue b/src/main/resources/frontend/src/components/config/BannerConfigEditor.vue
index f6729e96..7c800258 100644
--- a/src/main/resources/frontend/src/components/config/BannerConfigEditor.vue
+++ b/src/main/resources/frontend/src/components/config/BannerConfigEditor.vue
@@ -31,10 +31,11 @@ const submitBanner = async () => {
}
try {
await setBanner(bannerMessageToSubmit.value, bannerLinkToSubmit.value, bannerColorToSubmit.value, combinedDateTime)
+ closeEditor()
} catch (e) {
+ appConfigStore.updateConfig()
alert("There was a problem in saving the updated banner message:\n" + e)
}
- closeEditor()
}
@@ -65,8 +66,8 @@ const submitBanner = async () => {
- Save
- Clear
+ Submit
+ Clear Editor
diff --git a/src/main/resources/frontend/src/components/config/LivePhaseConfigEditor.vue b/src/main/resources/frontend/src/components/config/LivePhaseConfigEditor.vue
index de746ea9..8ebee204 100644
--- a/src/main/resources/frontend/src/components/config/LivePhaseConfigEditor.vue
+++ b/src/main/resources/frontend/src/components/config/LivePhaseConfigEditor.vue
@@ -24,10 +24,11 @@ const submitLivePhases = async () => {
try {
await setLivePhases(livePhases)
+ closeEditor()
} catch (e) {
+ appConfigStore.updateConfig()
alert("There was a problem in saving live phases")
}
- closeEditor()
}
@@ -44,7 +45,7 @@ const submitLivePhases = async () => {
Enable all
Disable all
- Submit Changes
+ Submit
diff --git a/src/main/resources/frontend/src/components/config/PenaltyConfigEditor.vue b/src/main/resources/frontend/src/components/config/PenaltyConfigEditor.vue
new file mode 100644
index 00000000..859301fa
--- /dev/null
+++ b/src/main/resources/frontend/src/components/config/PenaltyConfigEditor.vue
@@ -0,0 +1,63 @@
+
+
+
+
+
Git Commit Penalty
+
Applied when students don't have enough commits
+
%
+
+
+
+
Late Penalty
+
Applied per day the submission is late
+
%
+
+
+
+
Max Late Days
+
Days after which the late penalty caps out
+
days
+
+
+ Submit
+
+
+
diff --git a/src/main/resources/frontend/src/services/configService.ts b/src/main/resources/frontend/src/services/configService.ts
index 605b266f..653c7206 100644
--- a/src/main/resources/frontend/src/services/configService.ts
+++ b/src/main/resources/frontend/src/services/configService.ts
@@ -13,6 +13,14 @@ export const getConfig = async ():Promise => {
return await ServerCommunicator.getRequest(endpoint)
}
+export const setPenalties = async (maxLateDaysPenalized: number, gitCommitPenalty: number, perDayLatePenalty: number) => {
+ await doSetConfigItem("POST", '/api/admin/config/penalties', {
+ maxLateDaysPenalized: maxLateDaysPenalized,
+ gitCommitPenalty: gitCommitPenalty,
+ perDayLatePenalty: perDayLatePenalty,
+ })
+}
+
export const setBanner = async (message: String, link: String, color: String, expirationTimestamp: String): Promise => {
await doSetConfigItem("POST", '/api/admin/config/banner', {
"bannerMessage": message,
diff --git a/src/main/resources/frontend/src/views/AdminView/ConfigView.vue b/src/main/resources/frontend/src/views/AdminView/ConfigView.vue
index 24f4c430..e0ef45f2 100644
--- a/src/main/resources/frontend/src/views/AdminView/ConfigView.vue
+++ b/src/main/resources/frontend/src/views/AdminView/ConfigView.vue
@@ -4,6 +4,7 @@ import { listOfPhases } from '@/types/types'
import { useAppConfigStore } from '@/stores/appConfig'
import { generateClickableLink, readableTimestamp } from '@/utils/utils'
import ConfigSection from '@/components/config/ConfigSection.vue'
+import PenaltyConfigEditor from '@/components/config/PenaltyConfigEditor.vue'
// Lazy Load Editor Components
const BannerConfigEditor = defineAsyncComponent(() => import('@/components/config/BannerConfigEditor.vue'))
@@ -50,12 +51,12 @@ onMounted( async () => {
-
+
- Daily Late Penalty: {{appConfigStore.perDayLatePenalty * 100}}%
+ Git Commit Penalty: {{Math.round(appConfigStore.gitCommitPenalty * 100)}}%
+ Late Penalty: {{Math.round(appConfigStore.perDayLatePenalty * 100)}}%
Max Days Penalized: {{appConfigStore.maxLateDaysPenalized}} days
- Git Commit Penalty: {{appConfigStore.gitCommitPenalty * 100}}%
From 603c3bc87107e538fdf696eef03c44794e0678dc Mon Sep 17 00:00:00 2001
From: DallinFromEarth <112426674+DallinFromEarth@users.noreply.github.com>
Date: Thu, 14 Nov 2024 01:46:07 -0700
Subject: [PATCH 05/17] add argument validation on front and backend
---
src/main/java/edu/byu/cs/service/ConfigService.java | 12 ++++++++++++
.../src/components/config/PenaltyConfigEditor.vue | 13 +++++++++++--
2 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/src/main/java/edu/byu/cs/service/ConfigService.java b/src/main/java/edu/byu/cs/service/ConfigService.java
index 742b7df0..b1619cfe 100644
--- a/src/main/java/edu/byu/cs/service/ConfigService.java
+++ b/src/main/java/edu/byu/cs/service/ConfigService.java
@@ -223,6 +223,10 @@ public static void updateCourseIdsUsingCanvas(User user) throws CanvasException,
}
public static void setMaxLateDays(User user, Integer maxDays) throws DataAccessException {
+ if (maxDays < 0) {
+ throw new IllegalArgumentException("Max Late Days must be non-negative");
+ }
+
ConfigurationDao dao = DaoService.getConfigurationDao();
dao.setConfiguration(ConfigurationDao.Configuration.MAX_LATE_DAYS_TO_PENALIZE, maxDays, Integer.class);
logConfigChange("set maximum late days penalized to %s".formatted(maxDays), user.netId());
@@ -235,6 +239,10 @@ public static void setMaxLateDays(User user, Integer maxDays) throws DataAccessE
* passed in as 0.1
*/
public static void setPerDayLatePenalty(User user, Float perDayPenalty) throws DataAccessException {
+ if ((perDayPenalty < 0) || (perDayPenalty > 1)) {
+ throw new IllegalArgumentException("Per Day Late Penalty must be 0-1");
+ }
+
ConfigurationDao dao = DaoService.getConfigurationDao();
dao.setConfiguration(ConfigurationDao.Configuration.PER_DAY_LATE_PENALTY, perDayPenalty, Float.class);
logConfigChange("set the per day late penalty to %s".formatted(perDayPenalty), user.netId());
@@ -247,6 +255,10 @@ public static void setPerDayLatePenalty(User user, Float perDayPenalty) throws D
* penalty per day should be passed in as 0.1
*/
public static void setGitCommitPenalty(User user, Float gitCommitPenalty) throws DataAccessException {
+ if ((gitCommitPenalty < 0) || (gitCommitPenalty > 1)) {
+ throw new IllegalArgumentException("Git Commit Penalty must be 0-1");
+ }
+
ConfigurationDao dao = DaoService.getConfigurationDao();
dao.setConfiguration(ConfigurationDao.Configuration.GIT_COMMIT_PENALTY, gitCommitPenalty, Float.class);
logConfigChange("set the git commit penalty to %s".formatted(gitCommitPenalty), user.netId());
diff --git a/src/main/resources/frontend/src/components/config/PenaltyConfigEditor.vue b/src/main/resources/frontend/src/components/config/PenaltyConfigEditor.vue
index 859301fa..6c5aa41c 100644
--- a/src/main/resources/frontend/src/components/config/PenaltyConfigEditor.vue
+++ b/src/main/resources/frontend/src/components/config/PenaltyConfigEditor.vue
@@ -13,6 +13,12 @@ const gitPenalty = ref(Math.round(appConfig.gitCommitPenalty * 100))
const latePenalty = ref(Math.round(appConfig.perDayLatePenalty * 100))
const maxLateDays = ref(appConfig.maxLateDaysPenalized)
+const valuesReady = () => {
+ return (gitPenalty.value >= 0) && (gitPenalty.value <= 100)
+ && (latePenalty.value >= 0) && (latePenalty.value <= 100)
+ && (maxLateDays.value >= 0)
+}
+
const submit = async () => {
try {
await setPenalties(maxLateDays.value, gitPenalty.value / 100, latePenalty.value / 100)
@@ -43,7 +49,8 @@ const submit = async () => {
days
- Submit
+ Submit
+ All values must be non-negative, and penalties must be equal to or less than 100%
From 94307a65c132f5b635b169b3ed885510b3d38dde Mon Sep 17 00:00:00 2001
From: DallinFromEarth <112426674+DallinFromEarth@users.noreply.github.com>
Date: Thu, 14 Nov 2024 01:57:15 -0700
Subject: [PATCH 06/17] skip logging if value didn't change
---
.../java/edu/byu/cs/service/ConfigService.java | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/src/main/java/edu/byu/cs/service/ConfigService.java b/src/main/java/edu/byu/cs/service/ConfigService.java
index b1619cfe..fde59159 100644
--- a/src/main/java/edu/byu/cs/service/ConfigService.java
+++ b/src/main/java/edu/byu/cs/service/ConfigService.java
@@ -22,17 +22,18 @@
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.Map;
+import java.util.Objects;
public class ConfigService {
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigService.class);
private static void logConfigChange(String changeMessage, String adminNetId) {
- LOGGER.info("[CONFIG] Admin {} has {}}", adminNetId, changeMessage);
+ LOGGER.info("[CONFIG] Admin {} has {}", adminNetId, changeMessage);
}
private static void logAutomaticConfigChange(String changeMessage) {
- LOGGER.info("[CONFIG] Automatic change: {}}", changeMessage);
+ LOGGER.info("[CONFIG] Automatic change: {}", changeMessage);
}
/**
@@ -228,6 +229,10 @@ public static void setMaxLateDays(User user, Integer maxDays) throws DataAccessE
}
ConfigurationDao dao = DaoService.getConfigurationDao();
+
+ Integer current = dao.getConfiguration(ConfigurationDao.Configuration.MAX_LATE_DAYS_TO_PENALIZE, Integer.class);
+ if (current.equals(maxDays)) { return; }
+
dao.setConfiguration(ConfigurationDao.Configuration.MAX_LATE_DAYS_TO_PENALIZE, maxDays, Integer.class);
logConfigChange("set maximum late days penalized to %s".formatted(maxDays), user.netId());
}
@@ -244,6 +249,10 @@ public static void setPerDayLatePenalty(User user, Float perDayPenalty) throws D
}
ConfigurationDao dao = DaoService.getConfigurationDao();
+
+ Float current = dao.getConfiguration(ConfigurationDao.Configuration.PER_DAY_LATE_PENALTY, Float.class);
+ if (current.equals(perDayPenalty)) { return; }
+
dao.setConfiguration(ConfigurationDao.Configuration.PER_DAY_LATE_PENALTY, perDayPenalty, Float.class);
logConfigChange("set the per day late penalty to %s".formatted(perDayPenalty), user.netId());
}
@@ -260,6 +269,10 @@ public static void setGitCommitPenalty(User user, Float gitCommitPenalty) throws
}
ConfigurationDao dao = DaoService.getConfigurationDao();
+
+ Float current = dao.getConfiguration(ConfigurationDao.Configuration.GIT_COMMIT_PENALTY, Float.class);
+ if (current.equals(gitCommitPenalty)) { return; }
+
dao.setConfiguration(ConfigurationDao.Configuration.GIT_COMMIT_PENALTY, gitCommitPenalty, Float.class);
logConfigChange("set the git commit penalty to %s".formatted(gitCommitPenalty), user.netId());
}
From 4b66a9f58c25b6ff53acc4bc9482d1929a04f03b Mon Sep 17 00:00:00 2001
From: DallinFromEarth <112426674+DallinFromEarth@users.noreply.github.com>
Date: Thu, 14 Nov 2024 10:08:02 -0700
Subject: [PATCH 07/17] integrate late penalty values
---
.../cs/autograder/score/LateDayCalculator.java | 8 +++-----
.../edu/byu/cs/autograder/score/Scorer.java | 18 +++++++++++++++---
2 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/src/main/java/edu/byu/cs/autograder/score/LateDayCalculator.java b/src/main/java/edu/byu/cs/autograder/score/LateDayCalculator.java
index fe340f8b..d9aeafe2 100644
--- a/src/main/java/edu/byu/cs/autograder/score/LateDayCalculator.java
+++ b/src/main/java/edu/byu/cs/autograder/score/LateDayCalculator.java
@@ -3,6 +3,7 @@
import edu.byu.cs.autograder.GradingException;
import edu.byu.cs.canvas.CanvasException;
import edu.byu.cs.canvas.CanvasService;
+import edu.byu.cs.dataAccess.ConfigurationDao;
import edu.byu.cs.dataAccess.DaoService;
import edu.byu.cs.dataAccess.DataAccessException;
import edu.byu.cs.model.Phase;
@@ -30,10 +31,6 @@ public class LateDayCalculator {
private static final Logger LOGGER = Logger.getLogger(LateDayCalculator.class.getName());
- /**
- * The max number of days that the late penalty should be applied for.
- */
- private static final int MAX_LATE_DAYS_TO_PENALIZE = 5;
private Set publicHolidays;
public LateDayCalculator() {
@@ -54,7 +51,8 @@ public int calculateLateDays(Phase phase, String netId) throws GradingException,
}
ZonedDateTime handInDate = ScorerHelper.getHandInDateZoned(netId);
- return Math.min(getNumDaysLate(handInDate, dueDate), MAX_LATE_DAYS_TO_PENALIZE);
+ int maxLateDaysToPenalize = DaoService.getConfigurationDao().getConfiguration(ConfigurationDao.Configuration.MAX_LATE_DAYS_TO_PENALIZE, Integer.class);
+ return Math.min(getNumDaysLate(handInDate, dueDate), maxLateDaysToPenalize);
}
/**
diff --git a/src/main/java/edu/byu/cs/autograder/score/Scorer.java b/src/main/java/edu/byu/cs/autograder/score/Scorer.java
index b4402c08..4e747400 100644
--- a/src/main/java/edu/byu/cs/autograder/score/Scorer.java
+++ b/src/main/java/edu/byu/cs/autograder/score/Scorer.java
@@ -9,6 +9,7 @@
import edu.byu.cs.canvas.model.CanvasRubricAssessment;
import edu.byu.cs.canvas.model.CanvasRubricItem;
import edu.byu.cs.canvas.model.CanvasSubmission;
+import edu.byu.cs.dataAccess.ConfigurationDao;
import edu.byu.cs.dataAccess.DaoService;
import edu.byu.cs.dataAccess.DataAccessException;
import edu.byu.cs.dataAccess.UserDao;
@@ -33,11 +34,17 @@ public class Scorer {
* The penalty to be applied per day to a late submission.
* This is out of 1. So putting 0.1 would be a 10% deduction per day
*/
- private static final float PER_DAY_LATE_PENALTY = 0.1F;
+ private final float PER_DAY_LATE_PENALTY;
private final GradingContext gradingContext;
public Scorer(GradingContext gradingContext) {
this.gradingContext = gradingContext;
+ try {
+ PER_DAY_LATE_PENALTY = DaoService.getConfigurationDao().getConfiguration(ConfigurationDao.Configuration.PER_DAY_LATE_PENALTY, Float.class);
+ } catch (DataAccessException e) {
+ LOGGER.error("Error while getting Per Day Late Penalty for Scorer.");
+ throw new RuntimeException(e);
+ }
}
/**
@@ -394,8 +401,13 @@ public Submission generateSubmissionObject(Rubric rubric, CommitVerificationResu
String headHash = commitVerificationResult.headHash();
String netId = gradingContext.netId();
- if (numDaysLate > 0)
- notes += " " + numDaysLate + " days late. -" + (int)(numDaysLate * PER_DAY_LATE_PENALTY * 100) + "%";
+ Integer maxLateDays = DaoService.getConfigurationDao().getConfiguration(ConfigurationDao.Configuration.MAX_LATE_DAYS_TO_PENALIZE, Integer.class);
+
+ if (numDaysLate >= maxLateDays)
+ notes += " Late penalty maxed out at " + numDaysLate + " days late: -";
+ else if (numDaysLate > 0)
+ notes += " " + numDaysLate + " days late: -";
+ notes += (int)(numDaysLate * PER_DAY_LATE_PENALTY * 100) + "%";
ZonedDateTime handInDate = ScorerHelper.getHandInDateZoned(netId);
Submission.VerifiedStatus verifiedStatus;
From e0c041b2ed40c47e1ae2a0b3615756ced24d6857 Mon Sep 17 00:00:00 2001
From: DallinFromEarth <112426674+DallinFromEarth@users.noreply.github.com>
Date: Fri, 15 Nov 2024 19:39:04 -0700
Subject: [PATCH 08/17] add git commit penalty
---
.../edu/byu/cs/autograder/score/Scorer.java | 2 +-
.../edu/byu/cs/service/SubmissionService.java | 3 +-
src/main/java/edu/byu/cs/util/PhaseUtils.java | 7 ++-
.../src/components/config/ConfigSection.vue | 4 +-
.../components/config/PenaltyConfigEditor.vue | 47 +++++++++++++------
5 files changed, 44 insertions(+), 19 deletions(-)
diff --git a/src/main/java/edu/byu/cs/autograder/score/Scorer.java b/src/main/java/edu/byu/cs/autograder/score/Scorer.java
index 4e747400..4389f1f4 100644
--- a/src/main/java/edu/byu/cs/autograder/score/Scorer.java
+++ b/src/main/java/edu/byu/cs/autograder/score/Scorer.java
@@ -407,7 +407,7 @@ public Submission generateSubmissionObject(Rubric rubric, CommitVerificationResu
notes += " Late penalty maxed out at " + numDaysLate + " days late: -";
else if (numDaysLate > 0)
notes += " " + numDaysLate + " days late: -";
- notes += (int)(numDaysLate * PER_DAY_LATE_PENALTY * 100) + "%";
+ notes += (int)(numDaysLate * PER_DAY_LATE_PENALTY * 100) + "% ";
ZonedDateTime handInDate = ScorerHelper.getHandInDateZoned(netId);
Submission.VerifiedStatus verifiedStatus;
diff --git a/src/main/java/edu/byu/cs/service/SubmissionService.java b/src/main/java/edu/byu/cs/service/SubmissionService.java
index 6ba4fc5c..f594c978 100644
--- a/src/main/java/edu/byu/cs/service/SubmissionService.java
+++ b/src/main/java/edu/byu/cs/service/SubmissionService.java
@@ -184,8 +184,7 @@ public static Collection getSubmissionsForUser(String netId) throws
public static void approveSubmission(String adminNetId, ApprovalRequest request) throws GradingException, DataAccessException {
int penalty = 0;
if (request.penalize()) {
- //TODO: Put somewhere better/more configurable
- penalty = 10;
+ penalty = Math.round((DaoService.getConfigurationDao().getConfiguration(ConfigurationDao.Configuration.GIT_COMMIT_PENALTY, Float.class) * 100));
}
SubmissionUtils.approveSubmission(request.netId(), request.phase(), adminNetId, penalty);
diff --git a/src/main/java/edu/byu/cs/util/PhaseUtils.java b/src/main/java/edu/byu/cs/util/PhaseUtils.java
index 03f6dad0..9c7f8879 100644
--- a/src/main/java/edu/byu/cs/util/PhaseUtils.java
+++ b/src/main/java/edu/byu/cs/util/PhaseUtils.java
@@ -170,7 +170,12 @@ public static float extraCreditValue(Phase phase) {
public static CommitVerificationConfig verificationConfig(Phase phase) throws GradingException {
int minimumLinesChanged = 5;
- int penaltyPct = 10;
+ int penaltyPct;
+ try {
+ penaltyPct = Math.round(DaoService.getConfigurationDao().getConfiguration(ConfigurationDao.Configuration.GIT_COMMIT_PENALTY, Float.class) * 100);
+ } catch (DataAccessException e) {
+ throw new GradingException("Error getting git commit penalty", e);
+ }
int forgivenessMinutesHead = 3;
return switch (phase) {
case Phase0, Phase1 -> new CommitVerificationConfig(8, 2, minimumLinesChanged, penaltyPct, forgivenessMinutesHead);
diff --git a/src/main/resources/frontend/src/components/config/ConfigSection.vue b/src/main/resources/frontend/src/components/config/ConfigSection.vue
index a35d2e74..8b14281a 100644
--- a/src/main/resources/frontend/src/components/config/ConfigSection.vue
+++ b/src/main/resources/frontend/src/components/config/ConfigSection.vue
@@ -57,7 +57,9 @@ const closeEditor = () => {
v-if="editorPopup"
@closePopUp="editorPopup = false">
Edit {{ title }}
-
+
+
+
diff --git a/src/main/resources/frontend/src/components/config/PenaltyConfigEditor.vue b/src/main/resources/frontend/src/components/config/PenaltyConfigEditor.vue
index 6c5aa41c..5d347513 100644
--- a/src/main/resources/frontend/src/components/config/PenaltyConfigEditor.vue
+++ b/src/main/resources/frontend/src/components/config/PenaltyConfigEditor.vue
@@ -32,35 +32,54 @@ const submit = async () => {
-
Git Commit Penalty
-
Applied when students don't have enough commits
-
%
+
+
Late Penalty
+
Applied per day the submission is late
+
%
+
+
+
Max Late Days
+
Days after which the late penalty caps out
+
days
+
-
-
Late Penalty
-
Applied per day the submission is late
-
%
-
+
-
Max Late Days
-
Days after which the late penalty caps out
-
days
+
+
Git Commit Penalty
+
Applied when students don't have enough commits
+
%
+
+
+
Lines Changed Per Commit
+
The minimum number of lines that must change for a commit to count.
+
lines
+
+
+
Clock Variability
+
The commit checker will block if commits are authored in the future.
+ This value controls how far in the future a student's commit can be to account for differences in system time.
+
minutes
+
+
+
Submit
All values must be non-negative, and penalties must be equal to or less than 100%
+ None of these values affect admin submissions