Commit e932632b by Sarina Canelake

Remove psychometrics app

parent 92a436b1
......@@ -1125,9 +1125,6 @@ class CapaMixin(CapaFields):
self.attempts,
)
if hasattr(self.runtime, 'psychometrics_handler'): # update PsychometricsData using callback
self.runtime.psychometrics_handler(self.get_state_for_lcp())
# render problem into HTML
html = self.get_problem_html(encapsulate=False)
......@@ -1375,10 +1372,6 @@ class CapaMixin(CapaFields):
event_info['attempts'] = self.attempts
self.track_function_unmask('problem_rescore', event_info)
# psychometrics should be called on rescoring requests in the same way as check-problem
if hasattr(self.runtime, 'psychometrics_handler'): # update PsychometricsData using callback
self.runtime.psychometrics_handler(self.get_state_for_lcp())
return {'success': success}
def save_problem(self, data):
......
......@@ -2528,20 +2528,6 @@ CREATE TABLE `programs_programsapiconfig` (
CONSTRAINT `programs_programsa_changed_by_id_b7c3b49d5c0dcd3_fk_auth_user_id` FOREIGN KEY (`changed_by_id`) REFERENCES `auth_user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `psychometrics_psychometricdata`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `psychometrics_psychometricdata` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`done` tinyint(1) NOT NULL,
`attempts` int(11) NOT NULL,
`checktimes` longtext,
`studentmodule_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `studentmodule_id` (`studentmodule_id`),
CONSTRAINT `D758b867e6fa9161734bd9cb58b9a485` FOREIGN KEY (`studentmodule_id`) REFERENCES `courseware_studentmodule` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `self_paced_selfpacedconfiguration`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
......
......@@ -56,7 +56,6 @@ from openedx.core.lib.xblock_utils import (
wrap_xblock,
request_token as xblock_request_token,
)
from psychometrics.psychoanalyze import make_psychometrics_data_update_handler
from student.models import anonymous_id_for_user, user_by_anonymous_id
from student.roles import CourseBetaTesterRole
from xblock.core import XBlock
......@@ -760,11 +759,6 @@ def get_module_system_for_user(user, student_data, # TODO # pylint: disable=to
position = None
system.set('position', position)
if settings.FEATURES.get('ENABLE_PSYCHOMETRICS') and user.is_authenticated():
system.set(
'psychometrics_handler', # set callback for updating PsychometricsData
make_psychometrics_data_update_handler(course_id, user, descriptor.location)
)
system.set(u'user_is_staff', user_is_staff)
system.set(u'user_is_admin', bool(has_access(user, u'staff', 'global')))
......
......@@ -1766,17 +1766,6 @@ class TestRebindModule(TestSubmittingProblems):
self.assertEqual(module.scope_ids.user_id, user2.id)
self.assertEqual(module.descriptor.scope_ids.user_id, user2.id)
@patch('courseware.module_render.make_psychometrics_data_update_handler')
@patch.dict(settings.FEATURES, {'ENABLE_PSYCHOMETRICS': True})
def test_psychometrics_anonymous(self, psycho_handler):
"""
Make sure that noauth modules with anonymous users don't have
the psychometrics callback bound.
"""
module = self.get_module_for_user(self.anon_user)
module.system.rebind_noauth_module_to_user(module, self.anon_user)
self.assertFalse(psycho_handler.called)
@attr('shard_1')
@ddt.ddt
......
......@@ -48,7 +48,6 @@ from instructor_task.api import (
from instructor_task.views import get_task_completion_info
from edxmako.shortcuts import render_to_response, render_to_string
from class_dashboard import dashboard_data
from psychometrics import psychoanalyze
from student.models import (
CourseEnrollment,
CourseEnrollmentAllowed,
......@@ -97,7 +96,7 @@ def instructor_dashboard(request, course_id):
plots = []
datatable = {}
# the instructor dashboard page is modal: grades, psychometrics, admin
# the instructor dashboard page is modal: grades, admin
# keep that state in request.session (defaults to grades mode)
idash_mode = request.POST.get('idash_mode', '')
idash_mode_key = u'idash_mode:{0}'.format(course_id)
......@@ -320,18 +319,6 @@ def instructor_dashboard(request, course_id):
datatable = ret['datatable']
#----------------------------------------
# psychometrics
elif action == 'Generate Histogram and IRT Plot':
problem = request.POST['Problem']
nmsg, plots = psychoanalyze.generate_plots_for_problem(problem)
msg += nmsg
track.views.server_track(request, "psychometrics-histogram-generation", {"problem": unicode(problem)}, page="idashboard")
if idash_mode == 'Psychometrics':
problems = psychoanalyze.problems_with_psychometric_data(course_key)
#----------------------------------------
# analytics
def get_analytics_result(analytics_name):
"""Return data for an Analytic piece, or None if it doesn't exist. It
......@@ -435,8 +422,6 @@ def instructor_dashboard(request, course_id):
'show_email_tab': show_email_tab, # email
'problems': problems, # psychometrics
'plots': plots, # psychometrics
'course_errors': modulestore().get_course_errors(course.id),
'instructor_tasks': instructor_tasks,
'offline_grade_log': offline_grades_available(course_key),
......
'''
django admin pages for courseware model
'''
from psychometrics.models import PsychometricData
from django.contrib import admin
admin.site.register(PsychometricData)
#!/usr/bin/python
#
# generate pyschometrics data from tracking logs and student module data
import json
from courseware.models import StudentModule
from track.models import TrackingLog
from psychometrics.models import PsychometricData
from django.conf import settings
from django.core.management.base import BaseCommand
#db = "ocwtutor" # for debugging
#db = "default"
db = getattr(settings, 'DATABASE_FOR_PSYCHOMETRICS', 'default')
class Command(BaseCommand):
help = "initialize PsychometricData tables from StudentModule instances (and tracking data, if in SQL)."
help += "Note this is done for all courses for which StudentModule instances exist."
def handle(self, *args, **options):
# delete all pmd
#PsychometricData.objects.all().delete()
#PsychometricData.objects.using(db).all().delete()
smset = StudentModule.objects.using(db).exclude(max_grade=None)
for sm in smset:
usage_key = sm.module_state_key
if not usage_key.block_type == "problem":
continue
try:
state = json.loads(sm.state)
done = state['done']
except:
print "Oops, failed to eval state for %s (state=%s)" % (sm, sm.state)
continue
if done: # only keep if problem completed
try:
pmd = PsychometricData.objects.using(db).get(studentmodule=sm)
except PsychometricData.DoesNotExist:
pmd = PsychometricData(studentmodule=sm)
pmd.done = done
pmd.attempts = state['attempts']
# get attempt times from tracking log
uname = sm.student.username
tset = TrackingLog.objects.using(db).filter(username=uname, event_type__contains='problem_check')
tset = tset.filter(event_source='server')
tset = tset.filter(event__contains="'%s'" % usage_key)
checktimes = [x.dtcreated for x in tset]
pmd.checktimes = checktimes
if not len(checktimes) == pmd.attempts:
print "Oops, mismatch in number of attempts and check times for %s" % pmd
#print pmd
pmd.save(using=db)
print "%d PMD entries" % PsychometricData.objects.using(db).all().count()
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('courseware', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='PsychometricData',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('done', models.BooleanField(default=False)),
('attempts', models.IntegerField(default=0)),
('checktimes', models.TextField(null=True, blank=True)),
('studentmodule', models.OneToOneField(to='courseware.StudentModule')),
],
),
]
#
# db model for psychometrics data
#
# this data is collected in real time
#
from django.db import models
from courseware.models import StudentModule
class PsychometricData(models.Model):
"""
This data is a table linking student, module, and module performance,
including number of attempts, grade, max grade, and time of checks.
Links to instances of StudentModule, but only those for capa problems.
Note that StudentModule.module_state_key is a :class:`Location` instance.
checktimes is extracted from tracking logs, or added by capa module via psychometrics callback.
"""
class Meta(object):
app_label = "psychometrics"
studentmodule = models.OneToOneField(StudentModule, db_index=True) # contains student, module_state_key, course_id
done = models.BooleanField(default=False)
attempts = models.IntegerField(default=0) # extracted from studentmodule.state
checktimes = models.TextField(null=True, blank=True) # internally stored as list of datetime objects
# keep in mind
# grade = studentmodule.grade
# max_grade = studentmodule.max_grade
# student = studentmodule.student
# course_id = studentmodule.course_id
# location = studentmodule.module_state_key
def __unicode__(self):
sm = self.studentmodule
return "[PsychometricData] %s url=%s, grade=%s, max=%s, attempts=%s, ct=%s" % (sm.student,
sm.module_state_key,
sm.grade,
sm.max_grade,
self.attempts,
self.checktimes)
......@@ -116,8 +116,6 @@ FEATURES = {
# in their emails, and they will have no way to resubscribe.
'ENABLE_DISCUSSION_EMAIL_DIGEST': False,
'ENABLE_PSYCHOMETRICS': False, # real-time psychometrics (eg item response theory analysis in instructor dashboard)
'ENABLE_DJANGO_ADMIN_SITE': True, # set true to enable django's admin site, even on prod (e.g. for course ops)
'ENABLE_SQL_TRACKING_LOGS': False,
'ENABLE_LMS_MIGRATION': False,
......@@ -1833,7 +1831,6 @@ INSTALLED_APPS = (
'instructor',
'instructor_task',
'open_ended_grading',
'psychometrics',
'licenses',
'openedx.core.djangoapps.course_groups',
'bulk_email',
......
......@@ -24,7 +24,6 @@ FEATURES['SUBDOMAIN_COURSE_LISTINGS'] = False # Enable to test subdomains--othe
FEATURES['SUBDOMAIN_BRANDING'] = True
FEATURES['FORCE_UNIVERSITY_DOMAIN'] = None # show all university courses if in dev (ie don't use HTTP_HOST)
FEATURES['ENABLE_MANUAL_GIT_RELOAD'] = True
FEATURES['ENABLE_PSYCHOMETRICS'] = False # real-time psychometrics (eg item response theory analysis in instructor dashboard)
FEATURES['ENABLE_SERVICE_STATUS'] = True
FEATURES['ENABLE_INSTRUCTOR_EMAIL'] = True # Enable email for all Studio courses
FEATURES['REQUIRE_COURSE_EMAIL_AUTH'] = False # Give all courses email (don't require django-admin perms)
......
......@@ -148,9 +148,6 @@ function goto( mode)
%endif
<h2 class="navbar">[ <a href="#" onclick="goto('Grades');" class="${modeflag.get('Grades')}">Grades</a> |
%if settings.FEATURES.get('ENABLE_PSYCHOMETRICS'):
<a href="#" onclick="goto('Psychometrics');" class="${modeflag.get('Psychometrics')}">${_("Psychometrics")}</a> |
%endif
<a href="#" onclick="goto('Admin');" class="${modeflag.get('Admin')}">${_("Admin")}</a> |
<a href="#" onclick="goto('Forum Admin');" class="${modeflag.get('Forum Admin')}">${_("Forum Admin")}</a> |
<a href="#" onclick="goto('Enrollment');" class="${modeflag.get('Enrollment')}">${_("Enrollment")}</a> |
......@@ -268,27 +265,6 @@ function goto( mode)
%endif
##-----------------------------------------------------------------------------
%if modeflag.get('Psychometrics'):
<p>${_("Select a problem and an action:")}
</p>
<p>
<select name="Problem">
%for problem, count in sorted(problems.items(), key=lambda x: x[0]):
<option value="${problem}">${problem} [${count}]</option>
%endfor
</select>
</p>
<p>
<input type="submit" name="action" value="Generate Histogram and IRT Plot">
</p>
<p></p>
%endif
##-----------------------------------------------------------------------------
%if modeflag.get('Admin'):
%if instructor_access or admin_access:
......@@ -398,7 +374,7 @@ function goto( mode)
##-----------------------------------------------------------------------------
%if datatable and modeflag.get('Psychometrics') is None:
%if datatable:
<br/>
<br/>
......@@ -492,32 +468,6 @@ function goto( mode)
%endif
##-----------------------------------------------------------------------------
%if modeflag.get('Psychometrics'):
%for plot in plots:
<br/>
<h3>${plot['title']}</h3>
<br/>
<p>${plot['info']}</p>
<br/>
<div id="plot_${plot['id']}" style="width:600px;height:300px;"></div>
<script type="text/javascript">
$(function () {
${plot['data']}
$.plot($("#plot_${plot['id']}"), ${plot['cmd']} );
});
</script>
<br/>
<br/>
%endfor
%endif
##-----------------------------------------------------------------------------
## always show msg
##-----------------------------------------------------------------------------
%if modeflag.get('Admin'):
% if course_errors is not UNDEFINED:
<h2>${_("Course errors")}</h2>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment