easyproctor 2.5.2 → 2.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/esm/index.js +270 -70
- package/index.js +270 -70
- package/interfaces/ParamsConfig.d.ts +0 -1
- package/new-flow/backend/BackendService.d.ts +1 -1
- package/new-flow/proctoring/ProctoringSession.d.ts +5 -2
- package/new-flow/recorders/AlertRecorder.d.ts +18 -2
- package/package.json +1 -1
- package/proctoring/proctoring.d.ts +1 -0
- package/proctoring/useProctoring.d.ts +1 -1
- package/unpkg/easyproctor.min.js +39 -39
package/README.md
CHANGED
|
@@ -263,6 +263,9 @@ const {
|
|
|
263
263
|
token: "...",
|
|
264
264
|
});
|
|
265
265
|
```
|
|
266
|
+
## Release Note V 2.5.3
|
|
267
|
+
- Fix: Resolução do video
|
|
268
|
+
- Melhorias no proctoring do tipo REALTIME
|
|
266
269
|
|
|
267
270
|
## Release Note V 2.5.2
|
|
268
271
|
- Alteração do nome do callback 'onFinish' para 'onResultAvailable'
|
package/esm/index.js
CHANGED
|
@@ -8791,6 +8791,14 @@ var BaseDetection = class {
|
|
|
8791
8791
|
return "Face n\xE3o centralizada, mova-se para cima";
|
|
8792
8792
|
case "wrong_face_position_move_bottom_detected":
|
|
8793
8793
|
return "Face n\xE3o centralizada, mova-se para baixo";
|
|
8794
|
+
case "face_turned_left_detected":
|
|
8795
|
+
return "Face virada para a esquerda, centralize-a";
|
|
8796
|
+
case "face_turned_right_detected":
|
|
8797
|
+
return "Face virada para a direita, centralize-a";
|
|
8798
|
+
case "face_turned_up_detected":
|
|
8799
|
+
return "Face virada para cima, centralize-a";
|
|
8800
|
+
case "face_turned_down_detected":
|
|
8801
|
+
return "Face virada para baixo, centralize-a";
|
|
8794
8802
|
default:
|
|
8795
8803
|
return description;
|
|
8796
8804
|
}
|
|
@@ -8821,7 +8829,14 @@ function buildVideoPreview() {
|
|
|
8821
8829
|
// src/modules/faceDetection.ts
|
|
8822
8830
|
var FaceDetection = class extends BaseDetection {
|
|
8823
8831
|
constructor(options, paramsConfig, classVideo = "videoPreviewFrameDetection", classDiv = "liveViewFrameDetection") {
|
|
8824
|
-
super(
|
|
8832
|
+
super(
|
|
8833
|
+
"FaceDetector",
|
|
8834
|
+
`https://storage.googleapis.com/mediapipe-models/face_detector/blaze_face_short_range/float16/1/blaze_face_short_range.tflite`,
|
|
8835
|
+
options,
|
|
8836
|
+
paramsConfig,
|
|
8837
|
+
classVideo,
|
|
8838
|
+
classDiv
|
|
8839
|
+
);
|
|
8825
8840
|
this.emmitedPositionAlert = false;
|
|
8826
8841
|
this.emmitedFaceAlert = false;
|
|
8827
8842
|
}
|
|
@@ -8967,8 +8982,8 @@ var FaceDetection = class extends BaseDetection {
|
|
|
8967
8982
|
for (const keypoint of detection.keypoints) {
|
|
8968
8983
|
const keypointEl = document.createElement("span");
|
|
8969
8984
|
keypointEl.className = "key-point";
|
|
8970
|
-
|
|
8971
|
-
|
|
8985
|
+
const kpX = keypoint.x < 2 ? keypoint.x * videoElement.videoWidth : keypoint.x;
|
|
8986
|
+
const kpY = keypoint.y < 2 ? keypoint.y * videoElement.videoHeight : keypoint.y;
|
|
8972
8987
|
const mirroredKpX = videoElement.videoWidth - kpX;
|
|
8973
8988
|
const screenX = mirroredKpX * scaleX;
|
|
8974
8989
|
const screenY = kpY * scaleY;
|
|
@@ -9007,55 +9022,87 @@ var FaceDetection = class extends BaseDetection {
|
|
|
9007
9022
|
}
|
|
9008
9023
|
}
|
|
9009
9024
|
if (result.detections.length === 0) return;
|
|
9010
|
-
let
|
|
9011
|
-
|
|
9025
|
+
let failedFacePosition = false;
|
|
9026
|
+
const video = document.getElementById(this.classVideo);
|
|
9012
9027
|
const imageWidth = video.videoWidth;
|
|
9013
9028
|
const imageHeight = video.videoHeight;
|
|
9014
|
-
|
|
9029
|
+
const detection = result.detections[0];
|
|
9030
|
+
const face = detection.boundingBox;
|
|
9031
|
+
const keypoints = detection.keypoints;
|
|
9032
|
+
const rightEye = keypoints[0];
|
|
9033
|
+
const leftEye = keypoints[1];
|
|
9034
|
+
const mouth = keypoints[3];
|
|
9035
|
+
const rightEar = keypoints[4];
|
|
9036
|
+
const leftEar = keypoints[5];
|
|
9037
|
+
const nose = keypoints[2];
|
|
9015
9038
|
if (imageWidth > imageHeight) {
|
|
9016
9039
|
if (face.height / imageHeight > 0.7) {
|
|
9017
|
-
!this.emmitedPositionAlert && this.handleAlert(
|
|
9040
|
+
!this.emmitedPositionAlert && this.handleAlert(
|
|
9041
|
+
"wrong_face_size_detected",
|
|
9042
|
+
"position_detection_on_stream"
|
|
9043
|
+
);
|
|
9018
9044
|
failedFacePosition = true;
|
|
9019
9045
|
this.emmitedPositionAlert = true;
|
|
9020
9046
|
} else if (face.width / imageWidth > 0.7) {
|
|
9021
|
-
!this.emmitedPositionAlert && this.handleAlert(
|
|
9047
|
+
!this.emmitedPositionAlert && this.handleAlert(
|
|
9048
|
+
"wrong_face_size_detected",
|
|
9049
|
+
"position_detection_on_stream"
|
|
9050
|
+
);
|
|
9022
9051
|
this.emmitedPositionAlert = true;
|
|
9023
9052
|
failedFacePosition = true;
|
|
9024
9053
|
}
|
|
9025
9054
|
}
|
|
9026
|
-
|
|
9027
|
-
|
|
9055
|
+
const start = [face.originX, face.originY];
|
|
9056
|
+
const end = [face.originX + face.width, face.originY + face.height];
|
|
9028
9057
|
if (start[0] < 0.1 * face.width || start[1] < 0.2 * face.height || end[0] > imageWidth - 0.1 * face.width || end[1] > imageHeight - 5) {
|
|
9029
|
-
!this.emmitedPositionAlert && this.handleAlert(
|
|
9058
|
+
!this.emmitedPositionAlert && this.handleAlert(
|
|
9059
|
+
"wrong_face_position_edge_detected",
|
|
9060
|
+
"position_detection_on_stream"
|
|
9061
|
+
);
|
|
9030
9062
|
this.emmitedPositionAlert = true;
|
|
9031
9063
|
failedFacePosition = true;
|
|
9032
9064
|
}
|
|
9033
|
-
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
|
|
9065
|
+
const leftGap = start[0];
|
|
9066
|
+
const rightGap = imageWidth - end[0];
|
|
9067
|
+
const topGap = start[1];
|
|
9068
|
+
const bottomGap = imageHeight - end[1];
|
|
9037
9069
|
if (leftGap > 2 * rightGap) {
|
|
9038
|
-
!this.emmitedPositionAlert && this.handleAlert(
|
|
9070
|
+
!this.emmitedPositionAlert && this.handleAlert(
|
|
9071
|
+
"wrong_face_position_move_right_detected",
|
|
9072
|
+
"position_detection_on_stream"
|
|
9073
|
+
);
|
|
9039
9074
|
this.emmitedPositionAlert = true;
|
|
9040
9075
|
failedFacePosition = true;
|
|
9041
9076
|
}
|
|
9042
9077
|
if (topGap > 4 * bottomGap) {
|
|
9043
|
-
!this.emmitedPositionAlert && this.handleAlert(
|
|
9078
|
+
!this.emmitedPositionAlert && this.handleAlert(
|
|
9079
|
+
"wrong_face_position_move_top_detected",
|
|
9080
|
+
"position_detection_on_stream"
|
|
9081
|
+
);
|
|
9044
9082
|
this.emmitedPositionAlert = true;
|
|
9045
9083
|
failedFacePosition = true;
|
|
9046
9084
|
}
|
|
9047
9085
|
if (rightGap > 2 * leftGap) {
|
|
9048
|
-
!this.emmitedPositionAlert && this.handleAlert(
|
|
9086
|
+
!this.emmitedPositionAlert && this.handleAlert(
|
|
9087
|
+
"wrong_face_position_move_left_detected",
|
|
9088
|
+
"position_detection_on_stream"
|
|
9089
|
+
);
|
|
9049
9090
|
this.emmitedPositionAlert = true;
|
|
9050
9091
|
failedFacePosition = true;
|
|
9051
9092
|
}
|
|
9052
9093
|
if (bottomGap > 3 * topGap) {
|
|
9053
|
-
!this.emmitedPositionAlert && this.handleAlert(
|
|
9094
|
+
!this.emmitedPositionAlert && this.handleAlert(
|
|
9095
|
+
"wrong_face_position_move_bottom_detected",
|
|
9096
|
+
"position_detection_on_stream"
|
|
9097
|
+
);
|
|
9054
9098
|
this.emmitedPositionAlert = true;
|
|
9055
9099
|
failedFacePosition = true;
|
|
9056
9100
|
}
|
|
9057
9101
|
if (failedFacePosition == false) {
|
|
9058
|
-
this.emmitedPositionAlert && this.handleOk(
|
|
9102
|
+
this.emmitedPositionAlert && this.handleOk(
|
|
9103
|
+
"ok_position_face_detected",
|
|
9104
|
+
"position_detection_on_stream"
|
|
9105
|
+
);
|
|
9059
9106
|
this.emmitedPositionAlert = false;
|
|
9060
9107
|
}
|
|
9061
9108
|
}
|
|
@@ -11772,12 +11819,12 @@ var BackendService = class {
|
|
|
11772
11819
|
});
|
|
11773
11820
|
return result.data;
|
|
11774
11821
|
}
|
|
11775
|
-
async verifyFace(proctoringId2, faceImage) {
|
|
11822
|
+
async verifyFace(proctoringId2, faceImage, retry) {
|
|
11776
11823
|
const result = await this.makeRequestAxios({
|
|
11777
11824
|
path: `/Realtime/verify-face`,
|
|
11778
11825
|
method: "POST",
|
|
11779
11826
|
jwt: this.token,
|
|
11780
|
-
body: { "proctoringId": proctoringId2, "base64": faceImage }
|
|
11827
|
+
body: { "proctoringId": proctoringId2, "base64": faceImage, "retry": retry }
|
|
11781
11828
|
});
|
|
11782
11829
|
return result.data;
|
|
11783
11830
|
}
|
|
@@ -12653,7 +12700,6 @@ var CameraRecorder = class {
|
|
|
12653
12700
|
noiseLimit: 40
|
|
12654
12701
|
},
|
|
12655
12702
|
imageBehaviourParameters: {
|
|
12656
|
-
frames: 40,
|
|
12657
12703
|
useUploadImage: true,
|
|
12658
12704
|
uploadInterval: 20,
|
|
12659
12705
|
saveVideo: true
|
|
@@ -12665,7 +12711,6 @@ var CameraRecorder = class {
|
|
|
12665
12711
|
}
|
|
12666
12712
|
};
|
|
12667
12713
|
// private imageParams: ImageParameters = {
|
|
12668
|
-
// frames: 40,
|
|
12669
12714
|
// useUploadImage: true,
|
|
12670
12715
|
// uploadInterval: 20,
|
|
12671
12716
|
// saveVideo: true
|
|
@@ -13574,8 +13619,20 @@ var DeviceCheckerUI = class {
|
|
|
13574
13619
|
);
|
|
13575
13620
|
checkmark_FacePosition.appendChild(checkmark_stem_FacePosition);
|
|
13576
13621
|
checkmark_FacePosition.appendChild(checkmark_kick_FacePosition);
|
|
13622
|
+
const info_FacePosition = document.createElement("span");
|
|
13623
|
+
const info_stem_FacePosition = document.createElement("div");
|
|
13624
|
+
const info_kick_FacePosition = document.createElement("div");
|
|
13625
|
+
info_FacePosition.style.marginLeft = "10px";
|
|
13626
|
+
info_FacePosition.setAttribute("class", "info");
|
|
13627
|
+
info_FacePosition.setAttribute("id", "info_FacePosition");
|
|
13628
|
+
info_FacePosition.style.display = "none";
|
|
13629
|
+
info_stem_FacePosition.setAttribute("class", "info_stem");
|
|
13630
|
+
info_kick_FacePosition.setAttribute("class", "info_kick");
|
|
13631
|
+
info_FacePosition.appendChild(info_stem_FacePosition);
|
|
13632
|
+
info_FacePosition.appendChild(info_kick_FacePosition);
|
|
13577
13633
|
alertDivFacePosition.appendChild(checkmark_FacePosition);
|
|
13578
13634
|
alertDivFacePosition.appendChild(facePositionAlert);
|
|
13635
|
+
alertDivFacePosition.appendChild(info_FacePosition);
|
|
13579
13636
|
const alertDivAmbientVerify = document.createElement("div");
|
|
13580
13637
|
alertDivAmbientVerify.setAttribute("class", "alert-div");
|
|
13581
13638
|
alertDivAmbientVerify.setAttribute("id", "alertDivAmbientVerify");
|
|
@@ -13906,6 +13963,8 @@ var DeviceCheckerUI = class {
|
|
|
13906
13963
|
realtimeAlertsUI(response) {
|
|
13907
13964
|
const facePositionAlert = document.getElementById("facePositionAlert");
|
|
13908
13965
|
const ambientVerifyAlert = document.getElementById("ambientVerifyAlert");
|
|
13966
|
+
const alertDivFacePosition = document.getElementById("alertDivFacePosition");
|
|
13967
|
+
const info_FacePosition = document.getElementById("info_FacePosition");
|
|
13909
13968
|
const checkmark_FacePosition = document.getElementById("checkmark_FacePosition");
|
|
13910
13969
|
const checkmark_stem_FacePosition = document.getElementById("checkmark_stem_FacePosition");
|
|
13911
13970
|
const checkmark_kick_FacePosition = document.getElementById("checkmark_kick_FacePosition");
|
|
@@ -13916,6 +13975,8 @@ var DeviceCheckerUI = class {
|
|
|
13916
13975
|
if (response.status === "OK") {
|
|
13917
13976
|
facePositionAlert && (facePositionAlert.style.color = "#16A34A");
|
|
13918
13977
|
ambientVerifyAlert && (ambientVerifyAlert.style.color = "#16A34A");
|
|
13978
|
+
alertDivFacePosition && alertDivFacePosition.setAttribute("title", ``);
|
|
13979
|
+
info_FacePosition && (info_FacePosition.style.display = "none");
|
|
13919
13980
|
alertDivAmbientVerify && alertDivAmbientVerify.setAttribute("title", ``);
|
|
13920
13981
|
if (checkmark_FacePosition) {
|
|
13921
13982
|
checkmark_FacePosition.setAttribute("class", "checkmark");
|
|
@@ -13930,6 +13991,8 @@ var DeviceCheckerUI = class {
|
|
|
13930
13991
|
} else {
|
|
13931
13992
|
if (checkmark_FacePosition && (response.type === "position_detection_on_stream" || response.type === "face_detection_on_stream")) {
|
|
13932
13993
|
facePositionAlert && (facePositionAlert.style.color = "#FF0000");
|
|
13994
|
+
info_FacePosition && (info_FacePosition.style.display = "block");
|
|
13995
|
+
alertDivFacePosition && alertDivFacePosition.setAttribute("title", response.description);
|
|
13933
13996
|
checkmark_FacePosition.setAttribute("class", "checkmark_error");
|
|
13934
13997
|
checkmark_stem_FacePosition.setAttribute("class", "checkmark_stem_error");
|
|
13935
13998
|
checkmark_kick_FacePosition.setAttribute("class", "checkmark_kick_error");
|
|
@@ -15040,64 +15103,186 @@ var ProctoringUploader = class {
|
|
|
15040
15103
|
var AlertRecorder = class {
|
|
15041
15104
|
constructor(options, optionsProctoring) {
|
|
15042
15105
|
this.alerts = [];
|
|
15106
|
+
// Variáveis para controle de inatividade
|
|
15107
|
+
this.lastActivityTime = Date.now();
|
|
15108
|
+
this.IDLE_THRESHOLD_MS = 3e4;
|
|
15109
|
+
// ==========================================
|
|
15110
|
+
// HANDLERS (Funções Arrow para preservar o 'this')
|
|
15111
|
+
// ==========================================
|
|
15112
|
+
// 1. LOST / RETURN FOCUS
|
|
15113
|
+
this.handleLostFocus = () => {
|
|
15114
|
+
if (this.getRelativeTime() > 1e4) {
|
|
15115
|
+
const alertPayload = {
|
|
15116
|
+
begin: this.getRelativeTime(),
|
|
15117
|
+
end: 0,
|
|
15118
|
+
alert: 25 /* FocusOff */,
|
|
15119
|
+
type: 3 /* Screen */
|
|
15120
|
+
};
|
|
15121
|
+
this.onLostFocusCallback(alertPayload);
|
|
15122
|
+
this.alerts.push(alertPayload);
|
|
15123
|
+
}
|
|
15124
|
+
};
|
|
15125
|
+
this.handleReturnFocus = () => {
|
|
15126
|
+
const lastAlert = this.alerts[this.alerts.length - 1];
|
|
15127
|
+
if (lastAlert) {
|
|
15128
|
+
this.onFocusCallback({
|
|
15129
|
+
begin: lastAlert.begin,
|
|
15130
|
+
end: this.getRelativeTime(),
|
|
15131
|
+
alert: 25 /* FocusOff */,
|
|
15132
|
+
type: 3 /* Screen */
|
|
15133
|
+
});
|
|
15134
|
+
lastAlert.end = this.getRelativeTime();
|
|
15135
|
+
}
|
|
15136
|
+
};
|
|
15137
|
+
// 2. SPLIT SCREEN DETECTION
|
|
15138
|
+
this.handleResize = () => {
|
|
15139
|
+
clearTimeout(this.resizeTimeout);
|
|
15140
|
+
this.resizeTimeout = setTimeout(() => {
|
|
15141
|
+
const screenWidth = window.screen.availWidth;
|
|
15142
|
+
const windowWidth = window.outerWidth;
|
|
15143
|
+
if (windowWidth < screenWidth * 0.85) {
|
|
15144
|
+
const msg = `Split Screen Detectado: Janela ocupa ${(windowWidth / screenWidth * 100).toFixed(0)}% da tela`;
|
|
15145
|
+
this.createAlert(200 /* System */, 3 /* Screen */, msg);
|
|
15146
|
+
this.onRealtimeAlertCallback && this.onRealtimeAlertCallback({
|
|
15147
|
+
status: "ALERT",
|
|
15148
|
+
description: msg,
|
|
15149
|
+
type: "split_screen"
|
|
15150
|
+
});
|
|
15151
|
+
}
|
|
15152
|
+
}, 1e3);
|
|
15153
|
+
};
|
|
15154
|
+
// 3. DETECÇÃO DE INATIVIDADE (NO INPUT)
|
|
15155
|
+
this.handleUserActivity = (e3) => {
|
|
15156
|
+
this.lastActivityTime = Date.now();
|
|
15157
|
+
console.log("\u{1F449} handleUserActivity", e3);
|
|
15158
|
+
};
|
|
15159
|
+
// 5. CLIPBOARD HANDLERS
|
|
15160
|
+
this.handleCopy = (e3) => {
|
|
15161
|
+
e3.preventDefault();
|
|
15162
|
+
const msg = "Tentativa de Copiar (Clipboard)";
|
|
15163
|
+
this.createAlert(100 /* ForbiddenAction */, 6 /* System */, msg);
|
|
15164
|
+
this.onRealtimeAlertCallback && this.onRealtimeAlertCallback({
|
|
15165
|
+
status: "ALERT",
|
|
15166
|
+
description: msg,
|
|
15167
|
+
type: "clipboard_copy"
|
|
15168
|
+
});
|
|
15169
|
+
};
|
|
15170
|
+
this.handleCut = (e3) => {
|
|
15171
|
+
e3.preventDefault();
|
|
15172
|
+
const msg = "Tentativa de Recortar (Clipboard)";
|
|
15173
|
+
this.createAlert(100 /* ForbiddenAction */, 6 /* System */, msg);
|
|
15174
|
+
this.onRealtimeAlertCallback && this.onRealtimeAlertCallback({
|
|
15175
|
+
status: "ALERT",
|
|
15176
|
+
description: msg,
|
|
15177
|
+
type: "clipboard_cut"
|
|
15178
|
+
});
|
|
15179
|
+
};
|
|
15180
|
+
this.handlePaste = (e3) => {
|
|
15181
|
+
e3.preventDefault();
|
|
15182
|
+
const msg = "Tentativa de Colar (Clipboard)";
|
|
15183
|
+
this.createAlert(100 /* ForbiddenAction */, 6 /* System */, msg);
|
|
15184
|
+
this.onRealtimeAlertCallback && this.onRealtimeAlertCallback({
|
|
15185
|
+
status: "ALERT",
|
|
15186
|
+
description: msg,
|
|
15187
|
+
type: "clipboard_paste"
|
|
15188
|
+
});
|
|
15189
|
+
};
|
|
15043
15190
|
this.onLostFocusCallback = options.onLostFocusCallback;
|
|
15044
15191
|
this.onFocusCallback = options.onFocusCallback;
|
|
15192
|
+
this.onRealtimeAlertCallback = options.onRealtimeAlertCallback;
|
|
15045
15193
|
this.optionsProctoring = optionsProctoring;
|
|
15046
15194
|
}
|
|
15047
15195
|
async startRecording() {
|
|
15048
15196
|
this.startTime = new Date(Date.now());
|
|
15049
|
-
|
|
15050
|
-
|
|
15051
|
-
window.addEventListener("focus", () => this.onReturnFocus());
|
|
15052
|
-
}
|
|
15197
|
+
this.alerts = [];
|
|
15198
|
+
this.attachListeners();
|
|
15053
15199
|
}
|
|
15054
15200
|
async pauseRecording() {
|
|
15055
|
-
|
|
15056
|
-
window.removeEventListener("focus", () => this.onReturnFocus());
|
|
15201
|
+
this.detachListeners();
|
|
15057
15202
|
}
|
|
15058
15203
|
async resumeRecording() {
|
|
15059
|
-
|
|
15060
|
-
window.addEventListener("blur", () => this.onLostFocus());
|
|
15061
|
-
window.addEventListener("focus", () => this.onReturnFocus());
|
|
15062
|
-
}
|
|
15204
|
+
this.attachListeners();
|
|
15063
15205
|
}
|
|
15064
15206
|
async stopRecording() {
|
|
15065
|
-
|
|
15066
|
-
window.removeEventListener("focus", () => this.onReturnFocus());
|
|
15207
|
+
this.detachListeners();
|
|
15067
15208
|
}
|
|
15068
15209
|
async saveOnSession(session) {
|
|
15069
15210
|
this.alerts.forEach((alert) => {
|
|
15070
15211
|
session.addAlert(alert);
|
|
15071
15212
|
});
|
|
15072
15213
|
}
|
|
15073
|
-
|
|
15074
|
-
|
|
15075
|
-
|
|
15076
|
-
|
|
15077
|
-
|
|
15078
|
-
|
|
15079
|
-
|
|
15080
|
-
|
|
15081
|
-
|
|
15082
|
-
|
|
15083
|
-
|
|
15084
|
-
|
|
15085
|
-
|
|
15086
|
-
|
|
15087
|
-
|
|
15088
|
-
|
|
15214
|
+
// ==========================================
|
|
15215
|
+
// GERENCIAMENTO DE LISTENERS
|
|
15216
|
+
// ==========================================
|
|
15217
|
+
attachListeners() {
|
|
15218
|
+
if (this.optionsProctoring.captureScreen) {
|
|
15219
|
+
window.addEventListener("blur", this.handleLostFocus);
|
|
15220
|
+
window.addEventListener("focus", this.handleReturnFocus);
|
|
15221
|
+
window.addEventListener("resize", this.handleResize);
|
|
15222
|
+
window.document.addEventListener("copy", this.handleCopy);
|
|
15223
|
+
window.document.addEventListener("cut", this.handleCut);
|
|
15224
|
+
window.document.addEventListener("paste", this.handlePaste);
|
|
15225
|
+
}
|
|
15226
|
+
}
|
|
15227
|
+
detachListeners() {
|
|
15228
|
+
window.removeEventListener("blur", this.handleLostFocus);
|
|
15229
|
+
window.removeEventListener("focus", this.handleReturnFocus);
|
|
15230
|
+
window.removeEventListener("resize", this.handleResize);
|
|
15231
|
+
window.document.removeEventListener("copy", this.handleCopy);
|
|
15232
|
+
window.document.removeEventListener("cut", this.handleCut);
|
|
15233
|
+
window.document.removeEventListener("paste", this.handlePaste);
|
|
15234
|
+
}
|
|
15235
|
+
// private startIdleChecker() {
|
|
15236
|
+
// this.stopIdleChecker(); // Garante que não tenha duplicação
|
|
15237
|
+
// this.idleCheckInterval = setInterval(() => {
|
|
15238
|
+
// const idleTime = Date.now() - this.lastActivityTime;
|
|
15239
|
+
// if (idleTime > this.IDLE_THRESHOLD_MS) {
|
|
15240
|
+
// // Verifica se já não mandamos esse alerta recentemente para não floodar
|
|
15241
|
+
// const lastAlert = this.alerts[this.alerts.length - 1];
|
|
15242
|
+
// // Se o último alerta não foi de inatividade ou foi há muito tempo, cria novo
|
|
15243
|
+
// if (!lastAlert || lastAlert.alert !== AlertCategory.ForbiddenAction || (this.getRelativeTime() - lastAlert.begin > 5000)) {
|
|
15244
|
+
// const msg = "Usuário inativo por muito tempo";
|
|
15245
|
+
// // Assumindo ForbiddenAction ou outra categoria adequada
|
|
15246
|
+
// this.createAlert(AlertCategory.ForbiddenAction, AlertType.System, msg);
|
|
15247
|
+
// this.onRealtimeAlertCallback && this.onRealtimeAlertCallback({
|
|
15248
|
+
// status: 'ALERT',
|
|
15249
|
+
// description: msg,
|
|
15250
|
+
// type: 'user_idle'
|
|
15251
|
+
// });
|
|
15252
|
+
// }
|
|
15253
|
+
// }
|
|
15254
|
+
// }, 5000); // Checa a cada 5 segundos
|
|
15255
|
+
// }
|
|
15256
|
+
// private stopIdleChecker() {
|
|
15257
|
+
// if (this.idleCheckInterval) {
|
|
15258
|
+
// clearInterval(this.idleCheckInterval);
|
|
15259
|
+
// this.idleCheckInterval = null;
|
|
15260
|
+
// }
|
|
15261
|
+
// }
|
|
15262
|
+
// 4. BACKGROUND EVENTS (Eventos disparados manualmente)
|
|
15263
|
+
addBackgroundEvent(description, category = 200 /* System */) {
|
|
15264
|
+
this.createAlert(category, 6 /* System */, description);
|
|
15265
|
+
this.onRealtimeAlertCallback && this.onRealtimeAlertCallback({
|
|
15266
|
+
status: "ALERT",
|
|
15267
|
+
description,
|
|
15268
|
+
type: "background_event"
|
|
15269
|
+
});
|
|
15089
15270
|
}
|
|
15090
|
-
|
|
15091
|
-
|
|
15092
|
-
|
|
15093
|
-
|
|
15094
|
-
|
|
15095
|
-
|
|
15096
|
-
|
|
15097
|
-
|
|
15098
|
-
|
|
15099
|
-
|
|
15100
|
-
|
|
15271
|
+
// ==========================================
|
|
15272
|
+
// HELPERS
|
|
15273
|
+
// ==========================================
|
|
15274
|
+
getRelativeTime() {
|
|
15275
|
+
return Date.now() - this.startTime.getTime();
|
|
15276
|
+
}
|
|
15277
|
+
createAlert(category, type, description) {
|
|
15278
|
+
this.alerts.push({
|
|
15279
|
+
begin: this.getRelativeTime(),
|
|
15280
|
+
end: this.getRelativeTime(),
|
|
15281
|
+
// Eventos pontuais começam e terminam no mesmo ms (exceto focus)
|
|
15282
|
+
alert: category,
|
|
15283
|
+
type
|
|
15284
|
+
// description: description // Se sua interface Alert suportar descrição, descomente
|
|
15285
|
+
});
|
|
15101
15286
|
}
|
|
15102
15287
|
addAlert({ alert, type }) {
|
|
15103
15288
|
this.alerts.push({
|
|
@@ -21520,7 +21705,6 @@ var Proctoring = class {
|
|
|
21520
21705
|
noiseLimit: 40
|
|
21521
21706
|
},
|
|
21522
21707
|
imageBehaviourParameters: {
|
|
21523
|
-
frames: 40,
|
|
21524
21708
|
useUploadImage: true,
|
|
21525
21709
|
uploadInterval: 20,
|
|
21526
21710
|
saveVideo: true
|
|
@@ -21738,7 +21922,8 @@ var Proctoring = class {
|
|
|
21738
21922
|
const alertRecorder = new AlertRecorder(
|
|
21739
21923
|
{
|
|
21740
21924
|
onFocusCallback: (response) => this.onFocusAlertRecorderCallback(response),
|
|
21741
|
-
onLostFocusCallback: (response) => this.onLostFocusAlertRecorderCallback(response)
|
|
21925
|
+
onLostFocusCallback: (response) => this.onLostFocusAlertRecorderCallback(response),
|
|
21926
|
+
onRealtimeAlertCallback: (response) => this.onRealtimeAlertsCallback(response)
|
|
21742
21927
|
},
|
|
21743
21928
|
options
|
|
21744
21929
|
);
|
|
@@ -21846,11 +22031,23 @@ Navigator: ${JSON.stringify(_navigator2)}`
|
|
|
21846
22031
|
startResponse.screenStream = this.allRecorders.screenRecorder.screenStream;
|
|
21847
22032
|
}
|
|
21848
22033
|
this.state = "Recording" /* Recording */;
|
|
21849
|
-
|
|
22034
|
+
let verifyFirstFaceIntervalCount = 0;
|
|
22035
|
+
let verifyingFace = false;
|
|
22036
|
+
this.verifyFirstFaceInterval = setInterval(async () => {
|
|
21850
22037
|
if (this.sessionOptions.proctoringType === "REALTIME") {
|
|
21851
|
-
|
|
22038
|
+
if (verifyingFace) return;
|
|
22039
|
+
verifyingFace = true;
|
|
22040
|
+
verifyFirstFaceIntervalCount++;
|
|
22041
|
+
try {
|
|
22042
|
+
var response = await this.backend.verifyFace(this.proctoringId, await this.allRecorders.cameraRecorder.getCurrentImageBase64(), verifyFirstFaceIntervalCount > 5 ? false : true);
|
|
22043
|
+
verifyingFace = false;
|
|
22044
|
+
clearInterval(this.verifyFirstFaceInterval);
|
|
22045
|
+
} catch (error) {
|
|
22046
|
+
verifyingFace = false;
|
|
22047
|
+
return;
|
|
22048
|
+
}
|
|
21852
22049
|
}
|
|
21853
|
-
},
|
|
22050
|
+
}, 1500);
|
|
21854
22051
|
return startResponse;
|
|
21855
22052
|
} catch (error) {
|
|
21856
22053
|
console.log(error);
|
|
@@ -21987,6 +22184,9 @@ Upload Services: ${uploaderServices}`,
|
|
|
21987
22184
|
await this.backend.externalCameraFinish(externalSessionId);
|
|
21988
22185
|
}
|
|
21989
22186
|
}
|
|
22187
|
+
if (this.verifyFirstFaceInterval) {
|
|
22188
|
+
clearInterval(this.verifyFirstFaceInterval);
|
|
22189
|
+
}
|
|
21990
22190
|
this.state = "Stop" /* Stop */;
|
|
21991
22191
|
} catch (error) {
|
|
21992
22192
|
await this.cancel();
|
|
@@ -22321,12 +22521,12 @@ function useProctoring(proctoringOptions, enviromentConfig = "prod") {
|
|
|
22321
22521
|
const photo = new CapturePhoto();
|
|
22322
22522
|
const login = proctoring.login.bind(proctoring);
|
|
22323
22523
|
const originalStart = proctoring.start.bind(proctoring);
|
|
22324
|
-
const start = async (parameters2) => {
|
|
22524
|
+
const start = async (parameters2, videoOptions) => {
|
|
22325
22525
|
const deviceResult = checker.getDeviceCheckResult();
|
|
22326
22526
|
if (deviceResult) {
|
|
22327
22527
|
proctoring.setDeviceCheckData(deviceResult);
|
|
22328
22528
|
}
|
|
22329
|
-
return originalStart(parameters2);
|
|
22529
|
+
return originalStart(parameters2, videoOptions);
|
|
22330
22530
|
};
|
|
22331
22531
|
const finish = proctoring.finish.bind(proctoring);
|
|
22332
22532
|
const pause = proctoring.pause.bind(proctoring);
|