diff --git a/ubcpi/static/css/ubcpi.css b/ubcpi/static/css/ubcpi.css index 1740057..2d153c0 100644 --- a/ubcpi/static/css/ubcpi.css +++ b/ubcpi/static/css/ubcpi.css @@ -25,11 +25,6 @@ h2.question-text { padding: 0; } -.choicegroup fieldset .ubcpi-possible-options { - padding-left: 20px; - border-left: 2px solid #e5e5e5; -} - div.course-wrapper section.course-content fieldset .ubcpi-option { margin: 0; } @@ -77,6 +72,20 @@ fieldset .ubcpi-option:last-of-type .ubcpi-label { float: none; } +.ubcpi-no-pointer { + cursor: default; +} + +.ubcpi-answer img { + display: block; +} + +.ubcpi-label.ubcpi-explain-label { + border: none; + margin-bottom: 0; + padding: 0px; +} + .results-container .ubcpi-label { margin-bottom: 15px; } @@ -116,7 +125,8 @@ textarea.ubcpi-field { -webkit-font-smoothing: antialiased; } -.choicegroup .ubcpi_submit { +.choicegroup .ubcpi_submit, +.others-responses .ubcpi_submit { padding: 10px 40px; border: 1px solid #2b8dbb; color: #fff; @@ -140,7 +150,10 @@ textarea.ubcpi-field { .ubcpi_block .choicegroup .ubcpi_submit:hover, .ubcpi_block .choicegroup .ubcpi_submit:active, -.ubcpi_block .choicegroup .ubcpi_submit:focus { +.ubcpi_block .choicegroup .ubcpi_submit:focus, +.others-responses .ubcpi_submit:hover, +.others-responses .ubcpi_submit:active, +.others-responses .ubcpi_submit:focus { border-color: #00a7f6; box-shadow: none; background: #00a7f6 none; @@ -178,8 +191,30 @@ div.course-wrapper section.course-content .vert-mod > div ul.ubcpi-other-answers border-bottom: 1px solid #cfc6c6; } -div.course-wrapper section.course-content .vert-mod > div ul.ubcpi-other-answers li:last-of-type { - border-bottom: none; +div.course-wrapper section.course-content .vert-mod .sample-answer-list > :not(:first-child) { + border-top: 1px solid #cfc6c6; +} + +div.course-wrapper section.course-content .vert-mod .sample-answer { + margin: 1em; + display: block; +} + +div.course-wrapper section.course-content .vert-mod .no-sample-answer { + font-style: italic; + margin: 1em; + display: block; +} + +div.course-wrapper section.course-content .vert-mod .sample-answer .other-rationale { + line-height: 140%; + padding-left: 1em; +} + +div.course-wrapper section.course-content .vert-mod .own-answer { + padding-top: 15px; + margin: 1em; + font-weight: bold; } .ubcpi-other-answers, @@ -198,8 +233,15 @@ div.course-wrapper section.course-content .vert-mod > div ul.ubcpi-other-answers } .ubcpi-other-answers h4, -.ubcpi-solution-your-initial-answer, +.ubcpi-solution-your-initial-answer { + font-weight: 900; +} + .ubcpi-solution-your-final-answer { + border-top: 1px solid #ddd; + margin-top: 10px; + padding-top: 5px; + font-size: 0.85em; font-weight: 900; } @@ -385,7 +427,6 @@ textarea.pi-options { position: relative; margin: 20px 0; border: 1px solid #d7dbdf; - border-left: 10px solid #b9c1c8; box-shadow: inset 0 1px 2px 1px rgba(2, 2, 3, 0.1); padding: 20px; background: #fdfdfd; @@ -499,8 +540,26 @@ label.ubcpi-label { fill: #50c67b; } -.ubcpibar:hover { - opacity: 1.0; +.ubcpibar.original { + opacity: 0.4; +} + +text.ubcpibar { + font-size: 12px; + font-weight: 600; + fill: #000000; +} + +text.ubcpibar.correct-answer { + font-size: 12px; + font-weight: 600; + fill: #000000; +} + +text.ubcpibar.label { + font-size: 12px; + font-weight: 600; + fill: #000000; } .ubcpi-correct-answer-option { @@ -509,6 +568,11 @@ label.ubcpi-label { } .ubcpi-show-correct { + font-size: 0.85em; +} + +.ubcpi-correct-answer-highlight { + font-weight: bold; color: #50c67b; } @@ -525,11 +589,13 @@ label.ubcpi-label { .ubcpi-correct-answer-rationale { display: block; margin-bottom: 20px; + font-size: 0.85em; } .ubcpi-solution-rationales { padding-left: 10px; word-break: break-all; + font-weight: normal; } .other-rationale { @@ -630,6 +696,12 @@ div.course-wrapper section.course-content .warning-notice p { font-style: italic; } +#decision-prompt { + font-weight: normal; + font-size: 120%; + padding-right: 4.8em; +} + .response-text { padding-left: 22px; } @@ -780,4 +852,6 @@ pi-barchart > svg { text-transform: capitalize; } - +#not-enough-data { + font-size: 0.85em; +} diff --git a/ubcpi/static/html/ubcpi.html b/ubcpi/static/html/ubcpi.html index 73a35d1..3340585 100644 --- a/ubcpi/static/html/ubcpi.html +++ b/ubcpi/static/html/ubcpi.html @@ -5,59 +5,36 @@

{{display_name}}

-
-
 ({{weight}} point possible)
-
 ({{weight}} points possible)
+
+
({{weight}} point possible)
+
({{weight}} points possible)

Question

- {{question_text.image_alt}} + {{question_text.image_alt}} - + - {{question_text.image_alt}} + {{question_text.image_alt}}
- + +
- +
    -

  1. Answer, Completed
  2. +

  3. Answer, In Progress
  4. -

  5. Reflection, In Progress
  6. +

  7. Reflection, Upcoming

  8. Results, Upcoming
-
- -
- - Step 2) Read Other Students Answers -

