#!/usr/bin/perl use strict; use warnings; use Data::Dumper; package EnerTree; use Moose; use List::Util qw /max/; has 'title' => ( is => 'rw' ); has 'follow_ups' => ( is => 'rw', isa => 'ArrayRef', default => sub {[]} ); my %lut_fuse = ( # guessing NYM 2 => 1.5, 4 => 1.5, 6 => 1.5, 10 => 1.5, 13 => 1.5, 16 => 1.5, 20 => 2.5, 25 => 2.5, 35 => 4, 40 => 6, 63 => 10, 80 => 16, ); sub add_follow_up { my $self = shift; my $other = shift; die "add_follow_up(): wrong argument type\n" unless (blessed $other eq 'Wire' or blessed $other eq 'Fuse'); push @{$self->follow_ups}, $other; } sub get_tree_resistance { my $self = shift; my $r = $self->get_resistance; my @fr = map { $_->get_tree_resistance } @{$self->follow_ups}; my $fr = max @fr; $r += $fr if defined($fr) and $fr > 0; return $r; } sub check_selectivity { my $self = shift; my $prev = shift || 100; my $hook = sub { warn $self->title . '/' . $self->rated_current . ' is not selectiv to: ' . $prev }; if (blessed $self eq 'Fuse') { $hook->() if ($self->rated_current > $prev / 1.6); $prev = $self->rated_current; } $_->check_selectivity($prev) for @{$self->follow_ups}; return; } 1; package Fuse; use Data::Dumper; use Moose; extends 'EnerTree'; has 'rated_current' => ( is => 'rw', isa => 'Num' ); sub get_resistance { return 0 }; override 'get_tree_resistance' => sub { my $self = shift; my $r = super(); my $voltage_drop = $r * $self->rated_current; print "voltage_drop: " . $voltage_drop . "\n"; warn "after: " . $self->title . " voltage drop exceeds limit of 3%!\n" if $voltage_drop > 0.03 * 230; return $r; }; sub check_width { my $self = shift; my $hook = sub { warn $self->title .' is to big for : ' . shift }; for (@{$self->follow_ups}) { $hook->($_->width) if $_->width < $lut_fuse{$self->rated_current}; } return; } 1; package Wire; use Moose; extends 'EnerTree'; has 'len' => ( is => 'rw', isa => 'Num' ); has 'width' => ( is => 'rw', isa => 'Num', default => 1.5 ); has 'type' => ( is => 'rw' ); has 'specific_resistance' => ( is => 'rw', isa => 'Num', default => 1/56.0 ); sub get_resistance { my $self = shift; return 2 * (($self->len * $self->specific_resistance) / $self->width); } 1; package main; my $w1 = Wire->new( width => 35, len => 200, specific_resistance => 1/37.8 ); my $w2 = Wire->new( width => 10, len => 12 ); my $w3 = Wire->new( len => 22 ); my $f1 = Fuse->new( title => 'F1', rated_current => 20 ); my $w4 = Wire->new( len => 19 ); $w1->add_follow_up( $w2 ); $w2->add_follow_up( $w3 ); $w2->add_follow_up( $f1 ); $f1->add_follow_up( $w4 ); print Dumper $w1; # # print $w1->get_resistance . "\n"; # print $w2->get_resistance . "\n"; # print $w3->get_resistance . "\n"; # print $w4->get_resistance . "\n"; # my $r_all = $w1->get_tree_resistance; $w1->check_selectivity; $f1->check_width; print $r_all . "\n"; print "max Ik: " . 230 / $r_all . "\n";