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

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

useractivity with black and white lists

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