def create_testdata(challenges=10, tasks=100, users=10): """Creates test data in the database""" import uuid import random from maproulette import db from maproulette.models import User, Challenge, Task, TaskGeometry, Action from shapely.geometry import Point, LineString, box # statuses to use statuses = ['available', 'skipped', 'fixed', 'deleted', 'alreadyfixed', 'falsepositive'] # challenge default strings challenge_help_test = "Sample challenge *help* text" challenge_instruction_test = "Challenge instruction text" task_instruction_text = "Task instruction text" # delete old tasks and challenges db.session.query(TaskGeometry).delete() db.session.query(Action).delete() db.session.query(Task).delete() db.session.query(Challenge).delete() db.session.query(User).delete() db.session.commit() # create users for uid in range(int(users)): user = User() user.id = uid user.display_name = 'Test User {uid}'.format(uid=uid) db.session.add(user) db.session.commit() # create ten challenges for i in range(1, int(challenges) + 1): print "Generating Test Challenge #%d" % i minx = -120 maxx = -40 miny = 20 maxy = 50 challengepoly = None slug = "test%d" % i title = "Test Challenge %d" % i challenge = Challenge(slug, title) challenge.difficulty = random.choice([1, 2, 3]) challenge.active = True challenge.blurb = "This is test challenge number %d" % i challenge.description = "This describes challenge %d in detail" % i challenge.help = challenge_help_test challenge.instruction = challenge_instruction_test # have bounding boxes for all but the first two challenges. if i > 2: minx = random.randrange(-120, -40) miny = random.randrange(20, 50) maxx = minx + 1 maxy = miny + 1 challengepoly = box(minx, miny, maxx, maxy) print "\tChallenge has a bounding box of ", challengepoly challenge.polygon = challengepoly db.session.add(challenge) # add some tasks to the challenge print "\tGenerating %i tasks for challenge %i" % (int(tasks), i) # generate NUM_TASKS random tasks for j in range(int(tasks)): # generate a unique identifier identifier = str(uuid.uuid4()) # create two random points not too far apart task_geometries = [] p1 = Point( random.randrange(minx, maxx) + random.random(), random.randrange(miny, maxy) + random.random()) p2 = Point( p1.x + (random.random() * random.choice((1, -1)) * 0.01), p1.y + (random.random() * random.choice((1, -1)) * 0.01)) # create a linestring connecting the two points # no constructor for linestring from points? l1 = LineString([(p1.x, p1.y), (p2.x, p2.y)]) # add the first point and the linestring to the task's geometries task_geometries.append(TaskGeometry(p1)) # set a linestring for every other challenge if not j % 2: task_geometries.append(TaskGeometry(l1)) # instantiate the task and register it with challenge 'test' # Initialize a task with its challenge slug and persistent ID task = Task(challenge.slug, identifier, task_geometries) # because we are not using the API, we need to call set_location # explicitly to set the task's location task.set_location() # generate random string for the instruction task.instruction = task_instruction_text # set a status action = Action(random.choice(statuses), user_id=random.choice(range(int(users)))) task.append_action(action) # add the task to the session db.session.add(task) # commit the generated tasks and the challenge to the database. db.session.commit()
def retrieve_osm_data(): """Get and store the user data from OSM""" # FIXME this is a messy function. data = osm.get('user/details').data app.logger.debug("getting user data from osm") if not data: # FIXME this requires handling return False userxml = data.find('user') osmid = userxml.attrib['id'] # query for existing user if bool(User.query.filter(User.id == osmid).count()): app.logger.debug('user exists, getting from database') user = User.query.filter(User.id == osmid).first() else: app.logger.debug('user is new, create local account') user = User() user.id = osmid user.display_name = userxml.attrib['display_name'] user.osm_account_created = userxml.attrib['account_created'] homexml = userxml.find('home') if homexml is not None: lon = float(homexml.attrib['lon']) # this is to work around a bug in OSM where the set user longitude # can be outside of the -180 ... 180 range if the user panned the # map across the 180 / -180 meridian lon = abs(lon) % 180 * (lon / abs(lon)) lat = homexml.attrib['lat'] user.home_location = WKTElement('POINT(%s %s)' % (lon, lat)) app.logger.debug('setting user home location') else: app.logger.debug('no home for this user') # languages = userxml.find('languages') # FIXME parse languages and add to user.languages string field user.changeset_count = userxml.find('changesets').attrib['count'] # get last changeset info changesetdata = get_latest_changeset(user.id) try: lastchangeset = changesetdata.find('changeset') if 'min_lon' in lastchangeset.attrib: wktbbox = 'POLYGON((%s %s, %s %s, %s %s, %s %s, %s %s))' % ( lastchangeset.attrib['min_lon'], lastchangeset.attrib['min_lat'], lastchangeset.attrib['min_lon'], lastchangeset.attrib['max_lat'], lastchangeset.attrib['max_lon'], lastchangeset.attrib['max_lat'], lastchangeset.attrib['max_lon'], lastchangeset.attrib['min_lat'], lastchangeset.attrib['min_lon'], lastchangeset.attrib['min_lat']) user.last_changeset_bbox = WKTElement(wktbbox) user.last_changeset_date = lastchangeset.attrib['created_at'] user.last_changeset_id = lastchangeset.attrib['id'] except: app.logger.debug('could not get changeset data from OSM') db.session.add(user) db.session.commit() app.logger.debug('user created') # we need to convert the GeoAlchemy object to something picklable if user.home_location is not None: point = to_shape(user.home_location) session['home_location'] = [point.x, point.y] or None session['display_name'] = user.display_name app.logger.debug('session now has display name: %s' % (session['display_name'])) session['osm_id'] = user.id session['difficulty'] = user.difficulty
def retrieve_osm_data(): """Get and store the user data from OSM""" # FIXME this is a messy function. data = osm.get('user/details').data app.logger.debug('received data: {}'.format(data)) if not data or not data.find('user'): app.logger.debug('could not authenticate user') return False userxml = data.find('user') osmid = userxml.attrib['id'] # query for existing user if bool(User.query.filter(User.id == osmid).count()): app.logger.debug('user exists, getting from database') user = User.query.filter(User.id == osmid).first() else: app.logger.debug('user is new, create local account') user = User() user.id = osmid user.display_name = userxml.attrib['display_name'] user.osm_account_created = userxml.attrib['account_created'] homexml = userxml.find('home') if homexml is not None: lon = float(homexml.attrib['lon']) # this is to work around a bug in OSM where the set user longitude # can be outside of the -180 ... 180 range if the user panned the # map across the 180 / -180 meridian lon = abs(lon) % 180 * (lon / abs(lon)) lat = homexml.attrib['lat'] user.home_location = WKTElement( 'POINT(%s %s)' % (lon, lat)) app.logger.debug('setting user home location') else: app.logger.debug('no home for this user') # languages = userxml.find('languages') # FIXME parse languages and add to user.languages string field user.changeset_count = userxml.find('changesets').attrib['count'] # get last changeset info changesetdata = get_latest_changeset(user.id) try: lastchangeset = changesetdata.find('changeset') if 'min_lon' in lastchangeset.attrib: wktbbox = 'POLYGON((%s %s, %s %s, %s %s, %s %s, %s %s))' % ( lastchangeset.attrib['min_lon'], lastchangeset.attrib['min_lat'], lastchangeset.attrib['min_lon'], lastchangeset.attrib['max_lat'], lastchangeset.attrib['max_lon'], lastchangeset.attrib['max_lat'], lastchangeset.attrib['max_lon'], lastchangeset.attrib['min_lat'], lastchangeset.attrib['min_lon'], lastchangeset.attrib['min_lat']) user.last_changeset_bbox = WKTElement(wktbbox) user.last_changeset_date = lastchangeset.attrib['created_at'] user.last_changeset_id = lastchangeset.attrib['id'] except: app.logger.debug('could not get changeset data from OSM') db.session.add(user) db.session.commit() app.logger.debug('user created') # we need to convert the GeoAlchemy object to something picklable if user.home_location is not None: point = to_shape(user.home_location) session['home_location'] = [point.x, point.y] or None session['display_name'] = user.display_name app.logger.debug('session now has display name: %s' % (session['display_name'])) session['osm_id'] = user.id session['difficulty'] = user.difficulty
def create_testdata(challenges=10, tasks=100, users=10): """Creates test data in the database""" import uuid import random from maproulette import db from maproulette.models import User, Challenge, Task, TaskGeometry, Action from shapely.geometry import Point, LineString, box # statuses to use statuses = ['available', 'skipped', 'fixed', 'deleted', 'alreadyfixed', 'falsepositive'] # challenge default strings challenge_help_test = "Sample challenge *help* text" challenge_instruction_test = "Challenge instruction text" task_instruction_text = "Task instruction text" # delete old tasks and challenges db.session.query(TaskGeometry).delete() db.session.query(Action).delete() db.session.query(Task).delete() db.session.query(Challenge).delete() db.session.query(User).delete() db.session.commit() # create users for uid in range(int(users)): user = User() user.id = uid user.display_name = 'Test User {uid}'.format(uid=uid) db.session.add(user) db.session.commit() # create ten challenges for i in range(1, int(challenges) + 1): print "Generating Test Challenge #%d" % i minx = -120 maxx = -40 miny = 20 maxy = 50 challengepoly = None slug = "test%d" % i title = "Test Challenge %d" % i challenge = Challenge(slug, title) challenge.difficulty = random.choice([1, 2, 3]) challenge.active = True challenge.blurb = "This is test challenge number %d" % i challenge.description = "This describes challenge %d in detail" % i challenge.help = challenge_help_test challenge.instruction = challenge_instruction_test # have bounding boxes for all but the first two challenges. if i > 2: minx = random.randrange(-120, -40) miny = random.randrange(20, 50) maxx = minx + 1 maxy = miny + 1 challengepoly = box(minx, miny, maxx, maxy) print "\tChallenge has a bounding box of ", challengepoly challenge.polygon = challengepoly db.session.add(challenge) # add some tasks to the challenge print "\tGenerating %i tasks for challenge %i" % (int(tasks), i) # generate NUM_TASKS random tasks for j in range(int(tasks)): # generate a unique identifier identifier = str(uuid.uuid4()) # create two random points not too far apart task_geometries = [] p1 = Point( random.randrange(minx, maxx) + random.random(), random.randrange(miny, maxy) + random.random()) p2 = Point( p1.x + (random.random() * random.choice((1, -1)) * 0.01), p1.y + (random.random() * random.choice((1, -1)) * 0.01)) # create a linestring connecting the two points # no constructor for linestring from points? l1 = LineString([(p1.x, p1.y), (p2.x, p2.y)]) # generate some random 'osm ids' osmids = [random.randrange(1000000, 1000000000) for _ in range(2)] # add the first point and the linestring to the task's geometries task_geometries.append(TaskGeometry(osmids[0], p1)) # set a linestring for every other challenge if not j % 2: task_geometries.append(TaskGeometry(osmids[1], l1)) # instantiate the task and register it with challenge 'test' # Initialize a task with its challenge slug and persistent ID task = Task(challenge.slug, identifier, task_geometries) # because we are not using the API, we need to call set_location # explicitly to set the task's location task.set_location() # generate random string for the instruction task.instruction = task_instruction_text # set a status action = Action(random.choice(statuses), user_id=random.choice(range(int(users)))) task.append_action(action) # add the task to the session db.session.add(task) # commit the generated tasks and the challenge to the database. db.session.commit()