@elice/material-exercise 1.250521.0-resetsubmit.0 → 1.250529.0

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.
Files changed (45) hide show
  1. package/cjs/components/material-exercise/context/index.js +2 -1
  2. package/cjs/components/material-exercise/context/recoil.d.ts +4 -4
  3. package/cjs/components/material-exercise/context/recoil.js +32 -30
  4. package/cjs/components/material-exercise/context/subjects.d.ts +5 -0
  5. package/cjs/components/material-exercise/context/subjects.js +5 -0
  6. package/cjs/components/material-exercise/context/types.d.ts +5 -1
  7. package/cjs/components/material-exercise/exercise-file-editor/ExerciseFileEditor.js +32 -1
  8. package/cjs/components/material-exercise/exercise-runner/ExerciseRunner.js +36 -4
  9. package/cjs/components/material-exercise/exercise-runner/ExerciseRunnerControllerButtonGroup.js +1 -1
  10. package/cjs/components/material-exercise/exercise-runner/ExerciseRunnerControllerStatusMessage.js +30 -11
  11. package/cjs/components/material-exercise/exercise-runner/locales/en.json.js +1 -1
  12. package/cjs/components/material-exercise/exercise-runner/locales/ja.json.js +1 -1
  13. package/cjs/components/material-exercise/exercise-runner/locales/ko.json.js +1 -1
  14. package/cjs/components/material-exercise/exercise-runner/locales/th.json.js +1 -1
  15. package/cjs/hooks/useRunnerRoomWebSocket.js +2 -1
  16. package/cjs/hooks/useStdioWebSocket.js +2 -1
  17. package/cjs/hooks/useUsercodeEditWebSocket.d.ts +9 -1
  18. package/cjs/hooks/useUsercodeEditWebSocket.js +10 -2
  19. package/cjs/utils/async.d.ts +4 -0
  20. package/cjs/utils/async.js +15 -0
  21. package/cjs/utils/index.d.ts +1 -0
  22. package/cjs/utils/index.js +2 -0
  23. package/es/components/material-exercise/context/index.js +2 -2
  24. package/es/components/material-exercise/context/recoil.d.ts +4 -4
  25. package/es/components/material-exercise/context/recoil.js +32 -30
  26. package/es/components/material-exercise/context/subjects.d.ts +5 -0
  27. package/es/components/material-exercise/context/subjects.js +5 -1
  28. package/es/components/material-exercise/context/types.d.ts +5 -1
  29. package/es/components/material-exercise/exercise-file-editor/ExerciseFileEditor.js +33 -2
  30. package/es/components/material-exercise/exercise-runner/ExerciseRunner.js +37 -5
  31. package/es/components/material-exercise/exercise-runner/ExerciseRunnerControllerButtonGroup.js +2 -2
  32. package/es/components/material-exercise/exercise-runner/ExerciseRunnerControllerStatusMessage.js +33 -14
  33. package/es/components/material-exercise/exercise-runner/locales/en.json.js +1 -1
  34. package/es/components/material-exercise/exercise-runner/locales/ja.json.js +1 -1
  35. package/es/components/material-exercise/exercise-runner/locales/ko.json.js +1 -1
  36. package/es/components/material-exercise/exercise-runner/locales/th.json.js +1 -1
  37. package/es/hooks/useRunnerRoomWebSocket.js +2 -1
  38. package/es/hooks/useStdioWebSocket.js +2 -1
  39. package/es/hooks/useUsercodeEditWebSocket.d.ts +9 -1
  40. package/es/hooks/useUsercodeEditWebSocket.js +10 -2
  41. package/es/utils/async.d.ts +4 -0
  42. package/es/utils/async.js +13 -0
  43. package/es/utils/index.d.ts +1 -0
  44. package/es/utils/index.js +1 -0
  45. package/package.json +3 -3
@@ -36,9 +36,9 @@ exports.exerciseRunnerRunTypeState = recoil.exerciseRunnerRunTypeState;
36
36
  exports.exerciseRunnerRunningState = recoil.exerciseRunnerRunningState;
37
37
  exports.exerciseRunnerStdioFilesState = recoil.exerciseRunnerStdioFilesState;
38
38
  exports.exerciseRunnerSubmittingState = recoil.exerciseRunnerSubmittingState;
39
- exports.exerciseRunnerWebSocketStatusQuery = recoil.exerciseRunnerWebSocketStatusQuery;
40
39
  exports.exerciseState = recoil.exerciseState;
41
40
  exports.exerciseUserState = recoil.exerciseUserState;
41
+ exports.exerciseWebSocketTotalStatusQuery = recoil.exerciseWebSocketTotalStatusQuery;
42
42
  exports.exerciseWebsocketQuery = recoil.exerciseWebsocketQuery;
43
43
  exports.exerciseWebsocketStates = recoil.exerciseWebsocketStates;
44
44
  exports.ExerciseContext = context.ExerciseContext;
@@ -52,6 +52,7 @@ Object.defineProperty(exports, "ExercisePreviewType", {
52
52
  });
53
53
  exports.exerciseFileEditorContentChange$ = subjects.exerciseFileEditorContentChange$;
54
54
  exports.exerciseFileEditorSaveAction$ = subjects.exerciseFileEditorSaveAction$;
55
+ exports.exerciseFileEditorSyncRequestAction$ = subjects.exerciseFileEditorSyncRequestAction$;
55
56
  exports.exerciseRunnerRoomsOpen$ = subjects.exerciseRunnerRoomsOpen$;
56
57
  exports.exerciseRunnerTextSend$ = subjects.exerciseRunnerTextSend$;
57
58
  exports.ExerciseProvider = ExerciseProvider.default;
@@ -61,10 +61,6 @@ export declare const exerciseRunnerRoomConnectionInfoState: import("recoil").Rec
61
61
  *
62
62
  */
63
63
  export declare const exerciseRunnerStdioFilesState: import("recoil").RecoilState<AtomRunnerStdioFilesState>;
64
- /**
65
- *
66
- */
67
- export declare const exerciseRunnerWebSocketStatusQuery: import("recoil").RecoilValueReadOnly<number>;
68
64
  /**
69
65
  *
70
66
  */
@@ -73,6 +69,10 @@ export declare const exerciseWebsocketStates: import("recoil").RecoilState<AtomW
73
69
  *
74
70
  */
75
71
  export declare const exerciseWebsocketQuery: (param: AtomWebSocketStateKey) => import("recoil").RecoilState<number>;
72
+ /**
73
+ * Check all necessary websockets and return the status.
74
+ */
75
+ export declare const exerciseWebSocketTotalStatusQuery: import("recoil").RecoilValueReadOnly<number>;
76
76
  /**
77
77
  *
78
78
  */
@@ -455,30 +455,6 @@ var exerciseRunnerStdioFilesState = recoil.atom({
455
455
  key: "".concat(KEY_PREFIX, "/Runner/StdioFiles"),
456
456
  default: []
457
457
  });
458
- /**
459
- *
460
- */
461
- var exerciseRunnerWebSocketStatusQuery = recoil.selector({
462
- key: "".concat(KEY_PREFIX, "/Runner/WebsocketState"),
463
- get: function get(_ref19) {
464
- var _get = _ref19.get;
465
- var states = Object.freeze([_get(exerciseWebsocketStates).runnerRoom, _get(exerciseWebsocketStates).stdio]);
466
- // connecting
467
- if (states.includes(websocket.EliceWebSocket.CLOSED) || states.includes(websocket.EliceWebSocket.CONNECTING)) {
468
- return websocket.EliceWebSocket.CONNECTING;
469
- }
470
- // connected
471
- else if (states.every(function (state) {
472
- return state === WebSocket.OPEN;
473
- })) {
474
- return websocket.EliceWebSocket.OPEN;
475
- }
476
- // reconnecting
477
- else {
478
- return websocket.EliceWebSocket.CONNECTING;
479
- }
480
- }
481
- });
482
458
  //
483
459
  // =============== websocket ===============
484
460
  //
