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

Last change on this file since 23856 was 23856, checked in by gary68, 9 years ago

bug in useractivity solved

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