예제 #1
0
파일: validator.py 프로젝트: 3taps/geo
def validator(request):
    """Respond to the "/validator" URL.
    """
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW))

    # Display a "please wait" message while waiting for the results to be
    # calculated.

    if not pleasewait.shown(request):
        return pleasewait.message(request,
                                  "Whenua Admin",
                                  "Polygon Validator",
                                  "Validating location outlines, " +
                                  "please wait...")

    # Process each outline in turn.

    bad_locs = []

    for i,outline in enumerate(Outline.objects.all()):
        if i % 100 == 0:
            print "  %d" % i

        loc   = outline.location
        mpoly = outline.outline

        if mpoly == None: continue
        if is_geometry_valid(mpoly): continue

        fixed_polygon = fix_geometry(mpoly)
        if fixed_polygon != None:
            mpoly = wrap_geometry(fixed_polygon)
            if mpoly != None:
                outline.outline = mpoly
                outline.save()
            status = "Fixed"
        else:
            status = "Unable to fix"

        bad_locs.append({'level'  : loc.level.name,
                         'code'   : loc.code,
                         'name'   : loc.name,
                         'status' : status})

    # Finally, show the user the results of the validation.

    return render_to_response(
                        "polygon_editor/templates/validation_results.html",
                        {'bad_locs'       : bad_locs},
                        context_instance=RequestContext(request))