@@ -499,19 +475,45 @@ var exerciseWebsocketStates = recoil.atom({
499
475
  var exerciseWebsocketQuery = recoil.selectorFamily({
500
476
  key: "".concat(KEY_PREFIX, "/Websocket/State"),
501
477
  get: function get(key) {
502
- return function (_ref20) {
503
- var get = _ref20.get;
478
+ return function (_ref19) {
479
+ var get = _ref19.get;
504
480
  return get(exerciseWebsocketStates)[key];
505
481
  };
506
482
  },
507
483
  set: function set(key) {
508
- return function (_ref21, newWebSocketState) {
509
- var get = _ref21.get,
510
- set = _ref21.set;
484
+ return function (_ref20, newWebSocketState) {
485
+ var get = _ref20.get,
486
+ set = _ref20.set;
511
487
  set(exerciseWebsocketStates, Object.assign(Object.assign({}, get(exerciseWebsocketStates)), _rollupPluginBabelHelpers.defineProperty({}, key, newWebSocketState)));
512
488
  };
513
489
  }
514
490
  });
491
+ /**
492
+ * Check all necessary websockets and return the status.
493
+ */
494
+ var exerciseWebSocketTotalStatusQuery = recoil.selector({
495
+ key: "".concat(KEY_PREFIX, "/Websocket/TotalStatus"),
496
+ get: function get(_ref21) {
497
+ var _get = _ref21.get;
498
+ var states = Object.freeze([_get(exerciseWebsocketStates).usercodeEdit, _get(exerciseWebsocketStates).runnerRoom, _get(exerciseWebsocketStates).stdio]);
499
+ switch (true) {
500
+ case states.every(function (state) {
501
+ return state === websocket.EliceWebSocket.OPEN;
502
+ }):
503
+ return websocket.EliceWebSocket.OPEN;
504
+ case states.every(function (state) {
505
+ return state === websocket.EliceWebSocket.CLOSED;
506
+ }):
507
+ return websocket.EliceWebSocket.CLOSED;
508
+ case states.every(function (state) {
509
+ return state === websocket.EliceWebSocket.CLOSING;
510
+ }):
511
+ return websocket.EliceWebSocket.CLOSING;
512
+ default:
513
+ return websocket.EliceWebSocket.CONNECTING;
514
+ }
515
+ }
516
+ });
515
517
  //
516
518
  // =============== multi language ===============
517
519
  //
@@ -853,8 +855,8 @@ exports.exerciseRunnerRunTypeState = exerciseRunnerRunTypeState;
853
855
  exports.exerciseRunnerRunningState = exerciseRunnerRunningState;
854
856
  exports.exerciseRunnerStdioFilesState = exerciseRunnerStdioFilesState;
855
857
  exports.exerciseRunnerSubmittingState = exerciseRunnerSubmittingState;
856
- exports.exerciseRunnerWebSocketStatusQuery = exerciseRunnerWebSocketStatusQuery;
857
858
  exports.exerciseState = exerciseState;
858
859
  exports.exerciseUserState = exerciseUserState;
860
+ exports.exerciseWebSocketTotalStatusQuery = exerciseWebSocketTotalStatusQuery;
859
861
  exports.exerciseWebsocketQuery = exerciseWebsocketQuery;
860
862
  exports.exerciseWebsocketStates = exerciseWebsocketStates;
@@ -1,4 +1,5 @@
1
1
  import { Subject } from 'rxjs';
2
+ import type { MaterialExerciseCodeEditorSyncRequest } from "./types";
2
3
  /**
3
4
  * Content change request to code editor.
4
5
  */
@@ -7,6 +8,10 @@ export declare const exerciseFileEditorContentChange$: Subject<string | null>;
7
8
  * Save action emitted by file editor.
8
9
  */
9
10
  export declare const exerciseFileEditorSaveAction$: Subject<void>;
11
+ /**
12
+ * Request file editor to sync full code.
13
+ */
14
+ export declare const exerciseFileEditorSyncRequestAction$: Subject<MaterialExerciseCodeEditorSyncRequest>;
10
15
  /**
11
16
  * Send text request to runner stdio.
12
17
  */
@@ -10,6 +10,10 @@ var exerciseFileEditorContentChange$ = new rxjs.Subject();
10
10
  * Save action emitted by file editor.
11
11
  */
12
12
  var exerciseFileEditorSaveAction$ = new rxjs.Subject();
13
+ /**
14
+ * Request file editor to sync full code.
15
+ */
16
+ var exerciseFileEditorSyncRequestAction$ = new rxjs.Subject();
13
17
  /**
14
18
  * Send text request to runner stdio.
15
19
  */
@@ -21,5 +25,6 @@ var exerciseRunnerRoomsOpen$ = new rxjs.Subject();
21
25
 
22
26
  exports.exerciseFileEditorContentChange$ = exerciseFileEditorContentChange$;
23
27
  exports.exerciseFileEditorSaveAction$ = exerciseFileEditorSaveAction$;
28
+ exports.exerciseFileEditorSyncRequestAction$ = exerciseFileEditorSyncRequestAction$;
24
29
  exports.exerciseRunnerRoomsOpen$ = exerciseRunnerRoomsOpen$;
25
30
  exports.exerciseRunnerTextSend$ = exerciseRunnerTextSend$;
@@ -1,5 +1,5 @@
1
1
  /// <reference types="react" />
2
- import type { GetOrgMaterialExerciseExerciseRunningListResponses, PostOrgMaterialExerciseExerciseRunningSubmitResponses } from '@elice/types';
2
+ import type { GetOrgMaterialExerciseExerciseRunningListResponses, PostOrgMaterialExerciseExerciseRunningSubmitResponses, WebsocketUsercodeMessageWriteFailed, WebsocketUsercodeMessageWriteSucceed } from '@elice/types';
3
3
  import type { MonacoEditorApis } from "../../shared/monaco-editor";
4
4
  import type { CodeHelperError } from "../../../utils";
5
5
  import type { ExerciseProviderNoImageProps } from './ExerciseProviderNoImage';
@@ -133,3 +133,7 @@ export interface ExerciseProviderDedicatedProps {
133
133
  */
134
134
  readOnlyActiveFile: boolean;
135
135
  }
136
+ export interface MaterialExerciseCodeEditorSyncRequest {
137
+ onSucceed: (msg: WebsocketUsercodeMessageWriteSucceed) => void;
138
+ onFailed: (msg: WebsocketUsercodeMessageWriteFailed) => void;
139
+ }
@@ -91,6 +91,8 @@ var ExerciseFileEditor = function ExerciseFileEditor() {
91
91
  _React$useState8 = _rollupPluginBabelHelpers.slicedToArray(_React$useState7, 2),
92
92
  isFileResettable = _React$useState8[0],
93
93
  setFileResettable = _React$useState8[1];
94
+ // requests to editor
95
+ var usercodeSyncRequestsRef = React__default.default.useRef(new Map());
94
96
  var setExerciseMonacoEditorApisState = recoil.useSetRecoilState(recoil$1.exerciseMonacoEditorApisState);
95
97
  React__default.default.useEffect(function () {
96
98
  if (editorApis.current) {
@@ -222,6 +224,13 @@ var ExerciseFileEditor = function ExerciseFileEditor() {
222
224
  _iterator.f();
223
225
  }
224
226
  };
227
+ var handleWebsocketUsercodeWriteSucceed = function handleWebsocketUsercodeWriteSucceed(msg, requestId) {
228
+ var request = usercodeSyncRequestsRef.current.get(requestId);
229
+ if (request) {
230
+ usercodeSyncRequestsRef.current.delete(requestId);
231
+ request.onSucceed(msg);
232
+ }
233
+ };
225
234
  /**
226
235
  * Usercode edit web socket.
227
236
  */
@@ -231,7 +240,8 @@ var ExerciseFileEditor = function ExerciseFileEditor() {
231
240
  onInit: function onInit() {
232
241
  return setWebSocketReady(true);
233
242
  },
234
- onWriteNoti: handleWebsocketUsercodeWriteNoti
243
+ onWriteNoti: handleWebsocketUsercodeWriteNoti,
244
+ onWriteSucceed: handleWebsocketUsercodeWriteSucceed
235
245
  });
236
246
  /**
237
247
  *
@@ -354,6 +364,27 @@ var ExerciseFileEditor = function ExerciseFileEditor() {
354
364
  // eslint-disable-next-line react-hooks/exhaustive-deps
355
365
  []);
356
366
  //
367
+ // Sync full usercode before submitting/running the code.
368
+ //
369
+ React__default.default.useEffect(function () {
370
+ var syncRequestSub = subjects.exerciseFileEditorSyncRequestAction$.subscribe(function (request) {
371
+ var _a;
372
+ var model = (_a = editorApis === null || editorApis === void 0 ? void 0 : editorApis.current) === null || _a === void 0 ? void 0 : _a.getMonacoModel();
373
+ if (!model) {
374
+ return;
375
+ }
376
+ var content = model.getValue();
377
+ var _wsUsercode$sendOTs = wsUsercode.sendOTs([{
378
+ d: content
379
+ }, content]),
380
+ requestId = _wsUsercode$sendOTs.requestId;
381
+ usercodeSyncRequestsRef.current.set(requestId, request);
382
+ });
383
+ return function () {
384
+ syncRequestSub.unsubscribe();
385
+ };
386
+ }, [wsUsercode]);
387
+ //
357
388
  // Emit editor change event to parent component.
358
389
  //
359
390
  reactUse.useDebounce(function () {
@@ -21,6 +21,7 @@ var context = require('../context/context.js');
21
21
  var recoilTypes = require('../context/recoilTypes.js');
22
22
  var subjects = require('../context/subjects.js');
23
23
  require('../context/ExerciseProvider.js');
24
+ var async = require('../../../utils/async.js');
24
25
  var runner = require('../../../utils/runner.js');
25
26
  var useRunnerRoomWebSocket = require('../../../hooks/useRunnerRoomWebSocket.js');
26
27
  var useStdioWebSocket = require('../../../hooks/useStdioWebSocket.js');
@@ -296,6 +297,14 @@ var ExerciseRunner = function ExerciseRunner(_ref) {
296
297
  break;
297
298
  }
298
299
  };
300
+ var requestUsercodeSync = function requestUsercodeSync() {
301
+ return new Promise(function (resolve, reject) {
302
+ subjects.exerciseFileEditorSyncRequestAction$.next({
303
+ onSucceed: resolve,
304
+ onFailed: reject
305
+ });
306
+ });
307
+ };
299
308
  /**
300
309
  * Handle submit code to runner and run / grade.
301
310
  */
@@ -305,14 +314,37 @@ var ExerciseRunner = function ExerciseRunner(_ref) {
305
314
  return _rollupPluginBabelHelpers.regeneratorRuntime().wrap(function _callee$(_context) {
306
315
  while (1) switch (_context.prev = _context.next) {
307
316
  case 0:
317
+ _context.prev = 0;
318
+ _context.next = 3;
319
+ return async.withTimeout(requestUsercodeSync(), 2000);
320
+ case 3:
321
+ _context.next = 9;
322
+ break;
323
+ case 5:
324
+ _context.prev = 5;
325
+ _context.t0 = _context["catch"](0);
326
+ setRunnerSubmitErrorDialog({
327
+ code: 'try_again',
328
+ message: __intl.formatMessage({
329
+ id: 'exerciseRunner.submitErrorDialog.body.networkError'
330
+ }),
331
+ action: __intl.formatMessage({
332
+ id: 'exerciseRunner.submitErrorDialog.action.reload'
333
+ }),
334
+ onAction: function onAction() {
335
+ return window.location.reload();
336
+ }
337
+ });
338
+ return _context.abrupt("return");
339
+ case 9:
308
340
  readyExerciseImage = exercise === null || exercise === void 0 ? void 0 : exercise.readyExerciseImage;
309
341
  roomToken = (_a = wsRunnerRoom.roomConnectionInfo) === null || _a === void 0 ? void 0 : _a.roomToken;
310
342
  if (!(!readyExerciseImage || !roomToken)) {
311
- _context.next = 4;
343
+ _context.next = 13;
312
344
  break;
313
345
  }
314
346
  return _context.abrupt("return");
315
- case 4:
347
+ case 13:
316
348
  setRunnerStdioFilesState([]);
317
349
  setRunnerRunTypeState(runType);
318
350
  setRunnerSubmitting(true);
@@ -333,11 +365,11 @@ var ExerciseRunner = function ExerciseRunner(_ref) {
333
365
  onError(err);
334
366
  }
335
367
  }));
336
- case 8:
368
+ case 17:
337
369
  case "end":
338
370
  return _context.stop();
339
371
  }
340
- }, _callee);
372
+ }, _callee, null, [[0, 5]]);
341
373
  }));
