-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
276 lines (274 loc) · 13.9 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
<html>
<head>
<meta charset="utf-8">
<meta content="width=device-width,initial-scale=1,minimal-ui" name="viewport">
<link rel="stylesheet" href="https://unpkg.com/vue-material@beta/dist/vue-material.min.css">
<link rel="stylesheet" href="https://unpkg.com/vue-material@beta/dist/theme/default.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.32.0/codemirror.min.css" />
</head>
<body>
<h1>Pythonic Code Activity by Team 1</h1>
<div id="app">
<md-tabs>
<md-tab v-for="question in questions" :key=question.name v-bind:md-label=question.name+question.status>
<doctest-activity v-bind:layout-things=question.layoutItems v-bind:question-name=question.name @questionhandler="toggleQuestionStatus"/>
</md-tab>
</md-tabs>
</div>
</div>
</body>
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vue-material@beta"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.32.0/codemirror.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.4/mode/python/python.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue-codemirror.min.js"></script>
<script>
Vue.use(VueMaterial.default)
Vue.use(window.VueCodemirror)
Vue.component('doctest-activity', {
props: ['layoutThings', 'questionName'],
data: function () {
return {
answer:"",
layoutItems: this.layoutThings,
cmOptions: {
mode: 'python',
lineNumbers: true
},
cmReadOnly: {
lineNumbers: true,
mode: "python",
readOnly: true
}
}
},
methods: {
postContents: function () {
// comment: leaving the gatewayUrl empty - API will post back to itself
const gatewayUrl = '';
fetch(gatewayUrl, {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({shown:{0:this.layoutItems[0].vModel},editable:{0:this.layoutItems[1].vModel}})
}).then(response => {
return response.json()
}).then(data => {
this.answer = JSON.parse(JSON.stringify(data))
return this.$emit('questionhandler',{data, questionName:this.questionName})
})
}
},
template:
`<div class="md-layout md-gutter">
<div id="cardGroupCreator" class="md-layout-item md-size-50">
<md-card>
<md-card-header>
<md-card-header-text>
<div class="md-title">{{layoutItems[2].header}}</div>
<div class="md-subhead">{{layoutItems[2].subHeader}}</div>
</md-card-header-text>
</md-card-header>
<md-card-content>
<md-field>
<md-textarea v-model="layoutItems[2].vModel" readonly></md-textarea>
</md-field>
</md-card-content>
</md-card>
<md-card>
<md-card-header>
<md-card-header-text>
<div class="md-title">{{layoutItems[1].header}}</div>
<div class="md-subhead">{{layoutItems[1].subHeader}}</div>
</md-card-header-text>
<md-card-media>
<md-button class="md-raised md-primary" v-on:click="postContents">Submit</md-button>
</md-card-media>
</md-card-header>
<md-card-content>
<md-field>
<codemirror class="editableTextarea" v-model="layoutItems[1].vModel" :options="cmOptions"></codemirror>
</md-field>
</md-card-content>
</md-card>
</div>
<div id="cardGroupPreview" class="md-layout-item md-size-50">
<md-card>
<md-card-header>
<md-card-header-text>
<div class="md-title">{{layoutItems[0].header}}</div>
<div class="md-subhead">{{layoutItems[0].subHeader}}</div>
</md-card-header-text>
</md-card-header>
<md-card-content>
<md-field>
<codemirror class="editableTextarea" v-model="layoutItems[0].vModel" :options="cmReadOnly"></codemirror>
</md-field>
</md-card-content>
</md-card>
<md-card>
<md-card-header>
<md-card-header-text>
<div class="md-title">Output</div>
<div class="md-subhead">Test results</div>
</md-card-header-text>
</md-card-header>
<md-card-content>
<md-field>
<md-tabs>
<md-tab id="tab-htmlResults" md-label="HTML results">
<div v-html="answer.htmlFeedback"></div>
</md-tab>
<md-tab id="tab-jsonResults" md-label="JSON results">
<md-textarea v-model="answer.jsonFeedback" readonly></md-textarea>
</md-tab>
<md-tab id="tab-textResults" md-label="Text results">
<md-textarea v-model="answer.textFeedback" readonly></md-textarea>
</md-tab>
</md-tabs>
</md-field>
</md-card-content>
</md-card>
</div>
</div>
`
})
new Vue({
el: '#app',
data: function () {
return {
questions:[
{name:"question 1", layoutItems: [
{header:"Tests", subHeader:'byteCodeChecker() and codeInfoChecker() are our functions used in these tests', vModel:">>> ifFunc(True,2)\\n2 \\n>>> ifFunc(bool('a'),11)\\n11 \\n>>> byteCodeChecker(ifFunc, 'ARGREPR', '==')\\n'== not found'"},
{header:"Editable Code Block", subHeader:'Your code goes below. Avoid double quotes.', vModel:"def ifFunc(a,b):\\n if a == True: \\n return b\\n"},
{header:"Introduction", subHeader:'', vModel:"When checking if a condition is True, prefer relying on the implicit “truthiness” of the object in the conditional statement using \\nif object:\\nthan\\nif object == True:"}
], status:" 🔴"},
{name:"question 2", layoutItems: [
{header:"Tests", subHeader:'byteCodeChecker() and codeInfoChecker() are our functions used in these tests', vModel:">>> forLoop([1,2,3])\\n6 \\n>>> forLoop([1,2,3,4,5])\\n15 \\n>>> byteCodeChecker(forLoop, 'OPNAME', 'FOR_ITER')\\n'found FOR_ITER'"},
{header:"Editable Code Block", subHeader:'Your code goes below. Avoid double quotes.', vModel:"def forLoop(listOfNumbers):\\n total = 0 \\n index = 0 \\n while index < len(listOfNumbers):\\n total += listOfNumbers[index]\\n index += 1\\n return total"},
{header:"Introduction", subHeader:'', vModel:"Use a for-in loop to iterate through elements of an iterable like a list/dictionary than creating an index and incrementing that index after every loop."}
], status:" 🔴"},
{name:"question 3", layoutItems: [
{header:"Tests", subHeader:'byteCodeChecker() and codeInfoChecker() are our functions used in these tests', vModel:">>> useEnumerate(['bunnyA','bunnyB'])\\n'bunnyA is at index 0 bunnyB is at index 1 ' \\n>>> useEnumerate(['crabbyA','crabbyB'])\\n'crabbyA is at index 0 crabbyB is at index 1 ' \\n>>> codeInfoChecker(useEnumerate, 'enumerate')\\n'found enumerate'"},
{header:"Editable Code Block", subHeader:'Your code goes below. Avoid double quotes.', vModel:"def useEnumerate(list):\\n locationOfItems = '' \\n for index in range(len(list)): \\n value = list[index]\\n locationOfItems += f'{value} is at index {index} '\\n return locationOfItems"},
{header:"Introduction", subHeader:'', vModel:"We can use the enumerate function to obtain the index that the loop is in. The range(len()) solution below works but it is more pythonic to use enumerate"}
], status:" 🔴"},
{name:"question 4", layoutItems: [
{header:"Tests", subHeader:'byteCodeChecker() and codeInfoChecker() are our functions used in these tests', vModel:">>> useZip(['pikachu','bulbasaur'],['lightning type','grass type'])\\n'pikachu is lightning type bulbasaur is grass type ' \\n>>> useZip(['Barney','Pooh'],['T-rex','teddy bear'])\\n'Barney is T-rex Pooh is teddy bear ' \\n>>> codeInfoChecker(useZip, 'zip')\\n'found zip'"},
{header:"Editable Code Block", subHeader:'Your code goes below. Avoid double quotes.', vModel:"def useZip(list1, list2):\\n resultString = ''\\n for index, value in enumerate(list1):\\n resultString += f'{value} is {list2[index]} '\\n return resultString"},
{header:"Introduction", subHeader:'', vModel:"The zip function pairs the first elements of each iterator together then pairs the second elements together and so on. If the iterables in the zip function are not the same length, then the smallest length iterable decides the length of the generated output."}
], status:" 🔴"},
{name:"question 5", layoutItems: [
{header:"Tests", subHeader:'byteCodeChecker() and codeInfoChecker() are our functions used in these tests', vModel:">>> eat()\\n'I ate burger I ate fries '\\n>>> codeInfoChecker(foodGenerator, 'GENERATOR')\\n'found GENERATOR'"},
{header:"Editable Code Block", subHeader:'Your code goes below. Avoid double quotes.', vModel:"# generator function which yields data values\\ndef foodGenerator():\\n yield 'ice cream'\\n\\n# eat() function calls foodGenerator() and iterates over the yielded values\\ndef eat():\\n foodEaten = ''\\n for food in foodGenerator():\\n foodEaten += f'I ate {food} '\\n return foodEaten"},
{header:"Introduction", subHeader:'', vModel:"Using something called generators, we can handle large amounts of data or computation easily.\\n\\nThis is because how ever large the amount of data, generators represent it as a stream of data and provide one data value at a time out of the data stream. This means we can run intensive computation without crashing our computer since it works with just one value at a time.\\n\\nA generator function consists of one or more yield statements. Calling the generator function creates an iterable, and iterating it runs the code in the function. Each yield statement executed produces another value in the stream."}
], status:" 🔴"}
]
}
},
methods: {
toggleQuestionStatus (response) {
const {data, questionName} = response
if (data.htmlFeedback) {
const searchText = data.htmlFeedback
searchText.search(/b2d8b2/) !== -1 ?
searchText.search(/#ff9999/) == -1 ?
this.questions.find(item => item.name === questionName).status = " ✔️"
:
this.questions.find(item => item.name === questionName).status = " 🤨"
:
this.questions.find(item => item.name === questionName).status = " 🔴"
}
}
}
})
</script>
<style lang="scss" scoped>
.md-card {
width: 90%;
margin: 20px;
display: inline-block;
vertical-align: top;
min-height:200px
}
.md-card-content {
padding-bottom: 16px !important;
}
button {
display:block;
margin: 20px 60px 20px 60px;
width:200px !important;
border-radius: 50%
}
#cardGroupCreator {
display:flex;
flex-direction:column;
padding-right: 0px
}
#cardGroupPreview .md-card {
width: 90%;
}
#cardGroupPreview{
padding-left: 0px
}
#cardGroupPreview .md-tab{
height:100%
}
textarea {
font-size: 1rem !important;
min-height: 175px !important
}
.md-tabs{
width:100%;
}
.md-tab{
overflow-x: auto;
}
.md-tab::-webkit-scrollbar {
width: 0px;
}
html {
width:95%;
margin:auto;
mix-blend-mode: darken
}
body {
background-image: url("https://img.freepik.com/free-vector/blue-abstract-acrylic-brush-stroke-textured-background_53876-86373.jpg?size=626&ext=jpg");
}
h1{
padding:20px;
margin:auto;
text-align: center;
color: #2f5687;
font-family: "Courier New"
}
.md-content{
min-height:300px
}
.md-tabs-container, .md-tabs-container .md-tab textarea, .md-tabs-content{
height:100% !important
}
.md-field{
margin:0px;
padding:0px
}
.md-tabs-navigation{
justify-content:center !important
}
.md-card-media{
width:400px !important
}
.md-button{
margin:10px !important;
border-radius: 50%;
}
.cm-s-default{
height:100%
}
.md-card-header{
padding:0 16px 16px 16px
}
</style>
</html>