File Coverage

blib/lib/App/Math/Tutor/Cmd/VulFrac/Cmd/Mul.pm
Criterion Covered Total %
statement 56 73 76.7
branch 14 24 58.3
condition 8 26 30.7
subroutine 8 9 88.8
pod n/a
total 86 132 65.1


line stmt bran cond sub pod time code
1             package App::Math::Tutor::Cmd::VulFrac::Cmd::Mul;
2              
3 1     1   21997 use warnings;
  1         2  
  1         35  
4 1     1   5 use strict;
  1         2  
  1         37  
5              
6 1     1   4 use vars qw(@ISA $VERSION);
  1         2  
  1         81  
7              
8             =head1 NAME
9              
10             App::Math::Tutor::Cmd::VulFrac::Cmd::Mul - Plugin for multiplication and division of vulgar fraction
11              
12             =cut
13              
14             our $VERSION = '0.004';
15              
16 1     1   4 use Moo;
  1         2  
  1         8  
17 1     1   287 use MooX::Cmd;
  1         2  
  1         8  
18 1     1   1711 use MooX::Options;
  1         1  
  1         8  
19              
20             has template_filename => (
21             is => "ro",
22             default => "twocols"
23             );
24              
25             with "App::Math::Tutor::Role::VulFracExercise";
26              
27             my %result_formats = (
28             keep => 1,
29             reducable => 1,
30             );
31              
32             =head1 ATTRIBUTES
33              
34             =head2 result_format
35              
36             Allows controlling of accepted format of exercise output
37              
38             =cut
39              
40             option result_format => (
41             is => "ro",
42             predicate => 1,
43             doc => "Let one specify result format behavior",
44             long_doc => "Let one specify result format behavior, pick one of\n\n"
45             . "reducable: result can be reduced, "
46             . "keep: keep exercise format (after reducing)",
47             coerce => sub {
48             defined $_[0] or return {};
49             "HASH" eq ref $_[0] and return $_[0];
50             my ( @fail, %rf );
51             $rf{$_} = defined $result_formats{$_} or push @fail, $_ foreach @{ $_[0] };
52             @fail
53             and die "Invalid result format: "
54             . join( ", ", @fail )
55             . ", pick any of "
56             . join( ", ", keys %result_formats );
57             return \%rf;
58             },
59             format => "s@",
60             autosplit => ",",
61             repeatable => 1,
62             short => "r",
63             );
64              
65             sub _build_command_names
66             {
67 0     0   0 return qw(mul div);
68             }
69              
70             my $a_mult_b = sub {
71             return
72             ProdNum->new( operator => $_[0],
73             values => [ splice @_, 1 ] );
74             };
75              
76             sub _operands_ok
77             {
78 30     30   41 my ( $self, $op, @operands ) = @_;
79 30 50       124 $self->has_result_format or return 1;
80 0         0 my $s = shift @operands;
81 0         0 while (@operands)
82             {
83 0         0 my $b = shift @operands;
84 0         0 my $a = $s->_reduce;
85 0         0 $b = $b->_reduce;
86 0 0       0 $op eq "/" and $b = $b->_reciprocal;
87 0         0 $s = VulFrac->new(
88             num => int( $a_mult_b->( "*", $a->sign * $a->num, $b->sign * $b->num ) ),
89             denum => int( $a_mult_b->( "*", $a->denum, $b->denum ) ) );
90             }
91 0         0 my ( $max_num, $max_denum ) = ( @{ $_[0]->format } );
  0         0  
92 0         0 my %result_format = %{ $self->result_format };
  0         0  
93 0 0 0     0 $s->_gcd > 1 or return 0 if defined $result_format{reducable} and $result_format{reducable};
      0        
94 0         0 $s = $s->_reduce;
95 0 0 0     0 $s->num <= $max_num or return 0 if defined $result_format{keep} and $result_format{keep};
      0        
96 0 0 0     0 $s->denum <= $max_denum or return 0 if defined $result_format{keep} and $result_format{keep};
      0        
97 0         0 return 1;
98             }
99              
100             sub _build_exercises
101             {
102 1     1   31 my ($self) = @_;
103              
104 1         2 my (@tasks);
105 1         7 foreach my $i ( 1 .. $self->quantity )
106             {
107 15         15 my @line;
108 15         17 foreach my $j ( 0 .. 1 )
109             {
110 30         76 REDO: my ( $a, $b ) = $self->get_vulgar_fractions(2);
111 30 100       86 $self->_operands_ok( $j ? '/' : '*', $a, $b ) or goto REDO;
    50          
112 30         76 push @line, [ $a, $b ];
113             }
114 15         31 push @tasks, \@line;
115             }
116              
117 1         11 my $exercises = {
118             section => "Vulgar fraction multiplication / division",
119             caption => 'Fractions',
120             label => 'vulgar_fractions_multiplication',
121             header => [ [ 'Vulgar Fraction Multiplication', 'Vulgar Fraction Division' ] ],
122             solutions => [],
123             challenges => [],
124             };
125              
126 1         3 foreach my $line (@tasks)
127             {
128 15         14 my ( @solution, @challenge );
129              
130 15         20 foreach my $i ( 0 .. 1 )
131             {
132 30         33 my ( $a, $b ) = @{ $line->[$i] };
  30         56  
133 30 100       52 my $op = $i ? '/' : '*';
134 30         53 push @challenge, sprintf( '$ %s = $', $a_mult_b->( $op, $a, $b ) );
135              
136 30         70 my @way; # remember Frank Sinatra :)
137 30         58 push @way, $a_mult_b->( $op, $a, $b );
138              
139 30 100 50     616 ( $a, $b ) = ( $a->_reduce, $b = $b->_reduce ) and push @way, $a_mult_b->( $op, $a, $b )
      100        
140             if ( $a->_gcd > 1 or $b->_gcd > 1 );
141              
142 30 100       294 if ($i)
143             {
144 15         41 $b = $b->_reciprocal;
145 15         236 $op = '*';
146 15         29 push @way, $a_mult_b->( $op, $a, $b );
147             }
148              
149 30         357 my $s = VulFrac->new(
150             num => $a_mult_b->( $op, $a->sign * $a->num, $b->sign * $b->num ),
151             denum => $a_mult_b->( $op, $a->denum, $b->denum ) );
152 30         485 push @way, $s;
153 30         95 $s = VulFrac->new(
154             num => int( $s->num ),
155             denum => int( $s->denum ),
156             sign => $s->sign
157             );
158 30         524 push @way, $s;
159              
160 30 100 66     76 $s->_gcd > 1 and $s = $s->_reduce and push @way, $s;
161              
162 30 100 66     160 $s->num > $s->denum and $s->denum > 1 and push @way, $s->_stringify(1);
163              
164 30         187 push( @solution, '$ ' . join( " = ", @way ) . ' $' );
165             }
166              
167 15         19 push( @{ $exercises->{solutions} }, \@solution );
  15         33  
168 15         18 push( @{ $exercises->{challenges} }, \@challenge );
  15         35  
169             }
170              
171 1         54 return $exercises;
172             }
173              
174             =head1 LICENSE AND COPYRIGHT
175              
176             Copyright 2010-2014 Jens Rehsack.
177              
178             This program is free software; you can redistribute it and/or modify it
179             under the terms of either: the GNU General Public License as published
180             by the Free Software Foundation; or the Artistic License.
181              
182             See http://dev.perl.org/licenses/ for more information.
183              
184             =cut
185              
186             1;