Changes between Version 6 and Version 7 of Help/Plugin/Scripting/Python/RCN_Route_Validator


Ignore:
Timestamp:
2014-10-25T16:58:05+02:00 (6 years ago)
Author:
Polyglot
Comment:

correct latest version

Legend:

Unmodified
Added
Removed
Modified
  • Help/Plugin/Scripting/Python/RCN_Route_Validator

    v6 v7  
    55'''
    66CheckRouteOrNetworkOrCollectionOfRoutes.jy
    7 - Validation of a rcn route relation
     7- Validation of a rXn route relation
    88
    99This code is released under the GNU General
     
    4343import org.openstreetmap.josm.actions.AutoScaleAction as AutoScaleAction
    4444import re, time
     45import codecs
     46
     47
     48# the file name where the report for the wiki goes, needs to be configurable
     49wikiReportFN = 'C:/data/wikiReport.txt'
     50# comment to disable side effect
     51sideEffects = {
     52    'addRouteToNetwork': None,
     53    'removeNameRefKey_xx-yyAndcreated_by': None,
     54    'modifyNoteTo_xx-yy': None,
     55    'flipOrderOfMembers': None, # such that ways go from lower rXn_ref to higher rXn_ref
     56    #'sortRouteRelations': None,
     57    #'sortNetworkRelations': None,
     58    #'removeNodesFromRoutes': None,
     59    #'addNodes2Routes': None,
     60    #'selectObjects': None,
     61    #'zoomToSelection': None,
     62    #'downloadReferrersForNodes': None, # This will download all ways and relations for nodes with an rXn_ref
     63    #'downloadReferrersForWays': None, # This will download all relations for ways that have an endnode with an rXn_ref
     64    'downloadIncompleteMembers': None,
     65    'createWikiReport': None,
     66        'reportWhenWaysAreUsedInAnotherRelationToo': None,
     67    'addFixmeTODOtags': None, # This will add todo tags to the data containing problems,
     68                              # the intention is that these tags are removed before uploading,
     69                              # once the reported problems are resolved
     70    #'createGarminGPX': None, # not implemented yet
     71    #'checkOneWays = False, # not implemented yet
     72    }
     73
     74logVerbosity = 30
     75'''
     7610: only report problems that require attention
     7720: report on collection
     7830: report on network nodes
     7940: report on which routes are being checked
     8050: report everything
     81'''
    4582
    4683def getMapView():
     
    5188
    5289def sortRouteRelation(route, nodesDict, beginAndEndnodes):
     90    # TODO This can still be improved a lot. Now it aborts at the first sign of probable failure.
     91    # TODO It sorts the simple cases though (i.e. the ones with no forward/backward roles which actually are continuous)
    5392    nextNode = None
    5493    routeToReturn = Relation(route)
    55     ##print dir (routeToReturn)
    56     #routeToReturn.clearOsmId()
     94    # Which node has the lower rXn_ref?
    5795    lowestNodeInt = 10000; lowPos = 0
    5896    for nodeTuple in beginAndEndnodes:
     
    6199    if not(nextNode):
    62100        return route
     101
     102    '''
     103    node1: way1
     104    node2: way1,way2
     105    node3: way2,way3,way4
     106    node4: way3,way5
     107    node5: way5,way6
     108    node6:
     109    node8: way8, way9
     110    node9: way7,way9,way10
     111    node10: way10, way11
     112    w1,w2,w3,w5,w6,w7,w4,w8,w9,w10'''
     113    # At this point nextNode contains the unique ID of the node with the lower rXn_ref
    63114    members=nodesDict[nextNode]
    64     processedMembers = {}
     115    processedMembers = {}; inBranch = False
    65116    #print len(nodesDict)
    66117    #print dir(route)
     
    69120        if len(members) == 1:
    70121            member = members[0]
     122        elif len(members) == 3:
     123            # road is splitting or recombining
     124            if inBranch:
     125                inBranch = False
     126            else:
     127                inBranch = True
     128                # road is splitting, which is the member we need next?
     129                # probably the one not going against a oneway restriction
     130                for member in members:
     131                    if member in processedMembers: continue
     132                    way = member.getWay()
     133                    oneway = way.get('oneway')
     134                    if oneway:
     135                        oneway = oneway.lower()
     136                    else:
     137                        oneway = ''
     138                    if oneway and not(oneway == 'no'):
     139                        ob=way.get('oneway:bicycle')
     140                        if ob:
     141                            ob = ob.lower()
     142                        else:
     143                            ob = ''
     144                        bo=way.get('bicycle:oneway')
     145                        if bo:
     146                            bo = bo.lower()
     147                        else:
     148                            bo = ''
     149                        co=way.get('cycleway_opposite')
     150                        if co:
     151                            co = co.lower()
     152                        else:
     153                            co = ''
     154                        onewayForBicycle = oneway in ['yes', '1', 'true', '-1'] and not(ob in ['yes', '1', 'true'] or
     155                                                                                        bo in ['yes', '1', 'true'] or
     156                                                                                        co in ['yes', '1', 'true'])
     157                        if oneway == '-1': pass # TODO this also needs to be taken in consideration
     158                    if way.getNode(0).getUniqueId() == nextNode:
     159                        break
    71160        else:
    72161            member = members[1]
     
    75164        way = member.getWay()
    76165        routeToReturn.removeMembersFor(way)
     166        print 'lowPos',lowPos
    77167        routeToReturn.addMember(lowPos,member)
    78168        #routeToReturn.setModified(True)
    79169        currentNode = nextNode
    80         nextNode = way.getNode(way.nodesCount-1).getId()
     170        nextNode = way.getNode(way.nodesCount-1).getUniqueId()
    81171        if currentNode == nextNode:
    82             nextNode = way.getNode(0).getId()           
     172            nextNode = way.getNode(0).getUniqueId()
    83173        if nextNode in nodesDict:
    84174            members=nodesDict[nextNode]
     
    89179        if len(nodesDict)<3: break
    90180        lowPos += 1
    91     #print 'before return', routeToReturn
     181    print 'before return', routeToReturn
    92182    return routeToReturn
    93183
     
    98188            way = member.getWay()
    99189            #print dir(way)
    100             #print way.getKeys()
    101             #print way.get('name')
    102             #print way.nodesCount-1, way
     190            if logVerbosity > 49:
     191                print way.getKeys()
     192                print way.get('name')
     193                print way.nodesCount-1, way
    103194            if way.get('junction') == 'roundabout':
    104195                endnodes = way.getNodes()
     
    110201            foundTheNode = False
    111202            for endnode in endnodes:
    112                 #print endnode, prev_endnodes
     203                if logVerbosity > 49: print endnode, prev_endnodes
    113204                if endnode in prev_endnodes:
    114205                    foundTheNode = True
    115206            if prev_endnodes and not(foundTheNode):
    116207                listIsContinuous = False
    117                 #print way
    118                 #print endnodes
    119                 #print prev_endnodes
     208                if logVerbosity > 49:
     209                    print way
     210                    print endnodes
     211                    print prev_endnodes
    120212                break
    121213            prev_endnodes = endnodes
    122     #print listIsContinuous
    123214    return listIsContinuous
    124215
    125 def checkRCNroute(route):
    126     commandsList = []
    127     reNumberDashNumber = re.compile(r'\d+-\d+')
    128     newRelation = Relation(route)
    129     relationChanged = False
    130     created_by = route.get('created_by')
    131     if created_by:
    132         print 'removing created_by'
    133         newRelation.remove('created_by')
    134         relationChanged = True
    135     name = route.get('name')
    136     if name:
    137         if reNumberDashNumber.match(name):
    138             print 'removing name when it is of the form ##-##'
     216def checkPTroute(route,  aDownloadWasNeeded):
     217    if aDownloadWasNeeded:
     218        return None, False, ''
     219    fixme = route.get('fixme')
     220   
     221    newRelation = Relation(route); commandslist = []; i=0; roundabout = []
     222    wayssequence = []; stopssequence = []
     223    unusedways = []; unservedstops = []
     224    routeMembers = route.getMembers()
     225    modified = False
     226    for member in routeMembers:
     227        if member.isWay():
     228            wayssequence.append(member)
     229            unusedways.append(member.getWay())
     230        elif member.isNode() and (member.getNode().get("highway") in ['bus_stop', 'bus_station'] or member.getNode().get("public_transport") in ['platform']):
     231            stopssequence.append(member.getNode())
     232            unservedstops.append(member.getNode())
     233    print(checkForContinuity(wayssequence))
     234def checkRxNroute(route, networklevel, aDownloadWasNeeded):
     235    if aDownloadWasNeeded:
     236        return None, False, ''
     237    if 'removeNameRefKey_xx-yyAndcreated_by' in sideEffects:
     238        commandsList = []
     239        reNumberDashNumber = re.compile(r'\d+\s-\s\d+')
     240        newRelation = Relation(route)
     241        relationChanged = False
     242        created_by = route.get('created_by')
     243        if created_by:
     244            print 'removing created_by'
     245            newRelation.remove('created_by')
     246            relationChanged = True
     247        name = route.get('name')
     248        if name:
     249            #if reNumberDashNumber.match(name):
     250            print 'removing name'
    139251            newRelation.remove('name')
    140252            relationChanged = True
    141     else:
    142         name = ''
    143     ref = route.get('ref')
    144     if ref:
    145         if reNumberDashNumber.match(ref):
    146             print 'removing ref when it is of the form ##-##'
    147             newRelation.remove('ref')
    148             relationChanged = True
    149     else:
    150         ref = ''
    151     if relationChanged:
    152         commandsList.append(Command.ChangeCommand(route, newRelation))
    153        
    154         Main.main.undoRedo.add(Command.SequenceCommand("Removing name and/or ref and/or created_by" + name + '/' + ref, commandsList))
    155         commandsList = []
    156 
    157     fixme = route.get('fixme') == 'incomplete'
    158     rcn_refs = []; route_relation_names = []; memberslist = []; roleInNetwork = ''
     253        else:
     254            name = ''
     255        ref = route.get('ref')
     256        if ref:
     257            if reNumberDashNumber.match(ref):
     258                print 'removing ref when it is of the form ##-##'
     259                newRelation.remove('ref')
     260                relationChanged = True
     261        else:
     262            ref = ''
     263        if relationChanged:
     264            commandsList.append(Command.ChangeCommand(route, newRelation))
     265           
     266            Main.main.undoRedo.add(Command.SequenceCommand("Removing name and/or ref and/or created_by" + name + '/' + ref, commandsList))
     267            commandsList = []
     268
     269    fixme = route.get('fixme')
     270    rXn_refs = []; actual_rXn_refs = []; route_relation_names = []
     271    memberslist = []; waymembersinlist = 0; roleInNetwork = ''
    159272    sameNodeNumberRepeated = False
    160     continuous_forward = True; continuous_backward = True
    161273    allWaysgoingFromLowerToHigher = []; allWaysgoingFromHigherToLower = []; branch = None
    162     nodesForSorting = {}; beginAndEndNodes = []
    163     newRelation = Relation(route); commandslist = []; modified = False; i=0; roundabout = []
    164 
    165     for member in route.getMembers():
     274    allWaysgoingFromLowerToHigherBeyondEndOfRoute = []; allWaysgoingFromHigherToLowerBeyondEndOfRoute = []
     275    nodesWithrXn_ref = {}; likelyCandidateNodesForActualStartOfRoute = {}
     276    tentacle = 0; tentacles = {}; routeHasStarted = False; high_rXn_refEncountered = 0
     277    rXn_refAsInt = None
     278    # tentacles is a nested list of all the segments of ways wich are present before the actual start of the route
     279    # sequence, UID of node with rXn_ref, list with ways, reference to next tentacle sequence
     280    # 1st level: rXn_refs
     281    # 2nd level: rXn_ref, tentacle sequence, ways, next tentacle
     282    # {40: [[1, [5n], 2],
     283    #       [2, [3n], 3],
     284    #       [3, [3n, 5n, 7n, 8n], 0],
     285    #       [4, [4n], 0]
     286    #      ],
     287    #  58: [[1, [2n], 0],
     288    #       [2, [7n], 1]
     289    #      ]
     290    # }
     291    newRelation = Relation(route); commandslist = []; i=0; roundabout = []
     292
     293    if 'sortRouteRelations' in sideEffects: nodesForSorting = {}; beginAndEndNodes = []
     294    routeMembers = route.getMembers()
     295    modified = False
     296
     297    for member in routeMembers:
     298        memberslist.append(member)
    166299        if member.isWay():
     300            waymembersinlist += 1
     301            if high_rXn_refEncountered: high_rXn_refEncountered += 1
    167302            role = member.getRole()
    168             memberslist.append(member)
     303            # make a Python list out of the members, in case we want to simply flip all of them
     304            # this would happen if we encounter the high rXn_ref before the low rXn_ref
    169305            way = member.getWay()
    170             #JOptionPane.showMessageDialog(Main.parent, 'way is selected')
     306            if logVerbosity > 49: print way.get('name')
    171307            wayNodes = way.getNodes()
    172             #if len(wayNodes):
    173                 #if way.get('junction') != 'roundabout':
    174                     #wayNodes = [way.getNode(0), way.getNode(way.nodesCount-1)]
    175             #else:
    176                 #newRelation.removeMember(i)
    177                 #modified = True
    178308
    179309            notfoundyet = True
     310            if logVerbosity > 49: print wayNodes
     311            if role in ['forward']:
     312                lastNode=wayNodes[-1]
     313            else:
     314                lastNode=wayNodes[0]
     315            lastNodeUid = lastNode.getUniqueId()
     316            if lastNodeUid in likelyCandidateNodesForActualStartOfRoute:
     317                likelyCandidateNodesForActualStartOfRoute[lastNodeUid] += 1
     318            else:
     319                likelyCandidateNodesForActualStartOfRoute[lastNodeUid] = 1
     320           
    180321            for endnode in wayNodes:
    181                 endnodeId = endnode.getId()
    182                 if not(endnodeId in nodesForSorting):
    183                     nodesForSorting[endnodeId] = []
    184                 nodesForSorting[endnodeId].append(member)
    185 
    186                 rcn_ref = endnode.get('rcn_ref')
    187                 if rcn_ref:
    188                     rcn_refAsInt = int(rcn_ref)
    189                     beginAndEndNodes.append([rcn_refAsInt, endnodeId])
    190                     if not(rcn_refAsInt in rcn_refs):
    191                         rcn_refs.append(rcn_refAsInt)
     322                endnodeId = endnode.getUniqueId()
     323                if 'sortRouteRelations' in sideEffects:
     324                    if not(endnodeId in nodesForSorting):
     325                        nodesForSorting[endnodeId] = []
     326                    nodesForSorting[endnodeId].append(member)
     327
     328                rXn_ref = endnode.get(networklevel + '_ref')
     329                if rXn_ref:
     330                    rXn_ref_digits = ''
     331                    for character in rXn_ref:
     332                        try:
     333                            int(character)
     334                            rXn_ref_digits += character
     335                        except: pass
     336                    if rXn_ref_digits and rXn_ref_digits==rXn_ref:
     337                        rXn_refAsInt = int(rXn_ref_digits)
     338                    else:
     339                        rXn_refAsInt = -1
     340
     341                        print rXn_ref
     342                    if 'sortRouteRelations' in sideEffects: beginAndEndNodes.append([rXn_refAsInt, endnodeId])
     343                    # keep track of distinct rXn_ref numbers in a list
     344                    if not(rXn_refAsInt in rXn_refs):
     345                        if len(rXn_refs): high_rXn_refEncountered += 1; tentacle = 0
     346                        rXn_refs.append(rXn_refAsInt)
     347                        if rXn_refAsInt == -1:
     348                            actual_rXn_refs.append(rXn_ref)
     349                        else:
     350                            actual_rXn_refs.append(str(rXn_refAsInt).zfill(2))
    192351                    else:
    193352                        sameNodeNumberRepeated = True
     353                    # keep track of node IDs with an rXn_ref on them
     354                    if not(rXn_refAsInt in nodesWithrXn_ref):
     355                        nodesWithrXn_ref[rXn_refAsInt] = []
     356                    nodesWithrXn_ref[rXn_refAsInt].append(endnode)
    194357                    referrersForNode = endnode.getReferrers(); networkNotFoundForNode = True
    195358                    for referrer in referrersForNode:
    196359                        if referrer.getType() is dummy_relation.getType():
    197                             if referrer.get('type') in ['network'] and referrer.get('network') in ['rcn']:
     360                            # This node belongs to a relation
     361                            if referrer.get('type') in ['network'] and referrer.get('network') in [networklevel]:
     362                                # and we have a winner
    198363                                networkNotFoundForNode = False
    199                                 break
    200                     if networkNotFoundForNode:
    201                          Main.main.getCurrentDataSet().setSelected(endnode)
    202                          AutoScaleAction.zoomToSelection()
    203                          #selectedNode = mv.editLayer.data.getSelected()
    204                          print "Would download referrers for ", endnode.get('rcn_ref'), ' ', wayNodes
    205                          # DownloadReferrersAction.downloadReferrers(mv.editLayer, wayNodes)
    206                          referrersForNode = endnode.getReferrers()
    207                     for referrer in referrersForNode:
    208                         if referrer.getType() is dummy_relation.getType():
    209                             networkOrRouteType = referrer.get('type') in ['network'] #, 'route']
    210                             if referrer.get('network')=='rcn' and networkOrRouteType:
    211364                                relname=referrer.get('name')
    212365                                if relname:
    213366                                    route_relation_names.append(relname)
    214                             elif not(referrer.get('type') in ['route']):
    215                                 route_relation_names.append('Node not assigned to network yet')
    216             # build 2 structures to help check for continuity on ways
     367                                break
     368                    if networkNotFoundForNode:
     369                        route_relation_names.append('Node not assigned to network yet')
     370                        if 'selectObjects' in sideEffects: Main.main.getCurrentDataSet().setSelected(endnode)
     371                        if 'zoomToSelection' in sideEffects: AutoScaleAction.zoomToSelection()
     372                        if 'downloadReferrersForNodes' in sideEffects:
     373                            aDownloadWasNeeded = True
     374                            print "Downloading referrers for ", endnode.get(networklevel + '_ref'), ' ', wayNodes
     375                            DownloadReferrersAction.downloadReferrers(mv.editLayer, wayNodes)
     376                            return None, False, ''
     377                        else:
     378                            print "Would download referrers for ", endnode.get(networklevel + '_ref'), ' ', wayNodes
     379                           
     380            # *** Now let's process the ways ***
     381            # build at least 2 structures to help check for continuity on ways
     382            # possibly there are 'tentacles' before the start or after the end when there are split network nodes
     383            if logVerbosity > 49:
     384                print 'L2H', allWaysgoingFromLowerToHigher
     385                print 'H2L', allWaysgoingFromHigherToLower
     386                print 'L2H', allWaysgoingFromLowerToHigherBeyondEndOfRoute
     387                print 'H2L', allWaysgoingFromHigherToLowerBeyondEndOfRoute
     388           
    217389            if i==0:
    218390                lastNodesBeforeSplit = [wayNodes]
     391            else:
     392                if not(routeHasStarted):
     393                    if role:
     394                        if role in ['forward']:
     395                            firstNode=wayNodes[0]
     396                        else:
     397                            firstNode=wayNodes[-1]
     398                        firstNodeUid = firstNode.getUniqueId()
     399                        print firstNodeUid, firstNodeUid in likelyCandidateNodesForActualStartOfRoute
     400                        if firstNodeUid in likelyCandidateNodesForActualStartOfRoute: print likelyCandidateNodesForActualStartOfRoute[firstNodeUid]
     401                        print likelyCandidateNodesForActualStartOfRoute
     402                        if firstNodeUid in likelyCandidateNodesForActualStartOfRoute and likelyCandidateNodesForActualStartOfRoute[firstNodeUid]>1:
     403                            routeHasStarted = True
     404                        if firstNode.get(networklevel + '_ref'):
     405                            if logVerbosity > 49: print 'rXn_ref', firstNode.get(networklevel + '_ref'), 'found in ', firstNode.getUniqueId()
     406                            # This is not the first member anymore and the first node has an rXn_ref and the member has a role,
     407                            # so we have to assign what we thought was the start of the route to one of our tentacles
     408                            tentacle +=1; reference = 0; interestingNodeId = None; tentacledescription = []
     409                            if allWaysgoingFromLowerToHigher:
     410                                prevRole = allWaysgoingFromLowerToHigher[-1].getRole()
     411                                if logVerbosity > 49: print 'prevRoleL2H', prevRole
     412                                if prevRole in ['forward']:
     413                                    interestingNodeId = allWaysgoingFromLowerToHigher[-1].getWay().getNodes()[-1].getUniqueId()
     414                                elif prevRole in ['backward']:
     415                                    interestingNodeId = allWaysgoingFromLowerToHigher[-1].getWay().getNodes()[0].getUniqueId()
     416                            elif allWaysgoingFromHigherToLower:
     417                                prevRole = allWaysgoingFromHigherToLower[-1].getRole()
     418                                if logVerbosity > 49: print 'prevRoleH2L', prevRole
     419                                if prevRole in ['forward']:
     420                                    interestingNodeId = allWaysgoingFromHigherToLower[-1].getWay().getNodes()[0].getUniqueId()
     421                                elif prevRole in ['backward']:
     422                                    interestingNodeId = allWaysgoingFromHigherToLower[-1].getWay().getNodes()[-1].getUniqueId()
     423                            if interestingNodeId and firstNode.getUniqueId() == interestingNodeId:
     424                                reference = tentacle+1
     425                            if allWaysgoingFromLowerToHigher:
     426                                tentacledescription = [tentacle, allWaysgoingFromLowerToHigher, reference]
     427                            elif allWaysgoingFromHigherToLower:
     428                                tentacledescription = [tentacle, allWaysgoingFromHigherToLower, reference]
     429                            allWaysgoingFromLowerToHigher = []; allWaysgoingFromHigherToLower = []; branch = None
     430                            if tentacledescription:
     431                                if rXn_refAsInt and not(rXn_refAsInt in tentacles):
     432                                    tentacles[rXn_refAsInt] = []
     433                                tentacles[rXn_refAsInt].append(tentacledescription)
     434                    else:
     435                        # no role on way means this is the actual start of our route
     436                        # so, all that went into allWaysgoingFromLowerToHigher etc has to go to the last tentacle
     437                        routeHasStarted = True
     438                        if allWaysgoingFromLowerToHigher or allWaysgoingFromHigherToLower:
     439                            tentacle +=1
     440                            if allWaysgoingFromHigherToLower:
     441                                allWaysgoingFromLowerToHigher # .append(allWaysgoingFromHigherToLower)
     442                            tentacledescription = [tentacle, allWaysgoingFromLowerToHigher, 0]
     443                            # allWaysgoingFromHigherToLower was assigned the start of the route in mistake in this case
     444                            # it should have gone to both 'branches', so we create a shallow copy
     445                            allWaysgoingFromLowerToHigher = allWaysgoingFromHigherToLower[:]; branch = None
     446                            if not(rXn_refAsInt in tentacles):
     447                                tentacles[rXn_refAsInt] = []
     448                            tentacles[rXn_refAsInt].append(tentacledescription)
     449                if high_rXn_refEncountered > 1:
     450                    # We're past the first high rXn_ref, time to disover more tentacles
     451                    if role:
     452                        if role in ['forward']:
     453                            lastNode=wayNodes[-1]
     454                        else:
     455                            lastNode=wayNodes[0]
     456                        if lastNode.get(networklevel + '_ref'):
     457                            print 'rXn_ref', lastNode.get(networklevel + '_ref'), 'found in ', lastNode.getUniqueId()
     458                            tentacle +=1; reference = 0; interestingNodeId = None; tentacledescription = []
     459                            if interestingNodeId and lastNode.getUniqueId() == interestingNodeId:
     460                                reference = tentacle+1
     461                            if allWaysgoingFromLowerToHigher:
     462                                tentacledescription = [tentacle, allWaysgoingFromLowerToHigherBeyondEndOfRoute, reference]
     463                            elif allWaysgoingFromHigherToLower:
     464                                tentacledescription = [tentacle, allWaysgoingFromHigherToLowerBeyondEndOfRoute, reference]
     465                            allWaysgoingFromLowerToHigherBeyondEndOfRoute = []; allWaysgoingFromHigherToLowerBeyondEndOfRoute = []; branch = None
     466                            if tentacledescription:
     467                                if rXn_refAsInt and not(rXn_refAsInt in tentacles):
     468                                    tentacles[rXn_refAsInt] = []
     469                                tentacles[rXn_refAsInt].append(tentacledescription)
     470            if logVerbosity > 49: print tentacle, repr(tentacles)
     471                           
    219472            if role and role in ['forward', 'backward']:
    220                 if not(branch):
    221                     if role in ['forward']:
    222                         lastNodesBeforeSplit = [wayNodes[0]]
     473                # if there is a role, it might be part of the route proper when it starts or ends in a fork
     474                # this is what we suppose, if we encounter another node with a low rXn_ref, we add what we already had
     475                # to the tentacles structure and clear fromLowToHigh
     476                if not(branch):                   
     477                    if wayNodes:
     478                        if role in ['forward']:
     479                            lastNodesBeforeSplit = [wayNodes[0]]
     480                        else:
     481                            lastNodesBeforeSplit = [wayNodes[-1]]
    223482                    else:
    224                         lastNodesBeforeSplit = [wayNodes[-1]]
    225                 print 'wayNodes', wayNodes
    226                 print 'lastNodesBeforeSplit', lastNodesBeforeSplit
    227                 print way.getNodesCount(), 'startnode', wayNodes[0], 'endnode', wayNodes[-1]
    228                 print 'roundabout', roundabout
    229 
     483                        return '', True, '|align="right" | way has no nodes||align="right" | {{BrowseRoute|' + str(route.getId()) + '}}||align="right" needs to be downloaded first\n'
     484                        if logVerbosity > 49: print waynodes
     485                if logVerbosity > 29:
     486                    print 'lastNodesBeforeSplit', lastNodesBeforeSplit
     487                    print way.getNodesCount(), 'startnode', wayNodes[0], 'endnode', wayNodes[-1]
     488                    print 'roundabout', roundabout
     489                    print wayNodes[-1].get(networklevel + '_ref'),not(member.getUniqueId() == routeMembers[-1].getUniqueId())
    230490                if role in ['forward'] and (wayNodes[-1] in lastNodesBeforeSplit or wayNodes[-1] in roundabout):
    231491                    branch = 'HigherToLower'
    232492                elif role in ['backward'] and wayNodes[0] in lastNodesBeforeSplit:
    233493                    branch = 'HigherToLower'
    234                 elif not(allWaysgoingFromHigherToLower) and wayNodes[-1].get('rcn_ref'):
     494                   
     495                elif branch == 'LowerToHigher' and not(allWaysgoingFromHigherToLower) and wayNodes[-1].get(networklevel + '_ref') and not(member.getUniqueId() == routeMembers[-1].getUniqueId()):
     496                    # This is for when the route starts forked from a different rXn node (split node situation), we don't want it to kick in for the last member of the route
    235497                    branch = 'HigherToLower'
    236498                elif not(branch == 'HigherToLower'):
    237499                    branch = 'LowerToHigher'
    238500                print branch
    239                 if branch == 'LowerToHigher':
    240                     allWaysgoingFromLowerToHigher.append(member)
    241                 elif branch == 'HigherToLower':
    242                     allWaysgoingFromHigherToLower.append(member)
     501                if high_rXn_refEncountered < 2:
     502                    if branch == 'LowerToHigher':
     503                        allWaysgoingFromLowerToHigher.append(member)
     504                    elif branch == 'HigherToLower':
     505                        allWaysgoingFromHigherToLower.append(member)
     506                else:
     507                    if branch == 'LowerToHigher':
     508                        allWaysgoingFromLowerToHigherBeyondEndOfRoute.append(member)
     509                    elif branch == 'HigherToLower':
     510                        allWaysgoingFromHigherToLowerBeyondEndOfRoute.append(member)
    243511            else:
    244512                branch = None; roundabout = []
    245                 allWaysgoingFromLowerToHigher.append(member)
    246                 allWaysgoingFromHigherToLower.append(member)
     513                routeHasStarted = True
     514                if high_rXn_refEncountered < 2:
     515                    allWaysgoingFromLowerToHigher.append(member)
     516                    allWaysgoingFromHigherToLower.append(member)
     517                else:
     518                    allWaysgoingFromLowerToHigherBeyondEndOfRoute.append(member)
     519                    allWaysgoingFromHigherToLowerBeyondEndOfRoute.append(member)
    247520            if way.get('junction') == 'roundabout':
    248521                roundabout = way.getNodes()
    249522        i+=1
     523    modified = False
     524    if 'removeNodesFromRoutes' in sideEffects:
     525        newRelation = Relation(route)
     526        for member in routeMembers:
     527            if member.isNode():
     528                node = member.getNode()
     529                newRelation.removeMembersFor(node)
     530                modified = True
    250531    if modified:
    251532        commandsList.append(Command.ChangeCommand(route, newRelation))
    252         Main.main.undoRedo.add(Command.SequenceCommand("Removing way which has no nodes", commandsList))
     533        Main.main.undoRedo.add(Command.SequenceCommand("Removing nodes with rXn_ref", commandsList))
    253534        commandsList = []
    254     #print allWaysgoingFromLowerToHigher
     535    modified = False
     536    if 'addNodes2Routes' in sideEffects:
     537        newRelation = Relation(route)
     538        # (re)add nodes to route
     539        lowrXn_ref2BDone = True; lowPos = 0
     540        for nodeNumber in sorted(nodesWithrXn_ref.keys()):
     541            for node in nodesWithrXn_ref[nodeNumber]:
     542               newRelation.removeMembersFor(node)
     543               newMember = RelationMember("",node)
     544               if lowrXn_ref2BDone:
     545                   newRelation.addMember(lowPos, newMember)
     546                   lowPos += 1
     547               else:
     548                   newRelation.addMember(newRelation.getMembersCount(), newMember)
     549            lowrXn_ref2BDone = False; modified = True
     550
     551    if modified:
     552        commandsList.append(Command.ChangeCommand(route, newRelation))
     553        Main.main.undoRedo.add(Command.SequenceCommand("Adding nodes with rXn_ref", commandsList))
     554        commandsList = []
     555
     556    continuous_forward = True; continuous_backward = True
    255557    if len(allWaysgoingFromLowerToHigher) > 1:
    256558        continuous_forward = checkForContinuity(allWaysgoingFromLowerToHigher)
    257         #if not(continuous_forward) and not(fixme):
    258             #sortedRelation = sortRouteRelation(route, nodesForSorting, beginAndEndNodes)
    259            
    260             #print route
    261             #print sortedRelation
    262             #commandsList.append(Command.ChangeCommand(route, sortedRelation))
    263             #Main.main.undoRedo.add(Command.SequenceCommand("Sorted route relation", commandsList))           
    264             #allWaysgoingFromLowerToHigher = []; allWaysgoingFromHigherToLower = []
    265             #for member in route.getMembers():
    266                 #if member.isWay():
    267                     #role = member.getRole()
    268                     #way = member.getWay()
    269                     #if role=='forward':
    270                         #allWaysgoingFromLowerToHigher.append(member)
    271                     #elif role=='backward':
    272                         #allWaysgoingFromHigherToLower.append(member)
    273                     #else:
    274                         #allWaysgoingFromLowerToHigher.append(member)
    275                         #allWaysgoingFromHigherToLower.append(member)
    276             #print allWaysgoingFromLowerToHigher
    277             #continuous_forward = checkForContinuity(allWaysgoingFromLowerToHigher)
    278         #else:
     559        if 'sortRouteRelations' in sideEffects and not(continuous_forward) and not(fixme):
     560            sortedRelation = sortRouteRelation(route, nodesForSorting, beginAndEndNodes)
     561
     562            if logVerbosity>49:
     563                print route
     564                print sortedRelation
     565
     566            allWaysgoingFromLowerToHigher = []; allWaysgoingFromHigherToLower = []
     567            routeMembers = sortedRelation.getMembers(); i=0
     568            for member in routeMembers:
     569                if member.isWay():
     570                    role = member.getRole()
     571                    if i==0:
     572                        lastNodesBeforeSplit = [wayNodes] # why nodes in plural? situations occur where the branch starts on a roundabout
     573                    if role and role in ['forward', 'backward']:
     574                        if not(branch):
     575                            if role in ['forward']:
     576                                lastNodesBeforeSplit = [wayNodes[0]]
     577                            else:
     578                                lastNodesBeforeSplit = [wayNodes[-1]]
     579                        if logVerbosity > 29:
     580                            print 'wayNodes', wayNodes
     581                            print 'lastNodesBeforeSplit', lastNodesBeforeSplit
     582                            print way.getNodesCount(), 'startnode', wayNodes[0], 'endnode', wayNodes[-1]
     583                            print 'roundabout', roundabout
     584
     585                        if role in ['forward'] and (wayNodes[-1] in lastNodesBeforeSplit or wayNodes[-1] in roundabout):
     586                            branch = 'HigherToLower'
     587                        elif role in ['backward'] and wayNodes[0] in lastNodesBeforeSplit:
     588                            branch = 'HigherToLower'
     589                        elif wayNodes[-1].get(networklevel + '_ref') and not(member.getUniqueId() == routeMembers[-1].getUniqueId()): # not(allWaysgoingFromHigherToLower) and ## this last part is probably not necessary anymore
     590                            # This is for when the route starts forked from a different rXn node (split node situation), we don't want it to kick in for the last member of the route
     591                            branch = 'HigherToLower'
     592                        elif not(branch == 'HigherToLower'):
     593                            branch = 'LowerToHigher'
     594                        print branch
     595                        if branch == 'LowerToHigher':
     596                            allWaysgoingFromLowerToHigher.append(member)
     597                        elif branch == 'HigherToLower':
     598                            allWaysgoingFromHigherToLower.append(member)
     599                    else:
     600                        branch = None; roundabout = []
     601                        allWaysgoingFromLowerToHigher.append(member)
     602                        allWaysgoingFromHigherToLower.append(member)
     603                    if way.get('junction') == 'roundabout':
     604                        roundabout = way.getNodes()
     605                i+=1
     606            continuous_forward = checkForContinuity(allWaysgoingFromLowerToHigher)
     607            if continuous_forward:
     608                # we only want to store the sorted relation, when sorting actually succeeded in getting it continuous
     609                commandsList.append(Command.ChangeCommand(route, sortedRelation))
     610                Main.main.undoRedo.add(Command.SequenceCommand("Sorted route relation", commandsList))           
    279611    else:
     612        # a route relation with only one way member
    280613        continuous_forward = True
    281614    if len(allWaysgoingFromHigherToLower) > 1:
    282615        continuous_backward = checkForContinuity(reversed(allWaysgoingFromHigherToLower))
    283616    else:
     617        # a route relation with only one way member
    284618        continuous_backward = True
    285     # Drawing conclusions about rcn_refs
    286     print rcn_refs
     619    print continuous_forward, continuous_backward
     620
     621    for rXn_nodeTentacles in tentacles:
     622        for seq, tentacleMember, next in tentacles[rXn_nodeTentacles]:
     623            print rXn_nodeTentacles, ' ', seq, ' ', next, ' ', checkForContinuity(tentacleMember)
     624           
     625    # Drawing conclusions about rXn_refs
     626    fixmetodo = ''
     627    if logVerbosity > 39: print rXn_refs
    287628    if sameNodeNumberRepeated:
    288         rcn_refs.append(rcn_refs[0])
    289     newNote = note = repr(rcn_refs)
     629        rXn_refs.append(rXn_refs[0])
     630    newNote = note = repr(rXn_refs)
    290631    sortedRelation = route
    291     if len(rcn_refs) > 1:
    292         #newRelation = Relation(route)
     632    if len(rXn_refs) > 1:
    293633        relationChanged = False
    294634
    295         if rcn_refs[0] > rcn_refs[1]:
    296             rcn_refs.sort()
    297             if len(memberslist)>1:
    298                 print 'Flipping members order'
     635        if rXn_refs[0] > rXn_refs[1]:
     636            rXn_refs.sort()
     637            if waymembersinlist>1 and 'flipOrderOfMembers' in sideEffects:
    299638                for member in reversed(memberslist):
    300639                    sortedRelation.addMember( sortedRelation.getMembersCount(), member)
     
    304643                commandsList = []
    305644        note = route.get('note')
    306         newNote = str(rcn_refs[0]).zfill(2) + '-' + str(rcn_refs[1]).zfill(2)
    307         #print note, newNote
    308         if not(note) or note != newNote:
    309             if not(note): note = 'nothing'
    310             newRelation.put('note', newNote)
     645        if not(-1 in rXn_refs):
     646            rXn_refs.sort()
     647            newNote = str(rXn_refs[0]).zfill(2) + '-' + str(rXn_refs[-1]).zfill(2)
     648        else:
     649            newNote = ''
     650            for ref in actual_rXn_refs:
     651               newNote+=ref + '-'
     652            newNote = newNote[:-1]
     653        if logVerbosity > 49: print note, newNote
     654        if 'modifyNoteTo_xx-yy' in sideEffects:
     655            if (not(note) or note != newNote) and rXn_refs[0] != rXn_refs[-1]:
     656                newRelation = Relation(route)
     657                #print newRelation.getUniqueId()
     658                #print route.getUniqueId()
     659                if not(note): note = 'nothing'
     660                newRelation.put('note', newNote)
     661                relationChanged = True
     662                commandsList.append(Command.ChangeCommand(route, newRelation))
     663           
     664                Main.main.undoRedo.add(Command.SequenceCommand("Changing note from " + note + ' to ' + newNote, commandsList))
     665                commandsList = []
     666
     667        if len(route_relation_names) > 1 and route_relation_names[0] != route_relation_names[1]:
     668            # print 'This is probably a CONNECTION to another network'
     669            if logVerbosity > 9: print newNote, route_relation_names
     670            roleInNetwork = 'connection'
     671        wikiEN = ''
     672    else:
     673        if logVerbosity > 9: print 'less than 2 end nodes with '+networklevel+'_ref found for route', newNote
     674        wikiEN = 'style="color:red" | ' + repr(rXn_refs) + ' - ?'
     675        if 'addFixmeTODOtags' in sideEffects and not(route.get(networklevel+':external_connection')) and not(route.get('roundtrip')):
     676            newRelation = Relation(route)
     677            #print newRelation.getUniqueId()
     678            #print route.getUniqueId()
     679            fixmetodo = 'less than 2 end nodes with '+networklevel+'_ref found for route' + newNote + ' ' + repr(rXn_refs) + ' ' + note
     680            newRelation.put('fixmetodo', fixmetodo)
    311681            relationChanged = True
    312682            commandsList.append(Command.ChangeCommand(route, newRelation))
    313683       
    314             Main.main.undoRedo.add(Command.SequenceCommand("Changing note from " + note + ' to ' + newNote, commandsList))
     684            Main.main.undoRedo.add(Command.SequenceCommand("report that only one '+networklevel+'_ref was found " + note + ' to ' + newNote, commandsList))
    315685            commandsList = []
    316 
    317         if len(route_relation_names) > 1 and route_relation_names[0] != route_relation_names[1]:
    318             # print 'This is probably a CONNECTION to another network'
    319             print route_relation_names
    320             roleInNetwork = 'connection'
    321     else:
    322         print 'less than 2 end nodes with rcn_ref found'
    323686    if fixme and not(continuous_forward or continuous_backward):
    324         print 'FIXME flag is INCOMPLETE'
     687        if logVerbosity > 9: print 'FIXME flag is INCOMPLETE for route', newNote
    325688    if continuous_forward:
    326689        wikiCF = 'align="right" | continuous'
    327         #print 'route is continous in the forward direction'
     690        if logVerbosity > 29: print 'route is continous in the forward direction'
    328691    else:
    329692        wikiCF = 'align="right" style="color:red" | NOT continuous'
    330         print 'route ',newNote,' is NOT CONTINUOUS in the forward direction'
    331         #print allWaysgoingFromLowerToHigher
     693        if logVerbosity > 9: print 'route ',newNote,' is NOT CONTINUOUS going from xx to yy; xx<yy'
     694        if logVerbosity > 49: print 'L2H:', allWaysgoingFromLowerToHigher
     695        if not(fixme) and 'addFixmeTODOtags' in sideEffects:
     696            newRelation = Relation(route)
     697            #print newRelation.getUniqueId()
     698            #print route.getUniqueId()
     699            fixmetodo += ' ' + newNote + 'is not continuous going from xx to yy; xx<yy'
     700            newRelation.put('fixmetodo', fixmetodo)
     701            relationChanged = True
     702            commandsList.append(Command.ChangeCommand(route, newRelation))
     703            if not(note): note = 'UNKNOWN'
     704           
     705            Main.main.undoRedo.add(Command.SequenceCommand("report that  " + note + ' is not continuous going from xx to yy; xx<yy' , commandsList))
     706            commandsList = []
    332707    if continuous_backward:
    333708        wikiCB = 'align="right" | continuous'
    334         #print 'route is continous in the backward direction'
     709        if logVerbosity > 29: print 'route is continous in the backward direction'
    335710    else:
    336711        wikiCB = 'align="right" style="color:red" | NOT continuous'
    337         print 'route ',newNote,' is NOT CONTINUOUS in the backward direction'
    338         #print allWaysgoingFromHigherToLower
     712        if logVerbosity > 9: print 'route ',newNote,' is NOT CONTINUOUS coming back from yy to xx; xx<yy'
     713        if logVerbosity > 49: print 'H2L: ', allWaysgoingFromHigherToLower
     714        if not(fixme) and 'addFixmeTODOtags' in sideEffects:
     715            newRelation = Relation(route)
     716            #print newRelation.getUniqueId()
     717            #print route.getUniqueId()
     718            fixmetodo += ' ' + newNote + 'is not continuous coming back from yy to xx; xx<yy'
     719            newRelation.put('fixmetodo', fixmetodo)
     720            relationChanged = True
     721            commandsList.append(Command.ChangeCommand(route, newRelation))
     722       
     723            Main.main.undoRedo.add(Command.SequenceCommand("report that  " + note + ' is not continuous coming back from yy to xx; xx<yy' , commandsList))
     724            commandsList = []
    339725    print
    340726    if fixme:
    341         wikiFM = 'style="color:red" | fixme'
     727        wikiFM = 'style="color:red" | ' + fixme
    342728    else:
    343729        wikiFM = ' | '
    344     if fixme or not(continuous_forward) or not(continuous_backward):
    345         problem = True
     730    if fixme or not(continuous_forward) or not(continuous_backward) or (len(rXn_refs)<2 and not(route.get(networklevel+':external_connection'))):
     731        problem = 'yes'
    346732    else:
    347         problem = False
    348     return roleInNetwork, problem, '|align="right" | ' + note + '||align="right" | {{BrowseRoute|' + str(route.getId()) + '}}||align="right" ' + wikiFM + ' ||' + wikiCF + ' ||' + wikiCB + '\n'
    349 
    350 def checkNetwork(network):
     733        problem = ''
     734
     735    print 'PROBLEM:', problem
     736    return str(roleInNetwork), problem, '|align="right" | ' + str(note) + '||align="right" | {{BrowseRoute|' + str(route.getId()) + '}}||align="right" ' + str(wikiFM) + ' ||' + str(wikiCF) + ' ||' + str(wikiCB)  + ' ||' + str(wikiEN) + '\n'
     737
     738def sortNetwork(network):
     739    # While making a list of all the nodes in the relation with an rXn_ref, find the node with the lowest rXn_ref in the network, not necessarily 01 and bring it to the first position
     740    # Look at the ways connecting to this node and their parent route relations with network=rXn
     741    # For all these relations, make a list of all the rXn_ref numbers, they lead to and remember the UIDs of these nodes and keep a ref to the relations
     742    # Split this list in two, one for internal routes, another for route relations connecting to a foreign network (so the ones with a connection role)
     743    # Sort both lists and bring the relations in positions following the first node
     744    # Do the same for all the relations in the second list
     745    # Then add the lowest rXn_ref number and remove it from the general todo list of rXn_ref nodes that were encountered in internal route relations
    351746    name = network.get('name')
    352     print '********************************************'
    353     print name
    354     print '********************************************'
    355     #'===' + name + '===\n' +
    356     wikiReportOnNodes = ('{| class="wikitable" align="left" style="margin:0 0 2em 2em;"\n|-\n|+' + name +
    357                          '\n|-\n!style="width:2.5em" | Node\n!Link\n! # Roads\n! # Relations\n|-\n')
    358 
    359     wikiReportOnRelations = ('{| class="wikitable" align="left" style="margin:0 0 2em 2em;"\n|-\n|+' + name +
    360                              '\n|-\n!style="width:2.5em" | note\n!link\n!fixme\n! forward\n! backward\n|-\n')
     747    if logVerbosity>19:
     748        print '********************************************'
     749        print name
     750        print '********************************************'
     751    lowestrXn_refInNetwork=9999; listOfNodeMembersSeen = []
     752    dictionaryWithAllNodesBelongingToThisNetwork = {}; dictionaryWithAllNodesBelongingToNeighbouringNetworks = {}
     753    ListOfInternalRoutesSeen = []; ListOfExternalRoutesSeen = []; dictionaryLinkingRoutesToNotes = {}
     754    members = network.getMembers()
     755    # Find a member node with the lowestrXn_refInNetwork and bring it to the front if such node is not there yet
     756    firstMember = members[0]
     757    if firstMember.isRelation() or firstMember.isNode() and int(firstMember.getNode().get(networklevel + '_ref')) != lowestrXn_refInNetwork:
     758        memberNode = None
     759        for networkMember in members:
     760            if networkMember.isNode():
     761                memberNode = networkMember.getNode()
     762                if int(memberNode.get(networklevel + '_ref')) == 1: break
     763        if memberNode:
     764            network.removeMembersFor(memberNode)
     765            network.addMember(0, networkMember)
     766   
     767    for networkMember in network.getMembers():
     768        if networkMember.isNode():
     769            node = networkMember.getNode()
     770            rXn_ref = node.get(networklevel + '_ref')
     771            if int(rXn_ref) == 1:
     772                referrersForNode = node.getReferrers()
     773                for referrer in referrersForNode:
     774                    if referrer.getType() is dummy_way.getType():
     775                        referrersForWay = referrer.getReferrers()
     776                        for wayReferrer in referrersForWay:
     777                            if wayReferrer.getType() is dummy_relation.getType():
     778                                aRelation = wayReferrer
     779                                if aRelation.get('type') == 'route' and aRelation.get('network') ==networklevel and not(aRelation.get('ref')):
     780                                    rXnNetworkCountForNode+=1
     781                                    if aRelation.hasIncompleteMembers():
     782                                        name = aRelation.get('name')
     783                                        if not(name): name = ''
     784                                        note = aRelation.get('note')
     785                                        if not(note): note = ''
     786                                        networkname = aRelation.get('network')
     787                                        if not(networkname): networkname = ''
     788                                        if 'downloadIncompleteMembers' in sideEffects:
     789                                            aDownloadWasNeeded = True
     790                                            print 'Downloading incomplete members for', note
     791                                            DownloadRelationMemberTask.run(DownloadRelationMemberTask(aRelation, aRelation.getIncompleteMembers(), mv.editLayer ))
     792                                            time.sleep(1)
     793                                            continue
     794                                        else:
     795                                            JOptionPane.showMessageDialog(Main.parent, 'Please download all incomplete members of the route relations first: ' + networkname + ' ' + note + ' ' + name)
     796                                            break
     797                                networkMembersList = []
     798                                for subMember in network.getMembers():
     799                                    if subMember.isRelation():
     800                                        routeRelation = subMember.getRelation()
     801                                        networkMembersList.append(routeRelation.getUniqueId())
     802                                routeId = aRelation.getUniqueId()
     803                                if rXnRelationWeWantToProcess and not(routeId in networkMembersList):
     804                                    roleFromRouteCheck, problemReported, wikiReport = checkRCNroute(aRelation, aDownloadWasNeeded)
     805                                    if problemReported and 'createWikiReport' in sideEffects:
     806                                        wikiReportOnRelations += wikiReport + '\n|-\n'
     807                                    if 'addRouteToNetwork' in sideEffects and not(aDownloadWasNeeded):
     808                                        newRelation = Relation(network)
     809                                        newmember = RelationMember(roleFromRouteCheck, aRelation)
     810                                        if logVerbosity > 9: print newRelation.getMembersCount(), ' ',i, ' ', newmember
     811                                        newRelation.addMember( i, newmember)
     812                                        commandsList = []
     813                                        commandsList.append(Command.ChangeCommand(network, newRelation))
     814                                        note = aRelation.get('note')
     815                                        if not(note):
     816                                            note = ''
     817                                        Main.main.undoRedo.add(Command.SequenceCommand("Adding " + note + " to network", commandsList))
     818                                        commandsList = []
     819                                        if logVerbosity > 9: print 'Added newly found RCN route relation to network: ', note
     820                                        i+=1
     821
     822def checkNetwork(network, networklevel, aDownloadWasNeeded):
     823    name = ''; name = network.get('name')
     824    if logVerbosity>19:
     825        print '********************************************'
     826        print name
     827        print '********************************************'
     828    if 'createWikiReport' in sideEffects:
     829        wikiReportOnNodes = ('\n==' + name + '==\n{| class="wikitable" align="left" style="margin:0 0 2em 2em;"\n|-\n|+' + name +
     830                             '\n|-\n!style="width:2.5em" | Node\n!Link\n! # Roads\n! # Relations\n|-\n')
     831        wikiReportOnRelations = ('{| class="wikitable" align="left" style="margin:0 0 2em 2em;"\n|-\n|+' + name +
     832                                 '\n|-\n!style="width:2.5em" | note\n!link\n!fixme\n! forward\n! backward\n! end nodes\n|-\n')
    361833    i=1
    362     for networkmember in network.getMembers():
    363         if networkmember.isRelation():
    364             subrelation = networkmember.getRelation()
    365             if subrelation.hasIncompleteMembers():
    366                 #JOptionPane.showMessageDialog(Main.parent, 'Please download all incomplete member of the route relations first')
    367                 DownloadRelationMemberTask.run(DownloadRelationMemberTask(subrelation, subrelation.getIncompleteMembers(), mv.editLayer ))
    368                 break
    369             roleFromRouteCheck, problemReported, wikiReport = checkRCNroute(subrelation)
    370             if problemReported:
    371                 wikiReportOnRelations += wikiReport + '\n|-\n'
    372             #if roleFromRouteCheck:
    373             role = networkmember.getRole()
    374             if role != roleFromRouteCheck:
    375                 print
    376                 print 'Role in network is ', role
    377                 print 'Maybe this should be: ', roleFromRouteCheck
    378         if networkmember.isNode():
    379             node = networkmember.getNode()
    380             rcn_ref = node.get('rcn_ref')
    381             expected_rcn_route_relations = node.get('expected_rcn_route_relations')
    382             if expected_rcn_route_relations:
    383                  expected_rcn_route_relations = int(expected_rcn_route_relations)
     834    for networkMember in network.getMembers():
     835        if networkMember.isRelation():
     836            routeRelation = networkMember.getRelation()
     837            if routeRelation.get('network') ==networklevel:
     838                if routeRelation.hasIncompleteMembers():
     839                    name = routeRelation.get('name')
     840                    if not(name): name = ''
     841                    note = routeRelation.get('note')
     842                    if not(note): note = ''
     843                    kindOfNetwork = routeRelation.get('network')
     844                    if not(kindOfNetwork): kindOfNetwork = ''
     845                    if 'downloadIncompleteMembers' in sideEffects:
     846                        aDownloadWasNeeded = True
     847                        print 'Downloading incomplete members for', note
     848                        DownloadRelationMemberTask.run(DownloadRelationMemberTask(routeRelation, routeRelation.getIncompleteMembers(), mv.editLayer ))
     849                        time.sleep(1)
     850                        continue
     851                    else:
     852                        JOptionPane.showMessageDialog(Main.parent, 'Please download all incomplete members of the route relations first: ' + kindOfNetwork + ' ' + note + ' ' + name)
     853                        break
     854                roleFromRouteCheck, problemReported, wikiReport = checkRxNroute(routeRelation, networklevel, aDownloadWasNeeded)
     855                if problemReported and 'createWikiReport' in sideEffects:
     856                    wikiReportOnRelations += wikiReport + '\n|-\n'
     857                role = networkMember.getRole()
     858                if logVerbosity > 29 and role != roleFromRouteCheck:
     859                    print
     860                    print 'Role in network is ', role
     861                    print 'Maybe this should be: ', roleFromRouteCheck
     862        if networkMember.isNode():
     863            node = networkMember.getNode()
     864            rXn_ref = node.get(networklevel + '_ref')
     865            expected_rXn_route_relations = node.get('expected_' + networklevel + '_route_relations')
     866            if expected_rXn_route_relations:
     867                expected_rXn_route_relations = int(expected_rXn_route_relations)
    384868            else:
    385                 expected_rcn_route_relations = 3
    386             if rcn_ref:
    387                 #print rcn_ref
     869                expected_rXn_route_relations = 3
     870            if rXn_ref:
     871                if logVerbosity > 39: print rXn_ref
    388872                referrersForNode = node.getReferrers()
    389873                networkNotFoundForNode = True
    390874                for referrer in referrersForNode:
    391875                    if referrer.getType() is dummy_relation.getType():
    392                         if referrer.get('type') in ['network'] and referrer.get('network') in ['rcn']:
     876                        if referrer.get('type') in ['network'] and referrer.get('network') in ['rcn','rwn','rhn']:
    393877                            networkNotFoundForNode = False
    394878                            break
    395                 if networkNotFoundForNode:
    396                     #Main.main.getCurrentDataSet().setSelected(node)
    397                     #AutoScaleAction.zoomToSelection()
     879                if networkNotFoundForNode and 'downloadReferrersNodes' in sideEffects:
     880                    aDownloadWasNeeded = True
     881                    if 'selectObjects' in sideEffects: Main.main.getCurrentDataSet().setSelected(node)
     882                    if 'zoomToSelection' in sideEffects: AutoScaleAction.zoomToSelection()
    398883                    #selectedNode = mv.editLayer.data.getSelected()
    399                     #DownloadReferrersAction.downloadReferrers(mv.editLayer, selectedNode)
    400                     referrersForNode = node.getReferrers()
    401 
    402                 rcnNetworkCountForNode = roads = 0
     884                    print 'Downloading referrers for ', node.get(networklevel + '_ref')
     885                    DownloadReferrersAction.downloadReferrers(mv.editLayer, node)
     886
     887                rXnNetworkCountForNode = roads = 0
    403888                for referrer in referrersForNode:
    404889                    if referrer.getType() is dummy_way.getType():
    405890                        if referrer.get('highway'): roads += 1
    406891                        referrersForWay = referrer.getReferrers()
    407                         if len(referrersForWay) < 1:
    408                             Main.main.getCurrentDataSet().setSelected(referrer)
    409                             AutoScaleAction.zoomToSelection()
    410                             ##selectedWay = mv.editLayer.data.getSelected()
    411                             #DownloadReferrersAction.downloadReferrers(mv.editLayer, referrersForNode)
    412                             referrersForWay = referrer.getReferrers()
    413                         for wayreferrer in referrersForWay:
    414                             if wayreferrer.getType() is dummy_relation.getType():
    415                                 memberslist = []
    416                                 if wayreferrer.get('type') == 'route' and wayreferrer.get('network') == 'rcn':
    417                                     rcnNetworkCountForNode+=1
    418                                 for submember in network.getMembers():
    419                                     if submember.isRelation():
    420                                         subrelation = submember.getRelation()
    421                                         memberslist.append(subrelation.getId())
    422                                 if not(wayreferrer.getId()):
    423                                     print dir(wayreferrer)
    424                                     break
    425                                 routeId = wayreferrer.getId()
    426                                 if not(routeId) or not(routeId in memberslist):
    427                                     if wayreferrer.get('network') == 'rcn':
    428                                         roleFromRouteCheck, problemReported, wikiReport = checkRCNroute(wayreferrer)
    429                                         print wikiReport
    430                                         if problemReported:
    431                                             wikiReportOnRelations += wikiReport + '\n|-\n'
     892                        if len(referrersForWay) < 1 and 'downloadReferrersForWays' in sideEffects:
     893                            aDownloadWasNeeded = True
     894                            if 'selectObjects' in sideEffects: Main.main.getCurrentDataSet().setSelected(referrer)
     895                            if 'zoomToSelection' in sideEffects: AutoScaleAction.zoomToSelection()
     896                            print 'Downloading referrers for ', referrer.get('name') , ' ', rXn_ref
     897                            DownloadReferrersAction.downloadReferrers(mv.editLayer, referrer)
     898
     899                        for wayReferrer in referrersForWay:
     900                            if wayReferrer.getType() is dummy_relation.getType():
     901                                aRelation = wayReferrer
     902                                rXnRelationWeWantToProcess = False # We need this again further on, when deciding whether or not to add this relation to the network
     903                                if aRelation.get('type') == 'route' and aRelation.get('network') ==networklevel and not(aRelation.get('ref')): # in ['RUR','NRR','NRW','2LR','3LR','KAI','EHR','DFR','WBR','Nk']):
     904                                    # The check on the ref is for Germany, where many rXn networks run crisscross through another.
     905                                    # We wouldn't want to get entangled in that mess.
     906                                    # The list is continuously getting longer, of course. But it's the best we can do here
     907                                    rXnRelationWeWantToProcess = True
     908                                    rXnNetworkCountForNode+=1
     909                                    if aRelation.hasIncompleteMembers():
     910                                        name = aRelation.get('name')
     911                                        if not(name): name = ''
     912                                        note = aRelation.get('note')
     913                                        if not(note): note = ''
     914                                        kindOfNetwork = aRelation.get('network')
     915                                        if not(kindOfNetwork): kindOfNetwork = ''
     916                                        if 'downloadIncompleteMembers' in sideEffects:
     917                                            aDownloadWasNeeded = True
     918                                            print 'Downloading incomplete members for', note
     919                                            DownloadRelationMemberTask.run(DownloadRelationMemberTask(aRelation, aRelation.getIncompleteMembers(), mv.editLayer ))
     920                                            time.sleep(1)
     921                                            continue
     922                                        else:
     923                                            JOptionPane.showMessageDialog(Main.parent, 'Please download all incomplete members of the route relations first: ' + kindOfNetwork + ' ' + note + ' ' + name)
     924                                            break
     925                                networkMembersList = []
     926                                # print network
     927                                for subMember in network.getMembers():
     928                                    if subMember.isRelation():
     929                                        routeRelation = subMember.getRelation()
     930                                        networkMembersList.append(routeRelation.getUniqueId())
     931                                routeId = aRelation.getUniqueId()
     932                                if rXnRelationWeWantToProcess and not(routeId in networkMembersList):
     933                                    roleFromRouteCheck, problemReported, wikiReport = checkRxNroute(aRelation, networklevel, aDownloadWasNeeded)
     934                                    if problemReported and 'createWikiReport' in sideEffects:
     935                                        wikiReportOnRelations += wikiReport + '\n|-\n'
     936                                    if 'addRouteToNetwork' in sideEffects and not(aDownloadWasNeeded):
    432937                                        newRelation = Relation(network)
    433                                         newmember = RelationMember(roleFromRouteCheck, wayreferrer)
    434                                         print newRelation.getMembersCount(), ' ',i, ' ', newmember
    435                                         ##if i>newRelation.getMembersCount()
     938                                        newmember = RelationMember(roleFromRouteCheck, aRelation)
     939                                        if logVerbosity > 9: print newRelation.getMembersCount(), ' ',i, ' ', newmember
    436940                                        newRelation.addMember( i, newmember)
    437941                                        commandsList = []
    438942                                        commandsList.append(Command.ChangeCommand(network, newRelation))
    439                                         note = wayreferrer.get('note')
     943                                        note = aRelation.get('note')
    440944                                        if not(note):
    441945                                            note = ''
    442946                                        Main.main.undoRedo.add(Command.SequenceCommand("Adding " + note + " to network", commandsList))
    443947                                        commandsList = []
    444                                         print 'Added newly found RCN route relation to network: ', note
     948                                        if logVerbosity > 9: print 'Added newly found RCN route relation to network: ', note
    445949                                        i+=1
    446                 if rcnNetworkCountForNode < expected_rcn_route_relations:
    447                     print 'Node ', rcn_ref, ' only has ', rcnNetworkCountForNode, ' rcn routes connected to it'
    448                     wikiReportOnNodes += '|align="right" | ' + rcn_ref + '||align="right" | {{Node|' + str(node.getId()) + '}}||align="right" |' + str(roads) + ' ||align="right" style="color:red" | ' + str(rcnNetworkCountForNode) + '\n|-\n'
     950                if rXnNetworkCountForNode < expected_rXn_route_relations:
     951                    if logVerbosity > 9: print 'Node ', rXn_ref, ' only has ', rXnNetworkCountForNode, ' rXn routes connected to it'
     952                    if 'createWikiReport' in sideEffects: wikiReportOnNodes += '|align="right" | ' + rXn_ref + '||align="right" | {{Node|' + str(node.getId()) + '}}||align="right" |' + str(roads) + ' ||align="right" style="color:red" | ' + str(rXnNetworkCountForNode) + '\n|-\n'
    449953
    450954        i+=1
    451     print
    452     wikiReportOnNodes += ('|-\n|}\n')
    453     wikiReportOnRelations += ('|-\n|}\n<br style="clear:left;" />\n')
    454     fh = open('C:/wikiReport.txt', 'a')
    455     fh.write(wikiReportOnNodes)
    456     fh.write(wikiReportOnRelations)
    457     fh.close()
    458 
     955    if logVerbosity > 19: print
     956    if 'createWikiReport' in sideEffects:
     957        fh = codecs.open(wikiReportFN, 'a', encoding="UTF-8")
     958        wikiReportOnNodes += ('|-\n|}\n')
     959        wikiReportOnRelations += ('|-\n|}\n<br style="clear:left;" />\n')
     960        fh.write(wikiReportOnNodes)
     961        fh.write(wikiReportOnRelations)
     962        fh.close()
     963
     964def checkAssociatedStreet(street):
     965    streetnameOfRelation = street.get('name')
     966    streetname = []; housenumber = []
     967    for member in street.getMembers():
     968        role = member.getRole()
     969        if role =='street':
     970            if member.isWay():
     971                m = member.getWay()
     972            elif member.isRelation():
     973                m = member.getRelation()
     974            sname = m.get('name')
     975            if sname and not(sname in streetname):
     976             streetname.append(sname)
     977        elif role =='house':
     978            if member.isNode():
     979                element = member.getNode()
     980            elif member.isWay():
     981                element = member.getWay()
     982            housenumber=element.get('addr:housenumber')
     983            sname = element.get('addr:street')
     984            if sname and not(sname in streetname):
     985                streetname.append(sname)
     986        #print streetnameOfRelation, streetname, housenumber
     987    if len(streetname) != 1 or streetnameOfRelation!=streetname[0]:
     988        print streetnameOfRelation, len(streetname), streetname
     989       
     990aDownloadWasNeeded = False
     991'''
     992Since Downloading referrers or missing members happens asynchronously in a separate worker thread
     993the script can run in three modes
     994
     9951. No downloads allowed/offline run; output mentions that data was incomplete in its reports.
     9962. Download run; When incomplete items are encountered, they are scheduled to be downloaded. From then on, no more quality checks are performed on the data.
     997   All hierarchies are still checked, looking for more incomplete data for which more downloads need to be scheduled.
     9983. Normal run; All data is available and proper reporting can be performed.
     999'''
    4591000
    4601001dummy_way = Way()
     
    4631004mv = getMapView()
    4641005if mv and mv.editLayer and mv.editLayer.data:
    465     fh = open('C:/wikiReport.txt', 'w')
    466     fh.close()
    467     dummy_relation = Relation()
    4681006    selectedRelations = mv.editLayer.data.getSelectedRelations()
    4691007
     
    4711009        JOptionPane.showMessageDialog(Main.parent, "Please select a route, network or collection relation")
    4721010    else:
     1011        if 'createWikiReport' in sideEffects:
     1012            fh = codecs.open(wikiReportFN, 'w', encoding="UTF-8")
     1013            fh.close()
    4731014        for relation in selectedRelations:
    474             #print relation
    475             #print relation.hasIncompleteMembers()
     1015            if logVerbosity> 49: print relation
    4761016            if relation.hasIncompleteMembers():
    477                 #JOptionPane.showMessageDialog(Main.parent, 'Please download all incomplete member of the relations first')
    478                 DownloadRelationMemberTask.run(DownloadRelationMemberTask(relation, relation.getIncompleteMembers(), mv.editLayer ))
    479                 break
    480             if relation.get('type') == 'route' and relation.get('network') == 'rcn':
    481                 checkRCNroute(relation)
    482             if relation.get('type') == 'network' and relation.get('network') == 'rcn':
    483                 checkNetwork(relation)
    484             if relation.get('type') == 'collection' and relation.get('network') == 'rcn':
    485                 for networkmember in relation.getMembers():
    486                     if networkmember.isRelation():
    487                         subrelation = networkmember.getRelation()
    488                         if subrelation.hasIncompleteMembers():
    489                             #JOptionPane.showMessageDialog(Main.parent, 'Please download all incomplete member of the network relations first')
    490                             DownloadRelationMemberTask.run(DownloadRelationMemberTask(subrelation, subrelation.getIncompleteMembers(), mv.editLayer ))
    491                             #break
    492                         checkNetwork(subrelation)
    493 
     1017                if 'downloadIncompleteMembers' in sideEffects:
     1018                    aDownloadWasNeeded = True
     1019                    print 'Downloading referrers for ', str(relation.get('name')), ' ', str(relation.get('note'))
     1020                    DownloadRelationMemberTask.run(DownloadRelationMemberTask(relation, relation.getIncompleteMembers(), mv.editLayer ))
     1021                    continue
     1022                else:
     1023                    JOptionPane.showMessageDialog(Main.parent, 'Please download all incomplete member of the relations first')
     1024                    exit()
     1025            networklevel = relation.get('network')
     1026            relationType = relation.get('type')
     1027
     1028            if networklevel in ('rcn','rwn','rhn'):
     1029                if relationType == 'route':
     1030                    checkRxNroute(relation, networklevel, aDownloadWasNeeded)
     1031                elif relationType == 'network':
     1032                    checkNetwork(relation, networklevel, aDownloadWasNeeded)
     1033                elif relationType == 'collection':
     1034                    for collectionMember in relation.getMembers():
     1035                        if collectionMember.isRelation():
     1036                            networkRelation = collectionMember.getRelation()
     1037                            if networkRelation.hasIncompleteMembers():
     1038                                name = networkRelation.get('name')
     1039                                if not(name): name = ''
     1040                                networkname = networkRelation.get('network')
     1041                                if not(networkname): networkname = ''
     1042                                if 'downloadIncompleteMembers' in sideEffects:
     1043                                    aDownloadWasNeeded = True
     1044                                    print 'Downloading referrers for ', name
     1045                                    DownloadRelationMemberTask.run(DownloadRelationMemberTask(networkRelation, networkRelation.getIncompleteMembers(), mv.editLayer ))
     1046                                    continue
     1047                                else:
     1048                                    JOptionPane.showMessageDialog(Main.parent, 'Please download all incomplete members of the network relations first:' + networkname + ' ' + name)
     1049                                    break
     1050                            checkNetwork(networkRelation, networklevel, aDownloadWasNeeded)
     1051            elif relationType == 'associatedStreet':
     1052                checkAssociatedStreet(relation)
     1053            elif relationType == "route_master":
     1054                pass
     1055            elif relationType == "route" and relation.get('route') in ['bus','tram']:
     1056                checkPTroute(relation, aDownloadWasNeeded)
     1057
     1058        if aDownloadWasNeeded:
     1059            JOptionPane.showMessageDialog(Main.parent, 'There was incomplete data and downloading mode was initiated,\nNo further quality checks were performed.\nPlease run the script again when all downloads have completed')
    4941060
    4951061}}}