def getMostRecentPhase(vote_id, db): phase = getPhaseForVote(vote_id, db) if phase is None: return createPhase(vote_id, unixtime(datetime.now()), db) else: return phase
def getMostRecentPhase(video_id, db, restart_if_converged = False): phase = getByVideo(video_id, db) # is there a phase ongoing? if phase is not None and not phase['is_abandoned'] and not (phase['end'] is not None and restart_if_converged): # if it's not a closed phase and we're forcing restart of converged phases (e.g., choosing a random video) # how old is this -- is it abandoned? sql = """SELECT servertime FROM locations WHERE phase = %s ORDER BY servertime DESC LIMIT 1""" time_result = db.query_and_return_array(sql, (phase['phase'], )) time_bound = unixtime(datetime.now() - timedelta(seconds = PHASE_MAX_AGE_IN_SECONDS)) if phase['start'] > time_bound or (len(time_result) > 0 and time_result[0]['servertime'] > time_bound): # it's a recent, ongoing phase. return it. return phase else: # it's an old phase and we need to abandon it abandonPhase(phase['phase'], db) # if we got here, we need to create a new phase return createPhase( video_id, Decimal(0), Decimal(1), unixtime(datetime.now()), None, db)
def log_submission_in_db(request): """ Mapping of db columns (left) to form keys (right): assignmentid = assignmentId workerid = w vote = v accept = a show = sh go = g submit = su """ form = util.FieldStorage(request) # Get all the items out of the form assignmentid = get_value_or_none(form, "assignmentId") workerid = get_value_or_none(form, "w") vote = get_value_or_none(form, "v") # Parse the times accept = get_time_or_none(form, "a") show = get_time_or_none(form, "sh") go = get_time_or_none(form, "g") submit = get_time_or_none(form, "su") sql = """UPDATE `assignments` SET `show` = %s, `go` = %s, `submit` = %s WHERE assignmentid = %s; """ try: db = DBConnection() db.query_and_return_array(sql, (show, go, submit, assignmentid)) voteid = getVoteForAssignment(assignmentid, db) phase = getMostRecentPhase(voteid, db) sql = """INSERT INTO responses (voteid, phaseid, assignmentid, response) VALUES (%s, %s, %s, %s) ON DUPLICATE KEY UPDATE response=%s""" db.query_and_return_array( sql, (voteid, phase['pk'], assignmentid, vote, vote)) result = db.query_and_return_array( """SELECT COUNT(*) FROM responses WHERE phaseid = %s""", (phase['pk'], )) if result[0]['COUNT(*)'] >= MIN_VOTES_TO_DECIDE and phase['end'] == 0: closePhase(phase['pk'], unixtime(datetime.now()), db) decideVote(phase['phase_list'], db) except: logging.exception("couldn't insert into the database")
def locationPing(request): request.content_type = "application/json" db = DBConnection(autocommit = False) start = datetime.now() try: (phase, assignment, location, video_id) = getArgs(request) servertime = unixtime(datetime.now()) # logging.debug("Location %s for video %s on phase %s" % (location, video_id, phase)) cur_phase = getMostRecentPhase(video_id, db) # Ensure that there isn't already a newer phase that # we should be returning to the client if cur_phase['phase'] != phase: request.write(json.dumps(cur_phase, cls=DecimalEncoder)) else: # Record where we are pushLocation(location, phase, assignment, video_id, servertime, db) # Has the phase already converged? (i.e., too small to be divisible) (is_new_phase, new_min, new_max) = compareLocations(cur_phase, servertime, db) if is_new_phase: closePhase(cur_phase['phase'], servertime, False, db) # Agreement! Create a new phase. new_phase = createPhase(video_id, new_min, new_max, servertime, cur_phase['phase_list'], db) logging.debug("Creating new phase: %s" % new_phase) if not phaseIsDivisible(new_phase): logging.debug("Picture has converged!") closePhase(new_phase['phase'], servertime, False, db) takePicture(new_phase, video_id, db) request.write(json.dumps(new_phase, cls=DecimalEncoder)) else: request.write(json.dumps(cur_phase, cls=DecimalEncoder)) db.commit() except Exception, e: db.rollback() logging.exception(e) raise
def getRandomVideo(request): request.content_type = "application/json" form = util.FieldStorage(request) assignmentid = form['assignmentid'].value is_slow = False if form.has_key('slow') and form['slow'] == "1": is_slow = True videoid = None db = DBConnection() if form.has_key('videoid'): videoid = int(form['videoid'].value) else: if not is_slow: # are there any videos with incomplete phases that we can join? # grab the most recently touched one sql = """ SELECT videoid FROM phases, phase_lists WHERE end IS NULL AND is_abandoned = 0 AND start >= %s AND phases.phase_list = phase_lists.pk ORDER BY start DESC LIMIT 1 """ max_age = unixtime(datetime.now() - timedelta( seconds=location_ping.PHASE_MAX_AGE_IN_SECONDS)) unfinished_phases = db.query_and_return_array(sql, (max_age, )) if len(unfinished_phases) > 0: videoid = unfinished_phases[0]['videoid'] if is_slow or videoid is None: # TODO: this will not scale once we have over ~10,000 rows logging.debug("Getting random video") #videoid = db.query_and_return_array("""SELECT pk FROM videos LEFT JOIN study_videos ON videos.pk = study_videos.videoid WHERE study_videos.videoid IS NULL ORDER BY RAND() LIMIT 1""")[0]['pk'] videoid = db.query_and_return_array( """SELECT pictures.videoid FROM `phase_lists`, pictures WHERE pictures.phase_list = phase_lists.pk AND is_historical = 0 ORDER BY RAND() LIMIT 1""" )[0]['videoid'] video_json = ready.getAndAssignVideo(assignmentid, videoid, db) logging.debug(video_json) request.write(json.dumps(video_json, cls=location_ping.DecimalEncoder))