Created
July 11, 2016 16:48
-
-
Save kevinburleigh75/108f4ac71690e35a3cb5969aee24b418 to your computer and use it in GitHub Desktop.
This file contains 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