source: subversion/applications/utils/gary68/useractivity.pl @ 17698

Last change on this file since 17698 was 17698, checked in by gary68, 10 years ago

ua version 2.3 - html puts out version now. renamed objects are drawn
now.

  • Property svn:executable set to *
File size: 40.7 KB
Line 
1#!/usr/bin/perl
2#
3# useractivity.pl by gary68
4#
5#
6#
7# Copyright (C) 2009, Gerhard Schwanz
8#
9# This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the
10# Free Software Foundation; either version 3 of the License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>
16#
17#
18# Version 2
19# - map support added
20# - way support added
21#
22# Version 2.1
23# - separate files for time slots (privacy)
24#
25# Version 2.2
26# - some bugs fixed
27#
28# Version 2.3
29# - html print program version number
30# - draw renamed ways
31#
32#
33
34use strict ;
35use warnings ;
36
37use OSM::osm ;
38use OSM::osmgraph ;
39use File::stat ;
40use Time::localtime ;
41use Compress::Bzip2 ;
42
43my $program = "useractivity.pl" ;
44my $usage = $program . " file1.osm file2.osm out.htm Mode [numTopUsers] [picSize] (Mode = [N|P|D|S], picSize x in pixels)\n" ;
45$usage .= "N = normal\nP = with picture\nPD = with detailed picture\nPS/PDS = also write SVG file\n" ;
46my $version = "2.3" ;
47
48my $topMax = 10 ;
49
50my %lon1 ; my %lat1 ; my %lon2 ; my %lat2 ;
51my $wayId1 ; my $wayVersion1 ; my $wayTimestamp1 ; my $wayUid1 ; my $wayUser1 ; my $wayChangeset1 ; my @wayNodes1 ; my @wayTags1 ;
52my $wayId2 ; my $wayVersion2 ; my $wayTimestamp2 ; my $wayUid2 ; my $wayUser2 ; my $wayChangeset2 ; my @wayNodes2 ; my @wayTags2 ;
53
54my $nodeId1 ; my $nodeUser1 ; my $nodeLat1 ; my $nodeLon1 ; my @nodeTags1 ; my $nodeVersion1 ; my $nodeTimestamp1 ; my $nodeUid1 ; my $nodeChangeset1 ;
55my $nodeId2 ; my $nodeUser2 ; my $nodeLat2 ; my $nodeLon2 ; my @nodeTags2 ; my $nodeVersion2 ; my $nodeTimestamp2 ; my $nodeUid2 ; my $nodeChangeset2 ;
56my $aRef1 ; my $aRef2 ;
57
58my $time0 = time() ; 
59
60my $mode = "" ; my $sizeX = 1024 ;
61my $html ; my $htmlName ;
62my $osm1Name ; my $osm2Name ;
63
64my $file1 ; my $file2 ; my $bz1 ; my $bz2 ; my $isBz21 ; my $isBz22 ; my $line1 ; my $line2 ; my $bzerrno ;
65my $file1Name ; my $file2Name ;
66
67my %minLon ; my %minLat ; my %maxLon ; my %maxLat ; # per user
68my $deletedNodes = 0 ; my $deletedNodesWithTags = 0 ;
69my $deletedWays = 0 ; my $deletedWaysWithTags = 0 ;
70my %nodesAdded ; my %nodesMovedNumber ; my %nodesMovedDistance ; my %nodesMovedMax ;
71my %waysAdded ;
72my %tagsAdded ; my %tagsDeleted ; my %tagsRenamed ; my %tagsReclassified ; my %tagsRereffed ;
73my %tagsDeletedName ;
74my %renames ; my %reclassifications ; my %rerefs ;
75my @deletedNodesIds = () ; my %deletedNodesTags = () ;
76my @deletedWaysIds = () ; my %deletedWaysTags = () ;
77my %versionJumpsNodes = () ;
78my %versionJumpsWays = () ;
79my %opTime ;
80my %neededNodes = () ;
81
82my $reName ; my $reClass ; my $reRef ;
83my $name1 ; my $name2 ; my $ref1 ; my $ref2 ; my $class1 ; my $class2 ;
84
85my $objectProcessed = 0 ; # 0=node, 1=way
86
87###############
88# get parameter
89###############
90$osm1Name = shift||'';
91if (!$osm1Name) { die (print $usage, "\n") ; }
92
93$osm2Name = shift||'';
94if (!$osm2Name) { die (print $usage, "\n") ; }
95
96$htmlName = shift||'';
97if (!$htmlName) { die (print $usage, "\n") ; }
98
99$mode = shift||'';
100if (!$mode) {   $mode = "N" ; }
101
102$topMax = shift||'';
103if (!$topMax) { $topMax = 10 ; }
104
105$sizeX = shift||'';
106if (!$sizeX) {  $sizeX = 1024 ; }
107
108print "\n$program $version for files:\n\n" ;
109print stringFileInfo ($osm1Name), "\n"  ;
110print stringFileInfo ($osm2Name), "\n\n"  ;
111
112#------------------------------------------------------------------------------------
113# Main
114#------------------------------------------------------------------------------------
115
116if (grep /P/, $mode) { initializeMap() ; }
117
118openOsm1File ($osm1Name) ;
119moveNodeFile1() ;
120
121openOsm2File ($osm2Name) ;
122moveNodeFile2() ;
123
124processNodes() ;
125
126moveWayFile1() ;
127moveWayFile2() ;
128
129processWays() ;
130
131closeOsm1File () ;
132closeOsm2File () ;
133
134if ( ! (grep /P/, $mode) )  { 
135        processNeededWayNodes() ; 
136}
137
138if (grep /P/, $mode) { print "paint areas and save map...\n" ; }
139if (grep /P/, $mode) { paintAreas() ; }
140if (grep /P/, $mode) { saveMap() ; }
141if (grep /P/, $mode) { print "done.\n" ; }
142
143
144output() ;
145
146#-------
147# FINISH
148#-------
149
150print "\n$program finished after ", stringTimeSpent (time()-$time0), "\n\n" ;
151
152
153#------------------------------------------------------------------------------------
154# Node procesing
155#------------------------------------------------------------------------------------
156
157sub processNodes {
158        print "processing nodes...\n" ;
159        while ( ($nodeId1 > -1) or ($nodeId2 > -1) ) {
160                # print "while $nodeId1     $nodeId2\n" ;
161                if ($nodeId1 == -1) {
162                        # get rest from file 2, new nodes
163                        while ( $nodeId2 != -1 ) {
164                                # print "$nodeId1     $nodeId2   2-NEW\n" ;
165                                $nodesAdded{$nodeUser2}++ ;
166                                addOperationTime ($nodeUser2, $nodeTimestamp2) ;
167                                if (grep /P/, $mode) { paintNewNode() ; }
168                                userArea ($nodeUser2, $nodeLon2, $nodeLat2) ;
169                                moveNodeFile2() ;
170                        }
171                }
172
173                if ($nodeId2 == -1) {
174                        # get rest from file 1, deleted nodes
175                        while ( $nodeId1 != -1 ) {
176                                $deletedNodes++ ;
177                                if (scalar @nodeTags1 > 0) { 
178                                        $deletedNodesWithTags++ ; 
179                                        if (grep /P/, $mode) { paintDeletedNodeWithTag() ; }
180                                        push @deletedNodesIds, $nodeId1 ;
181                                        @{$deletedNodesTags{$nodeId1}} = @nodeTags1 ;
182                                }
183                                else {
184                                        if (grep /P/, $mode) { paintDeletedNode() ; }
185                                }
186                                moveNodeFile1() ;
187                        }
188                }
189
190                if ( ($nodeId1 == $nodeId2) and ($nodeId1 != -1) ) {
191                        # print "equal $nodeId1     $nodeId2\n" ;
192
193                        # place?
194                        if (grep /P/, $mode) {
195                                my $place = 0 ; my $placeName = "" ; my $placeNameGiven = 0 ;
196                                foreach my $t (@nodeTags1) {
197                                        if ($t->[0] eq "place") { $place = 1 ; }
198                                        if ($t->[0] eq "name") { $placeNameGiven = 1 ; $placeName = $t->[1] ; }
199                                }
200                                if ( ($place == 1) and ($placeNameGiven == 1) ) { paintPlace ($nodeLon1, $nodeLat1, $placeName) ; } 
201                        }
202
203                        # position...
204                        if ( ($nodeLon1 != $nodeLon2) or ($nodeLat1 != $nodeLat2) ) {
205                                $nodesMovedNumber{$nodeUser2}++ ;
206                                addOperationTime ($nodeUser2, $nodeTimestamp2) ;
207                                if (grep /P/, $mode) { paintMovedNode() ; }
208                                my ($d) = distance ($nodeLon1, $nodeLat1, $nodeLon2, $nodeLat2) ;
209                                $nodesMovedDistance{$nodeUser2} += $d ;
210                                if (defined $nodesMovedMax{$nodeUser2}) {
211                                        if ($nodesMovedMax{$nodeUser2} < $d) { $nodesMovedMax{$nodeUser2} = $d ; }
212                                }
213                                else {
214                                        $nodesMovedMax{$nodeUser2} = $d ;
215                                }
216                                userArea ($nodeUser2, $nodeLon1, $nodeLat1) ;
217                                userArea ($nodeUser2, $nodeLon2, $nodeLat2) ;
218                        } # moved
219
220                        if ($nodeVersion2 - $nodeVersion1 > 2) { 
221                                push @{$versionJumpsNodes{$nodeUser2}}, [$nodeId2, $nodeVersion2 - $nodeVersion1] ;
222                        }
223
224                        # process tags
225                        my ($added, $deleted, $renamed, $reclassified) = compareTags (\@nodeTags1, \@nodeTags2) ; 
226                        if ($added) { $tagsAdded{$nodeUser2} += $added ; }
227                        if ($deleted) { $tagsDeleted{$nodeUser2} += $deleted ; }
228                        if ($renamed) { 
229                                $tagsRenamed{$nodeUser2} += $renamed ; 
230                                if (grep /P/, $mode) { paintRenamedNode() ; }
231                        }
232                        if ($added or $deleted or $renamed or $reclassified) {
233                                addOperationTime ($nodeUser2, $nodeTimestamp2) ;
234                        }
235                        moveNodeFile1() ;
236                        moveNodeFile2() ;
237                }
238
239                if ( ($nodeId1 > $nodeId2) and ($nodeId2 != -1) ) {
240                        # print "1 > 2 $nodeId1     $nodeId2   2-NEW\n" ;
241                        # id 2 not found in file 1, nodeId2 new
242                        $nodesAdded{$nodeUser2}++ ;
243                        addOperationTime ($nodeUser2, $nodeTimestamp2) ;
244                        if (grep /P/, $mode) { paintNewNode() ; }
245                        userArea ($nodeUser2, $nodeLon2, $nodeLat2) ;
246                        # move file2 until id2>=id1
247                        while ( ($nodeId2 < $nodeId1) and ($nodeId2 != -1) ) {
248                                moveNodeFile2() ;
249                        }
250                }
251
252                if ( ($nodeId1 < $nodeId2) and ($nodeId1 != -1) ) {
253                        # print "1 < 2 $nodeId1     $nodeId2   1-DELETED\n" ;
254                        # id 1 not found in file 2, nodeId1 deleted
255                        $deletedNodes++ ;
256                        if (scalar @nodeTags1 > 0) { 
257                                $deletedNodesWithTags++ ; 
258                                if (grep /P/, $mode) { paintDeletedNodeWithTag() ; }
259                                push @deletedNodesIds, $nodeId1 ;
260                                @{$deletedNodesTags{$nodeId1}} = @nodeTags1 ;
261                        }
262                        else {
263                                if (grep /P/, $mode) { paintDeletedNode() ; }
264                        }
265                        # move file1 until id1>=id2
266                        while ( ($nodeId1 < $nodeId2) and ($nodeId1 != -1) ) {
267                                moveNodeFile1() ;
268                        }
269                }
270        }
271        print "finished.\n" ;
272}
273
274#------------------------------------------------------------------------------------
275# Way procesing
276#------------------------------------------------------------------------------------
277
278sub processWays {
279        $objectProcessed = 1 ;
280        print "processing ways...\n" ;
281        while ( ($wayId1 > -1) or ($wayId2 > -1) ) {
282                if ($wayId1 == -1) {
283                        # get rest from file 2, new ways
284                        while ( $wayId2 != -1 ) {
285                                # print "$wayId1     $wayId2   2-NEW\n" ;
286                                $waysAdded{$wayUser2}++ ;
287                                addOperationTime ($wayUser2, $wayTimestamp2) ;
288                                if (scalar @wayNodes2 >= 2) {
289                                        #userArea ($wayUser2, $lon2{$wayNodes2[0]}, $lat2{$wayNodes2[0]}) ;
290                                        #userArea ($wayUser2, $lon2{$wayNodes2[-1]}, $lat2{$wayNodes2[-1]}) ;
291                                        userAreaWay ($wayUser2, $wayNodes2[0]) ;
292                                        userAreaWay ($wayUser2, $wayNodes2[-1]) ;
293                                        if (grep /P/, $mode) { paintNewWay() ; }
294                                }
295                                #next
296                                moveWayFile2() ;
297                        }
298                }
299
300                if ($wayId2 == -1) {
301                        # get rest from file 1, deleted ways
302                        while ( $wayId1 != -1 ) {
303                                $deletedWays++ ;
304                                if (scalar @wayTags1 > 0) { 
305                                        $deletedWaysWithTags++ ; 
306                                        if (scalar @wayNodes1 >= 2) {
307                                                if (grep /P/, $mode) { paintDeletedWayWithTag() ; }
308                                        }
309                                        push @deletedWaysIds, $wayId1 ;
310                                        @{$deletedWaysTags{$wayId1}} = @wayTags1 ;
311                                }
312                                else {
313                                        if (scalar @wayNodes1 >= 2) {
314                                                if (grep /P/, $mode) { paintDeletedWay() ; }
315                                        }
316                                }
317                                #next
318                                moveWayFile1() ;
319                        }
320                }
321
322                if ( ($wayId1 == $wayId2) and ($wayId1 != -1) ) {
323                        # print "equal $wayId1     $wayId2\n" ;
324                        # TODO position
325                        # TODO nodes number
326
327                        if ($wayVersion2 - $wayVersion1 > 2) { 
328                                push @{$versionJumpsWays{$wayUser2}}, [$wayId2, $wayVersion2 - $wayVersion1] ;
329                        }
330
331                        # process tags
332                        my ($added, $deleted, $renamed, $reclassified, $rereffed) = compareTags (\@wayTags1, \@wayTags2) ; 
333                        if ($added) { $tagsAdded{$wayUser2} += $added ; }
334                        if ($deleted) { $tagsDeleted{$wayUser2} += $deleted ; }
335                        if ($renamed) { 
336                                $tagsRenamed{$wayUser2} += $renamed ; 
337                                if (grep /P/, $mode) { paintRenamedWay() ; }
338                        }
339                        if ($reclassified) { 
340                                $tagsReclassified{$wayUser2} += $reclassified ; 
341                                if (scalar @wayNodes1 >= 2) {
342                                        if (grep /P/, $mode) { paintReclassifiedWay() ; }
343                                }
344                        } 
345                        if ($rereffed) { 
346                                $tagsRereffed{$wayUser2} += $rereffed ; 
347                                if (scalar @wayNodes1 >= 2) {
348                                        if (grep /P/, $mode) { paintRereffedWay() ; }
349                                }
350                        } 
351                        if ($added or $deleted or $renamed or $reclassified or $rereffed) { 
352                                addOperationTime ($wayUser2, $wayTimestamp2) ; 
353                                if ( (scalar @wayNodes1 >= 2) and (scalar @wayNodes2 >= 2) ) {
354                                        # userArea ($wayUser2, $lon2{$wayNodes2[0]}, $lat2{$wayNodes2[0]}) ;
355                                        # userArea ($wayUser2, $lon2{$wayNodes2[-1]}, $lat2{$wayNodes2[-1]}) ;
356                                        userAreaWay ($wayUser2, $wayNodes2[0]) ;
357                                        userAreaWay ($wayUser2, $wayNodes2[-1]) ;
358                                }
359                        }
360                        moveWayFile1() ;
361                        moveWayFile2() ;
362                }
363
364                if ( ($wayId1 > $wayId2) and ($wayId2 != -1) ) {
365                        # print "1 > 2 $wayId1     $wayId2   2-NEW\n" ;
366                        # id 2 not found in file 1, wayId2 new
367                        $waysAdded{$wayUser2}++ ;
368                        addOperationTime ($wayUser2, $wayTimestamp2) ; 
369                        if (scalar @wayNodes2 >= 2) {
370                                # userArea ($wayUser2, $lon2{$wayNodes2[0]}, $lat2{$wayNodes2[0]}) ;
371                                # userArea ($wayUser2, $lon2{$wayNodes2[-1]}, $lat2{$wayNodes2[-1]}) ;
372                                userAreaWay ($wayUser2, $wayNodes2[0]) ;
373                                userAreaWay ($wayUser2, $wayNodes2[-1]) ;
374                                if (grep /P/, $mode) { paintNewWay() ; }
375                        }
376                        # move file2 until id2>=id1
377                        while ( ($wayId2 < $wayId1) and ($wayId2 != -1) ) {
378                                moveWayFile2() ;
379                        }
380                }
381
382                if ( ($wayId1 < $wayId2) and ($wayId1 != -1) ) {
383                        # print "1 < 2 $wayId1     $wayId2   1-DELETED\n" ;
384                        # id 1 not found in file 2, wayId1 deleted
385                        $deletedWays++ ;
386                        if (scalar @wayTags1 > 0) { 
387                                $deletedWaysWithTags++ ; 
388                                if (scalar @wayNodes1 >= 2) {
389                                        if (grep /P/, $mode) { paintDeletedWayWithTag() ; }
390                                }
391                                push @deletedWaysIds, $wayId1 ;
392                                @{$deletedWaysTags{$wayId1}} = @wayTags1 ;
393                        }
394                        else {
395                                if (scalar @wayNodes1 >= 2) {
396                                        if (grep /P/, $mode) { paintDeletedWay() ; }
397                                }
398                        }
399                        # move file1 until id1>=id2
400                        while ( ($wayId1 < $wayId2) and ($wayId1 != -1) ) {
401                                moveWayFile1() ;
402                        }
403                }
404        }
405        print "finished.\n" ;
406}
407
408
409#------------------------------------------------------------------------------------
410# Output functions
411#------------------------------------------------------------------------------------
412
413sub output {
414        print "outputting html...\n" ;
415        my @a ; my @list ;
416        open ($html, ">", $htmlName) or die ("can't open html output file") ;
417        printHTMLHeader ($html, "UserActvity by Gary68") ;
418        print $html "<H1>UserActvity by gary68</H1>" ;
419        print $html "<p>Version: ", $version, "</p>\n"  ;
420        print $html "<p>", stringFileInfo ($osm1Name), "</p>\n"  ;
421        print $html "<p>", stringFileInfo ($osm2Name), "</p>\n"  ;
422        print $html "<p>A deleted tag can result out of a change of a tag. The same is true for the addition of a tag. Real changes are not counted.</p>" ;
423        print $html "<H1>Results</H1>" ;
424        print $html "<p>DELETED NODES: $deletedNodes</p>\n" ;
425        print $html "<p>DELETED NODES WITH TAGS: $deletedNodesWithTags (details see further down)</p>\n" ;
426       
427        @a = () ;
428        foreach my $e (keys %nodesMovedNumber) { push @a, [$e, $nodesMovedNumber{$e}] ; }
429        printTop ("TOP moved nodes number", 0, @a) ;
430        @a = () ;
431        foreach my $e (keys %nodesMovedDistance) { push @a, [$e, $nodesMovedDistance{$e}] ; }
432        printTop ("TOP moved nodes total distance (km)", 1, @a) ;
433        @a = () ;
434        foreach my $e (keys %nodesMovedDistance) { push @a, [$e, $nodesMovedDistance{$e}/$nodesMovedNumber{$e}] ; }
435        printTop ("TOP moved nodes average distance (km)", 1, @a) ;
436        @a = () ;
437        foreach my $e (keys %nodesMovedMax) { push @a, [$e, $nodesMovedMax{$e}] ; }
438        printTop ("TOP moved nodes maximum distance (km)", 1, @a) ;
439
440        @a = () ;
441        foreach my $u (keys %maxLon) {
442                # print "calc area for user: $u\n" ;
443                push @a, [$u, distance ($minLon{$u}, $minLat{$u}, $minLon{$u}, $maxLat{$u}) * distance ($minLon{$u}, $minLat{$u}, $maxLon{$u}, $minLat{$u})] ;
444        }
445        printTop ("TOP work areas (km²)", 1, @a) ;
446
447        @a = () ;
448        foreach my $e (keys %tagsAdded) { push @a, [$e, $tagsAdded{$e}] ; }
449        printTop ("TOP tags added", 0, @a) ;
450
451        @a = () ;
452        foreach my $e (keys %tagsRenamed) { push @a, [$e, $tagsRenamed{$e}] ; }
453        printTop ("TOP objects renamed", 0, @a) ;
454
455        @list = @a ; @list = reverse (sort {$a->[1]<=>$b->[1]} @list) ;
456        # if (scalar @list > $topMax) { @list = @list[0..$topMax-1] ; }
457        print $html "<h2>Renames by ALL users</h2>\n" ;
458        printHTMLTableHead ($html) ;
459        printHTMLTableHeadings ($html, "User", "Tag", "Number") ; 
460        foreach my $e (@list) {
461                foreach my $t (keys %{$renames{$e->[0]}}) {
462                        # printf $html "%-25s %-80s %5i<br>\n" , $e->[0], $t, $renames{$e->[0]}{$t} ;
463                        printHTMLRowStart ($html) ;
464                        printHTMLCellLeft ($html, userLink ($e->[0])) ;                 
465                        printHTMLCellLeft ($html, $t) ;                 
466                        printHTMLCellRight ($html, $renames{$e->[0]}{$t}) ;                     
467                        printHTMLRowEnd ($html) ;
468                }
469        }
470        printHTMLTableFoot ($html) ;
471
472        @a = () ;
473        foreach my $e (keys %tagsRereffed) { push @a, [$e, $tagsRereffed{$e}] ; }
474        printTop ("TOP objects rereffed", 0, @a) ;
475
476        @list = @a ; @list = reverse (sort {$a->[1]<=>$b->[1]} @list) ;
477        # if (scalar @list > $topMax) { @list = @list[0..$topMax-1] ; }
478        print $html "<h2>Rerefs by ALL users</h2>\n" ;
479        printHTMLTableHead ($html) ;
480        printHTMLTableHeadings ($html, "User", "Tag", "Number") ; 
481        foreach my $e (@list) {
482                foreach my $t (keys %{$rerefs{$e->[0]}}) {
483                        # printf $html "%-25s %-80s %5i<br>\n" , $e->[0], $t, $rerefs{$e->[0]}{$t} ;
484                        printHTMLRowStart ($html) ;
485                        printHTMLCellLeft ($html, userLink ($e->[0])) ;                 
486                        printHTMLCellLeft ($html, $t) ;                 
487                        printHTMLCellRight ($html, $rerefs{$e->[0]}{$t}) ;                     
488                        printHTMLRowEnd ($html) ;
489                }
490        }
491        printHTMLTableFoot ($html) ;
492
493        @a = () ;
494        foreach my $e (keys %tagsReclassified) { push @a, [$e, $tagsReclassified{$e}] ; }
495        printTop ("TOP ways reclassified", 0, @a) ;
496
497        @list = @a ; @list = reverse (sort {$a->[1]<=>$b->[1]} @list) ;
498        # if (scalar @list > $topMax) { @list = @list[0..$topMax-1] ; }
499        print $html "<h2>Reclassifications by ALL users</h2>\n" ;
500        printHTMLTableHead ($html) ;
501        printHTMLTableHeadings ($html, "User", "Tag", "Number") ; 
502        foreach my $e (@list) {
503                foreach my $t (keys %{$reclassifications{$e->[0]}}) {
504                        # printf $html "%-25s %-80s %5i<br>\n" , $e->[0], $t, $reclassifications{$e->[0]}{$t} ;
505                        printHTMLRowStart ($html) ;
506                        printHTMLCellLeft ($html, userLink ($e->[0])) ;                 
507                        printHTMLCellLeft ($html, $t) ;                 
508                        printHTMLCellRight ($html, $reclassifications{$e->[0]}{$t}) ;                   
509                        printHTMLRowEnd ($html) ;
510                }
511        }
512        printHTMLTableFoot ($html) ;
513
514#       print $html "<h2>Version jumps nodes by ALL users</h2>\n" ;
515#       printHTMLTableHead ($html) ;
516#       printHTMLTableHeadings ($html, "User", "Nodes") ;
517#       foreach my $u (keys %versionJumpsNodes) {
518#               printHTMLRowStart ($html) ;
519#               printHTMLCellLeft ($html, userLink ($u)) ;                     
520#               my $jumps = "" ;
521#               foreach my $v (@{$versionJumpsNodes{$u}}) {
522#                       $jumps = $jumps . historyLink ("node", $v->[0]) . " (" . $v->[1] . ") " ;
523#               }
524#               printHTMLCellLeft ($html, $jumps) ;                     
525#               printHTMLRowEnd ($html) ;
526#       }
527#       printHTMLTableFoot ($html) ;
528
529#       print $html "<h2>Version jumps ways by ALL users</h2>\n" ;
530#       printHTMLTableHead ($html) ;
531#       printHTMLTableHeadings ($html, "User", "Ways") ;
532#       foreach my $u (keys %versionJumpsWays) {
533#               printHTMLRowStart ($html) ;
534#               printHTMLCellLeft ($html, userLink ($u)) ;                     
535#               my $jumps = "" ;
536#               foreach my $v (@{$versionJumpsWays{$u}}) {
537#                       $jumps = $jumps . historyLink ("node", $v->[0]) . " (" . $v->[1] . ") " ;
538#               }
539#               printHTMLCellLeft ($html, $jumps) ;                     
540#               printHTMLRowEnd ($html) ;
541#       }
542#       printHTMLTableFoot ($html) ;
543
544        @a = () ;
545        foreach my $e (keys %tagsDeleted) { push @a, [$e, $tagsDeleted{$e}] ; }
546        printTop ("TOP tags deleted", 0, @a) ;
547
548        @list = @a ; @list = reverse (sort {$a->[1]<=>$b->[1]} @list) ;
549        if (scalar @list > $topMax) { @list = @list[0..$topMax-1] ; }
550        print $html "<h2>Tags removed by TOP users</h2>\n" ;
551        printHTMLTableHead ($html) ;
552        printHTMLTableHeadings ($html, "User", "Removed", "Number") ; 
553        foreach my $e (@list) {
554                foreach my $t (keys %{$tagsDeletedName{$e->[0]}}) {
555                        # printf $html "%-25s %-50s %5i<br>\n" , $e->[0], $t, $tagsDeletedName{$e->[0]}{$t} ;
556                        printHTMLRowStart ($html) ;
557                        printHTMLCellLeft ($html, userLink ($e->[0])) ;                 
558                        printHTMLCellLeft ($html, $t) ;                 
559                        printHTMLCellRight ($html, $tagsDeletedName{$e->[0]}{$t}) ;                     
560                        printHTMLRowEnd ($html) ;
561                }
562        }
563        printHTMLTableFoot ($html) ;
564
565        print $html "<h2>ALL deleted Nodes with tags (details)</h2>\n" ;
566        printHTMLTableHead ($html) ;
567        printHTMLTableHeadings ($html, "NodeId", "Tags") ; 
568        foreach my $n (@deletedNodesIds) {
569                printHTMLRowStart ($html) ;
570                printHTMLCellLeft ($html, historyLink ("node", $n) ) ;                 
571                my $tagText = "" ;
572                foreach my $t (@{$deletedNodesTags{$n}}) { $tagText = $tagText . $t->[0] . ":" . $t->[1] . "<br>\n" ; }
573                printHTMLCellLeft ($html, $tagText) ;   
574                printHTMLRowEnd ($html) ;
575        }
576        printHTMLTableFoot ($html) ;
577
578        print $html "<h2>ALL deleted ways with tags (details)</h2>\n" ;
579        printHTMLTableHead ($html) ;
580        printHTMLTableHeadings ($html, "WayId", "Tags") ; 
581        foreach my $n (@deletedWaysIds) {
582                printHTMLRowStart ($html) ;
583                printHTMLCellLeft ($html, historyLink ("way", $n) ) ;                   
584                my $tagText = "" ;
585                foreach my $t (@{$deletedWaysTags{$n}}) { $tagText = $tagText . $t->[0] . ":" . $t->[1] . "<br>\n" ; }
586                printHTMLCellLeft ($html, $tagText) ;   
587                printHTMLRowEnd ($html) ;
588        }
589        printHTMLTableFoot ($html) ;
590
591        print $html "<p>$program finished after ", stringTimeSpent (time()-$time0), "</p>\n" ;
592        printHTMLFoot ($html) ;
593        close ($html) ;
594
595        my ($html2Name) = $htmlName ;
596        $html2Name =~ s/.htm/.time.htm/ ;
597        open ($html, ">", $html2Name) or die ("can't open html2 output file") ;
598        printHTMLHeader ($html, "UserActvity (TIME) by Gary68") ;
599        print $html "<H1>UserActvity (TIME) by gary68</H1>" ;
600        print $html "<p>", stringFileInfo ($osm1Name), "</p>\n"  ;
601        print $html "<p>", stringFileInfo ($osm2Name), "</p>\n"  ;
602
603        @a = () ;
604        foreach my $u (keys %opTime) { push @a, [$u, numOpHours ($u)] ; }
605        printTop ("TOP operation hour slots", 0, @a) ;
606
607        @list = reverse (sort {$a->[1]<=>$b->[1]} @a) ;
608        if (scalar @list > $topMax) { @list = @list[0..$topMax-1] ; }
609        print $html "<h2>Operation time slots TOP users</h2>\n" ;
610        printHTMLTableHead ($html) ;
611        printHTMLTableHeadings ($html, "User", "00","01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23") ; 
612        foreach my $e (@list) {
613                printHTMLRowStart ($html) ;
614                printHTMLCellLeft ($html, userLink ($e->[0])) ;                 
615                my $max = 0 ;
616                foreach my $h ("00","01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23") {
617                        if ( (defined $opTime{$e->[0]}{$h}) and ($opTime{$e->[0]}{$h} > $max) )  { $max = $opTime{$e->[0]}{$h} ; } 
618                }
619                # print "$e->[0] $max\n" ;
620                my $value = 0 ;
621                foreach my $h ("00","01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23") {
622                        if (defined $opTime{$e->[0]}{$h}) { $value = $opTime{$e->[0]}{$h} ; } else { $value = 0 ; }
623                        my ($colorValue) = 255 - ( int ($value / $max * 255) / 2) ; my ($colorString) = sprintf "%02x", $colorValue ;
624                        # print "$value $colorValue $colorString\n" ;
625                        my ($htmlString) = "<td align=\"right\" bgcolor=\"#" . $colorString . $colorString . $colorString . "\">" . $value . "</td>" ;
626                        print $html $htmlString ;
627                }
628                printHTMLRowEnd ($html) ;
629        }
630        printHTMLTableFoot ($html) ;
631
632
633        printHTMLFoot ($html) ;
634        close ($html) ;
635
636
637        print "done.\n" ;
638}
639
640sub printTop {
641        my ($heading, $decimal, @list) = @_ ;
642        print $html "<h2>$heading</h2>\n" ;
643        printHTMLTableHead ($html) ;
644        printHTMLTableHeadings ($html, "User", "Data") ; 
645        @list = reverse (sort {$a->[1]<=>$b->[1]} @list) ;
646        if (scalar @list > $topMax) { @list = @list[0..$topMax-1] ; }
647        foreach my $e (@list) {
648                printHTMLRowStart ($html) ;
649                my $s ;
650                if ($decimal) { 
651                        $s = sprintf "%8.3f", $e->[1] ;
652                }
653                else {
654                        $s = sprintf "%8i", $e->[1] ;
655                }
656                printHTMLCellLeft ($html, userLink ($e->[0]) ) ;                       
657                printHTMLCellRight ($html, $s) ;                       
658                printHTMLRowEnd ($html) ;
659        } 
660        printHTMLTableFoot ($html) ;
661}
662
663
664#------------------------------------------------------------------------------------
665# some functions
666#------------------------------------------------------------------------------------
667
668sub addOperationTime {
669        my ($user, $timestamp) = @_ ;
670        # timestamp="2008-04-13T13:23:55+01:00"
671        my ($hour) = substr ($timestamp, 11, 2) ;
672        $opTime{$user}{$hour}++ ;
673}
674
675sub numOpHours {
676        my ($user) = shift ;
677        my $hours = 0 ;
678        foreach my $hour ("00","01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23") {
679                if (defined $opTime{$user}{$hour}) { $hours++ ; }
680        }
681        return ($hours) ;
682}
683
684sub userAreaWay {
685        my ($u, $n) = @_ ;
686        if (grep /P/, $mode) {
687                userArea ($u, $lon2{$n}, $lat2{$n}) ;
688        }
689        else {
690                $neededNodes{$n} = $u ;
691        }
692}
693
694sub processNeededWayNodes {
695        print "get needed nodes for touched ways...\n" ;
696        openOsm2File ($osm2Name) ;
697        moveNodeFile2() ;
698        while ( $nodeId2 != -1 ) {
699                if (defined $neededNodes{$nodeId2}) {
700                        userArea ($neededNodes{$nodeId2}, $nodeLon2, $nodeLat2) ;
701                }
702                moveNodeFile2() ;
703        }
704        closeOsm2File () ;
705        print "done.\n" ;
706}
707
708sub userArea {
709        my ($u, $lon, $lat) = @_ ;
710
711        if ( (!defined $lon) or (! defined $lat) ) {
712                print "userArea ERROR user $u nodes $nodeId1 $nodeId2 ways $wayId1 $wayId2\n" ;
713        }
714
715        if (! defined $maxLon{$u}) {
716                $minLon{$u} = $lon ;
717                $minLat{$u} = $lat ;
718                $maxLon{$u} = $lon ;
719                $maxLat{$u} = $lat ;
720        }
721        else {
722                if ($lon > $maxLon{$u}) { $maxLon{$u} = $lon ; }
723                if ($lon < $minLon{$u}) { $minLon{$u} = $lon ; }
724                if ($lat > $maxLat{$u}) { $maxLat{$u} = $lat ; }
725                if ($lat < $minLat{$u}) { $minLat{$u} = $lat ; }
726        }
727}
728
729sub compareTags {
730        my ($aRef1, $aRef2) = @_ ;
731        my $added = 0 ; my $deleted = 0 ; my $renamed = 0 ; my $reclassified = 0 ; my $rereffed = 0 ;
732        my (@tags1) = @$aRef1 ; my (@tags2) = @$aRef2 ;
733
734        $reName = 0 ; $reClass = 0 ; $reRef = 0 ;
735
736        # RENAMED?
737        my $nameGiven = 0 ;
738        my $nameOld = "" ; 
739        my $nameNew = "" ;
740        foreach my $t (@tags1) { 
741                if ($t->[0] eq "name") { $nameGiven = 1 ; $nameOld = $t->[1] ; }
742        }
743        foreach my $t (@tags2) { 
744                if ($t->[0] eq "name") { $nameNew = $t->[1] ; }
745        }
746        if ( ($nameGiven == 1) and ($nameNew ne $nameOld) ) { 
747                $renamed = 1 ; 
748                $renames{$nodeUser2}{$nameOld . " > " . $nameNew} ++ ;
749                $reName = 1 ; $name1 = $nameOld ; $name2 = $nameNew ;
750        }
751       
752        if ($objectProcessed == 1 ) {
753                # REREF?
754                my $refGiven = 0 ;
755                my $refOld = "" ; 
756                my $refNew = "" ;
757                foreach my $t (@tags1) { 
758                        if ($t->[0] eq "ref") { $refGiven = 1 ; $refOld = $t->[1] ; }
759                }
760                foreach my $t (@tags2) { 
761                        if ($t->[0] eq "ref") { $refNew = $t->[1] ; }
762                }
763                if ( ($refGiven == 1) and ($refNew ne $refOld) ) { 
764                        $rereffed = 1 ; 
765                        $rerefs{$wayUser2}{$refOld . " > " . $refNew} ++ ;
766                        $reRef = 1 ; $ref1 = $refOld ; $ref2 = $refNew ;
767                }
768                # RECLASSIFIED?
769                my $highwayGiven = 0 ;
770                my $highwayOld = "" ;
771                my $highwayNew = "" ;
772                foreach my $t (@tags1) { 
773                        if ($t->[0] eq "highway") { $highwayGiven = 1 ; $highwayOld = $t->[1] ; }
774                }
775                foreach my $t (@tags2) { 
776                        if ($t->[0] eq "highway") { $highwayNew = $t->[1] ; }
777                }
778                if ( ($highwayGiven == 1) and ($highwayNew ne $highwayOld) ) { 
779                        $reclassified = 1 ; 
780                        $reclassifications{$wayUser2}{$highwayOld . " > " . $highwayNew} ++ ;
781                        $reClass = 1 ; $class1 = $highwayOld ; $class2 = $highwayNew ;
782                }
783        } # objectProcessed
784
785        # ADDED?
786        foreach my $t2 (@tags2) {
787                my $found = 0 ;
788                foreach my $t1 (@tags1) {
789                        if ( ($t1->[0] eq $t2->[0]) and ($t1->[1] eq $t2->[1]) ) { $found = 1 ; }
790                }
791                if ($found == 0) { $added++ ; }
792        }
793
794        # DELETED?
795        foreach my $t1 (@tags1) {
796                my $found = 0 ;
797                foreach my $t2 (@tags2) {
798                        if ( ($t1->[0] eq $t2->[0]) and ($t1->[1] eq $t2->[1]) ) { $found = 1 ; }
799                }
800                # if ($found == 0) {
801                if ( ($found == 0) and ($t1->[0] ne "created_by") ) { 
802                        $deleted++ ; 
803                        $tagsDeletedName{$nodeUser2}{$t1->[0].":".$t1->[1]}++ ;
804                }
805        }
806
807        return ($added, $deleted, $renamed, $reclassified, $rereffed) ;
808} # compareTags
809
810sub userLink {
811        my ($user) = shift ;
812        return "<a href=\"http://www.openstreetmap.org/user/" . $user . "\">" . $user . "</a>" ;
813}
814
815
816
817#------------------------------------------------------------------------------------
818# Map functions
819#------------------------------------------------------------------------------------
820
821sub paintNewWay {
822        drawWay ("black", 2, nodes2Coordinates2 (@wayNodes2) ) ;
823        if (grep /D/, $mode) { drawTextPos ($lon2{$wayNodes2[0]}, $lat2{$wayNodes2[0]}, 0, 0, $wayUser2, "black", 2) ; }
824}
825
826sub paintDeletedWay {
827        drawWay ("red", 2, nodes2Coordinates1 (@wayNodes1) ) ;
828}
829
830sub paintDeletedWayWithTag {
831        drawWay ("red", 3, nodes2Coordinates1 (@wayNodes1) ) ;
832}
833
834sub paintRenamedWay {
835        drawWay ("orange", 3, nodes2Coordinates1 (@wayNodes1) ) ;
836        if (grep /D/, $mode) { 
837                drawTextPos ($lon1{$wayNodes1[0]}, $lat1{$wayNodes1[0]}, 0, 0, $wayUser2, "orange", 2) ; 
838                drawTextPos ($lon1{$wayNodes1[0]}, $lat1{$wayNodes1[0]}, 0, -8, $name1 . "->" . $name2, "black", 2) ; 
839        }
840}
841
842sub paintRereffedWay {
843        drawWay ("orange", 3, nodes2Coordinates1 (@wayNodes1) ) ;
844        if (grep /D/, $mode) { 
845                drawTextPos ($lon1{$wayNodes1[0]}, $lat1{$wayNodes1[0]}, 0, 0, $wayUser2, "orange", 2) ; 
846                drawTextPos ($lon1{$wayNodes1[0]}, $lat1{$wayNodes1[0]}, 0, -8, $ref1 . "->" . $ref2, "black", 2) ; 
847        }
848}
849
850sub paintReclassifiedWay {
851        drawWay ("pink", 3, nodes2Coordinates1 (@wayNodes1) ) ;
852        if (grep /D/, $mode) { 
853                drawTextPos ($lon1{$wayNodes1[0]}, $lat1{$wayNodes1[0]}, 0, 0, $wayUser2, "pink", 2) ; 
854                drawTextPos ($lon1{$wayNodes1[0]}, $lat1{$wayNodes1[0]}, 0, -8, $class1 . "->" . $class2, "black", 2) ; 
855        }
856}
857
858sub paintMovedWay {
859}
860
861
862sub paintNewNode {
863        drawNodeDot ($nodeLon2, $nodeLat2, "black", 4) ;
864        if (grep /D/, $mode) { drawTextPos ($nodeLon2, $nodeLat2, 0, 0, $nodeUser2, "black", 2) ; }
865}
866
867sub paintDeletedNode {
868        drawNodeDot ($nodeLon1, $nodeLat1, "red", 4) ;
869}
870
871sub paintDeletedNodeWithTag {
872        drawNodeDot ($nodeLon1, $nodeLat1, "red", 5) ;
873}
874
875sub paintRenamedNode {
876        drawNodeDot ($nodeLon1, $nodeLat1, "orange", 4) ;
877        if (grep /D/, $mode) { 
878                drawTextPos ($nodeLon1, $nodeLat1, 0, 0, $nodeUser2, "orange", 2) ; 
879                drawTextPos ($nodeLon1, $nodeLat1, 0, -8, $name1 . "->" . $name2, "black", 2) ; 
880        }
881}
882
883sub paintMovedNode {
884        # blue
885        drawNodeDot ($nodeLon1, $nodeLat1, "lightblue", 4) ;
886        drawWay ("lightblue", 1, ($nodeLon1, $nodeLat1, $nodeLon2, $nodeLat2) ) ;
887        drawNodeDot ($nodeLon2, $nodeLat2, "blue", 4) ;
888        if (grep /D/, $mode) { drawTextPos ($nodeLon1, $nodeLat1, 0, 0, $nodeUser2, "blue", 2) ; }
889}
890
891sub paintAreas {
892        foreach my $user (keys %minLon) {
893                drawWay ("tomato", 1, $minLon{$user}, $minLat{$user}, $minLon{$user}, $maxLat{$user}, $maxLon{$user}, $maxLat{$user}, $maxLon{$user}, $minLat{$user}, $minLon{$user}, $minLat{$user} ) ;
894                drawTextPos ($minLon{$user}, $minLat{$user}, 0, 0, $user, "black", 2) ;
895        }
896}
897
898sub paintPlace {
899        my ($lon, $lat, $name) = @_ ;
900        drawTextPos ($lon, $lat, 0, 0, $name, "black", 4) ;     
901        drawNodeDot ($lon, $lat, "black", 2) ;
902}
903
904sub initializeMap {
905        print "initializing map...\n" ;
906        print "- parsing nodes file1...\n" ;
907        my $lonMax = -999 ; my $lonMin = 999 ; my $latMax = -999 ; my $latMin = 999 ;
908        openOsm1File ($osm1Name) ;
909        moveNodeFile1() ;       
910
911        # get all node information from file 1         
912        while ($nodeId1 != -1) {
913                $lon1{$nodeId1} = $nodeLon1 ; $lat1{$nodeId1} = $nodeLat1 ;
914                if ($nodeLon1 > $lonMax) { $lonMax = $nodeLon1 ; }
915                if ($nodeLat1 > $latMax) { $latMax = $nodeLat1 ; }
916                if ($nodeLon1 < $lonMin) { $lonMin = $nodeLon1 ; }
917                if ($nodeLat1 < $latMin) { $latMin = $nodeLat1 ; }
918                # next
919                moveNodeFile1() ;       
920        }
921        initGraph ($sizeX, $lonMin, $latMin, $lonMax, $latMax) ;
922        if (grep /S/, $mode) {
923                enableSVG() ;
924        }
925
926        # ways
927        print "- parsing ways file1...\n" ;
928        moveWayFile1() ;
929        while ($wayId1 != -1) {
930                drawWay ("lightgray", 1, nodes2Coordinates1 (@wayNodes1) ) ;
931                moveWayFile1() ;
932        }
933        closeOsm1File() ;
934
935        print "- parsing nodes file2...\n" ;
936        openOsm2File ($osm2Name) ;
937        moveNodeFile2() ;
938
939        # get all node information from file 2
940        while ($nodeId2 != -1) {
941                $lon2{$nodeId2} = $nodeLon2 ; $lat2{$nodeId2} = $nodeLat2 ;
942                # next
943                moveNodeFile2() ;
944        }
945        closeOsm2File() ;
946
947        print "done.\n" ;
948}
949
950sub saveMap {
951        print "saving map...\n" ;
952        drawHead ($program . " ". $version . " by Gary68", "black", 3) ;
953        drawFoot ("data by openstreetmap.org" . " " . $osm1Name . " " .ctime(stat($osm1Name)->mtime) . $osm2Name . " " .ctime(stat($osm2Name)->mtime), "black", 3) ;
954        drawLegend (3, "New", "black", "Deleted", "red", "Moved", "blue", "Renamed", "orange", "Reclassified", "pink", "User Area", "tomato") ;
955        drawRuler ("black") ;
956        my ($pngName) = $htmlName ;
957        $pngName =~ s/.htm/.png/ ;
958        writeGraph ($pngName) ; 
959        if (grep /S/, $mode) {
960                my ($svgName) = $htmlName ;
961                $svgName =~ s/.htm/.svg/ ;
962                writeSVG ($svgName) ; 
963        }
964        print "done.\n" ;
965}
966
967sub nodes2Coordinates1 {
968        my @nodes = @_ ;
969        my $i ;
970        my @result = () ;
971        for ($i=0; $i<=$#nodes; $i++) {
972                push @result, $lon1{$nodes[$i]} ;
973                push @result, $lat1{$nodes[$i]} ;
974        }
975        return @result ;
976}
977
978sub nodes2Coordinates2 {
979        my @nodes = @_ ;
980        my $i ;
981        my @result = () ;
982        for ($i=0; $i<=$#nodes; $i++) {
983                push @result, $lon2{$nodes[$i]} ;
984                push @result, $lat2{$nodes[$i]} ;
985        }
986        return @result ;
987}
988
989
990
991#------------------------------------------------------------------------------------
992# Basic object operations
993#------------------------------------------------------------------------------------
994
995sub getNode1 {
996        my ($id, $version, $timestamp, $uid, $user, $changeset, $lat, $lon) ;
997        my @gTags = () ;
998        if($line1 =~ /^\s*\<node/) {
999                if (! grep /changeset/, $line1) { $line1 =~ s/lat=/changeset=\"0\" lat=/ ; }
1000                if ( (grep /user=/, $line1) and (grep /uid=/, $line1) ) {
1001                        ($id, $version, $timestamp, $uid, $user, $changeset, $lat, $lon) = 
1002                        ($line1 =~ /^\s*\<node id=[\'\"](\d+)[\'\"].+version=[\'\"](\d+)[\'\"].+timestamp=[\'\"](.+)[\'\"].+uid=[\'\"](.+)[\'\"].+user=[\'\"](.+)[\'\"].+changeset=[\'\"](\d+)[\'\"].+lat=[\'\"](.+)[\'\"].+lon=[\'\"](.+)[\'\"]/) ;
1003                }
1004                else {
1005                        ($id, $version, $timestamp, $changeset, $lat, $lon) = 
1006                        ($line1 =~ /^\s*\<node id=[\'\"](\d+)[\'\"].+version=[\'\"](\d+)[\'\"].+timestamp=[\'\"](.+)[\'\"].+changeset=[\'\"](\d+)[\'\"].+lat=[\'\"](.+)[\'\"].+lon=[\'\"](.+)[\'\"]/) ;
1007                        $user = "unknown" ; $uid = 0 ;
1008                }
1009                if (!defined $user) { $user = "unknown" ; }
1010                if (!defined $uid) { $uid = 0 ; }
1011
1012                if (!$id or (! (defined ($lat))) or ( ! (defined ($lon))) ) {
1013                        print "WARNING reading osm file1, line follows (expecting id, lon, lat and user for node):\n", $line1, "\n" ; 
1014                }
1015                else {
1016                        if ( (grep (/">/, $line1)) or (grep (/'>/, $line1)) ) {                  # more lines, get tags
1017                                nextLine1() ;
1018                                while (!grep(/<\/node>/, $line1)) {
1019                                        my ($k, $v) = ($line1 =~ /^\s*\<tag k=[\'\"](.+)[\'\"]\s*v=[\'\"](.+)[\'\"]/) ;
1020                                        if ( (defined ($k)) and (defined ($v)) ) {
1021                                                my $tag = [$k, $v] ; push @gTags, $tag ;
1022                                        }
1023                                        else { 
1024                                                #print "WARNING tag not recognized file1: ", $line1, "\n" ;
1025                                        }
1026                                        nextLine1() ;
1027                                }
1028                                nextLine1() ;
1029                        }
1030                        else {
1031                                nextLine1() ;
1032                        }
1033                }
1034        }
1035        else {
1036                return (-1, -1, -1, -1, -1) ; 
1037        } # node
1038        return ($id, $version, $timestamp, $uid, $user, $changeset, $lat, $lon, \@gTags) ; # in main @array = @$ref
1039} # getNode1
1040
1041sub getNodeFile2 {
1042        my ($id, $version, $timestamp, $uid, $user, $changeset, $lat, $lon) ;
1043        my @gTags = () ;
1044        if($line2 =~ /^\s*\<node/) {
1045                if (! grep /changeset/, $line2) { $line2 =~ s/lat=/changeset=\"0\" lat=/ ; }
1046                if ( (grep /user=/, $line2) and (grep /uid=/, $line2) ) {
1047                        ($id, $version, $timestamp, $uid, $user, $changeset, $lat, $lon) = 
1048                        ($line2 =~ /^\s*\<node id=[\'\"](\d+)[\'\"].+version=[\'\"](\d+)[\'\"].+timestamp=[\'\"](.+)[\'\"].+uid=[\'\"](.+)[\'\"].+user=[\'\"](.+)[\'\"].+changeset=[\'\"](\d+)[\'\"].+lat=[\'\"](.+)[\'\"].+lon=[\'\"](.+)[\'\"]/) ;
1049                }
1050                else {
1051                        ($id, $version, $timestamp, $changeset, $lat, $lon) = 
1052                        ($line2 =~ /^\s*\<node id=[\'\"](\d+)[\'\"].+version=[\'\"](\d+)[\'\"].+timestamp=[\'\"](.+)[\'\"].+changeset=[\'\"](\d+)[\'\"].+lat=[\'\"](.+)[\'\"].+lon=[\'\"](.+)[\'\"]/) ;
1053                        $user = "unknown" ; $uid = 0 ;
1054                }
1055                if (!defined $user) { $user = "unknown" ; }
1056                if (!defined $uid) { $uid = 0 ; }
1057
1058                if (!$id or (! (defined ($lat))) or ( ! (defined ($lon))) ) {
1059                        print "WARNING reading osm file 2, line follows (expecting id, lon, lat and user for node):\n", $line2, "\n" ; 
1060                }
1061                else {
1062                        if ( (grep (/">/, $line2)) or (grep (/'>/, $line2)) ) {                  # more lines, get tags
1063                                nextLine2() ;
1064                                while (!grep(/<\/node>/, $line2)) {
1065                                        my ($k, $v) = ($line2 =~ /^\s*\<tag k=[\'\"](.+)[\'\"]\s*v=[\'\"](.+)[\'\"]/) ;
1066                                        if ( (defined ($k)) and (defined ($v)) ) {
1067                                                my $tag = [$k, $v] ; push @gTags, $tag ;
1068                                        }
1069                                        else { 
1070                                                #print "WARNING tag not recognized file 2: ", $line2, "\n" ;
1071                                        }
1072                                        nextLine2() ;
1073                                }
1074                                nextLine2() ;
1075                        }
1076                        else {
1077                                nextLine2() ;
1078                        }
1079                }
1080        }
1081        else {
1082                return (-1, -1, -1, -1, -1) ; 
1083        } # node
1084        return ($id, $version, $timestamp, $uid, $user, $changeset, $lat, $lon, \@gTags) ; # in main @array = @$ref
1085} # getNodeFile2
1086
1087
1088
1089sub getWay1 {
1090        my $id ; my $u ; my @tags ; my @nodes ; my $version ; my $timestamp ; my $uid ; my $changeset ;
1091        if($line1 =~ /^\s*\<way/) {
1092
1093                if (! grep /changeset/, $line1) { $line1 =~ s/\">/\" changeset=\"0\">/ ; }
1094                if ( (grep /user=/, $line1) and (grep /uid=/, $line1) ) {
1095                        ($id, $version, $timestamp, $uid, $u, $changeset) = ($line1 =~ /^\s*\<way id=[\'\"](\d+)[\'\"].+version=[\'\"](\d+)[\'\"].+timestamp=[\'\"](.+)[\'\"].+uid=[\'\"](\d+)[\'\"].+user=[\'\"](.+)[\'\"].+changeset=[\'\"](\d+)[\'\"]>/) ;
1096                }
1097                else {
1098                        ($id, $version, $timestamp, $changeset) = ($line1 =~ /^\s*\<way id=[\'\"](\d+)[\'\"].+version=[\'\"](\d+)[\'\"].+timestamp=[\'\"](.+)[\'\"].+changeset=[\'\"](\d+)[\'\"]>/) ;
1099                        $uid = 0 ; $u = "unknown" ;
1100                }
1101
1102                if (!$u) { $u = "unknown" ; }
1103                if (!$id) { print "ERROR reading osm file1, line follows (expecting way id):\n", $line1, "\n" ; }
1104                unless ($id) { next; }
1105                nextLine1() ;
1106                while (not($line1 =~ /\/way>/)) { # more way data
1107                        my ($node) = ($line1 =~ /^\s*\<nd ref=[\'\"](\d+)[\'\"]/); # get node id
1108                        my ($k, $v) = ($line1 =~ /^\s*\<tag k=[\'\"](.+)[\'\"]\s*v=[\'\"](.+)[\'\"]/) ;
1109                        if ($node) {
1110                                push @nodes, $node ;
1111                        }
1112                        if ($k and defined($v)) { my $tag = [$k, $v] ; push @tags, $tag ; }
1113                        nextLine1() ;
1114                }
1115                nextLine1() ;
1116        }
1117        else {
1118                return (-1, -1, -1, -1, -1, -1, -1, -1) ;
1119        }
1120        return ($id, $version, $timestamp, $uid, $u, $changeset, \@nodes, \@tags) ;
1121} # getWay1
1122
1123sub getWayFile2 {
1124        my $id ; my $u ; my @tags ; my @nodes ; my $version ; my $timestamp ; my $uid ; my $changeset ;
1125        if($line2 =~ /^\s*\<way/) {
1126
1127                if (! grep /changeset/, $line2) { $line2 =~ s/\">/\" changeset=\"0\">/ ; }
1128                if ( (grep /user=/, $line2) and (grep /uid=/, $line2) ) {
1129                        ($id, $version, $timestamp, $uid, $u, $changeset) = ($line2 =~ /^\s*\<way id=[\'\"](\d+)[\'\"].+version=[\'\"](\d+)[\'\"].+timestamp=[\'\"](.+)[\'\"].+uid=[\'\"](\d+)[\'\"].+user=[\'\"](.+)[\'\"].+changeset=[\'\"](\d+)[\'\"]>/) ;
1130                }
1131                else {
1132                        ($id, $version, $timestamp, $changeset) = ($line2 =~ /^\s*\<way id=[\'\"](\d+)[\'\"].+version=[\'\"](\d+)[\'\"].+timestamp=[\'\"](.+)[\'\"].+changeset=[\'\"](\d+)[\'\"]>/) ;
1133                        $uid = 0 ; $u = "unknown" ;
1134                }
1135                if (!$u) { $u = "unknown" ; }
1136                if (!$id) { print "ERROR reading osm file2, line follows (expecting way id):\n", $line1, "\n" ; }
1137                unless ($id) { next; }
1138                nextLine2() ;
1139                while (not($line2 =~ /\/way>/)) { # more way data
1140                        my ($node) = ($line2 =~ /^\s*\<nd ref=[\'\"](\d+)[\'\"]/); # get node id
1141                        my ($k, $v) = ($line2 =~ /^\s*\<tag k=[\'\"](.+)[\'\"]\s*v=[\'\"](.+)[\'\"]/) ;
1142                        if ($node) {
1143                                push @nodes, $node ;
1144                        }
1145                        if ($k and defined($v)) { my $tag = [$k, $v] ; push @tags, $tag ; }
1146                        nextLine2() ;
1147                }
1148                nextLine2() ;
1149        }
1150        else {
1151                return (-1, -1, -1, -1, -1, -1, -1, -1) ;
1152        }
1153        return ($id, $version, $timestamp, $uid, $u, $changeset, \@nodes, \@tags) ;
1154} # getWayFile2
1155
1156
1157sub moveNodeFile1 {
1158        ($nodeId1, $nodeVersion1, $nodeTimestamp1, $nodeUid1, $nodeUser1, $nodeChangeset1, $nodeLat1, $nodeLon1, $aRef1) = getNode1 () ;
1159        if ($nodeId1 != -1) {
1160                @nodeTags1 = @$aRef1 ;
1161        }
1162}
1163
1164sub moveNodeFile2 {
1165        ($nodeId2, $nodeVersion2, $nodeTimestamp2, $nodeUid2, $nodeUser2, $nodeChangeset2, $nodeLat2, $nodeLon2, $aRef1) = getNodeFile2 () ;
1166        if ($nodeId2 != -1) {
1167                @nodeTags2 = @$aRef1 ;
1168        }
1169}
1170
1171sub moveWayFile1 {
1172        ($wayId1, $wayVersion1, $wayTimestamp1, $wayUid1, $wayUser1, $wayChangeset1, $aRef1, $aRef2) = getWay1() ;
1173        if ($wayId1 != -1) {
1174                @wayNodes1 = @$aRef1 ;
1175                @wayTags1 = @$aRef2 ;
1176        }
1177}
1178
1179sub moveWayFile2 {
1180        ($wayId2, $wayVersion2, $wayTimestamp2, $wayUid2, $wayUser2, $wayChangeset2, $aRef1, $aRef2) = getWayFile2() ;
1181        if ($wayId2 != -1) {
1182                @wayNodes2 = @$aRef1 ;
1183                @wayTags2 = @$aRef2 ;
1184        }
1185}
1186
1187
1188#------------------------------------------------------------------------------------
1189# Basic file operations
1190#------------------------------------------------------------------------------------
1191
1192sub openOsm1File {
1193        $file1Name = shift ;
1194        if (grep /.bz2/, $file1Name) { $isBz21 = 1 ; } else { $isBz21 = 0 ; }
1195        if ($isBz21) {
1196                $bz1 = bzopen($file1Name, "rb") or die "Cannot open $file1Name: $bzerrno\n" ;
1197        }
1198        else {
1199                open ($file1, "<", $file1Name) || die "can't open osm file1" ;
1200        }
1201        nextLine1() ;           
1202        while ( ! (grep /\<node/, $line1) ) {
1203                nextLine1() ;
1204        }
1205        return 1 ;
1206}
1207
1208sub closeOsm1File {
1209        if ($isBz21) { $bz1->bzclose() ; }
1210        else { close ($file1) ; }
1211}
1212
1213sub nextLine1 {
1214        if ($isBz21) { $bz1->bzreadline($line1) ; }
1215        else { $line1 = <$file1> ; }
1216}
1217
1218sub openOsm2File {
1219        $file2Name = shift ;
1220        if (grep /.bz2/, $file2Name) { $isBz22 = 1 ; } else { $isBz22 = 0 ; }
1221        if ($isBz22) {
1222                $bz2 = bzopen($file2Name, "rb") or die "Cannot open $file2Name: $bzerrno\n" ;
1223        }
1224        else {
1225                open ($file2, "<", $file2Name) || die "can't open osm file2" ;
1226        }
1227        nextLine2() ;           
1228        while ( ! (grep /\<node/, $line2) ) {
1229                nextLine2() ;
1230        }
1231        return 1 ;
1232}
1233
1234sub closeOsm2File {
1235        if ($isBz22) { $bz2->bzclose() ; }
1236        else { close ($file2) ; }
1237}
1238
1239sub nextLine2 {
1240        if ($isBz22) { $bz2->bzreadline($line2) ; }
1241        else { $line2 = <$file2> ; }
1242}
1243
Note: See TracBrowser for help on using the repository browser.