summaryrefslogtreecommitdiff
path: root/bin/umlauf-to-dot
blob: c884e26c2191f1343b121fd17429babd58b621f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/usr/bin/env perl

use strict;
use warnings;
use 5.020;
use utf8;

use File::Slurp qw(read_file);
use JSON;
use List::Util qw(uniq);

sub show_usage {
	my ($exit_code) = @_;

	say STDERR
"Usage: umlauf-to-dot <wagenreihung.json> [line number] | dot -Tpng > umlauf.png";

	exit $exit_code;
}

sub contained_in {
	my ( $value, @list ) = @_;

	for my $elem (@list) {
		if ( $elem eq $value ) {
			return 1;
		}
	}
	return;
}

sub format_train {
	my ( $train_no, $train ) = @_;

	return sprintf( '"%s %d\n%s\n%s"',
		$train->{type} // 'Zug',
		$train_no,
		$train->{route}{start} // $train->{route}{preStart} // '?',
		$train->{route}{end}   // $train->{route}{postEnd}  // '?' );
}

if ( @ARGV < 1 ) {
	show_usage(1);
}

my ( $file, $line ) = @ARGV;

my $file_content = read_file($file);
my $json         = JSON->new->utf8->decode($file_content);

my $map = $json->{train};

my @train_numbers;
if ($line) {
	my @queue = ($line);

	while (@queue) {
		my $train_number = pop @queue;
		push( @train_numbers, $train_number );
		my @candidates;
		push( @candidates, @{ $map->{$train_number}{cycle}{from} // [] } );
		push( @candidates, @{ $map->{$train_number}{cycle}{to}   // [] } );
		@candidates = uniq @candidates;
		@candidates
		  = grep { not contained_in( $_, @train_numbers, @queue ) } @candidates;
		if (@candidates) {
			printf( "# handle %s -> push %s\n",
				$train_number, join( " ", @candidates ) );
		}
		push( @queue, @candidates );
	}
}
else {
	@train_numbers = keys %{$map};
}

my @output;

for my $train_number (@train_numbers) {
	for my $from ( @{ $map->{$train_number}{cycle}{from} } ) {
		push(
			@output,
			sprintf( "%s -> %s;",
				format_train( $from,         $map->{$from} ),
				format_train( $train_number, $map->{$train_number} ) )
		);
	}
	for my $to ( @{ $map->{$train_number}{cycle}{to} } ) {
		push(
			@output,
			sprintf( "%s -> %s;",
				format_train( $train_number, $map->{$train_number} ),
				format_train( $to,           $map->{$to} ) )
		);
	}
}

say "digraph Umlauf {";
say join( "\n", uniq @output );
say "}"