Created
July 11, 2016 16:48
-
-
Save kevinburleigh75/108f4ac71690e35a3cb5969aee24b418 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class LocalClue | |
| attr_reader :aggregate | |
| attr_reader :left | |
| attr_reader :right | |
| attr_reader :threshold | |
| attr_reader :level | |
| attr_reader :confidence | |
| attr_reader :learners | |
| attr_reader :responses | |
| def initialize(learners: [], responses: []) | |
| @aggregate = 0.5 | |
| @left = 0.0 | |
| @right = 1.0 | |
| @threshold = :below | |
| @level = :medium | |
| @confidence = :bad | |
| @learners = learners | |
| @responses = responses | |
| self._update | |
| end | |
| def _update | |
| learner_responses = @responses.select{|response| @learners.include? response[:learner_id]} | |
| if learner_responses.count >= 3 | |
| trial_tot = learner_responses.count | |
| trial_suc = learner_responses.select{|response| response[:correct]}.count | |
| z_alpha = 0.68 | |
| p_hat = (trial_suc + 0.5*z_alpha**2) / (trial_tot + z_alpha**2) | |
| var = learner_responses.map{|response| response[:correct] ? 1.0 : 0.0} | |
| .map{|value| (p_hat - value)**2} | |
| .inject(&:+) / (learner_responses.count - 1) | |
| interval = ( z_alpha * Math.sqrt(p_hat*(1-p_hat)/(trial_tot + z_alpha**2)) + | |
| 0.1*Math.sqrt(var) + | |
| 0.05 ) | |
| @aggregate = p_hat | |
| @left = [p_hat - interval, 0].max | |
| @right = [p_hat + interval, 1].min | |
| end | |
| if @aggregate < 0.3 | |
| @level = :low | |
| elsif @aggregate < 0.8 | |
| @level = :medium | |
| else | |
| @level = :high | |
| end | |
| if (@right-@left).abs <= 0.5 | |
| @confidence = :good | |
| else | |
| @confidence = :bad | |
| end | |
| if learner_responses.count > 3 | |
| @threshold = :above | |
| else | |
| @threshold = :below | |
| end | |
| # puts "[#{@aggregate} #{@left} #{@right} #{@level} #{@confidence} #{@threshold}]" | |
| end | |
| end | |
| RSpec.describe LocalClue do | |
| let(:local_clue) { LocalClue.new(learners: learners, responses: responses) } | |
| context 'no learners or responses' do | |
| let(:learners) { [] } | |
| let(:responses) { [] } | |
| it "'aggregate' is 0.5" do | |
| expect(local_clue.aggregate).to be 0.5 | |
| end | |
| it "'left' is 0.0" do | |
| expect(local_clue.left).to be 0.0 | |
| end | |
| it "'right' is 1.0" do | |
| expect(local_clue.right).to be 1.0 | |
| end | |
| it "'level' is :medium" do | |
| expect(local_clue.level).to be :medium | |
| end | |
| it "'threshold' is :below" do | |
| expect(local_clue.threshold).to be :below | |
| end | |
| it "'confidence' is :bad" do | |
| expect(local_clue.confidence).to be :bad | |
| end | |
| end | |
| context 'single learner' do | |
| let(:learners) { ['lid1'] } | |
| context 'no responses' do | |
| let(:responses) { [] } | |
| it "'aggregate' is 0.5" do | |
| expect(local_clue.aggregate).to be 0.5 | |
| end | |
| it "'left' is 0.0" do | |
| expect(local_clue.left).to be 0.0 | |
| end | |
| it "'right' is 1.0" do | |
| expect(local_clue.right).to be 1.0 | |
| end | |
| it "'level' is :medium" do | |
| expect(local_clue.level).to be :medium | |
| end | |
| it "'threshold' is :below" do | |
| expect(local_clue.threshold).to be :below | |
| end | |
| it "'confidence' is :bad" do | |
| expect(local_clue.confidence).to be :bad | |
| end | |
| end | |
| context 'few responses' do | |
| let(:responses) { | |
| [ { learner_id: 'lid1', question_id: 'qid1', correct: true}, | |
| { learner_id: 'lid1', question_id: 'qid2', correct: false}, | |
| { learner_id: 'lid2', question_id: 'qid1', correct: false}, ] | |
| } | |
| it "'level' is :medium" do | |
| expect(local_clue.level).to be :medium | |
| end | |
| it "'threshold' is :below" do | |
| expect(local_clue.threshold).to be :below | |
| end | |
| it "'confidence' is :bad" do | |
| expect(local_clue.confidence).to be :bad | |
| end | |
| end | |
| context 'many responses' do | |
| let(:responses) { | |
| [ { learner_id: 'lid1', question_id: 'qid1', correct: true}, | |
| { learner_id: 'lid1', question_id: 'qid2', correct: false}, | |
| { learner_id: 'lid1', question_id: 'qid3', correct: false}, | |
| { learner_id: 'lid1', question_id: 'qid4', correct: true}, | |
| { learner_id: 'lid1', question_id: 'qid5', correct: true}, | |
| { learner_id: 'lid1', question_id: 'qid6', correct: true}, | |
| { learner_id: 'lid1', question_id: 'qid7', correct: true}, | |
| { learner_id: 'lid1', question_id: 'qid8', correct: true}, | |
| { learner_id: 'lid2', question_id: 'qid2', correct: false}, | |
| { learner_id: 'lid2', question_id: 'qid3', correct: true}, | |
| { learner_id: 'lid3', question_id: 'qid1', correct: false}, ] | |
| } | |
| it "'threshold' is :above" do | |
| expect(local_clue.threshold).to be :above | |
| end | |
| it "'confidence' is :good" do | |
| expect(local_clue.confidence).to be :good | |
| end | |
| end | |
| end | |
| context 'multiple learners' do | |
| let(:learners) { ['lid1', 'lid3'] } | |
| context 'no responses' do | |
| let(:responses) { [] } | |
| it "'aggregate' is 0.5" do | |
| expect(local_clue.aggregate).to be 0.5 | |
| end | |
| it "'left' is 0.0" do | |
| expect(local_clue.left).to be 0.0 | |
| end | |
| it "'right' is 1.0" do | |
| expect(local_clue.right).to be 1.0 | |
| end | |
| it "'level' is :medium" do | |
| expect(local_clue.level).to be :medium | |
| end | |
| it "'threshold' is :below" do | |
| expect(local_clue.threshold).to be :below | |
| end | |
| it "'confidence' is :bad" do | |
| expect(local_clue.confidence).to be :bad | |
| end | |
| end | |
| context 'few responses' do | |
| let(:responses) { | |
| [ { learner_id: 'lid1', question_id: 'qid1', correct: true}, | |
| { learner_id: 'lid1', question_id: 'qid2', correct: false}, | |
| { learner_id: 'lid2', question_id: 'qid1', correct: false}, ] | |
| } | |
| it "'level' is :medium" do | |
| expect(local_clue.level).to be :medium | |
| end | |
| it "'threshold' is :below" do | |
| expect(local_clue.threshold).to be :below | |
| end | |
| it "'confidence' is :bad" do | |
| expect(local_clue.confidence).to be :bad | |
| end | |
| end | |
| context 'many responses' do | |
| let(:responses) { | |
| [ { learner_id: 'lid1', question_id: 'qid1', correct: true}, | |
| { learner_id: 'lid1', question_id: 'qid2', correct: false}, | |
| { learner_id: 'lid1', question_id: 'qid3', correct: false}, | |
| { learner_id: 'lid1', question_id: 'qid4', correct: true}, | |
| { learner_id: 'lid1', question_id: 'qid5', correct: true}, | |
| { learner_id: 'lid1', question_id: 'qid6', correct: true}, | |
| { learner_id: 'lid1', question_id: 'qid7', correct: true}, | |
| { learner_id: 'lid1', question_id: 'qid8', correct: true}, | |
| { learner_id: 'lid2', question_id: 'qid2', correct: false}, | |
| { learner_id: 'lid2', question_id: 'qid3', correct: true}, | |
| { learner_id: 'lid3', question_id: 'qid1', correct: false}, ] | |
| } | |
| it "'threshold' is :above" do | |
| expect(local_clue.threshold).to be :above | |
| end | |
| it "'confidence' is :good" do | |
| expect(local_clue.confidence).to be :good | |
| end | |
| end | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment