Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prompt an instructor to write up her teaching experience as a retrospective on CaseLog #233

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Layout/ClassStructure:
- attr_writer
- attr_accessor
- alias_attribute
- time_for_a_boolean
- translates
associations:
- has_one
Expand Down
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ gem 'redis', '~> 3.0'
gem 'acts_as_list'
gem 'kaminari'
gem 'memoist'
gem 'time_for_a_boolean', git: 'https://github.com/calebthompson/time_for_a_boolean'
gem 'time_for_a_boolean', '~> 0.2.0'
gem 'virtus'

# Authentication and Authorization
Expand Down
13 changes: 4 additions & 9 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,6 @@ GIT
user_agent_parser
uuidtools

GIT
remote: https://github.com/calebthompson/time_for_a_boolean
revision: 636a4c6b4645f9888402ff49b40b7f42c270d946
specs:
time_for_a_boolean (0.1.0)
activerecord
railties

GIT
remote: https://github.com/cbothner/omniauth-lti
revision: 578245b0cabb755a209221ce1682667d9154ac4d
Expand Down Expand Up @@ -395,6 +387,9 @@ GEM
thor (0.19.4)
thread_safe (0.3.6)
tilt (2.0.8)
time_for_a_boolean (0.2.0)
activerecord
railties
tzinfo (1.2.3)
thread_safe (~> 0.1)
uglifier (3.2.0)
Expand Down Expand Up @@ -487,7 +482,7 @@ DEPENDENCIES
spring-commands-rspec
spring-watcher-listen (~> 2.0.0)
table_print
time_for_a_boolean!
time_for_a_boolean (~> 0.2.0)
uglifier (>= 1.3.0)
virtus
web-console
Expand Down
5 changes: 5 additions & 0 deletions app/models/deployment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@
# - 0 means no quiz (and assumes quiz == nil)
# @attr key [String] a random URL safe string used as the hard-to-guess
# identifier that allows the {MagicLink} to work
# @attr retrospective_prompt_sent_at [DateTime] at most once after a professor
# has deployed a case, we want to prompt them to write up their experience
# teaching with the case as a post in CaseLog
#
# @see GenericDeployment GenericDeployment: this model’s null object
class Deployment < ApplicationRecord
include Authority::Abilities

time_for_a_boolean :retrospective_prompt_sent

belongs_to :case
belongs_to :group
belongs_to :quiz
Expand Down
65 changes: 65 additions & 0 deletions app/services/send_retrospective_prompts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# frozen_string_literal: true

# After a professor has deployed a case in their classroom, we want to invite
# them to write up a retrospective of their experience as a post in the
# instructors-only community “CaseLog.” This service sends such notifications.
#
# Running once a week, on Wednesdays at noon (Eastern), we look for deployments
# whose members were much more active in the case 14 to 7 days ago than they
# were in the last 7 days. This is defined as an 80% drop-off of use from week
# to week, where the previous week measured over 500 events. This was chosen
# empirically based on recorded data at an early stage and should be subject to
# review. We exclude any deployments with fewer than five readers as a sanity
# check. When we send prompts to the instructors, we set the
# `retrospective_prompt_sent` flag so never to bug people more than once.
class SendRetrospectivePrompts
def self.call(time_basis: Time.zone.now)
new(time_basis).call
end

def initialize(now)
@now = now
end

def call
deployments_needing_prompts.map { |x| [x.group.name, x.case.slug] }
# deployments_needing_prompts.each do |deployment|
# deployment.update retrospective_prompt_set: true
# DeploymentMailer.retrospective_prompt(deployment).deliver
# end
end

private

def deployments_needing_prompts
candidate_deployments_with_enough_readers
.select { |d| much_more_use_two_weeks_ago d }
end

def candidate_deployments_with_enough_readers
count_readers_by_group = GroupMembership.group(:group_id).count(:reader_id)
Deployment.where(retrospective_prompt_sent_at: nil)
.select { |d| count_readers_by_group[d.group_id] > 5 }
end

def much_more_use_two_weeks_ago(deployment)
two_weeks_ago = count_interesting_events(
deployment,
(@now - 2.weeks)..(@now - 1.week)
)
last_week = count_interesting_events(
deployment,
(@now - 1.week)..@now
)

two_weeks_ago > 500 && (two_weeks_ago - last_week) / two_weeks_ago > -0.8
end

def count_interesting_events(deployment, range)
Ahoy::Event.interesting
.where(user_id: deployment.group.readers.pluck(:id))
.where_properties(case_slug: deployment.case.slug)
.where(time: range)
.count
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddRetrospectivePromptSentAtToDeployments < ActiveRecord::Migration[5.1]
def change
add_column :deployments, :retrospective_prompt_sent_at, :timestamp
end
end
6 changes: 4 additions & 2 deletions db/structure.sql
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,8 @@ CREATE TABLE deployments (
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
answers_needed integer DEFAULT 1,
key character varying
key character varying,
retrospective_prompt_sent_at timestamp without time zone
);


Expand Down Expand Up @@ -2309,6 +2310,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20171113192541'),
('20171220165301'),
('20180119170858'),
('20180129143420');
('20180129143420'),
('20180129162300');