342
374
  return function handleRunnerSubmit(_x) {
343
375
  return _ref2.apply(this, arguments);
@@ -52,7 +52,7 @@ var ExerciseRunnerControllerButtonGroup = function ExerciseRunnerControllerButto
52
52
  onSubmit = _React$useContext2.onSubmit,
53
53
  onSyncRequest = _React$useContext2.onSyncRequest,
54
54
  onCancel = _React$useContext2.onCancel;
55
- var runnerWebsocketStatus = recoil.useRecoilValue(recoil$1.exerciseRunnerWebSocketStatusQuery);
55
+ var runnerWebsocketStatus = recoil.useRecoilValue(recoil$1.exerciseWebSocketTotalStatusQuery);
56
56
  var exercise = recoil.useRecoilValue(recoil$1.exerciseState(materialExerciseId));
57
57
  var exerciseRunType = recoil.useRecoilValue(recoil$1.exerciseRunnerRunTypeState);
58
58
  var exerciseWithNoGrade = Boolean(exercise === null || exercise === void 0 ? void 0 : exercise.isNoSubmitGrade);
@@ -2,7 +2,9 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ var _rollupPluginBabelHelpers = require('../../../_virtual/_rollupPluginBabelHelpers.js');
5
6
  var jsxRuntime = require('react/jsx-runtime');
7
+ var React = require('react');
6
8
  var blocks = require('@elice/blocks');
7
9
  var intl = require('@elice/intl');
8
10
  var websocket = require('@elice/websocket');
@@ -24,7 +26,16 @@ var StyledMessageWrapper = styled__default.default(blocks.Flex).withConfig({
24
26
  })(["height:1rem;"]);
25
27
  var ExerciseRunnerControllerStatusMessage = function ExerciseRunnerControllerStatusMessage() {
26
28
  var intl$1 = intl.useRawEliceIntl();
27
- var websocketStatus = recoil.useRecoilValue(recoil$1.exerciseRunnerWebSocketStatusQuery);
29
+ var websocketStatus = recoil.useRecoilValue(recoil$1.exerciseWebSocketTotalStatusQuery);
30
+ var _useState = React.useState(false),
31
+ _useState2 = _rollupPluginBabelHelpers.slicedToArray(_useState, 2),
32
+ isOpenedOnce = _useState2[0],
33
+ setIsOpenedOnce = _useState2[1];
34
+ React.useEffect(function () {
35
+ if (websocketStatus === websocket.EliceWebSocket.OPEN) {
36
+ setIsOpenedOnce(true);
37
+ }
38
+ }, [websocketStatus]);
28
39
  /**
29
40
  * Websocket state message.
30
41
  */
@@ -48,16 +59,24 @@ var ExerciseRunnerControllerStatusMessage = function ExerciseRunnerControllerSta
48
59
  //
49
60
  //
50
61
  //
51
- return jsxRuntime.jsxs(StyledMessageWrapper, {
52
- align: "center",
53
- children: [jsxRuntime.jsx(ExerciseRunnerControllerStatusIndicator.default, {
54
- status: websocketStatus === websocket.EliceWebSocket.OPEN ? 'success' : websocketStatus === websocket.EliceWebSocket.CLOSED ? 'error' : 'warning'
55
- }), jsxRuntime.jsx(blocks.Text, {
56
- role: "gray3",
57
- size: "tiny",
58
- bold: true,
59
- children: getWebsocketStateMessage()
60
- })]
62
+ return jsxRuntime.jsx(blocks.Tooltip, {
63
+ visible: isOpenedOnce && websocketStatus !== websocket.EliceWebSocket.OPEN,
64
+ placement: "top-end",
65
+ dark: false,
66
+ title: intl$1.formatMessage({
67
+ id: 'exerciseRunner.controller.tooltip.closed'
68
+ }),
69
+ children: jsxRuntime.jsxs(StyledMessageWrapper, {
70
+ align: "center",
71
+ children: [jsxRuntime.jsx(ExerciseRunnerControllerStatusIndicator.default, {
72
+ status: websocketStatus === websocket.EliceWebSocket.OPEN ? 'success' : websocketStatus === websocket.EliceWebSocket.CLOSED ? 'error' : 'warning'
73
+ }), jsxRuntime.jsx(blocks.Text, {
74
+ role: "gray3",
75
+ size: "tiny",
76
+ bold: true,
77
+ children: getWebsocketStateMessage()
78
+ })]
79
+ })
61
80
  });
62
81
  };
63
82
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var messageEn = {"exerciseRunner.controller.arduino.connectionStatus.connected":"Connected to Arduino","exerciseRunner.controller.arduino.connectionStatus.connectedDevice":"Connected to {device}","exerciseRunner.controller.arduino.connectionStatus.connecting":"Connecting to Elice Arduino Agent","exerciseRunner.controller.arduino.connectionStatus.disconnected":"Disconnected from Elice Arduino Agent","exerciseRunner.controller.arduino.connectionStatus.noDevice":"No connected device","exerciseRunner.controller.arduino.connectionStatus.reconnecting":"Connecting to Elice Arduino Agent","exerciseRunner.controller.arduino.connectionStatus.uploading":"Uploading...","exerciseRunner.controller.arduino.agent.title":"Connect to Agent","exerciseRunner.controller.arduino.agent.instruction.install":"1. Install Elice arduino agent","exerciseRunner.controller.arduino.agent.instruction.install.detail":"Install 'elice-arduino-agent' program to connect to arduino.","exerciseRunner.controller.arduino.agent.instruction.install.window":"Download for Windows","exerciseRunner.controller.arduino.agent.instruction.install.mac":"Download for MacOS","exerciseRunner.controller.arduino.agent.instruction.connect":"2. Connect to arduino","exerciseRunner.controller.arduino.agent.instruction.connect.detail":"After the download is completed, it should be connected to exercise environment. If connection is unavailable, please follow the manual.\nClick the button below to read the manual.","exerciseRunner.controller.arduino.agent.instruction.connect.button":"Go to Manual","exerciseRunner.controller.arduino.agent.instruction.close":"Close","exerciseRunner.controller.buttonGroup.button.compile":"Compile","exerciseRunner.controller.buttonGroup.button.helpRequest":"Ask about the dragged code","exerciseRunner.controller.buttonGroup.button.run":"Run","exerciseRunner.controller.buttonGroup.button.stop":"Stop","exerciseRunner.controller.buttonGroup.button.submit":"Submit","exerciseRunner.controller.buttonGroup.button.submit.tooltip.noSubmit":"Exercise without submission","exerciseRunner.controller.buttonGroup.button.syncRequest":"Sync code","exerciseRunner.controller.buttonGroup.button.tooltip.aiHelp":"Ask any questions you may have.","exerciseRunner.controller.runningInfo.error.fetch":"An error occurred while fetching running info","exerciseRunner.controller.runningInfo.lastRunningDatetime":"Last running datetime","exerciseRunner.controller.runningInfo.lastSubmitDatetime":"Last submit datetime","exerciseRunner.controller.runningInfo.lastSubmitScore":"Last submit score","exerciseRunner.controller.runningInfo.score":"{score}","exerciseRunner.controller.statusMessage.closed":"Editor disconnected","exerciseRunner.controller.statusMessage.connecting":"Connecting to editor...","exerciseRunner.controller.statusMessage.open":"Editor connected","exerciseRunner.controller.timer.runningRemainingTime":"Remaining: {remainingTime}","exerciseRunner.submitErrorDialog.action.confirm":"OK","exerciseRunner.submitErrorDialog.action.reload":"Reload page","exerciseRunner.submitErrorDialog.body.commonError":"An error occurred while running the code.\nPlease refresh and try again.","exerciseRunner.submitErrorDialog.body.exceedSubmitGradeLimit":"You have exceeded the allowed number of lab submissions.","exerciseRunner.submitErrorDialog.body.expiredExerciseImage":"The exercise image has been updated.\nPlease refresh and try again.","exerciseRunner.submitErrorDialog.body.networkError":"An error occurred while running the code.\nPlease refresh and try again.\nIf the problem persists, please check the network status.","exerciseRunner.submitErrorDialog.body.notForSubmitGrade":"This exercise is not allowed to be submitted.","exerciseRunner.submitErrorDialog.body.notPreparedRoom":"The exercise room is being prepared.\nPlease try again later.","exerciseRunner.submitErrorDialog.body.roomIsBusy":"The exercise room is running.\nPlease wait a moment.","exerciseRunner.submitErrorDialog.body.unknown":"An error occurred while running the code.\nPlease try again later.","exerciseRunner.submitErrorDialog.title":"Unable to run the code"};
5
+ var messageEn = {"exerciseRunner.controller.arduino.connectionStatus.connected":"Connected to Arduino","exerciseRunner.controller.arduino.connectionStatus.connectedDevice":"Connected to {device}","exerciseRunner.controller.arduino.connectionStatus.connecting":"Connecting to Elice Arduino Agent","exerciseRunner.controller.arduino.connectionStatus.disconnected":"Disconnected from Elice Arduino Agent","exerciseRunner.controller.arduino.connectionStatus.noDevice":"No connected device","exerciseRunner.controller.arduino.connectionStatus.reconnecting":"Connecting to Elice Arduino Agent","exerciseRunner.controller.arduino.connectionStatus.uploading":"Uploading...","exerciseRunner.controller.arduino.agent.title":"Connect to Agent","exerciseRunner.controller.arduino.agent.instruction.install":"1. Install Elice arduino agent","exerciseRunner.controller.arduino.agent.instruction.install.detail":"Install 'elice-arduino-agent' program to connect to arduino.","exerciseRunner.controller.arduino.agent.instruction.install.window":"Download for Windows","exerciseRunner.controller.arduino.agent.instruction.install.mac":"Download for MacOS","exerciseRunner.controller.arduino.agent.instruction.connect":"2. Connect to arduino","exerciseRunner.controller.arduino.agent.instruction.connect.detail":"After the download is completed, it should be connected to exercise environment. If connection is unavailable, please follow the manual.\nClick the button below to read the manual.","exerciseRunner.controller.arduino.agent.instruction.connect.button":"Go to Manual","exerciseRunner.controller.arduino.agent.instruction.close":"Close","exerciseRunner.controller.buttonGroup.button.compile":"Compile","exerciseRunner.controller.buttonGroup.button.helpRequest":"Ask about the dragged code","exerciseRunner.controller.buttonGroup.button.run":"Run","exerciseRunner.controller.buttonGroup.button.stop":"Stop","exerciseRunner.controller.buttonGroup.button.submit":"Submit","exerciseRunner.controller.buttonGroup.button.submit.tooltip.noSubmit":"Exercise without submission","exerciseRunner.controller.buttonGroup.button.syncRequest":"Sync code","exerciseRunner.controller.buttonGroup.button.tooltip.aiHelp":"Ask any questions you may have.","exerciseRunner.controller.runningInfo.error.fetch":"An error occurred while fetching running info","exerciseRunner.controller.runningInfo.lastRunningDatetime":"Last running datetime","exerciseRunner.controller.runningInfo.lastSubmitDatetime":"Last submit datetime","exerciseRunner.controller.runningInfo.lastSubmitScore":"Last submit score","exerciseRunner.controller.runningInfo.score":"{score}","exerciseRunner.controller.statusMessage.closed":"Editor disconnected","exerciseRunner.controller.statusMessage.connecting":"Connecting to editor...","exerciseRunner.controller.statusMessage.open":"Editor connected","exerciseRunner.controller.tooltip.closed":"The connection to the code server is currently unstable, so your edits may not be saved.\nPlease check your network and try again.","exerciseRunner.controller.timer.runningRemainingTime":"Remaining: {remainingTime}","exerciseRunner.submitErrorDialog.action.confirm":"OK","exerciseRunner.submitErrorDialog.action.reload":"Reload page","exerciseRunner.submitErrorDialog.body.commonError":"An error occurred while running the code.\nPlease refresh and try again.","exerciseRunner.submitErrorDialog.body.exceedSubmitGradeLimit":"You have exceeded the allowed number of lab submissions.","exerciseRunner.submitErrorDialog.body.expiredExerciseImage":"The exercise image has been updated.\nPlease refresh and try again.","exerciseRunner.submitErrorDialog.body.networkError":"An error occurred while running the code.\nPlease refresh and try again.\nIf the problem persists, please check the network status.","exerciseRunner.submitErrorDialog.body.notForSubmitGrade":"This exercise is not allowed to be submitted.","exerciseRunner.submitErrorDialog.body.notPreparedRoom":"The exercise room is being prepared.\nPlease try again later.","exerciseRunner.submitErrorDialog.body.roomIsBusy":"The exercise room is running.\nPlease wait a moment.","exerciseRunner.submitErrorDialog.body.unknown":"An error occurred while running the code.\nPlease try again later.","exerciseRunner.submitErrorDialog.title":"Unable to run the code"};
6
6
 
7
7
  exports.default = messageEn;
@@ -2,6 +2,6 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var ja = {"exerciseRunner.controller.arduino.connectionStatus.connected":"Arduinoに接続されました","exerciseRunner.controller.arduino.connectionStatus.connectedDevice":"{device}に接続されました","exerciseRunner.controller.arduino.connectionStatus.connecting":"Elice Arduino エージェントに接続中","exerciseRunner.controller.arduino.connectionStatus.disconnected":"Elice Arduino エージェントから切断されました","exerciseRunner.controller.arduino.connectionStatus.noDevice":"接続されたデバイスはありません。","exerciseRunner.controller.arduino.connectionStatus.reconnecting":"Elice Arduino エージェントに接続中","exerciseRunner.controller.arduino.connectionStatus.uploading":"アップロード中...","exerciseRunner.controller.arduino.agent.title":"エージェントに接続します","exerciseRunner.controller.arduino.agent.instruction.install":"1. Elice Arduino エージェントをインストールします。","exerciseRunner.controller.arduino.agent.instruction.install.detail":"'elice-arduino-agent' プログラムをインストールして Arduino に接続してください。","exerciseRunner.controller.arduino.agent.instruction.install.window":"Windows用のダウンロード","exerciseRunner.controller.arduino.agent.instruction.install.mac":"MacOS用のダウンロード","exerciseRunner.controller.arduino.agent.instruction.connect":"2. Arduinoに接続します。","exerciseRunner.controller.arduino.agent.instruction.connect.detail":"ダウンロードが完了したら、運動環境に接続する必要があります。接続できない場合は、マニュアルに従ってください。\nマニュアルを読むために下のボタンをクリックしてください。","exerciseRunner.controller.arduino.agent.instruction.connect.button":"マニュアルを参照してください。","exerciseRunner.controller.arduino.agent.instruction.close":"閉じる","exerciseRunner.controller.buttonGroup.button.compile":"コンパイル","exerciseRunner.controller.buttonGroup.button.helpRequest":"ドラッグしたコードの質問","exerciseRunner.controller.buttonGroup.button.run":"ラン","exerciseRunner.controller.buttonGroup.button.stop":"停止","exerciseRunner.controller.buttonGroup.button.submit":"提出","exerciseRunner.controller.buttonGroup.button.submit.tooltip.noSubmit":"提出なしの運動","exerciseRunner.controller.buttonGroup.button.syncRequest":"コードを同期します","exerciseRunner.controller.buttonGroup.button.tooltip.aiHelp":"どんな質問がありますか。","exerciseRunner.controller.runningInfo.error.fetch":"ランニング情報を取得中にエラーが発生しました。","exerciseRunner.controller.runningInfo.lastRunningDatetime":"最終実行日時","exerciseRunner.controller.runningInfo.lastSubmitDatetime":"最終送信日時","exerciseRunner.controller.runningInfo.lastSubmitScore":"最後に提出したスコア","exerciseRunner.controller.runningInfo.score":"{得点}","exerciseRunner.controller.statusMessage.closed":"エディタが切断されました。","exerciseRunner.controller.statusMessage.connecting":"エディタへの接続中...","exerciseRunner.controller.statusMessage.open":"エディターが接続されました","exerciseRunner.controller.timer.runningRemainingTime":"残り時間: {remainingTime}","exerciseRunner.submitErrorDialog.action.confirm":"OK","exerciseRunner.submitErrorDialog.action.reload":"ページをリロードしてください。","exerciseRunner.submitErrorDialog.body.commonError":"コードを実行中にエラーが発生しました。\nページを更新してもう一度お試しください。","exerciseRunner.submitErrorDialog.body.exceedSubmitGradeLimit":"許可された実験提出回数を超えています。","exerciseRunner.submitErrorDialog.body.expiredExerciseImage":"エクササイズ画像が更新されました。\nもう一度更新してやり直してください。","exerciseRunner.submitErrorDialog.body.networkError":"コードを実行中にエラーが発生しました。\nページを更新して、もう一度お試しください。\n問題が解決しない場合は、ネットワークの状態を確認してください。","exerciseRunner.submitErrorDialog.body.notForSubmitGrade":"この演習は提出してはいけません。","exerciseRunner.submitErrorDialog.body.notPreparedRoom":"エクササイズルームは準備中です。\n後で再試行してください。","exerciseRunner.submitErrorDialog.body.roomIsBusy":"運動室は稼働しています。\n少々お待ちください。","exerciseRunner.submitErrorDialog.body.unknown":"コードの実行中にエラーが発生しました。\n後でもう一度お試しください。","exerciseRunner.submitErrorDialog.title":"コードを実行できません。"};
5
+ var ja = {"exerciseRunner.controller.arduino.connectionStatus.connected":"Arduinoに接続されました","exerciseRunner.controller.arduino.connectionStatus.connectedDevice":"{device}に接続されました","exerciseRunner.controller.arduino.connectionStatus.connecting":"Elice Arduino エージェントに接続中","exerciseRunner.controller.arduino.connectionStatus.disconnected":"Elice Arduino エージェントから切断されました","exerciseRunner.controller.arduino.connectionStatus.noDevice":"接続されたデバイスはありません。","exerciseRunner.controller.arduino.connectionStatus.reconnecting":"Elice Arduino エージェントに接続中","exerciseRunner.controller.arduino.connectionStatus.uploading":"アップロード中...","exerciseRunner.controller.arduino.agent.title":"エージェントに接続します","exerciseRunner.controller.arduino.agent.instruction.install":"1. Elice Arduino エージェントをインストールします。","exerciseRunner.controller.arduino.agent.instruction.install.detail":"'elice-arduino-agent' プログラムをインストールして Arduino に接続してください。","exerciseRunner.controller.arduino.agent.instruction.install.window":"Windows用のダウンロード","exerciseRunner.controller.arduino.agent.instruction.install.mac":"MacOS用のダウンロード","exerciseRunner.controller.arduino.agent.instruction.connect":"2. Arduinoに接続します。","exerciseRunner.controller.arduino.agent.instruction.connect.detail":"ダウンロードが完了したら、運動環境に接続する必要があります。接続できない場合は、マニュアルに従ってください。\nマニュアルを読むために下のボタンをクリックしてください。","exerciseRunner.controller.arduino.agent.instruction.connect.button":"マニュアルを参照してください。","exerciseRunner.controller.arduino.agent.instruction.close":"閉じる","exerciseRunner.controller.buttonGroup.button.compile":"コンパイル","exerciseRunner.controller.buttonGroup.button.helpRequest":"ドラッグしたコードの質問","exerciseRunner.controller.buttonGroup.button.run":"ラン","exerciseRunner.controller.buttonGroup.button.stop":"停止","exerciseRunner.controller.buttonGroup.button.submit":"提出","exerciseRunner.controller.buttonGroup.button.submit.tooltip.noSubmit":"提出なしの運動","exerciseRunner.controller.buttonGroup.button.syncRequest":"コードを同期します","exerciseRunner.controller.buttonGroup.button.tooltip.aiHelp":"どんな質問がありますか。","exerciseRunner.controller.runningInfo.error.fetch":"ランニング情報を取得中にエラーが発生しました。","exerciseRunner.controller.runningInfo.lastRunningDatetime":"最終実行日時","exerciseRunner.controller.runningInfo.lastSubmitDatetime":"最終送信日時","exerciseRunner.controller.runningInfo.lastSubmitScore":"最後に提出したスコア","exerciseRunner.controller.runningInfo.score":"{得点}","exerciseRunner.controller.statusMessage.closed":"エディタが切断されました。","exerciseRunner.controller.statusMessage.connecting":"エディタへの接続中...","exerciseRunner.controller.statusMessage.open":"エディターが接続されました","exerciseRunner.controller.tooltip.closed":"現在、コードサーバーとの接続が不安定なため、編集内容が反映されない可能性があります。\nネットワークの状態を確認してから作業を続けてください。","exerciseRunner.controller.timer.runningRemainingTime":"残り時間: {remainingTime}","exerciseRunner.submitErrorDialog.action.confirm":"OK","exerciseRunner.submitErrorDialog.action.reload":"ページをリロードしてください。","exerciseRunner.submitErrorDialog.body.commonError":"コードを実行中にエラーが発生しました。\nページを更新してもう一度お試しください。","exerciseRunner.submitErrorDialog.body.exceedSubmitGradeLimit":"許可された実験提出回数を超えています。","exerciseRunner.submitErrorDialog.body.expiredExerciseImage":"エクササイズ画像が更新されました。\nもう一度更新してやり直してください。","exerciseRunner.submitErrorDialog.body.networkError":"コードを実行中にエラーが発生しました。\nページを更新して、もう一度お試しください。\n問題が解決しない場合は、ネットワークの状態を確認してください。","exerciseRunner.submitErrorDialog.body.notForSubmitGrade":"この演習は提出してはいけません。","exerciseRunner.submitErrorDialog.body.notPreparedRoom":"エクササイズルームは準備中です。\n後で再試行してください。","exerciseRunner.submitErrorDialog.body.roomIsBusy":"運動室は稼働しています。\n少々お待ちください。","exerciseRunner.submitErrorDialog.body.unknown":"コードの実行中にエラーが発生しました。\n後でもう一度お試しください。","exerciseRunner.submitErrorDialog.title":"コードを実行できません。"};
6
6
 
7
7
  exports.default = ja;
@@ -2,6 +2,6 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var messageKo = {"exerciseRunner.controller.arduino.connectionStatus.connected":"아두이노 기기 연결됨","exerciseRunner.controller.arduino.connectionStatus.connectedDevice":"{device} 연결됨","exerciseRunner.controller.arduino.connectionStatus.connecting":"엘리스 아두이노 에이전트 연결 중","exerciseRunner.controller.arduino.connectionStatus.disconnected":"엘리스 아두이노 에이전트 연결 끊김","exerciseRunner.controller.arduino.connectionStatus.noDevice":"연결된 기기 없음","exerciseRunner.controller.arduino.connectionStatus.reconnecting":"엘리스 아두이노 에이전트 연결 중","exerciseRunner.controller.arduino.connectionStatus.uploading":"업로드 중","exerciseRunner.controller.arduino.agent.title":"에이전트 연결","exerciseRunner.controller.arduino.agent.instruction.install":"1. 엘리스 아두이노 에이전트 설치하기","exerciseRunner.controller.arduino.agent.instruction.install.detail":"아두이노와 연결하기 위해 ‘엘리스 아두이노 에이전트'를 설치해주세요.","exerciseRunner.controller.arduino.agent.instruction.install.window":"Windows 용 설치","exerciseRunner.controller.arduino.agent.instruction.install.mac":"MacOS 용 설치","exerciseRunner.controller.arduino.agent.instruction.connect":"2. 연결하기","exerciseRunner.controller.arduino.agent.instruction.connect.detail":"다운로드를 완료하였다면 실습 환경과 연결이 필요합니다. 연결되지 않을 경우 매뉴얼을 확인하세요.\n아래 버튼을 클릭해 매뉴얼을 확인하실 수 있습니다.","exerciseRunner.controller.arduino.agent.instruction.connect.button":"매뉴얼 이동","exerciseRunner.controller.arduino.agent.instruction.close":"닫기","exerciseRunner.controller.buttonGroup.button.compile":"컴파일","exerciseRunner.controller.buttonGroup.button.helpRequest":"드래그한 코드 질문","exerciseRunner.controller.buttonGroup.button.run":"실행","exerciseRunner.controller.buttonGroup.button.stop":"정지","exerciseRunner.controller.buttonGroup.button.submit":"제출","exerciseRunner.controller.buttonGroup.button.submit.tooltip.noSubmit":"실행만 가능한 실습입니다.","exerciseRunner.controller.buttonGroup.button.syncRequest":"코드 동기화","exerciseRunner.controller.buttonGroup.button.tooltip.aiHelp":"궁금한 사항을 질문해 보세요.","exerciseRunner.controller.runningInfo.error.fetch":"최종 실행 내역을 가져오는데 문제가 발생하였습니다.","exerciseRunner.controller.runningInfo.lastRunningDatetime":"최종 실행 시간","exerciseRunner.controller.runningInfo.lastSubmitDatetime":"최종 제출 시간","exerciseRunner.controller.runningInfo.lastSubmitScore":"최종 제출 점수","exerciseRunner.controller.runningInfo.score":"{score} 점","exerciseRunner.controller.statusMessage.closed":"에디터 연결 끊김","exerciseRunner.controller.statusMessage.connecting":"에디터 연결 중...","exerciseRunner.controller.statusMessage.open":"에디터 연결됨","exerciseRunner.controller.timer.runningRemainingTime":"실행 제한시간: {remainingTime}","exerciseRunner.submitErrorDialog.action.confirm":"확인","exerciseRunner.submitErrorDialog.action.reload":"새로고침","exerciseRunner.submitErrorDialog.body.commonError":"코드 실행 중 오류가 발생했습니다.\n새로고침 후 다시 시도해주세요.","exerciseRunner.submitErrorDialog.body.exceedSubmitGradeLimit":"실습 제출 허용 횟수를 초과했습니다.","exerciseRunner.submitErrorDialog.body.expiredExerciseImage":"실습환경이 업데이트 되었습니다.\n새로고침 후 다시 시도해주세요.","exerciseRunner.submitErrorDialog.body.networkError":"코드 실행 중 오류가 발생했습니다.\n새로고침 후 다시 시도해주세요.\n문제가 계속되면 네트워크 상태를 확인해주세요.","exerciseRunner.submitErrorDialog.body.notForSubmitGrade":"제출이 허용되지 않은 실습입니다.","exerciseRunner.submitErrorDialog.body.notPreparedRoom":"실습환경이 준비 중입니다.\n잠시 후 다시 시도해주세요.","exerciseRunner.submitErrorDialog.body.roomIsBusy":"실습을 실행하고 있습니다.\n잠시만 기다려 주세요.","exerciseRunner.submitErrorDialog.body.unknown":"코드 실행 중 오류가 발생했습니다.\n잠시 후 다시 시도해주세요.","exerciseRunner.submitErrorDialog.title":"실습을 실행할 수 없습니다"};
5
+ var messageKo = {"exerciseRunner.controller.arduino.connectionStatus.connected":"아두이노 기기 연결됨","exerciseRunner.controller.arduino.connectionStatus.connectedDevice":"{device} 연결됨","exerciseRunner.controller.arduino.connectionStatus.connecting":"엘리스 아두이노 에이전트 연결 중","exerciseRunner.controller.arduino.connectionStatus.disconnected":"엘리스 아두이노 에이전트 연결 끊김","exerciseRunner.controller.arduino.connectionStatus.noDevice":"연결된 기기 없음","exerciseRunner.controller.arduino.connectionStatus.reconnecting":"엘리스 아두이노 에이전트 연결 중","exerciseRunner.controller.arduino.connectionStatus.uploading":"업로드 중","exerciseRunner.controller.arduino.agent.title":"에이전트 연결","exerciseRunner.controller.arduino.agent.instruction.install":"1. 엘리스 아두이노 에이전트 설치하기","exerciseRunner.controller.arduino.agent.instruction.install.detail":"아두이노와 연결하기 위해 ‘엘리스 아두이노 에이전트'를 설치해주세요.","exerciseRunner.controller.arduino.agent.instruction.install.window":"Windows 용 설치","exerciseRunner.controller.arduino.agent.instruction.install.mac":"MacOS 용 설치","exerciseRunner.controller.arduino.agent.instruction.connect":"2. 연결하기","exerciseRunner.controller.arduino.agent.instruction.connect.detail":"다운로드를 완료하였다면 실습 환경과 연결이 필요합니다. 연결되지 않을 경우 매뉴얼을 확인하세요.\n아래 버튼을 클릭해 매뉴얼을 확인하실 수 있습니다.","exerciseRunner.controller.arduino.agent.instruction.connect.button":"매뉴얼 이동","exerciseRunner.controller.arduino.agent.instruction.close":"닫기","exerciseRunner.controller.buttonGroup.button.compile":"컴파일","exerciseRunner.controller.buttonGroup.button.helpRequest":"드래그한 코드 질문","exerciseRunner.controller.buttonGroup.button.run":"실행","exerciseRunner.controller.buttonGroup.button.stop":"정지","exerciseRunner.controller.buttonGroup.button.submit":"제출","exerciseRunner.controller.buttonGroup.button.submit.tooltip.noSubmit":"실행만 가능한 실습입니다.","exerciseRunner.controller.buttonGroup.button.syncRequest":"코드 동기화","exerciseRunner.controller.buttonGroup.button.tooltip.aiHelp":"궁금한 사항을 질문해 보세요.","exerciseRunner.controller.runningInfo.error.fetch":"최종 실행 내역을 가져오는데 문제가 발생하였습니다.","exerciseRunner.controller.runningInfo.lastRunningDatetime":"최종 실행 시간","exerciseRunner.controller.runningInfo.lastSubmitDatetime":"최종 제출 시간","exerciseRunner.controller.runningInfo.lastSubmitScore":"최종 제출 점수","exerciseRunner.controller.runningInfo.score":"{score} 점","exerciseRunner.controller.statusMessage.closed":"에디터 연결 끊김","exerciseRunner.controller.statusMessage.connecting":"에디터 연결 중...","exerciseRunner.controller.statusMessage.open":"에디터 연결됨","exerciseRunner.controller.tooltip.closed":"현재 코드 서버와 네트워크 연결 상태가 불안정하여 편집 내용이 반영되지 않습니다.\n네트워크 상태를 확인하여 코드 작성을 진행해주세요.","exerciseRunner.controller.timer.runningRemainingTime":"실행 제한시간: {remainingTime}","exerciseRunner.submitErrorDialog.action.confirm":"확인","exerciseRunner.submitErrorDialog.action.reload":"새로고침","exerciseRunner.submitErrorDialog.body.commonError":"코드 실행 중 오류가 발생했습니다.\n새로고침 후 다시 시도해주세요.","exerciseRunner.submitErrorDialog.body.exceedSubmitGradeLimit":"실습 제출 허용 횟수를 초과했습니다.","exerciseRunner.submitErrorDialog.body.expiredExerciseImage":"실습환경이 업데이트 되었습니다.\n새로고침 후 다시 시도해주세요.","exerciseRunner.submitErrorDialog.body.networkError":"코드 실행 중 오류가 발생했습니다.\n새로고침 후 다시 시도해주세요.\n문제가 계속되면 네트워크 상태를 확인해주세요.","exerciseRunner.submitErrorDialog.body.notForSubmitGrade":"제출이 허용되지 않은 실습입니다.","exerciseRunner.submitErrorDialog.body.notPreparedRoom":"실습환경이 준비 중입니다.\n잠시 후 다시 시도해주세요.","exerciseRunner.submitErrorDialog.body.roomIsBusy":"실습을 실행하고 있습니다.\n잠시만 기다려 주세요.","exerciseRunner.submitErrorDialog.body.unknown":"코드 실행 중 오류가 발생했습니다.\n잠시 후 다시 시도해주세요.","exerciseRunner.submitErrorDialog.title":"실습을 실행할 수 없습니다"};
6
6
 
7
7
  exports.default = messageKo;
@@ -2,6 +2,6 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var th = {"exerciseRunner.controller.arduino.connectionStatus.connected":"เชื่อมต่อกับ Arduino แล้ว","exerciseRunner.controller.arduino.connectionStatus.connectedDevice":"เชื่อมต่อกับ {device}","exerciseRunner.controller.arduino.connectionStatus.connecting":"กำลังเชื่อมต่อกับ Arduino Agent","exerciseRunner.controller.arduino.connectionStatus.disconnected":"ตัดการเชื่อมต่อกับ Arduino Agent","exerciseRunner.controller.arduino.connectionStatus.noDevice":"ไม่พบอุปกรณ์ที่เชื่อมต่อ","exerciseRunner.controller.arduino.connectionStatus.reconnecting":"กำลังเชื่อมต่อกับ Arduino Agent ใหม่","exerciseRunner.controller.arduino.connectionStatus.uploading":"กำลังอัปโหลด...","exerciseRunner.controller.arduino.agent.title":"เชื่อมต่อ Agent","exerciseRunner.controller.arduino.agent.instruction.install":"1. ติดตั้ง Arduino Agent","exerciseRunner.controller.arduino.agent.instruction.install.detail":"ติดตั้งโปรแกรม 'elice-arduino-agent' เพื่อเชื่อมต่อกับ Arduino ค่ะ.","exerciseRunner.controller.arduino.agent.instruction.install.window":"ดาวน์โหลดสำหรับ Windows","exerciseRunner.controller.arduino.agent.instruction.install.mac":"ดาวน์โหลดสำหรับ MacOS","exerciseRunner.controller.arduino.agent.instruction.connect":"2. เชื่อมต่อกับ Arduino","exerciseRunner.controller.arduino.agent.instruction.connect.detail":"หลังจากการดาวน์โหลดเสร็จสิ้นแล้ว ควรเชื่อมต่อกับสภาพแวดล้อมการฝึกหัด หากไม่สามารถเชื่อมต่อได้ โปรดทำตามคู่มือ\nคลิกที่ปุ่มด้านล่างเพื่ออ่านคู่มือ","exerciseRunner.controller.arduino.agent.instruction.connect.button":"ไปที่คู่มือ","exerciseRunner.controller.arduino.agent.instruction.close":"ปิด","exerciseRunner.controller.buttonGroup.button.compile":"คอมไพล์","exerciseRunner.controller.buttonGroup.button.helpRequest":"ถามเกี่ยวกับโค้ดที่ลาก","exerciseRunner.controller.buttonGroup.button.run":"เรียกใช้งาน","exerciseRunner.controller.buttonGroup.button.stop":"หยุด","exerciseRunner.controller.buttonGroup.button.submit":"ส่ง","exerciseRunner.controller.buttonGroup.button.submit.tooltip.noSubmit":"การฝึกอบรมนี้รองรับเฉพาะการรันเท่านั้น","exerciseRunner.controller.buttonGroup.button.syncRequest":"ซิงค์โค้ด","exerciseRunner.controller.buttonGroup.button.tooltip.aiHelp":"ถามคำถามได้เลยค่ะ","exerciseRunner.controller.runningInfo.error.fetch":"เกิดข้อผิดพลาดขณะดึงข้อมูลการทำงานใหม่","exerciseRunner.controller.runningInfo.lastRunningDatetime":"วันที่และเวลาที่ทำการเรียกใช้ครั้งล่าสุด","exerciseRunner.controller.runningInfo.lastSubmitDatetime":"เวลาส่งครั้งล่าสุด","exerciseRunner.controller.runningInfo.lastSubmitScore":"คะแนนส่งครั้งล่าสุด","exerciseRunner.controller.runningInfo.score":"{score} คะแนน","exerciseRunner.controller.statusMessage.closed":"การเชื่อมต่อกับ Editor ถูกยกเลิก","exerciseRunner.controller.statusMessage.connecting":"กำลังเชื่อมต่อกับ Editor...","exerciseRunner.controller.statusMessage.open":"เชื่อมต่อกับ Editor สำเร็จ","exerciseRunner.controller.timer.runningRemainingTime":"เวลาที่เหลืออยู่: {remainingTime}","exerciseRunner.submitErrorDialog.action.confirm":"ยืนยัน","exerciseRunner.submitErrorDialog.action.reload":"โหลดหน้าใหม่","exerciseRunner.submitErrorDialog.body.commonError":"เกิดข้อผิดพลาดขณะรันโค้ด\nโปรดรีเฟรชและลองอีกครั้ง","exerciseRunner.submitErrorDialog.body.exceedSubmitGradeLimit":"คุณส่งเกินจำนวนที่กำหนด","exerciseRunner.submitErrorDialog.body.expiredExerciseImage":"สภาพแวดล้อมการฝึกอบรมหมดอายุ กรุณารีเฟรชและลองอีกครั้ง","exerciseRunner.submitErrorDialog.body.networkError":"เกิดข้อผิดพลาดขณะรันโค้ด กรุณารีเฟรชและลองอีกครั้ง\nหากยังมีปัญหา กรุณาตรวจสอบสภาพการเชื่อมต่ออินเทอร์เน็ต","exerciseRunner.submitErrorDialog.body.notForSubmitGrade":"การส่งผลงานสำหรับการฝึกอบรมนี้ไม่ถูกต้อง","exerciseRunner.submitErrorDialog.body.notPreparedRoom":"สภาพแวดล้อมการฝึกอบรมกำลังถูกตั้งค่า กรุณารอสักครู่และลองอีกครั้ง","exerciseRunner.submitErrorDialog.body.roomIsBusy":"มีการรันโค้ดอยู่ในขณะนี้ กรุณารอจนกว่าจะเสร็จสิ้น","exerciseRunner.submitErrorDialog.body.unknown":"เกิดข้อผิดพลาดขณะรันโค้ด กรุณารอสักครู่และลองอีกครั้ง","exerciseRunner.submitErrorDialog.title":"ไม่สามารถรันโค้ดได้"};
5
+ var th = {"exerciseRunner.controller.arduino.connectionStatus.connected":"เชื่อมต่อกับ Arduino แล้ว","exerciseRunner.controller.arduino.connectionStatus.connectedDevice":"เชื่อมต่อกับ {device}","exerciseRunner.controller.arduino.connectionStatus.connecting":"กำลังเชื่อมต่อกับ Arduino Agent","exerciseRunner.controller.arduino.connectionStatus.disconnected":"ตัดการเชื่อมต่อกับ Arduino Agent","exerciseRunner.controller.arduino.connectionStatus.noDevice":"ไม่พบอุปกรณ์ที่เชื่อมต่อ","exerciseRunner.controller.arduino.connectionStatus.reconnecting":"กำลังเชื่อมต่อกับ Arduino Agent ใหม่","exerciseRunner.controller.arduino.connectionStatus.uploading":"กำลังอัปโหลด...","exerciseRunner.controller.arduino.agent.title":"เชื่อมต่อ Agent","exerciseRunner.controller.arduino.agent.instruction.install":"1. ติดตั้ง Arduino Agent","exerciseRunner.controller.arduino.agent.instruction.install.detail":"ติดตั้งโปรแกรม 'elice-arduino-agent' เพื่อเชื่อมต่อกับ Arduino ค่ะ.","exerciseRunner.controller.arduino.agent.instruction.install.window":"ดาวน์โหลดสำหรับ Windows","exerciseRunner.controller.arduino.agent.instruction.install.mac":"ดาวน์โหลดสำหรับ MacOS","exerciseRunner.controller.arduino.agent.instruction.connect":"2. เชื่อมต่อกับ Arduino","exerciseRunner.controller.arduino.agent.instruction.connect.detail":"หลังจากการดาวน์โหลดเสร็จสิ้นแล้ว ควรเชื่อมต่อกับสภาพแวดล้อมการฝึกหัด หากไม่สามารถเชื่อมต่อได้ โปรดทำตามคู่มือ\nคลิกที่ปุ่มด้านล่างเพื่ออ่านคู่มือ","exerciseRunner.controller.arduino.agent.instruction.connect.button":"ไปที่คู่มือ","exerciseRunner.controller.arduino.agent.instruction.close":"ปิด","exerciseRunner.controller.buttonGroup.button.compile":"คอมไพล์","exerciseRunner.controller.buttonGroup.button.helpRequest":"ถามเกี่ยวกับโค้ดที่ลาก","exerciseRunner.controller.buttonGroup.button.run":"เรียกใช้งาน","exerciseRunner.controller.buttonGroup.button.stop":"หยุด","exerciseRunner.controller.buttonGroup.button.submit":"ส่ง","exerciseRunner.controller.buttonGroup.button.submit.tooltip.noSubmit":"การฝึกอบรมนี้รองรับเฉพาะการรันเท่านั้น","exerciseRunner.controller.buttonGroup.button.syncRequest":"ซิงค์โค้ด","exerciseRunner.controller.buttonGroup.button.tooltip.aiHelp":"ถามคำถามได้เลยค่ะ","exerciseRunner.controller.runningInfo.error.fetch":"เกิดข้อผิดพลาดขณะดึงข้อมูลการทำงานใหม่","exerciseRunner.controller.runningInfo.lastRunningDatetime":"วันที่และเวลาที่ทำการเรียกใช้ครั้งล่าสุด","exerciseRunner.controller.runningInfo.lastSubmitDatetime":"เวลาส่งครั้งล่าสุด","exerciseRunner.controller.runningInfo.lastSubmitScore":"คะแนนส่งครั้งล่าสุด","exerciseRunner.controller.runningInfo.score":"{score} คะแนน","exerciseRunner.controller.statusMessage.closed":"การเชื่อมต่อกับ Editor ถูกยกเลิก","exerciseRunner.controller.statusMessage.connecting":"กำลังเชื่อมต่อกับ Editor...","exerciseRunner.controller.statusMessage.open":"เชื่อมต่อกับ Editor สำเร็จ","exerciseRunner.controller.tooltip.closed":"ขณะนี้การเชื่อมต่อกับเซิร์ฟเวอร์โค้ดไม่เสถียร การแก้ไขของคุณอาจไม่ถูกบันทึก\nกรุณาตรวจสอบเครือข่ายของคุณก่อนดำเนินการต่อ","exerciseRunner.controller.timer.runningRemainingTime":"เวลาที่เหลืออยู่: {remainingTime}","exerciseRunner.submitErrorDialog.action.confirm":"ยืนยัน","exerciseRunner.submitErrorDialog.action.reload":"โหลดหน้าใหม่","exerciseRunner.submitErrorDialog.body.commonError":"เกิดข้อผิดพลาดขณะรันโค้ด\nโปรดรีเฟรชและลองอีกครั้ง","exerciseRunner.submitErrorDialog.body.exceedSubmitGradeLimit":"คุณส่งเกินจำนวนที่กำหนด","exerciseRunner.submitErrorDialog.body.expiredExerciseImage":"สภาพแวดล้อมการฝึกอบรมหมดอายุ กรุณารีเฟรชและลองอีกครั้ง","exerciseRunner.submitErrorDialog.body.networkError":"เกิดข้อผิดพลาดขณะรันโค้ด กรุณารีเฟรชและลองอีกครั้ง\nหากยังมีปัญหา กรุณาตรวจสอบสภาพการเชื่อมต่ออินเทอร์เน็ต","exerciseRunner.submitErrorDialog.body.notForSubmitGrade":"การส่งผลงานสำหรับการฝึกอบรมนี้ไม่ถูกต้อง","exerciseRunner.submitErrorDialog.body.notPreparedRoom":"สภาพแวดล้อมการฝึกอบรมกำลังถูกตั้งค่า กรุณารอสักครู่และลองอีกครั้ง","exerciseRunner.submitErrorDialog.body.roomIsBusy":"มีการรันโค้ดอยู่ในขณะนี้ กรุณารอจนกว่าจะเสร็จสิ้น","exerciseRunner.submitErrorDialog.body.unknown":"เกิดข้อผิดพลาดขณะรันโค้ด กรุณารอสักครู่และลองอีกครั้ง","exerciseRunner.submitErrorDialog.title":"ไม่สามารถรันโค้ดได้"};
6
6
 
7
7
  exports.default = th;
@@ -134,7 +134,8 @@ var useRunnerRoomWebSocket = function useRunnerRoomWebSocket(_ref) {
134
134
  return;
135
135
  }
136
136
  websocket$1.current = new websocket.EliceWebSocket(createUsercodeUrl, undefined, {
137
- maxRetries: MAX_WEBSOCKET_RETRY_COUNT
137
+ maxRetries: MAX_WEBSOCKET_RETRY_COUNT,
138
+ maxPingQueueTolerance: 1
138
139
  });
139
140
  websocket$1.current.onopen = wsOpen;
140
141
  websocket$1.current.onclose = wsClose;
@@ -160,7 +160,8 @@ var useStdioWebSocket = function useStdioWebSocket(_ref) {
160
160
  }
161
161
  websocket$1.current = new websocket.EliceWebSocket("".concat(wsUri, "/client/stdio/").concat(roomToken), undefined, {
162
162
  maxRetries: MAX_WEBSOCKET_RETRY_COUNT,
163
- heartAttack: true
163
+ heartAttack: true,
164
+ maxPingQueueTolerance: 1
164
165
  });
165
166
  websocket$1.current.onopen = wsOpen;
166
167
  websocket$1.current.onclose = wsClose;
@@ -1,3 +1,4 @@
1
+ import type { WebsocketUsercodeMessageWriteSucceed as WSUsercodeMessageWriteSucceed } from '@elice/types';
1
2
  import type { TextOp } from 'ot-text-unicode';
2
3
  interface CursorRange {
3
4
  from: number;
@@ -17,6 +18,10 @@ export type UseUsercodeEditWebSocketPropOnInit = (doc: string) => void;
17
18
  * Event handler for `WRITE_NOTI` event.
18
19
  */
19
20
  export type UseUsercodeEditWebSocketPropOnWriteNoti = (ots: TextOp, isFromServer: boolean) => void;
21
+ /**
22
+ * Event handler for `WRITE_SUCCEED` event.
23
+ */
24
+ export type UseUsercodeEditWebSocketPropOnWriteSucceed = (msg: WSUsercodeMessageWriteSucceed, requestId: number) => void;
20
25
  /**
21
26
  * Props of `useUsercodeEditWebSocket`.
22
27
  */
@@ -25,6 +30,7 @@ interface UseUsercodeEditWebSocketProps {
25
30
  filename: string | null;
26
31
  onInit: UseUsercodeEditWebSocketPropOnInit;
27
32
  onWriteNoti: UseUsercodeEditWebSocketPropOnWriteNoti;
33
+ onWriteSucceed: UseUsercodeEditWebSocketPropOnWriteSucceed;
28
34
  }
29
35
  /**
30
36
  *
@@ -33,7 +39,9 @@ export type UseUsercodeEditWebSocketReturnSendCursor = (range: CursorRange) => v
33
39
  /**
34
40
  * Event handler for websocket message.
35
41
  */
36
- export type UseUsercodeEditWebSocketReturnSendOTs = (ots: TextOp) => void;
42
+ export type UseUsercodeEditWebSocketReturnSendOTs = (ots: TextOp) => {
43
+ requestId: number;
44
+ };
37
45
  /**
38
46
  * Return type of `useUsercodeEditWebSocket`.
39
47
  */
@@ -28,7 +28,8 @@ var useUsercodeEditWebSocket = function useUsercodeEditWebSocket(_ref) {
28
28
  var exerciseRoomId = _ref.exerciseRoomId,
29
29
  filename = _ref.filename,
30
30
  onInit = _ref.onInit,
31
- onWriteNoti = _ref.onWriteNoti;
31
+ onWriteNoti = _ref.onWriteNoti,
32
+ onWriteSucceed = _ref.onWriteSucceed;
32
33
  var _return = React.useRef({});
33
34
  var _useMaterialConfig = materialSharedUtils.useMaterialConfig(),
34
35
  apiWsOriginUrl = _useMaterialConfig.apiWsOriginUrl;
@@ -262,6 +263,10 @@ var useUsercodeEditWebSocket = function useUsercodeEditWebSocket(_ref) {
262
263
  _doc.current = otTextUnicode.type.apply(_doc.current, ots);
263
264
  otsBuffer.current.push(ots);
264
265
  sendWrite();
266
+ return {
267
+ // Use next doc. version as id for matching request-response.
268
+ requestId: version.current + 1
269
+ };
265
270
  }, [sendWrite]);
266
271
  //
267
272
  // =============== usercode ===============
@@ -426,6 +431,7 @@ var useUsercodeEditWebSocket = function useUsercodeEditWebSocket(_ref) {
426
431
  writeIndex.current = 0;
427
432
  writeFailCount.current = 0;
428
433
  updateCursorFromOts(msg.ots);
434
+ onWriteSucceed(msg, version.current);
429
435
  };
430
436
  /**
431
437
  * Websocket on `WRITE_NOTI` message.
@@ -490,7 +496,9 @@ var useUsercodeEditWebSocket = function useUsercodeEditWebSocket(_ref) {
490
496
  if (!isReady) {
491
497
  return;
492
498
  }
493
- websocket$1.current = new websocket.EliceWebSocket(createUsercodeUrl);
499
+ websocket$1.current = new websocket.EliceWebSocket(createUsercodeUrl, undefined, {
500
+ maxPingQueueTolerance: 1
501
+ });
494
502
  websocket$1.current.onopen = wsOpen;
495
503
  websocket$1.current.onclose = wsClose;
496
504
  websocket$1.current.onmessage = wsMessage;
@@ -0,0 +1,4 @@
1
+ /**
2
+ * @file Collection of utils for async. logics.
3
+ */
4
+ export declare function withTimeout<T>(promise: Promise<T>, timeout: number, timeoutMessage?: string): Promise<T>;