These are samples of other student answers for this question. Read them and then compare with your answer below.

- - - -
- -
- - +
    -

  1. Answer, In Progress
  2. +

  3. Answer, Completed
  4. -

  5. Reflection, Upcoming
  6. +

  7. Reflection, In Progress

  8. Results, Upcoming
@@ -68,69 +45,106 @@

{{display_n
- Step 1) Your Initial Answer You can change this answer later, if you change your mind. - Step 3) Your Final Answer You now have the option to change your initial selection and explanation, if you wish. + Step 1) Give Initial Answer You can change this answer later, if you change your mind. + Step 2) Read Other Student Answers +

These are samples of other student answers for this question. Read them and then compare with your answer below.

+
-
-

-

+
+ -

+
- - -

You are approaching the limit of {{rationale_size.max}} characters for this answer. Characters left: {{rationale_size.max - rc.rationale.length}}

-

Error: Please edit your explanation so that it is less than {{rationale_size.max}} characters.

- -

- - Hint In the next step, you will be shown a selection of other responses that may help you refine your answer. - -

- -
-
- -
-
-
- View Question Statistics -
- -
- -

Original Answer

-
- -
- -

Revised Answer

-
+
+ View Question Statistics +
+ +
+
+ + + +
-
- +
+
@@ -139,24 +153,22 @@