예제 #2
0
파일: views.py 프로젝트: 3taps/geo
def check(request):
    """ Respond to the "/check" URL.

        We display a "please wait" message while performing the sanity check,
        and then finally display the results back to the caller.
    """
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW))

    # Display a "please wait" message while waiting for the results to be
    # calculated.

    if not pleasewait.shown(request):
        return pleasewait.message(request,
                                  "Whenua Admin",
                                  "Location Sanity-Checker",
                                  "Checking locations, please wait...")

    # Get a connection to our database.

    cursor = connections['geo_shared'].cursor()

    # Load the list of Level records into memory.

    levelIDToNumber   = {} # Maps Level record ID to level number.
    levelNumberToName = {} # Maps Level number to name.

    for level in Level.objects.all():
        levelIDToNumber[level.id]      = level.level
        levelNumberToName[level.level] = level.name

    # Load the list of Location records into memory.

    locations = {} # Maps record ID to a (code, level_num, name, display_name)
                   # tuple.

    cursor.execute("SELECT id,code,level_id,name,display_name " +
                   "FROM shared_location")
    row = cursor.fetchone()
    while row != None:
        id,code,level_id,name,display_name = row

        level_num = levelIDToNumber[level_id]
        locations[id] = (code, level_num, name, display_name)

        row = cursor.fetchone()

    # Load the list of location parents into memory.

    location_parents = {} # Maps record ID to a set of parent record IDs.

    cursor.execute("SELECT from_location_id,to_location_id " +
                   "FROM shared_location_parents")
    row = cursor.fetchone()
    while row != None:
        from_loc_id,to_loc_id = row

        try:
            location_parents[from_loc_id].add(to_loc_id)
        except KeyError:
            location_parents[from_loc_id] = set([to_loc_id])

        row = cursor.fetchone()

    # Load the list of location children into memory.

    location_children = {} # Maps record ID to set of child record IDs.

    cursor.execute("SELECT from_location_id,to_location_id " +
                   "FROM shared_location_children")
    row = cursor.fetchone()
    while row != None:
        from_loc_id,to_loc_id = row

        try:
            location_children[from_loc_id].add(to_loc_id)
        except KeyError:
            location_children[from_loc_id] = set([to_loc_id])

        row = cursor.fetchone()

    # Load the list of location neighbours into memory.

    location_neighbours = {} # Maps record ID to set of neighbour record IDs.

    cursor.execute("SELECT from_location_id,to_location_id " +
                   "FROM shared_location_neighbors")
    row = cursor.fetchone()
    while row != None:
        from_loc_id,to_loc_id = row

        try:
            location_neighbours[from_loc_id].add(to_loc_id)
        except KeyError:
            location_neighbours[from_loc_id] = set([to_loc_id])

        row = cursor.fetchone()

    # Load the list of names into memory.

    names = {} # Maps record ID to name.

    cursor.execute("SELECT id,name FROM shared_name")
    row = cursor.fetchone()
    while row != None:
        id,name = row

        names[id] = name

        row = cursor.fetchone()

    # Load the list of names used by each location into memory.

    location_names = {} # Maps location record ID to set of name record IDs.

    cursor.execute("select location_id,name_id FROM shared_locationname")
    row = cursor.fetchone()
    while row != None:
        loc_id,name_id = row

        try:
            location_names[loc_id].add(name_id)
        except KeyError:
            location_names[loc_id] = set([name_id])

        row = cursor.fetchone()

    # Now that we've got all the information we need in memory, start looking
    # for potentially bad locations.

    bad_locs = [] # List of potentially bad locations.  Each list item is a
                  # dictionary with the following entries:
                  #
                  #     'code'
                  #
                  #         The location's code.
                  #
                  #     'level'
                  #
                  #         A descriptive name for this location's level
                  #
                  #     'name'
                  #
                  #         The name for this location.
                  #
                  #     'problem'
                  #
                  #         A string describing what was wrong with the
                  #         location.

    # Find any locations that aren't countries and lack parents.

    for loc_id in locations.keys():
        level_num = locations[loc_id][1]
        if level_num == 1: continue # ignore countries.

        if len(location_parents.get(loc_id, [])) == 0:
            # This location has no parents -> flag it as a bad location.
            code,level_num,name,display_name = locations[loc_id]
            bad_locs.append({'code'    : code,
                             'level'   : levelNumberToName[level_num],
                             'name'    : name,
                             'problem' : "lacks a parent"})

    # Find any locations which lack a name.

    for loc_id in locations.keys():
        level_num = locations[loc_id][1]
        if level_num == 8: continue # ZIP codes don't have names.

        if len(location_names.get(loc_id, [])) == 0:
            # This location has no name -> flag it as a bad location.
            code,level_num,name,display_name = locations[loc_id]
            bad_locs.append({'code'    : code,
                             'level'   : levelNumberToName[level_num],
                             'name'    : name,
                             'problem' : "has no names"})

    # Find any locations which have names ending or starting with a space.

    bad_name_ids = set() # Set of name IDs which have bad values.
    for name_id,name in names.items():
        badName = False
        if name.startswith(" "): badName = True
        if name.endswith(" "): badName = True

        if badName:
            bad_name_ids.add(name_id)

    for loc_id,name_ids_for_loc in location_names.items():
        for bad_name_id in name_ids_for_loc.intersection(bad_name_ids):
            code,level_num,name,display_name = locations[loc_id]
            bad_name = names[bad_name_id]
            bad_locs.append({'code'    : code,
                             'level'   : levelNumberToName[level_num],
                             'name'    : name,
                             'problem' : "has a name (" + bad_name + ") " +
                                         "starting or ending with a space"})

    # Find any locations which have been "disowned" by their parents.  That is,
    # location A lists location B as a parent, but location B doesn't list
    # location A as a child.

    for loc_id in locations.keys():
        if loc_id not in location_parents: continue # No parents.

        for parent_id in location_parents[loc_id]:
            disowned = False
            if parent_id not in location_children:
                disowned = True
            elif loc_id not in location_children[parent_id]:
                disowned = True

            if disowned:
                code,level_num,name,display_name = locations[loc_id]
                parent_code = locations[parent_id][0]
                parent_name = locations[parent_id][2]

                bad_locs.append({'code'    : code,
                                 'level'   : levelNumberToName[level_num],
                                 'name'    : name,
                                 'problem' : "has been disowned by parent " +
                                             parent_name+" ("+parent_code+")",
                                })

    # Find any locations which have been "disowned" by their children.  That
    # is, location A lists location B as a child, but location B doesn't list
    # location A as a parent.

    for loc_id in locations.keys():
        if loc_id not in location_children: continue # No children.

        for child_id in location_children[loc_id]:
            disowned = False
            if child_id not in location_parents:
                disowned = True
            elif loc_id not in location_parents[child_id]:
                disowned = True

            if disowned:
                code,level_num,name,display_name = locations[loc_id]
                child_code = locations[child_id][0]
                child_name = locations[child_id][2]

                bad_locs.append({'code'    : code,
                                 'level'   : levelNumberToName[level_num],
                                 'name'    : name,
                                 'problem' : "has been disowned by child " +
                                             child_name+" ("+child_code+")",
                                })

    # Find any locations which are "disowned" by their neighbours.  That is,
    # location A lists location B as a neighbour, but location B doesn't list
    # location A as a neighbour.

    for loc_id in locations.keys():
        if loc_id not in location_neighbours: continue # No neighbours.

        for neighbour_id in location_neighbours[loc_id]:
            disowned = False
            if neighbour_id not in location_neighbours:
                disowned = True
            elif loc_id not in location_neighbours[neighbour_id]:
                disowned = True

            if disowned:
                code,level_num,name,display_name = locations[loc_id]
                neighbour_code = locations[neighbour_id][0]
                neighbour_name = locations[neighbour_id][2]

                bad_locs.append({'code'    : code,
                                 'level'   : levelNumberToName[level_num],
                                 'name'    : name,
                                 'problem' : "has been disowned by neighbor " +
                                             neighbour_name +
                                             " (" + neighbour_code + ")",
                                })

    # Find any locations which lack a default tableau.

    cursor.execute("SELECT id FROM shared_location WHERE NOT EXISTS (" +
                   "SELECT * FROM shared_tableau WHERE shared_location.id=" +
                   "shared_tableau.location_id AND shared_tableau.name=" +
                   '"DEFAULT")')
    row = cursor.fetchone()
    while row != None:
        loc_id = row[0]
        code,level_num,name,display_name = locations[loc_id]
        bad_locs.append({'code'    : code,
                         'level'   : levelNumberToName[level_num],
                         'name'    : name,
                         'problem' : "is missing a default tableau"})
        row = cursor.fetchone()

    # Finally, display the potentially-bad locations to the user.

    admin_home_url = reverse(settings.ADMIN_HOME_VIEW)
    menu_html      = menus.generate(request, "sanity_checker", "main")

    return render_to_response("sanity_checker/templates/results.html",
                              {'menu_html'      : menu_html,
                               'bad_locs'       : bad_locs,
                               'admin_home_url' : admin_home_url},
                              context_instance=RequestContext(request))
