Skip to content

Commit f55ac0d

Browse files
authored
Merge pull request #41 from Deaponn/develop
Qol improvements
2 parents b2e8ac4 + d8efc8e commit f55ac0d

File tree

7 files changed

+62
-13
lines changed

7 files changed

+62
-13
lines changed

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"coffee-script": "1.10.0",
1111
"coffeelint": "1.15.7",
1212
"coffeelint-newline-at-eof": "0.4.1",
13+
"coffeescript": "^2.7.0",
1314
"del": "2.2.x",
1415
"group-array": "^0.3.1",
1516
"gulp": "3.9.1",
@@ -37,6 +38,9 @@
3738
"run-sequence": "1.2.2",
3839
"yargs": "5.0.0"
3940
},
41+
"overrides": {
42+
"graceful-fs": "^4.2.11"
43+
},
4044
"repository": {
4145
"type": "git",
4246
"url": "git://github.com/gronostajo/drill2.git"

src/app/20_main.js

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,20 @@
151151

152152
$scope.currentQuestion = $scope.questions[$scope.questionIndex - 1];
153153

154+
$scope.displayAsRadio = $scope.config.displayAsRadio && $scope.currentQuestion.totalCorrect() == 1;
155+
156+
for (var i = 0; i < $scope.questions.length; i++) {
157+
var q = $scope.questions[i];
158+
for (var j = 0; j < q.answers.length; j++) {
159+
q.answers[j].sortingKey = ($scope.config.shuffleAnswers)
160+
? Math.random() : j;
161+
}
162+
}
163+
154164
for (var i = 0; i < $scope.currentQuestion.answers.length; i++) {
155165
$scope.currentQuestion.answers[i].checked = false;
156166
}
167+
$scope.currentQuestion.checkedAnswer = undefined; // for radio input questions
157168

158169
ViewportHelper.scrollToTop(function() {
159170
$scope.$apply(function () {
@@ -193,6 +204,8 @@
193204
}
194205
}
195206

207+
if ($scope.view.isGraded()) return;
208+
196209
for (i = 0; i < $scope.currentQuestion.answers.length; i++) {
197210
sortingKeys.push($scope.currentQuestion.answers[i].sortingKey);
198211
}
@@ -201,12 +214,20 @@
201214

202215
for (i = 0; i < $scope.currentQuestion.answers.length; i++) {
203216
if ($scope.currentQuestion.answers[i].sortingKey === sortingKeys[$event.which - 49]) {
204-
$scope.currentQuestion.answers[i].checked = !$scope.currentQuestion.answers[i].checked;
217+
if ($scope.displayAsRadio)
218+
$scope.currentQuestion.checkedAnswer = $scope.currentQuestion.answers[i].id; // for radio input questions
219+
else
220+
$scope.currentQuestion.answers[i].checked = !$scope.currentQuestion.answers[i].checked;
205221
}
206222
}
207223
};
208224

209225
$scope.grade = function () {
226+
for (var i = 0; i < $scope.currentQuestion.answers.length; i++) {
227+
var answer = $scope.currentQuestion.answers[i];
228+
if (answer.id == $scope.currentQuestion.checkedAnswer) answer.checked = true;
229+
}
230+
210231
$scope.stopTimer();
211232

212233
$scope.view.current = 'graded';
@@ -238,14 +259,6 @@
238259
else {
239260
$scope.questions = $scope.loadedQuestions.slice(0); // shallow copy
240261
}
241-
242-
for (var i = 0; i < $scope.questions.length; i++) {
243-
var q = $scope.questions[i];
244-
for (var j = 0; j < q.answers.length; j++) {
245-
q.answers[j].sortingKey = ($scope.config.shuffleAnswers)
246-
? Math.random() : j;
247-
}
248-
}
249262
};
250263

251264
$scope.escapeQuestions = function () {
@@ -313,6 +326,7 @@
313326
for (var i = 0; i < $scope.currentQuestion.answers.length; i++) {
314327
$scope.currentQuestion.answers[i].checked = false;
315328
}
329+
$scope.currentQuestion.checkedAnswer = undefined; // for radio input questions
316330
$scope.grade();
317331
$scope.stopTimer();
318332
}

src/app/parser/meta/OptionsBlockProcessor.coffee

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ angular.module('DrillApp').service 'OptionsBlockProcessor', (JsonLoader, SafeEva
8686

8787
repeatIncorrect: parseBool
8888

89+
displayAsRadio: parseBool
90+
8991
explain: (vOrig, m, logFn) ->
9092
v = vOrig and vOrig.toLowerCase()
9193
if v in ['summary', 'optional', 'always']

src/app/screens/home/settings/settings.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,12 @@
108108
Repeat incorrectly answered questions
109109
</label>
110110
</div>
111+
<div class="checkbox">
112+
<label>
113+
<input type="checkbox" ng-model="model.displayAsRadio">
114+
Display questions with one correct answer as Radio (only one option at a time is selectable)
115+
</label>
116+
</div>
111117
</div>
112118
</div>
113119

src/app/screens/question/question.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ <h2 title="{{currentQuestion.id != false ? currentQuestion.id : 'No ID'}}">Quest
1616
<div ng-hide="config.markdown" ng-bind-html="currentQuestion.body | plaintext"></div>
1717
</div>
1818
<div class="form-group answers">
19-
<div class="checkbox answer no-selection correct-{{answer.correct}} checked-{{answer.checked}}" ng-class="{ explained: view.isGraded() && config.showExplanations && currentQuestion.hasExplanations }" ng-repeat="answer in currentQuestion.answers | orderBy:'sortingKey'">
19+
<div class="{{displayAsRadio ? 'radio' : 'checkbox'}} answer no-selection correct-{{answer.correct}} checked-{{displayAsRadio ? (currentQuestion.checkedAnswer == answer.id) : answer.checked}}" ng-class="{ explained: view.isGraded() && config.showExplanations && currentQuestion.hasExplanations }" ng-repeat="answer in currentQuestion.answers | orderBy:'sortingKey'">
2020
<label>
2121
<span class="label label-default keyboard-shortcut answer-number"></span>
22-
<input type="checkbox" ng-model="answer.checked" ng-disabled="view.isGraded()">
22+
<input type="radio" ng-model="currentQuestion.checkedAnswer" ng-value="answer.id" ng-disabled="view.isGraded()" ng-if="displayAsRadio">
23+
<input type="checkbox" ng-model="answer.checked" ng-disabled="view.isGraded()" ng-else>
2324
<span class="content">
2425
<span class="id" ng-show="view.isGraded() && config.showExplanations && currentQuestion.hasExplanations">{{answer.id}})&nbsp</span>
2526
<span ng-bind-html="answer.body | plaintext:'span.p'"></span>

src/app/screens/summary/summary.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ <h2>The test is over</h2>
1010
<div class="panel-body">
1111
<div class="question-body" ng-show="config.markdown" ng-bind-html="question.body | markdown:this"></div>
1212
<div class="question-body" ng-hide="config.markdown" ng-bind-html="question.body | plaintext"></div>
13-
<div class="checkbox answer explained" ng-repeat="answer in question.answers">
13+
<div class="{{(config.displayAsRadio && question.totalCorrect() == 1) ? 'radio' : 'checkbox'}} answer explained" ng-repeat="answer in question.answers">
1414
<label ng-class="{ correct: answer.checked && answer.correct, incorrect: answer.checked && !answer.correct, missed: !answer.checked && answer.correct }">
15-
<input type="checkbox" disabled ng-checked="answer.checked">
15+
<input type="{{(config.displayAsRadio && question.totalCorrect() == 1) ? 'radio' : 'checkbox'}}" disabled ng-checked="answer.checked">
1616
<span class="content">
1717
<span class="id">{{answer.id}})&nbsp;</span>
1818
<span ng-bind-html="answer.body | plaintext:'span.p'"></span>

test/src/parser/meta/OptionsBlockProcessorSpec.coffee

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ describe 'OptionsBlockProcessor', ->
1616
timeLimitEnabled: no
1717
timeLimitSecs: 60
1818
repeatIncorrect: no
19+
displayAsRadio: no
1920
explain: 'optional'
2021
showExplanations: no
2122
explanations: {}
@@ -182,6 +183,27 @@ describe 'OptionsBlockProcessor', ->
182183

183184
expect(logger).not.toHaveBeenCalled()
184185

186+
it 'should recognize display as radio setting option', ->
187+
expectedTrue = displayAsRadio: yes
188+
expectedFalse = displayAsRadio: no
189+
logger = jasmine.createSpy('logger')
190+
191+
expect(@OptionsBlockProcessor.process('{"displayAsRadio": true}', logger)).toHaveMemberValues(expectedTrue)
192+
expect(@OptionsBlockProcessor.process('{"displayAsRadio": "true"}', logger)).toHaveMemberValues(expectedTrue)
193+
expect(@OptionsBlockProcessor.process('{"displayAsRadio": "enabled"}', logger)).toHaveMemberValues(expectedTrue)
194+
expect(@OptionsBlockProcessor.process('{"displayAsRadio": "yes"}', logger)).toHaveMemberValues(expectedTrue)
195+
expect(@OptionsBlockProcessor.process('{"displayAsRadio": "1"}', logger)).toHaveMemberValues(expectedTrue)
196+
expect(@OptionsBlockProcessor.process('{"displayAsRadio": 1}', logger)).toHaveMemberValues(expectedTrue)
197+
198+
expect(@OptionsBlockProcessor.process('{"displayAsRadio": false}', logger)).toHaveMemberValues(expectedFalse)
199+
expect(@OptionsBlockProcessor.process('{"displayAsRadio": "false"}', logger)).toHaveMemberValues(expectedFalse)
200+
expect(@OptionsBlockProcessor.process('{"displayAsRadio": "disabled"}', logger)).toHaveMemberValues(expectedFalse)
201+
expect(@OptionsBlockProcessor.process('{"displayAsRadio": "no"}', logger)).toHaveMemberValues(expectedFalse)
202+
expect(@OptionsBlockProcessor.process('{"displayAsRadio": "0"}', logger)).toHaveMemberValues(expectedFalse)
203+
expect(@OptionsBlockProcessor.process('{"displayAsRadio": 0}', logger)).toHaveMemberValues(expectedFalse)
204+
205+
expect(logger).not.toHaveBeenCalled()
206+
185207
it 'should recognize explanation options', ->
186208
logger = jasmine.createSpy('logger')
187209

0 commit comments

Comments
 (0)