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

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

useractivity bug fixes

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