예제 #3
0
파일: views.py 프로젝트: 3taps/geo
def fix_disowned(request):
    """ Respond to the "/fixdisowned" URL.

        We fix any "disowned" locations -- locations where the parent/child,
        child/parent, or neighbour/neighbour relations aren't symmetrical.

        In particular:

          * If a location has a parent which doesn't list the locaiton as a
            child, a child entry will be added to the parent.

          * If a location has a child which doesn't list the location as a
            parent, a parent entry will be added to the child.

          * If a location has a neighbour which doesn't list the location as a
            neighbour, a neighbour entry will be added to the neighbour.
    """
    # Display a "please wait" message while we work.

    if not pleasewait.shown(request):
        return pleasewait.message(request,
                                  "Whenua Admin",
                                  "Location Sanity-Checker",
                                  "Fixing disowned locations, please wait...")

    # Get a connection to our database.

    cursor = connections['geo_shared'].cursor()

    # Load the list of Level records into memory.

    levelIDToNumber = {} # Maps Level record ID to level number.

    for level in Level.objects.all():
        levelIDToNumber[level.id] = level.level

    # Load the list of Location records into memory.

    locations = {} # Maps record ID to a (code, level_num, name, display_name)
                   # tuple.
    
    cursor.execute("SELECT id,code,level_id,name,display_name " +
                   "FROM shared_location")
    row = cursor.fetchone()
    while row != None:
        id,code,level_id,name,display_name = row

        level_num = levelIDToNumber[level_id]
        locations[id] = (code, level_num, name, display_name)

        row = cursor.fetchone()

    # Load the list of location parents into memory.

    location_parents = {} # Maps record ID to a set of parent record IDs.

    cursor.execute("SELECT from_location_id,to_location_id " +
                   "FROM shared_location_parents")
    row = cursor.fetchone()
    while row != None:
        from_loc_id,to_loc_id = row

        try:
            location_parents[from_loc_id].add(to_loc_id)
        except KeyError:
            location_parents[from_loc_id] = set([to_loc_id])

        row = cursor.fetchone()

    # Load the list of location children into memory.

    location_children = {} # Maps record ID to set of child record IDs.

    cursor.execute("SELECT from_location_id,to_location_id " +
                   "FROM shared_location_children")
    row = cursor.fetchone()
    while row != None:
        from_loc_id,to_loc_id = row

        try:
            location_children[from_loc_id].add(to_loc_id)
        except KeyError:
            location_children[from_loc_id] = set([to_loc_id])

        row = cursor.fetchone()

    # Load the list of location neighbours into memory.

    location_neighbours = {} # Maps record ID to set of neighbour record IDs.

    cursor.execute("SELECT from_location_id,to_location_id " +
                   "FROM shared_location_neighbors")
    row = cursor.fetchone()
    while row != None:
        from_loc_id,to_loc_id = row

        try:
            location_neighbours[from_loc_id].add(to_loc_id)
        except KeyError:
            location_neighbours[from_loc_id] = set([to_loc_id])

        row = cursor.fetchone()

    # Fix any locations which have been "disowned" by their parents.  That is,
    # location A lists location B as a parent, but location B doesn't list
    # location A as a child.

    num_parents_fixed = 0
    for loc_id in locations.keys():
        if loc_id not in location_parents: continue # No parents.

        for parent_id in location_parents[loc_id]:
            disowned = False
            if parent_id not in location_children:
                disowned = True
            elif loc_id not in location_children[parent_id]:
                disowned = True

            if disowned:
                location = Location.objects.get(id=loc_id)
                parent   = Location.objects.get(id=parent_id)
                parent.children.add(location)
                num_parents_fixed = num_parents_fixed + 1

    # Fix any locations which have been "disowned" by their children.  That is,
    # location A lists location B as a child, but location B doesn't list
    # location A as a parent.

    num_children_fixed = 0
    for loc_id in locations.keys():
        if loc_id not in location_children: continue # No children.

        for child_id in location_children[loc_id]:
            disowned = False
            if child_id not in location_parents:
                disowned = True
            elif loc_id not in location_parents[child_id]:
                disowned = True

            if disowned:
                location = Location.objects.get(id=loc_id)
                child    = Location.objects.get(id=child_id)
                child.parents.add(location)
                num_children_fixed = num_children_fixed + 1

    # Fix any locations which are "disowned" by their neighbours.  That is,
    # location A lists location B as a neighbour, but location B doesn't list
    # location A as a neighbour.

    num_neighbours_fixed = 0
    for loc_id in locations.keys():
        if loc_id not in location_neighbours: continue # No neighbours.

        for neighbour_id in location_neighbours[loc_id]:
            disowned = False
            if neighbour_id not in location_neighbours:
                disowned = True
            elif loc_id not in location_neighbours[neighbour_id]:
                disowned = True

            if disowned:
                location  = Location.objects.get(id=loc_id)
                neighbour = Location.objects.get(id=neighbour_id)
                neighbour.neighbors.add(location)
                num_neighbours_fixed = num_neighbours_fixed + 1

    # Finally, tell the user the results.

    admin_home_url = reverse(settings.ADMIN_HOME_VIEW)
    menu_html      = menus.generate(request, "sanity_checker", "main")

    return render_to_response("sanity_checker/templates/disowned_fixed.html",
                              {'menu_html'            : menu_html,
                               'num_parents_fixed'    : num_parents_fixed,
                               'num_children_fixed'   : num_children_fixed,
                               'num_neighbours_fixed' : num_neighbours_fixed,
                               'admin_home_url'       : admin_home_url},
                              context_instance=RequestContext(request))