blob: e0a51f316241a5ae9a8685066aa7f3d7f13f02be [file] [log] [blame]
#!/usr/bin/env python2.5
#
# Copyright 2009 the Melange authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""GradingRecord related functions.
"""
from google.appengine.ext import db
from soc.modules.gsoc.models.grading_project_survey_record import GSoCGradingProjectSurveyRecord
from soc.modules.gsoc.models.grading_record import GSoCGradingRecord
from soc.modules.gsoc.models.project_survey_record import GSoCProjectSurveyRecord
def updateOrCreateRecordsFor(survey_group, projects):
"""Updates or creates GradingRecords in batch.
Args:
survey_group: GradingSurveyGroup entity
projects: list of GSoCProjects which to process
Returns:
The list of updated and new records.
"""
records = []
for project in projects:
q = GSoCGradingRecord.all()
q.filter('grading_survey_group', survey_group)
q.ancestor(project)
# try to retrieve an existing record
record = q.get()
# retrieve the fields that should be set
record_fields = getFieldsForGradingRecord(
project, survey_group, record)
if not record and project.status in ['failed', 'invalid'] \
and not record_fields['mentor_record'] \
and not record_fields['student_record']:
# Don't create a new GradingRecord for an already failed project which
# has no records attached. Because it does not matter.
continue
if record:
# update existing GradingRecord
for key,value in record_fields.iteritems():
setattr(record, key, value)
else:
# create a new GradingRecord
record = GSoCGradingRecord(parent=project, **record_fields)
# prepare the new/updated record for storage
records.append(record)
db.put(records)
return records
def getFieldsForGradingRecord(project, survey_group, record_entity=None):
"""Returns the fields for a GradingRecord.
See GradingRecord model for description of the grade_decision value.
Args:
project: Project entity
survey_group: a GradingSurveyGroup entity
record_entity: an optional GradingRecord entity
Returns:
Dict containing the fields that should be set on a GradingRecord for this
GradingSurveyGroup and StudentProject
"""
# retrieve the two Surveys, student_survey might be None
grading_survey = survey_group.grading_survey
student_survey = survey_group.student_survey
# retrieve a GradingSurveyRecord
q = GSoCGradingProjectSurveyRecord.all()
q.filter('project', project)
q.filter('survey', grading_survey)
grading_survey_record = q.get()
if student_survey:
# retrieve ProjectSurveyRecord
q = GSoCProjectSurveyRecord.all()
q.filter('project', project)
q.filter('survey', student_survey)
project_survey_record = q.get()
else:
project_survey_record = None
# set the required fields
fields = {'grading_survey_group': survey_group,
'mentor_record': grading_survey_record,
'student_record': project_survey_record}
if not record_entity or not record_entity.locked:
# find grading decision for new or unlocked records
if not grading_survey_record:
# no record found, return undecided
grade_decision = 'undecided'
elif not student_survey or project_survey_record:
# if the grade is True then pass else fail
grade_decision = 'pass' if grading_survey_record.grade else 'fail'
else:
# no ProjectSurveyRecord on file while there is a survey to be taken
grade_decision = 'fail'
fields['grade_decision'] = grade_decision
# return the fields that should be set for a GradingRecord
return fields
def updateProjectsForGradingRecords(records):
"""Updates StudentProjects using a list of GradingRecord entities.
Args:
records: List of GradingRecord entities to process.
"""
projects_to_update = []
for record in records:
project = record.parent()
if project.status in ['withdrawn', 'invalid']:
# skip this project
continue
# get the key from the GradingRecord entity since that gets stored
record_key = record.key()
passed_evals = project.passed_evaluations
failed_evals = project.failed_evaluations
# try to remove this GradingRecord from the existing list of evals
if record_key in passed_evals:
passed_evals.remove(record_key)
if record_key in failed_evals:
failed_evals.remove(record_key)
# get the grade_decision from the GradingRecord
grade_decision = record.grade_decision
# update GradingRecord lists with respect to the grading_decision
if grade_decision == 'pass':
passed_evals.append(record_key)
elif grade_decision == 'fail':
failed_evals.append(record_key)
if project.status != 'completed':
# Only when the project has not been completed should the status be
# updated to reflect the new setting of the evaluations.
if len(failed_evals) == 0:
# no failed evaluations present
new_status = 'accepted'
else:
new_status = 'failed'
else:
new_status = project.status
# update the necessary fields and store it before updating
project.passed_evaluations = passed_evals
project.failed_evaluations = failed_evals
project.status = new_status
profile = project.parent()
profile.student_info.passed_evaluations = len(passed_evals)
profile.student_info.failed_evaluations = len(failed_evals)
projects_to_update.append(project)
projects_to_update.append(profile.student_info)
# batch put the StudentProjects that need to be updated
db.put(projects_to_update)