def testQueryUnclassifiedSectionsLowConfidence(self): from dao.user import User fakeEmail = "[email protected]" client = Client("testclient") client.update(createKey = False) tests.common.makeValid(client) (resultPre, resultReg) = client.preRegister("this_is_the_super_secret_id", fakeEmail) self.assertEqual(resultPre, 0) self.assertEqual(resultReg, 1) user = User.fromEmail(fakeEmail) self.assertEqual(user.getFirstStudy(), 'testclient') queriedUnclassifiedSections = tripManager.queryUnclassifiedSections(User.fromEmail(fakeEmail).uuid) self.assertEqual(queriedUnclassifiedSections.count(), 2) # Set the auto_confirmed values for the trips for section in queriedUnclassifiedSections: print section['_id'] self.SectionsColl.update({'_id': section['_id']}, {'test_auto_confirmed': {'mode': section['mode'], 'prob': 0.95}}) # Now, set the update timestamp to two weeks ago so that we will start filtering tests.common.updateUserCreateTime(user.uuid) queriedUnclassifiedSections = tripManager.queryUnclassifiedSections(User.fromEmail(fakeEmail).uuid) self.assertEqual(queriedUnclassifiedSections.count(), 0)
def testChangeUpdateTs(self): from datetime import datetime, timedelta user = User.register('[email protected]') self.assertTrue(User.isRegistered('[email protected]')) user.changeUpdateTs(timedelta(days = -20)) self.assertEqual((datetime.now() - user.getUpdateTS()).days, 20)
def testQueryUnclassifiedSectionsWeekAgo(self): # Add some old sections that shouldn't be returned by the query # This one is just over a week old old_sec_1 = self.SectionsColl.find_one({'$and': [{'user_id': User.fromEmail('[email protected]').uuid}, {'type':'move'}, {'mode':1}]}) old_sec_1['_id'] = 'old_sec_1' old_sec_1['section_start_datetime'] = self.weekago - timedelta(minutes = 30) old_sec_1['section_end_datetime'] = self.weekago - timedelta(minutes = 5) logging.debug("Inserting old_sec_1 %s" % old_sec_1) self.SectionsColl.insert(old_sec_1) # This one is a month old monthago = self.now - timedelta(days = 30) old_sec_2 = self.SectionsColl.find_one({'$and': [{'user_id':User.fromEmail('[email protected]').uuid}, {'type':'move'}, {'mode':4}]}) old_sec_2['_id'] = 'old_sec_2' old_sec_2['section_start_datetime'] = monthago - timedelta(minutes = 30) old_sec_2['section_end_datetime'] = monthago - timedelta(minutes = 5) logging.debug("Inserting old_sec_2 %s" % old_sec_2) self.SectionsColl.insert(old_sec_2) # This one is missing the predicted mode monthago = self.now - timedelta(days = 30) un_pred_sec = self.SectionsColl.find_one({'$and': [{'user_id':User.fromEmail('[email protected]').uuid}, {'type':'move'}, {'mode':4}]}) un_pred_sec['_id'] = 'un_pred_sec' del un_pred_sec['predicted_mode'] logging.debug("Inserting un_pred_sec %s" % un_pred_sec) self.SectionsColl.insert(un_pred_sec) queriedUnclassifiedSections = tripManager.queryUnclassifiedSections(User.fromEmail('[email protected]').uuid) self.assertEqual(queriedUnclassifiedSections.count(), 2)
def testClientSpecificPrecompute(self): for email in self.testUsers: currUser = User.fromEmail(email) self.assertEqual(currUser.getProfile().get("testfield1"), None) self.assertEqual(currUser.getProfile().get("testfield2"), None) self.assertEqual(data.getCarbonFootprint(currUser), None) fakeEmail = "[email protected]" client = Client("testclient") client.update(createKey = False) tests.common.makeValid(client) (resultPre, resultReg) = client.preRegister("this_is_the_super_secret_id", fakeEmail) user = User.fromEmail(fakeEmail) self.assertEqual(user.getFirstStudy(), 'testclient') self.pr.precomputeResults() self.assertEqual(user.getProfile()['testfield1'], 'value1') self.assertEqual(user.getProfile()['testfield2'], 'value2') for email in self.testUsers: if email != fakeEmail: currUser = User.fromEmail(email) carbonFootprint = data.getCarbonFootprint(currUser) self.assertEqual(len(carbonFootprint), 12)
def setUp(self): self.testUsers = ["[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]"] self.serverName = 'localhost' # Sometimes, we may have entries left behind in the database if one of the tests failed # or threw an exception, so let us start by cleaning up all entries tests.common.dropAllCollections(get_db()) self.ModesColl = get_mode_db() # self.ModesColl.remove() self.assertEquals(self.ModesColl.find().count(), 0) self.SectionsColl = get_section_db() # self.SectionsColl.remove() self.assertEquals(self.SectionsColl.find().count(), 0) load_database_json.loadTable(self.serverName, "Stage_Modes", "tests/data/modes.json") load_database_json.loadTable(self.serverName, "Stage_Sections", "tests/data/testCarbonFile") # Let's make sure that the users are registered so that they have profiles for userEmail in self.testUsers: User.register(userEmail) self.walkExpect = 1057.2524056424411 self.busExpect = 2162.668467546699 self.busCarbon = 267.0/1609 self.now = datetime.now() self.dayago = self.now - timedelta(days=1) self.weekago = self.now - timedelta(weeks = 1) tests.common.updateSections(self)
def testGetFirstStudy(self): user = User.register('[email protected]') self.assertTrue(User.isRegistered('[email protected]')) client = Client("testclient") client.update(createKey = False) common.makeValid(client) (resultPre, resultReg) = client.preRegister("this_is_the_super_secret_id", "[email protected]") self.assertEqual(resultPre, 0) self.assertEqual(resultReg, 1) user = User.fromEmail('[email protected]') self.assertEqual(user.getFirstStudy(), 'testclient')
def testSetClientSpecificFields(self): user = User.register('[email protected]') self.assertTrue(User.isRegistered('[email protected]')) # Check that the field doesn't exist initially self.assertTrue(user.getProfile().get('test_field', 'blank'), 'blank') # Check that a simple value update works user.setClientSpecificProfileFields({'test_field': 'something beautiful'}) self.assertTrue(user.getProfile().get('test_field', 'blank'), 'something beautiful') # Check that a data structure update works user.setClientSpecificProfileFields({'test_field': {'something': 'beautiful'}}) self.assertTrue(user.getProfile().get('test_field', 'blank'), {'something': 'beautiful'})
def getScoreComponents(user_uuid, start, end): # The score is based on the following components: # - Percentage of trips classified. We are not auto-classifying high # confidence trips, so don't need to handle those here user = User.fromUUID(user_uuid) pctClassified = common.getClassifiedRatio(user_uuid, start, end) (myModeShareCount, avgModeShareCount, myModeShareDistance, avgModeShareDistance, myModeCarbonFootprint, avgModeCarbonFootprint, myModeCarbonFootprintNoLongMotorized, avgModeCarbonFootprintNoLongMotorized, myOptimalCarbonFootprint, avgOptimalCarbonFootprint, myOptimalCarbonFootprintNoLongMotorized, avgOptimalCarbonFootprintNoLongMotorized) = carbon.getFootprintCompareForRange(user.uuid, start, end) carbon.delLongMotorizedModes(myModeShareDistance) myAllDrive = carbon.getAllDrive(user.uuid, myModeShareDistance) myCarbonFootprintSum = sum(myModeCarbonFootprintNoLongMotorized.values()) myOptimalFootprintSum = sum(myOptimalCarbonFootprintNoLongMotorized.values()) logging.debug("myCarbonFootprintSum = %s, myOptimalFootprintSum = %s, myAllDrive = %s" % (myCarbonFootprintSum, myOptimalFootprintSum, myAllDrive)) handleZero = lambda x, y: 0 if y == 0 else float(x)/y components = [pctClassified, handleZero(myCarbonFootprintSum - myOptimalFootprintSum, myOptimalFootprintSum), handleZero(myAllDrive - myCarbonFootprintSum, myAllDrive), handleZero(sb375DailyGoal - myCarbonFootprintSum, sb375DailyGoal)] return components
def setUp(self): import tests.common # Sometimes, we may have entries left behind in the database if one of the tests failed # or threw an exception, so let us start by cleaning up all entries tests.common.dropAllCollections(get_db()) user = User.register("[email protected]") self.uuid = user.uuid
def getResult(user_uuid): # This is in here, as opposed to the top level as recommended by the PEP # because then we don't have to worry about loading bottle in the unit tests from bottle import template user = User.fromUUID(user_uuid) currFootprint = getCarbonFootprint(user) if currFootprint is None: currFootprint = carbon.getFootprintCompare(user_uuid) setCarbonFootprint(user, currFootprint) (myModeShareCount, avgModeShareCount, myModeShareDistance, avgModeShareDistance, myModeCarbonFootprint, avgModeCarbonFootprint, myModeCarbonFootprintNoLongMotorized, avgModeCarbonFootprintNoLongMotorized, # ignored myOptimalCarbonFootprint, avgOptimalCarbonFootprint, myOptimalCarbonFootprintNoLongMotorized, avgOptimalCarbonFootprintNoLongMotorized) = currFootprint renderedTemplate = template("clients/data/result_template.html", myModeShareCount = json.dumps(myModeShareCount), avgModeShareCount = json.dumps(avgModeShareCount), myModeShareDistance = json.dumps(myModeShareDistance), avgModeShareDistance = json.dumps(avgModeShareDistance), myModeCarbonFootprint = json.dumps(myModeCarbonFootprint), avgModeCarbonFootprint = json.dumps(avgModeCarbonFootprint), myOptimalCarbonFootprint = json.dumps(myOptimalCarbonFootprint), avgOptimalCarbonFootprint = json.dumps(avgOptimalCarbonFootprint)) # logging.debug(renderedTemplate) return renderedTemplate
def testUnsetStudyExists(self): user = User.register('[email protected]') user.setStudy('testclient') self.assertEquals(userclient.countForStudy('testclient'), 1) user.unsetStudy('testclient') self.assertEquals(userclient.countForStudy('testclient'), 0)
def runBackgroundTasksForDay(user_uuid, today): today_dt = datetime.combine(today, time.max) user = User.fromUUID(user_uuid) # carbon compare results is a tuple. Tuples are converted to arrays # by mongodb # In [44]: testUser.setScores(('a','b', 'c', 'd'), ('s', 't', 'u', 'v')) # In [45]: testUser.getScore() # Out[45]: ([u'a', u'b', u'c', u'd'], [u's', u't', u'u', u'v']) weekago = today_dt - timedelta(days=7) carbonCompareResults = carbon.getFootprintCompareForRange(user_uuid, weekago, today_dt) setCarbonFootprint(user, carbonCompareResults) (myModeShareCount, avgModeShareCount, myModeShareDistance, avgModeShareDistance, myModeCarbonFootprint, avgModeCarbonFootprint, myModeCarbonFootprintNoLongMotorized, avgModeCarbonFootprintNoLongMotorized, # ignored myOptimalCarbonFootprint, avgOptimalCarbonFootprint, myOptimalCarbonFootprintNoLongMotorized, avgOptimalCarbonFootprintNoLongMotorized) = carbonCompareResults # We only compute server stats in the background, because including them in # the set call means that they may be invoked when the user makes a call and # the cached value is None, which would potentially slow down user response time msNow = systime.time() stats.storeResultEntry(user_uuid, stats.STAT_MY_CARBON_FOOTPRINT, msNow, getCategorySum(myModeCarbonFootprint)) stats.storeResultEntry(user_uuid, stats.STAT_MY_CARBON_FOOTPRINT_NO_AIR, msNow, getCategorySum(myModeCarbonFootprintNoLongMotorized)) stats.storeResultEntry(user_uuid, stats.STAT_MY_OPTIMAL_FOOTPRINT, msNow, getCategorySum(myOptimalCarbonFootprint)) stats.storeResultEntry(user_uuid, stats.STAT_MY_OPTIMAL_FOOTPRINT_NO_AIR, msNow, getCategorySum(myOptimalCarbonFootprintNoLongMotorized)) stats.storeResultEntry(user_uuid, stats.STAT_MY_ALLDRIVE_FOOTPRINT, msNow, getCategorySum(myModeShareDistance) * (278.0/(1609 * 1000))) stats.storeResultEntry(user_uuid, stats.STAT_MEAN_FOOTPRINT, msNow, getCategorySum(avgModeCarbonFootprint)) stats.storeResultEntry(user_uuid, stats.STAT_MEAN_FOOTPRINT_NO_AIR, msNow, getCategorySum(avgModeCarbonFootprintNoLongMotorized))
def testCarbonFootprintStore(self): user = User.fromUUID(self.uuid) # Tuple of JSON objects, similar to the real footprint dummyCarbonFootprint = ({'myModeShareCount': 10}, {'avgModeShareCount': 20}) self.assertEquals(data.getCarbonFootprint(user), None) data.setCarbonFootprint(user, dummyCarbonFootprint) # recall that pymongo converts tuples to lists somewhere down the line self.assertEquals(data.getCarbonFootprint(user), list(dummyCarbonFootprint))
def getCurrView(uuid): user = User.fromUUID(uuid) profile = user.getProfile() if profile is None: logging.debug("profile is None, returning data") return "data" logging.debug("profile.get('curr_view', 'dummy') is %s" % profile.get("curr_view", "data")) return profile.get("curr_view", "data")
def testMergeDict(self): dict1 = {'a': 'a1', 'b': 'b1', 'c': 'c1'} dict2 = {'d': 'd2', 'b': 'b2', 'c': 'c2'} mergedDict = User.mergeDicts(dict1, dict2) self.assertEqual(len(mergedDict), 4) self.assertEqual(mergedDict['a'], 'a1') self.assertEqual(mergedDict, {'a': 'a1', 'b': 'b2', 'c': 'c2', 'd': 'd2'})
def testRegisterExistingUser(self): user = User.register('[email protected]') self.assertEquals(user.getStudy(), []) client = Client("testclient") client.update(createKey = False) common.makeValid(client) (resultPre, resultReg) = client.preRegister("this_is_the_super_secret_id", "[email protected]") self.assertEqual(resultPre, 0) self.assertEqual(resultReg, 1) user = User.fromEmail("[email protected]") self.assertEquals(user.getStudy(), ['testclient']) # Here's the key difference, now register again user = User.register('[email protected]') self.assertEquals(user.getStudy(), ['testclient'])
def setUp(self): # Sometimes, we may have entries left behind in the database if one of the tests failed # or threw an exception, so let us start by cleaning up all entries tests.common.dropAllCollections(get_db()) user = User.register("[email protected]") self.uuid = user.uuid self.serverName = "localhost" self.now = datetime.now() self.dayago = self.now - timedelta(days=1) self.weekago = self.now - timedelta(weeks = 1)
def getResult(user_uuid): # This is in here, as opposed to the top level as recommended by the PEP # because then we don't have to worry about loading bottle in the unit tests from bottle import template (prevScore, currScore) = getStoredScore(User.fromUUID(user_uuid)) (level, sublevel) = getLevel(currScore) otherCurrScoreList = [] for user_uuid_dict in get_uuid_db().find({}, {'uuid': 1, '_id': 0}): (currPrevScore, currCurrScore) = getStoredScore(User.fromUUID(user_uuid_dict['uuid'])) otherCurrScoreList.append(currCurrScore) otherCurrScoreList.sort() renderedTemplate = template("clients/leaderboard/result_template.html", level_picture_filename = getFileName(level, sublevel), prevScore = prevScore, currScore = currScore, otherCurrScoreList = otherCurrScoreList) return renderedTemplate
def testRegisterStudyUser(self): client = Client("testclient") client.update(createKey = False) common.makeValid(client) (resultPre, resultReg) = client.preRegister("this_is_the_super_secret_id", "[email protected]") self.assertEqual(resultPre, 1) self.assertEqual(resultReg, 0) user = User.register('[email protected]') self.assertEquals(user.getStudy(), ['testclient'])
def loadMovesInputFile(userEmail, fileName): from dao.user import User user = User.fromEmail(userEmail) savedTokens = auth.getAccessToken(user.uuid) print savedTokens if len(savedTokens) == 0: auth.saveAccessToken(sampleAuthMessage, user.uuid) result = json.load(open(fileName)) print json.dumps(result) collect.processResult(user.uuid, result)
def testGetSettingsCustomUser(self): client = Client("testclient") client.update(createKey = False) common.makeValid(client) (resultPre, resultReg) = client.preRegister("this_is_the_super_secret_id", "[email protected]") self.assertEqual(resultPre, 1) self.assertEqual(resultReg, 0) user = User.register('[email protected]') self.assertRegexpMatches(user.getSettings()['result_url'], ".*/test/test/test")
def testRunBackgroundTasksForDay(self): self.testUsers = ["[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]"] load_database_json.loadTable(self.serverName, "Stage_Modes", "tests/data/modes.json") load_database_json.loadTable(self.serverName, "Stage_Sections", "tests/data/testCarbonFile") # Let's make sure that the users are registered so that they have profiles for userEmail in self.testUsers: User.register(userEmail) self.SectionsColl = get_section_db() tests.common.updateSections(self) self.assertNotEqual(len(self.uuid_list), 0) # Can access the zeroth element because we know that then length is greater than zero # (see above) test_uuid = self.uuid_list[0] test_user = User.fromUUID(test_uuid) self.assertNotIn('carbon_footprint', test_user.getProfile().keys()) data.runBackgroundTasks(test_user.uuid) self.assertIn('carbon_footprint', test_user.getProfile().keys())
def setUp(self): self.testUsers = ["[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]"] self.serverName = 'localhost' # Sometimes, we may have entries left behind in the database if one of the tests failed # or threw an exception, so let us start by cleaning up all entries tests.common.dropAllCollections(get_db()) self.ModesColl = get_mode_db() self.assertEquals(self.ModesColl.find().count(), 0) self.SectionsColl = get_section_db() self.assertEquals(self.SectionsColl.find().count(), 0) load_database_json.loadTable(self.serverName, "Stage_Modes", "tests/data/modes.json") load_database_json.loadTable(self.serverName, "Stage_Sections", "tests/data/testModeInferFile") # Let's make sure that the users are registered so that they have profiles for userEmail in self.testUsers: User.register(userEmail) self.now = datetime.now() self.dayago = self.now - timedelta(days=1) self.weekago = self.now - timedelta(weeks = 1) for section in self.SectionsColl.find(): section['section_start_datetime'] = self.dayago section['section_end_datetime'] = self.dayago + timedelta(hours = 1) if (section['confirmed_mode'] == 5): # We only cluster bus and train trips # And our test data only has bus trips section['section_start_point'] = {u'type': u'Point', u'coordinates': [-122.270039042, 37.8800285728]} section['section_end_point'] = {u'type': u'Point', u'coordinates': [-122.2690412952, 37.8739578595]} # print("Section start = %s, section end = %s" % # (section['section_start_datetime'], section['section_end_datetime'])) # Replace the user email with the UUID section['user_id'] = User.fromEmail(section['user_id']).uuid self.SectionsColl.save(section) self.pr = precompute_results.PrecomputeResults()
def loadMovesInputFile(userEmail, fileName): # load_database_json.loadTable("localhost", "Test_Groups", "tests/data/groups.json") # load_database_json.loadTable("localhost", "Test_Modes", "tests/data/modes.json") from dao.user import User user = User.fromEmail(userEmail) savedTokens = auth.getAccessToken(user.uuid) print savedTokens if len(savedTokens) == 0: auth.saveAccessToken(sampleAuthMessage, user.uuid) result = json.load(open(fileName)) print json.dumps(result) collect.processResult(user.uuid, result)
def getResult(user_uuid): # This is in here, as opposed to the top level as recommended by the PEP # because then we don't have to worry about loading bottle in the unit tests from bottle import template (prevScore, currScore) = getStoredScore(User.fromUUID(user_uuid)) (level, sublevel) = getLevel(currScore) renderedTemplate = template("clients/gamified/result_template.html", level_picture_filename = getFileName(level, sublevel), prevScore = prevScore, currScore = currScore) return renderedTemplate
def createUserProfile(): logging.debug("Called createUserProfile") userToken = request.json['user'] # This is the only place we should use the email, since we may not have a # UUID yet. All others should only use the UUID. if skipAuth: userEmail = userToken else: userEmail = verifyUserToken(userToken) logging.debug("userEmail = %s" % userEmail) user = User.register(userEmail) logging.debug("Looked up user = %s" % user) logging.debug("Returning result %s" % {'uuid': str(user.uuid)}) return {'uuid': str(user.uuid)}
def testGetUnclassifiedSectionsFiltered(self): """ Tests that queryUnclassifiedSections never returns a section with section['retained'] == False. A section is only returned if section['retained'] == True and all other query conditions are met """ # Clear previous Stage_Sections data and load new data # specific to filtering self.SectionsColl.remove() load_database_json.loadTable(self.serverName, "Stage_Sections", "tests/data/testFilterFile") tests.common.updateSections(self) # Extra updates to Sections necessary for testing filtering for section in self.SectionsColl.find(): section['section_start_point'] = "filler start point" section['section_end_point'] = "filler end point" self.SectionsColl.save(section) from dao.user import User fakeEmail = "[email protected]" client = Client("testclient") client.update(createKey = False) tests.common.makeValid(client) (resultPre, resultReg) = client.preRegister("this_is_the_super_secret_id", fakeEmail) self.assertEqual(resultPre, 0) self.assertEqual(resultReg, 1) user = User.fromEmail(fakeEmail) self.assertEqual(user.getFirstStudy(), 'testclient') unclassifiedSections = tripManager.getUnclassifiedSections(User.fromEmail(fakeEmail).uuid)['sections'] # Check that of the valid sections in the testFilterFile (2/3), only one of them is returned by the query self.assertEqual(len(unclassifiedSections), 1) # Check that the second entry in the testFilterFile is the only section # that is loaded into the database self.assertEqual('20140401T095742-0700',unclassifiedSections[0]['trip_id'])
def __preRegister(self, userEmail): from dao.user import User from main import userclient if User.isRegistered(userEmail): User.fromEmail(userEmail).setStudy(self.clientName) else: pendingDoc = { 'user_email': userEmail, 'study': self.clientName, 'last_update': datetime.now()} # Should I do insert or upsert here? If a user has pre-registered for one # study and then pre-registers for another study before registering, do we # want to throw an error or just update silently? # Update silently for now writeResult = get_pending_signup_db().update({'user_email': userEmail}, pendingDoc, upsert=True) print 'in __preRegister, writeResult = %s' % writeResult if 'err' in writeResult and writeResult['err'] is not None: e = Exception() e.code = writeResult['err'][0]["code"] e.msg = writeResult['err'][0]["errmsg"] raise e return (get_pending_signup_db().find({'study': self.clientName}).count(), userclient.countForStudy(self.clientName))
def load_config(config_json): """ Loads the specified config file into the specified user cache. If there is an existing entry with the same key in the cache, it will be overwritten. If there is no existing entry with the same key in the cache, an entry will be inserted. """ for entry in config_json: userEmail = entry['userEmail'] userObj = User.fromEmail(userEmail) if userObj is None: print "user with email %s is not found, ignoring...." % userEmail else: uc = ucauc.UserCache.getUserCache(userObj.uuid) key = entry['key'] value = entry['value'] uc.putDocument(key, value) print "successfully loaded key %s for user %s" % (key, userEmail)
def getSectionFilter(uuid): from dao.user import User from datetime import datetime, timedelta logging.info("testclient.getSectionFilter called for user %s" % uuid) # If this is the first two weeks, show everything user = User.fromUUID(uuid) # Note that this is the last time that the profile was updated. So if the # user goes to the "Auth" screen and signs in again, it will be updated, and # we will reset the clock. If this is not acceptable, we need to ensure that # we have a create ts that is never updated updateTS = user.getUpdateTS() if (datetime.now() - updateTS) < timedelta(days = 14): # In the first two weeks, don't do any filtering return [] else: return [{'test_auto_confirmed.prob': {'$lt': 0.9}}]