Skip to content

Instantly share code, notes, and snippets.

@kevinburleigh75
Created July 11, 2016 16:48
Show Gist options
  • Save kevinburleigh75/108f4ac71690e35a3cb5969aee24b418 to your computer and use it in GitHub Desktop.
Save kevinburleigh75/108f4ac71690e35a3cb5969aee24b418 to your computer and use it in GitHub Desktop.
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