Skip to content

Commit 0554a63

Browse files
Update + rename
1 parent 51f2947 commit 0554a63

463 files changed

Lines changed: 15228 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
15 KB
Binary file not shown.
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<title>Playback</title>
8+
<!-- external resources (editor, zip)-->
9+
<script src="js/ext/src-min-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>
10+
<script src="js/ext/src-min-noconflict/ext-modelist.js" type="text/javascript" charset="utf-8"></script>
11+
<script src="js/ext/markdown-it.min.js" type="text/javascript" charset="utf-8"></script>
12+
<script src="js/ext/jszip.min.js" type="text/javascript" charset="utf-8"></script>
13+
<!-- non-ui playback -->
14+
<script src="js/playbackEngine/EditorState.js"></script>
15+
<script src="js/playbackEngine/CodeDownloader.js"></script>
16+
<script src="js/playbackEngine/NewCodeFileMarker.js"></script>
17+
<script src="js/playbackEngine/NewCodeMarkerGenerator.js"></script>
18+
<script src="js/playbackEngine/PlaybackEngine.js"></script>
19+
<script src="js/playbackEngine/ServerProxy.js"></script>
20+
<!-- playback ui -->
21+
<script src="js/AceEditor.js"></script>
22+
<script src="js/AddEditComment.js"></script>
23+
<script src="js/AIGeneratedQuestion.js"></script>
24+
<script src="js/AIPromptInput.js"></script>
25+
<script src="js/App.js"></script>
26+
<script src="js/AudioVideoRecorder.js"></script>
27+
<script src="js/BlogCodeSnippet.js"></script>
28+
<script src="js/BlogComponent.js"></script>
29+
<script src="js/BlogView.js"></script>
30+
<script src="js/CodeView.js"></script>
31+
<script src="js/Collapsable.js"></script>
32+
<script src="js/CommentGroup.js"></script>
33+
<script src="js/CommentNavigator.js"></script>
34+
<script src="js/CommentTags.js"></script>
35+
<script src="js/CommentView.js"></script>
36+
<script src="js/CreateMultipleChoiceQuestion.js"></script>
37+
<script src="js/DevAvatar.js"></script>
38+
<script src="js/DevGroupAvatar.js"></script>
39+
<script src="js/EditorFileTabs.js"></script>
40+
<script src="js/EditorView.js"></script>
41+
<script src="js/FileSystemNavigator.js"></script>
42+
<script src="js/ImageGallery.js"></script>
43+
<script src="js/MultiLineTextInput.js"></script>
44+
<script src="js/OptionsMenu.js"></script>
45+
<script src="js/PlaybackControls.js"></script>
46+
<script src="js/PlaybackNavigator.js"></script>
47+
<script src="js/PlaybackSlider.js"></script>
48+
<script src="js/QuestionAnswerView.js"></script>
49+
<script src="js/SearchBar.js"></script>
50+
<script src="js/ShowHideComponent.js"></script>
51+
<script src="js/SurroundingLinesSelector.js"></script>
52+
<script src="js/TextToSpeechControl.js"></script>
53+
<script src="js/TagView.js"></script>
54+
<script src="js/TitleBar.js"></script>
55+
<script src="js/VerticalMediaContainer.js"></script>
56+
<!-- playback data -->
57+
<script src="js/loadPlayback.js"></script>
58+
<style>
59+
html, body {
60+
margin: 0;
61+
height: 100%;
62+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
63+
background-color: rgb(41, 41, 41);
64+
color: lightgray;
65+
-webkit-font-smoothing: antialiased;
66+
-moz-osx-font-smoothing: grayscale;
67+
}
68+
</style>
69+
</head>
70+
<body>
71+
<script>
72+
//create an alias for an Ace type
73+
const AceRange = ace.require('ace/range').Range;
74+
75+
window.addEventListener("DOMContentLoaded", (event) => {
76+
//get the playback data and pass it to the app
77+
const playbackData = {};
78+
loadPlaybackData(playbackData);
79+
80+
//look to see if there is a mode in the querystring
81+
const urlSearchParams = new URLSearchParams(window.location.search);
82+
const mode = urlSearchParams.get('mode');
83+
//for positional queries in the playback (make the numbers zero-based as that is what normal humans expect)
84+
const startingEventIndex = urlSearchParams.get('event') ? Number(urlSearchParams.get('event')) - 1 : null;
85+
const startingCommentIndex = urlSearchParams.get('comment') ? Number(urlSearchParams.get('comment')) - 1 : null;
86+
87+
//check if this is a small screen or an explicit request for blog mode
88+
let initialMode = 'code';
89+
if(window.innerWidth < 800 || (mode && mode === 'blog')) {
90+
initialMode = 'blog';
91+
}
92+
const app = new App(playbackData, initialMode, startingCommentIndex, startingEventIndex);
93+
document.body.appendChild(app);
94+
});
95+
</script>
96+
</body>
97+
</html>
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
class AIGeneratedQuestion extends HTMLElement {
2+
constructor(playbackEngine, sendResponseAsEvent=false) {
3+
super();
4+
5+
this.playbackEngine = playbackEngine;
6+
this.sendResponseAsEvent = sendResponseAsEvent;
7+
8+
this.attachShadow({ mode: 'open' });
9+
this.shadowRoot.innerHTML = `
10+
<style>
11+
:host {
12+
}
13+
14+
#submitButton {
15+
margin: 5px;
16+
padding: 5px;
17+
display: block;
18+
margin-left: auto;
19+
margin-right: auto;
20+
background-color: transparent;
21+
color: lightgrey;
22+
border: 1px solid lightgrey;
23+
border-radius: .25rem;
24+
transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out;
25+
opacity: 0.8;
26+
}
27+
28+
#submitButton:hover {
29+
opacity: 1.0;
30+
}
31+
</style>
32+
<button id="submitButton">Generate A Self-Grading Multiple Choice Question</button>
33+
<div class="questionContainer">
34+
</div>
35+
`;
36+
}
37+
38+
connectedCallback() {
39+
const submitButton = this.shadowRoot.querySelector('#submitButton');
40+
submitButton.addEventListener('click', this.submitText);
41+
}
42+
43+
disconnectedCallback() {
44+
const submitButton = this.shadowRoot.querySelector('#submitButton');
45+
submitButton.removeEventListener('click', this.submitText);
46+
}
47+
48+
submitText = async () => {
49+
const submitButton = this.shadowRoot.querySelector('#submitButton');
50+
let codeFromPlayback = this.playbackEngine.getMostRecentFileEdits(false);
51+
let promptWithCode = `
52+
Look at the following code and come up with a multiple choice question that can be asked about it:\n\n${codeFromPlayback}\n\n
53+
Look at the differences and come up with a question that a learner will find it challenging to answer.\n\n
54+
The format of the response should be raw JSON (no markdown, specifically no \`\`\`json designators) with the question in a member called 'question', another member called 'allAnswers' that is an array of all the answers.
55+
The correct answer should be duplicated in a member called 'correctAnswer'. The correct answer should have a very brief explanation of why it is correct stored in a member called 'explanation'.\n\n
56+
Put the correct answer at position 0 of the 'allAnswers' array.
57+
Here is an example of what the response should look like (make sure the response is a valid JSON object):\n\n
58+
{\n
59+
"question": "What is the capital of France?",\n
60+
"allAnswers": [\n
61+
"Paris",\n
62+
"London",\n
63+
"Berlin",\n
64+
"Madrid"\n
65+
],\n
66+
"correctAnswer": "Paris",\n
67+
"explanation": "Paris is the capital of France."\n
68+
}\n\n
69+
If you cannot come up with a question then return this object {question: "Error"}`;
70+
71+
let promptObject = {
72+
requestType: "Generate Question",
73+
prompt: promptWithCode,
74+
playbackViewId: document.body.dataset.playbackViewId ? document.body.dataset.playbackViewId : null
75+
};
76+
77+
submitButton.textContent = `Generating a question...`;
78+
submitButton.setAttribute('disabled', 'true');
79+
80+
//send the formatted one to the server
81+
const serverProxy = new ServerProxy();
82+
const responseObject = await serverProxy.sendAIPromptToServer(promptObject);
83+
84+
submitButton.textContent = 'Generate Another Self-Grading Multiple Choice Question';
85+
submitButton.removeAttribute('disabled');
86+
87+
const questionContainer = this.shadowRoot.querySelector('.questionContainer');
88+
89+
if(responseObject.error) {
90+
questionContainer.textContent = responseObject.response;
91+
} else {
92+
//turn the string response w/Q&A into an object
93+
const questionCommentData = JSON.parse(responseObject.response);
94+
95+
//swap the correct answer with a random one
96+
const randomIndex = Math.floor(Math.random() * questionCommentData.allAnswers.length);
97+
const temp = questionCommentData.allAnswers[0];
98+
questionCommentData.allAnswers[0] = questionCommentData.allAnswers[randomIndex];
99+
questionCommentData.allAnswers[randomIndex] = temp;
100+
101+
const md = markdownit();
102+
questionCommentData.question = md.render(questionCommentData.question);
103+
questionCommentData.explanation = md.render(questionCommentData.explanation);
104+
105+
if(this.sendResponseAsEvent) {
106+
const event = new CustomEvent('ai-generate-question-response', {
107+
detail: {
108+
response: questionCommentData
109+
},
110+
bubbles: true,
111+
composed: true
112+
});
113+
this.dispatchEvent(event);
114+
} else {
115+
const qAndAView = new QuestionAnswerView({ questionCommentData });
116+
questionContainer.prepend(qAndAView);
117+
}
118+
}
119+
}
120+
}
121+
122+
window.customElements.define('st-ai-generated-question', AIGeneratedQuestion);

0 commit comments

Comments
 (0)