{{display_n

{{display_name}}

-
- -
({{weight}} point possible)
- -
({{weight}} points possible)
+
+
({{weight}} point possible)
+
({{weight}} points possible)

Question

- {{question_text.image_alt}} + {{question_text.image_alt}} - + - {{question_text.image_alt}} + {{question_text.image_alt}}
-
- +
+

  1. Answer, Completed
  2. @@ -167,100 +179,50 @@

    {{display_n

+
-
Correct Answer
-
-
Instructor's Explanation
+ + Step 3) View Course-Wide Results +

This is a look at how your classmates answered the question initially and after revision.

+ +
-
- {{options[rc.correct_answer].image_alt}} + {{rc.correct_rationale.text}} -

{{options[rc.correct_answer].text}}

+
+
+
+ Correct Answer: + {{option.text}} - {{rc.correct_rationale.text}} - -
-
    -
  • -

    - Your initial answer: - {{options[rc.answer_original].text}} - {{options[rc.answer_original].text}} - {{options[rc.answer_original].text}} - ({{'Option' | translate }} {{rc.answer_original + 1}}) -

    - Student Rationale"{{rc.rationale_original}}" -
  • -
  • + {{option.image_alt}} + + + {{rc.correct_rationale.text}} + + + +

    - Your final answer: - {{options[rc.answer_revised].text}} - {{options[rc.answer_revised].text}} - {{options[rc.answer_revised].text}} - ({{'Option' | translate }} {{rc.answer_revised + 1}}) + Your final explanation: + "{{rc.rationale_revised}}"

    - Student Rationale"{{rc.rationale_revised}}" -
  • -
-

See how your classmates answered below

+
+
+
-
- - -
Class Breakdown
-

This is a look at how your classmates answered the question during the initial and final rounds.

-
Answer Options
-
- -

- {{option.image_alt}} - - Option {{$index + 1}} (correct) - {{option.text}} - {{rc.calc($index)}} - {{option.text}} - {{rc.calc($index)}} - - {{option.image_alt}} - - (You chose this option) -

- -
- -
-

-

  • - Option {{$index + 1}}: {{rc.calc($index)}} - (correct) -
  • -
    - -
    Initial Answer Selection
    - -
    - -
    Final Answer Selection
    - - -
    -
    diff --git a/ubcpi/static/js/spec/d3-pibar_spec.js b/ubcpi/static/js/spec/d3-pibar_spec.js index 16fab60..9452f6a 100644 --- a/ubcpi/static/js/spec/d3-pibar_spec.js +++ b/ubcpi/static/js/spec/d3-pibar_spec.js @@ -105,3 +105,96 @@ describe('D3 bar chart', function () { // expect(line.empty()).not.toBe(true); //}); }); + + +describe('D3 per answer chart', function () { + var chart; + var chartContainer; + + describe('instructor view', function(){ + + beforeEach(function() { + var scope = {role:'instructor'}; + chart = d3.custom.perAnswerChart(scope); + chartContainer = d3.select('body') + .append('div') + .attr('class', 'testContainer'); + }); + + afterEach(function() { + // clean up + chartContainer.remove(); + }); + + it('should provide getters and setters', function() { + var defaultChartWidth = chart.width(); + var defaultChartHeight = chart.height(); + var defaultMinTotalFrequency = chart.minTotalFrequency(); + + chart.width(100) + .height(50) + .minTotalFrequency(20); + + var newChartWidth = chart.width(); + var newChartHeight = chart.height(); + var newMinTotalFrequency = chart.minTotalFrequency(); + + + expect(defaultChartWidth).not.toBe(100); + expect(defaultChartHeight).not.toBe(50); + expect(defaultMinTotalFrequency).not.toBe(20); + expect(newChartWidth).toBe(100); + expect(newChartHeight).toBe(50); + expect(newMinTotalFrequency).toBe(20); + }); + + + it('should have a minTotalFrequency of 1', function(){ + var defaultMinTotalFrequency = chart.minTotalFrequency(); + expect(defaultMinTotalFrequency).toBe(1); + }); + }); + + describe('student view', function(){ + + beforeEach(function() { + var scope = {role:'student'}; + chart = d3.custom.barChart(scope); + chartContainer = d3.select('body') + .append('div') + .attr('class', 'testContainer'); + }); + + afterEach(function() { + // clean up + chartContainer.remove(); + }); + + it('should provide getters and setters', function() { + var defaultChartWidth = chart.width(); + var defaultChartHeight = chart.height(); + var defaultMinTotalFrequency = chart.minTotalFrequency(); + + chart.width(100) + .height(50) + .minTotalFrequency(20); + + var newChartWidth = chart.width(); + var newChartHeight = chart.height(); + var newMinTotalFrequency = chart.minTotalFrequency(); + + + expect(defaultChartWidth).not.toBe(100); + expect(defaultChartHeight).not.toBe(50); + expect(defaultMinTotalFrequency).not.toBe(20); + expect(newChartWidth).toBe(100); + expect(newChartHeight).toBe(50); + expect(newMinTotalFrequency).toBe(20); + }); + + it('should have a minTotalFrequency of 10', function(){ + var defaultMinTotalFrequency = chart.minTotalFrequency(); + expect(defaultMinTotalFrequency).toBe(10); + }); + }); +}); diff --git a/ubcpi/static/js/spec/ubcpi-barchar-directive_spec.js b/ubcpi/static/js/spec/ubcpi-barchar-directive_spec.js index 5039542..ac4cb06 100644 --- a/ubcpi/static/js/spec/ubcpi-barchar-directive_spec.js +++ b/ubcpi/static/js/spec/ubcpi-barchar-directive_spec.js @@ -115,4 +115,151 @@ describe('UBCPI', function () { }) }) }); + + + describe('pi-per-answer-chart', function () { + var element, scope; + + beforeEach(inject(function ($compile, $rootScope) { + scope = $rootScope; + + element = angular.element( + '' + ); + $compile(element)(scope); + scope.$digest(); + })); + + it('should not render anything when stats is empty', function () { + expect(element.find('svg').length).toBe(0); + expect(element.find('g').length).toBe(0); + }); + + describe('directive', function () { + var options = [{ + "text": "21", + "image_alt": "", + "image_url": "", + "image_position": "below", + "image_show_fields": 0 + }, { + "text": "42", + "image_alt": "", + "image_url": "", + "image_position": "below", + "image_show_fields": 0 + }, { + "text": "63", + "image_alt": "", + "image_url": "", + "image_position": "below", + "image_show_fields": 0 + }]; + var answers = {"original": 2, "revised": 1}; + var correct = 0; + + describe('with enough submissions', function() { + var stats = { + "original": {0: 4, 1: 5, 2: 1}, + "revised": {0: 1, 1: 8, 2: 1}, + }; + beforeEach(function() { + scope.$apply(function () { + scope.options = options; + scope.stats = stats; + scope.answers = answers; + scope.correct = correct; + scope.per_answer_stats = 1; + }); + }); + + it('should render the template with given data', function() { + // one graph for given answer per_answer_stats. two bars: one for initial choice, one for revision + expect(element.find('> svg').length).toBe(1); + expect(element.find('> svg > g').length).toBe(2); + }); + + it('should calculate percentage correctly for incorrect answer', function() { + expect(element.find('> svg > g').eq(0).find('> rect').length).toBe(2); + expect( + element.find('> svg > g').eq(0).find('> rect.ubcpibar').attr('width') / + element.find('> svg > g').eq(0).find('> rect:not(.ubcpibar)').attr('width')).toBe(0.5); + expect(element.find('> svg > g').eq(0).find('> svg > text').text()).toContain('50%'); + expect( + element.find('> svg > g').eq(1).find('> rect.ubcpibar').attr('width') / + element.find('> svg > g').eq(1).find('> rect:not(.ubcpibar)').attr('width')).toBe(0.8); + expect(element.find('> svg > g').eq(1).find('> svg > text').text()).toContain('80%'); + }); + }); + + describe('with enough submissions', function() { + var stats = { + "original": {0: 4, 1: 5, 2: 1}, + "revised": {0: 1, 1: 8, 2: 1}, + }; + beforeEach(function() { + scope.$apply(function () { + scope.options = options; + scope.stats = stats; + scope.answers = answers; + scope.correct = correct; + scope.per_answer_stats = correct; + }); + }); + + it('should calculate percentage correctly for correct answer', function() { + expect(element.find('> svg > g').eq(0).find('> rect').length).toBe(2); + expect( + element.find('> svg > g').eq(0).find('> rect.correct-answer').attr('width') / + element.find('> svg > g').eq(0).find('> rect:not(.correct-answer)').attr('width')).toBe(0.4); + expect(element.find('> svg > g').eq(0).find('> svg > text').text()).toContain('40%'); + expect( + element.find('> svg > g').eq(1).find('> rect.correct-answer').attr('width') / + element.find('> svg > g').eq(1).find('> rect:not(.correct-answer)').attr('width')).toBe(0.1); + expect(element.find('> svg > g').eq(1).find('> svg > text').text()).toContain('10%'); + }); + + it('should update when stats changed', function() { + scope.$apply(function() { + scope.stats = { + "original": {0: 10, 1: 6, 2: 4}, + "revised": {0: 4, 1: 14, 2: 2}, + }; + }); + expect(element.find('> svg > g').eq(0).find('> rect').length).toBe(2); + expect( + element.find('> svg > g').eq(0).find('> rect.correct-answer').attr('width') / + element.find('> svg > g').eq(0).find('> rect:not(.correct-answer)').attr('width')).toBe(0.5); + expect(element.find('> svg > g').eq(0).find('> svg > text').text()).toContain('50%'); + expect( + element.find('> svg > g').eq(1).find('> rect.correct-answer').attr('width') / + element.find('> svg > g').eq(1).find('> rect:not(.correct-answer)').attr('width')).toBe(0.2); + expect(element.find('> svg > g').eq(1).find('> svg > text').text()).toContain('20%'); + }); + }); + + describe('with enough submissions and showing stats for user\'s revision', function() { + var stats = { + "original": {0: 4, 1: 5, 2: 1}, + "revised": {0: 1, 1: 8, 2: 1}, + }; + beforeEach(function() { + scope.$apply(function () { + scope.options = options; + scope.stats = stats; + scope.answers = answers; + scope.correct = correct; + scope.per_answer_stats = answers['revised']; + }); + }); + + it('should not indicate it as user\'s initial answer', function() { + expect(element.find('> svg > g').eq(0).find('> svg > text').text()).not.toContain('including you'); + }); + it('should indicate it as user\'s revision', function() { + expect(element.find('> svg > g').eq(1).find('> svg > text').text()).toContain('including you'); + }); + }); + }) + }); }); diff --git a/ubcpi/static/js/spec/ubcpi_spec.js b/ubcpi/static/js/spec/ubcpi_spec.js index cf368ae..7ef0480 100644 --- a/ubcpi/static/js/spec/ubcpi_spec.js +++ b/ubcpi/static/js/spec/ubcpi_spec.js @@ -400,7 +400,6 @@ describe('UBCPI module', function () { }); controller.getStats(); expect(controller.stats).toEqual(response); - expect(controller.calc(0)).toBe(" Initial Answer Selection: 100% Final Answer Selection: 0%"); }); it('should call notify with error when backend errors', function() { diff --git a/ubcpi/static/js/src/d3-pibar.js b/ubcpi/static/js/src/d3-pibar.js index d76bb17..896fac7 100644 --- a/ubcpi/static/js/src/d3-pibar.js +++ b/ubcpi/static/js/src/d3-pibar.js @@ -156,3 +156,139 @@ d3.custom.barChart = function(scope, gettext) { return chart; }; +/** + * Data format: + * [ + * {percentage: 40, order: 0, label: '(including you) initial choise', class: 'ubcpibar'}, + * {percentage: 75, order: 1, label: 'after revision', class: 'ubcpibar'}, + * ] + */ +d3.custom.perAnswerChart = function(scope, gettext, allAnswerCount) { + // Private Variables + var chartWidth = 750; + var chartHeight = 56; + var labelWidth = 150; + var minTotalFrequency = 10; + + if(scope.role == 'instructor' || scope.role == 'staff'){ minTotalFrequency = 1} + + function chart(selection) { + selection.each(function(data) { + var totalFreq = allAnswerCount; + + // sort bars based on given order + data = data.sort(function(a, b) { + return d3.ascending(a.order, b.order); + }); + + if (totalFreq < minTotalFrequency) { + d3.select(this) + .append("span") + .attr("id", 'not-enough-data') + .text(gettext("Not enough data to generate the chart. Please check back later.")); + return; + } else { + var notEnoughDataSpan = d3.select('#not-enough-data'); + if (typeof notEnoughDataSpan !== 'undefined') { + notEnoughDataSpan.remove(); + } + } + + var svg = d3.select(this) + .classed("svg-container", true) + .append("svg") + .attr("preserveAspectRatio", "xMaxYMax meet") + .attr("viewBox", "0 0 " + chartWidth + " " + chartHeight) + .classed("svg-content-responsive", true); + + // x and y scale + var x = d3.scale.linear() + .range([0, chartWidth-labelWidth]) + .domain([0, 100]); + var y = d3.scale.ordinal() + .rangeRoundBands([0, chartHeight], 0.2) + .domain(data.map(function (d) { + return d.type; + })); + + var bars = svg.selectAll("g.bar") + .data(data) + .enter() + .append("g") + .attr("transform", function(d) { + return "translate(0," + y(d.type) + ")"; + }); + + // label of each bar + bars.append("text") + .attr("x", "0em") + .attr("dy", "1.2em") + .attr("text-anchor", "left") + .attr("class", function(d) { + return d.label_class; + }) + .text(function(d) { return d.type; }); + + // background of each bar at 100% full length + bars.append("rect") + .style("fill", "#dddddd") + .attr("x", labelWidth) + .attr("rx", 3) + .attr("ry", 3) + .attr("height", y.rangeBand()) + .attr("width", function(d) { + return x(100); + }); + + // the actual bar based on given percentage + bars.append("rect") + .attr("class", function (d) { + return d.class; + }) + .attr("x", labelWidth) + .attr("rx", 3) + .attr("ry", 3) + .attr("height", y.rangeBand()) + .attr("width", function (d) { + return x(d.percentage); + }); + + // text on each bar + bars.append("svg") + .attr({ height: y.rangeBand() }) + .append("text") + .attr("x", labelWidth+10) + .attr("dy", "1.2em") + .attr("text-anchor", "left") + .attr("class", function(d) { + return d.class; + }) + .text(function(d) { return Math.round(d.percentage) + "% " + d.text; }); + }); + + } + + // Public Variables/ (Getters and Setters) + chart.width = function(width) { + if (!arguments.length) return chartWidth; + chartWidth = width; + + return this; + }; + + chart.height = function(height) { + if (!arguments.length) return chartHeight; + chartHeight = height; + + return this; + }; + + chart.minTotalFrequency = function(min) { + if (!arguments.length) return minTotalFrequency; + minTotalFrequency = min; + + return this; + }; + + return chart; +}; diff --git a/ubcpi/static/js/src/ubcpi-barchart-directive.js b/ubcpi/static/js/src/ubcpi-barchart-directive.js index c88325b..6fb860f 100644 --- a/ubcpi/static/js/src/ubcpi-barchart-directive.js +++ b/ubcpi/static/js/src/ubcpi-barchart-directive.js @@ -37,3 +37,58 @@ angular.module('UBCPI'). } } }]); + + +angular.module('UBCPI'). + directive('piPerAnswerChart', ['gettext', function(gettext){ + return { + restrict: 'E', + scope: { + options: '=', + stats: '=', + correct: '=', + role: '=', + answers: '=', + perAnswerStats: '=' + }, + // no overwrite template + replace: false, + link: function(scope, element) { + // watch the stats as it could be async populated + scope.$watch('stats', function(stats) { + if(!stats) { + return; + } + + var data = []; + var allAnswerCount = 0; + for (var k in stats) { + var total = 0; + for (var op in stats[k]) { + total += stats[k][op]; + } + if (total > allAnswerCount) { + allAnswerCount = total; + } + data.push({ + percentage: (total > 0 && typeof stats[k][scope.perAnswerStats] !== 'undefined'? + (stats[k][scope.perAnswerStats] / total) * 100 : 0), + order: k === 'original'? 0 : 1, + text: (scope.answers[k] == scope.perAnswerStats? gettext('(including you) ') : ''), + class: 'ubcpibar' + (scope.correct == scope.perAnswerStats ? ' correct-answer' : '') + + (k === 'original'? ' original' : ''), + label_class: 'ubcpibar label', + type: k === 'original'? gettext('Chose initially') : gettext('Chose after revision') + }); + } + + d3.select(element[0]).select("svg").remove(); // remove old chart + // generate the chart + var chartLayout = d3.custom.perAnswerChart(scope, gettext, allAnswerCount); + d3.select(element[0]) + .datum(data) + .call(chartLayout); + }, true) + } + } + }]); diff --git a/ubcpi/static/js/src/ubcpi.js b/ubcpi/static/js/src/ubcpi.js index 6087b65..4519aef 100644 --- a/ubcpi/static/js/src/ubcpi.js +++ b/ubcpi/static/js/src/ubcpi.js @@ -151,6 +151,9 @@ angular.module('UBCPI', ['ngSanitize', 'ngCookies', 'gettext']) // By default, we're not submitting, this changes when someone presses the submit button self.submitting = false; + // Whether user is revising the answer + self.revising = false; + /** * Determine if the submit button should be disabled * If we have an answer selected, a rationale that is large @@ -191,6 +194,14 @@ angular.module('UBCPI', ['ngSanitize', 'ngCookies', 'gettext']) self.getStats = function () { return backendService.getStats().then(function(data) { self.stats = data; + + self.perAnswerStats = {}; + for (var i = 0; i < $scope.options.length; i++) { + self.perAnswerStats[i] = { + 'original': (typeof self.stats.original[i] !== 'undefined'? self.stats.original[i] : 0), + 'revised' : (typeof self.stats.revised[i] !== 'undefined'? self.stats.revised[i] : 0) + } + } }, function(error) { notify('error', { 'title': gettext('Error retrieving statistics!'), @@ -200,34 +211,6 @@ angular.module('UBCPI', ['ngSanitize', 'ngCookies', 'gettext']) }); }; - self.calc = function(s) { - var originalPercentage = gettext(" Initial Answer Selection: "); - var revisedPercentage = gettext(" Final Answer Selection: "); - if (typeof self.stats !== 'undefined' && typeof s !== 'undefined' && typeof self.stats.original[s] !== 'undefined') { - var totalCounts = 0; - for (var i = 0; i < data.options.length; i++) { - if (typeof self.stats.original[i] !== 'undefined') - totalCounts += self.stats.original[i]; - } - originalPercentage += self.stats.original[s] / totalCounts * 100 + "%"; - } - else - originalPercentage += "0%"; - - if (typeof self.stats !== 'undefined' && typeof s !== 'undefined' && typeof self.stats.revised[s] !== 'undefined') { - var totalCounts = 0; - for (var i = 0; i < data.options.length; i++) { - if (typeof self.stats.revised[i] !== 'undefined') - totalCounts += self.stats.revised[i]; - } - revisedPercentage += self.stats.revised[s] / totalCounts * 100 + "%"; - } - else - revisedPercentage += "0%"; - - return originalPercentage + " " + revisedPercentage; - }; - function get_data() { return backendService.get_data().then(function(data) { return data; @@ -257,6 +240,14 @@ angular.module('UBCPI', ['ngSanitize', 'ngCookies', 'gettext']) self.options = data.options; } + self.hasSampleExplanationForOption = function (option) { + for (var index in self.other_answers.answers) { + if (option == self.other_answers.answers[index].option) { + return true; + } + } + return false; + }; }]); /** diff --git a/ubcpi/ubcpi.py b/ubcpi/ubcpi.py index a630a85..b560ad3 100644 --- a/ubcpi/ubcpi.py +++ b/ubcpi/ubcpi.py @@ -618,7 +618,13 @@ def get_persisted_data(self, other_answers): "rationale_revised": answers.get_rationale(1), } if answers.has_revision(0) and not answers.has_revision(1): - ret['other_answers'] = other_answers + # If no persisted peer answers, generate new ones. + # Could happen if a student completed Step 1 before ubcpi upgraded to persist peer answers. + if not self.other_answers_shown: + ret['other_answers'] = get_other_answers( + self.sys_selected_answers, self.seeds, self.get_student_item_dict, self.algo, self.options) + else: + ret['other_answers'] = other_answers # reveal the correct answer in the end if answers.has_revision(1):