Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rounding feedback opportunity timestamp #14

Merged
merged 3 commits into from
Apr 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 6 additions & 14 deletions controllers/executionFlow.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import { ActiveIssues } from "../models/activeIssues.js";
import { ArchivedIssues } from "../models/archivedIssues.js";

import { computeTargets, runDetector, getFeedbackOpportunity, ExecutionEnv } from "./executor.js";
import { floorDateToNearestFiveMinutes } from "./utils.js";

/**
*
* TODO: comment
* @return {Promise<Array<EnforceDocument<T & Document<any, any, any>, {}, {}>>>}
*/
export const checkMonitoredScripts = async () => {
Expand Down Expand Up @@ -96,9 +97,10 @@ export const checkActiveIssues = async () => {
// convert outlet fn back to a function
feedbackOpp["outlet_fn"] = new Function(`return ${ feedbackOpp["outlet_fn"] }`)();

// TODO: this will fail since its looking for a direct match. Need to round this down.
// TODO: in the future, may want to change it to currTime >= oppTime (or on the same day, but >= time). This will need to check, though, if a ping has been sent for an active issue.
// check if it's time to send the actionable feedback
if (currDate.getTime() === feedbackOpp.opportunity.getTime()) {
// TODO: this should inject feedback message
// execute feedback function by creating an execution env with targets and outlet_fn
let feedbackExecutionEnv = new ExecutionEnv(feedbackOpp.target, feedbackOpp.outlet_fn);
await feedbackExecutionEnv.runScript();
Expand Down Expand Up @@ -135,6 +137,7 @@ export const cleanUpActiveIssues = async () => {

for (let issue of activeIssues) {
issue = issue.toObject();
// TODO: greater or equal?
if (currDate.getTime() > issue.expiry_time.getTime()) {
// archive issue
let currArchivedIssue = new ArchivedIssues({
Expand Down Expand Up @@ -248,15 +251,4 @@ const computeActionableFeedback = async (target, actionableFeedbackList) => {
currFeedback.outlet_fn = currFeedback.outlet_fn.toString()
return currFeedback;
});
};

/**
* Floors date down to nearest 5 minutes.
* From: https://stackoverflow.com/a/10789415
* @param currDate
* @return {Date}
*/
const floorDateToNearestFiveMinutes = (currDate) => {
let coeff = 1000 * 60 * 5;
return new Date(Math.floor(currDate.getTime() / coeff) * coeff);
}
};
6 changes: 5 additions & 1 deletion controllers/executor.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as triggerFn from './lib/triggerFn.js';
import * as communicationFn from './lib/communicationFn.js';
import * as peopleFn from './lib/peopleFn.js';
import * as projectFn from "./lib/projectFn.js";
import { floorDateToNearestFiveMinutes } from "./utils.js";

// TODO: target should be a single object with student and project (see issue 1)
/**
Expand Down Expand Up @@ -95,9 +96,12 @@ export async function getFeedbackOpportunity(target, actionableFeedback) {
let triggerDateExecutionEnv = new ExecutionEnv(target,
currActionableFeedback.feedback_opportunity);

// get opportunity date, and floor
let opportunityDate = await triggerDateExecutionEnv.runScript();

// create object to hold curr computed feedback opportunity
let computedFeedbackOpportunity = {
opportunity: await triggerDateExecutionEnv.runScript(),
opportunity: floorDateToNearestFiveMinutes(opportunityDate),
target: {
message: currActionableFeedback.feedback_message,
resources: [], // TODO, implement
Expand Down
4 changes: 4 additions & 0 deletions controllers/lib/triggerFn.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { DateTime } from "luxon";
// TODO: this might be messing up due to daylight savings time from using the default date in the studio api
/**
* Returns a timestamp for when to execute a script during the next instance of a venue.
* TODO: to support DST, start_time and end_time should be strings like HH:MM, and also timezone.
* @param venue object with information about the venue. Contains the following:
* {
* name: string name of venue
Expand Down Expand Up @@ -69,6 +70,7 @@ export const before = async function(venue, timeBefore) {
};

/**
* TODO: This will not work as expected if time needs to be rounded to be matched.
* Returns a timestamp for when to execute a script after the next instance of a venue.
* @param venue object with information about the venue. Contains the following:
* {
Expand Down Expand Up @@ -140,6 +142,8 @@ const computeNextVenue = function (currDate, targetDayOfWeek, venueStartTime, ve
let nextVenueEndTime = new Date(nextVenueDate);
nextVenueEndTime.setHours(venueEndTime.getHours(), venueEndTime.getMinutes());

// TODO: need to zero ou the seconds otherwise exact match will not work (this could happen

// console.log('Current date', currDate)
// console.log('Venue Start Time', venueStartTime)
// console.log('Venue End Time', venueEndTime)
Expand Down
10 changes: 10 additions & 0 deletions controllers/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Floors date down to nearest 5 minutes.
* From: https://stackoverflow.com/a/10789415
* @param currDate
* @return {Date}
*/
export const floorDateToNearestFiveMinutes = (currDate) => {
let coeff = 1000 * 60 * 5;
return new Date(Math.floor(currDate.getTime() / coeff) * coeff);
};
17 changes: 15 additions & 2 deletions imports/tester.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,24 @@ export const runSimulationOfScript = async (scriptId, simStartDate, simEndDate,
console.log(`\n${ currDate.toDateString() }`);
}

// add some jitter to the timestamp (0 - 30 seconds) to simulate lag on server
let step1Jitter = Math.round(Math.random() * 30);
clock.tick(step1Jitter * 1000);

// step (1): check all monitored scripts, and create issues for triggered scripts
let createdIssues = await checkMonitoredScripts();

// add more jitter to the timestamp (60 - 120 seconds) to simulate completion time of step 1
let step2Jitter = Math.round(60 + (Math.random() * 60));
clock.tick(step2Jitter * 1000);

// step (2): check active issues to see if any feedback was triggered
let triggeredFeedbackOpps = await checkActiveIssues();

// add more jitter to the timestamp (60 - 120 seconds) to simulate completion time of step 2
let step3Jitter = Math.round(60 + (Math.random() * 120));
clock.tick(step3Jitter * 1000);

// step (3): clean-up issues based on expiry time
let [archivedIssues, activeIssues] = await cleanUpActiveIssues();

Expand All @@ -68,8 +80,9 @@ export const runSimulationOfScript = async (scriptId, simStartDate, simEndDate,
console.log(currTimeStr);
}

// tick clock by 1 hour
clock.tick(tickAmount);
// tick clock by 1 hour - jitter that was added above
let totalJitter = step1Jitter + step2Jitter + step3Jitter;
clock.tick(tickAmount - (totalJitter * 1000));
currDate = new Date();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export default {
target: (async function() {
return await this.getAllProjects();
}).toString(),
// TODO: change this to run when it's the same week as the last SIG meeting (or have feedback opportunity run immediately)
detector: (async function() {
return true; // trigger immediately
}).toString(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/**
* TODO: this really should have a check where if it's week 1 of a sprint, then its only half the available points.
* Students over-committing to a sprint.
* @type {EnforceDocument<T & Document<any, any, any>, {}, {}>}
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export default {
target: (async function() {
return await this.getAllProjects();
}).toString(),
// TODO: change this to run when it's the same week as the last SIG meeting (or have feedback opportunity run immediately)
detector: (async function() {
return true; // trigger immediately
}).toString(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export default {
(currDate.getFullYear() === shiftedDate.getFullYear());
}).toString(),
actionable_feedback: [
// TODO: also support notification at next office hours
// TODO: also support notification at next office hours as an alternate strategy
{
feedback_message: "You have a status update in 1 week! Make sure to meet with your mentor to discuss your plan.",
feedback_opportunity: (async function () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export default {
target: (async function() {
return await this.getNonPhdProjects();
}).toString(),
// TODO: maybe have the feedback be immediate, and detector be what
detector: (async function() {
return true; // trigger immediately
}).toString(),
Expand Down