File Coverage

blib/lib/App/Math/Tutor/Cmd/VulFrac/Cmd/Mul.pm
Criterion Covered Total %
statement 18 73 24.6
branch 0 24 0.0
condition 0 27 0.0
subroutine 6 9 66.6
pod n/a
total 24 133 18.0


line stmt bran cond sub pod time code
1             package App::Math::Tutor::Cmd::VulFrac::Cmd::Mul;
2              
3 1     1   15417 use warnings;
  1         2  
  1         37  
4 1     1   4 use strict;
  1         1  
  1         35  
5              
6 1     1   4 use vars qw(@ISA $VERSION);
  1         1  
  1         66  
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.005';
15              
16 1     1   4 use Moo;
  1         1  
  1         7  
17 1     1   276 use MooX::Cmd;
  1         2  
  1         7  
18 1     1   1567 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: " . join( ", ", @fail ) . ", pick any of " . join( ", ", keys %result_formats );
54             \%rf;
55             },
56             format => "s@",
57             autosplit => ",",
58             repeatable => 1,
59             short => "r",
60             );
61              
62 0     0     sub _build_command_names { qw(mul div); }
63              
64             my $a_mult_b = sub {
65             ProdNum->new(
66             operator => $_[0],
67             values => [ splice @_, 1 ]
68             );
69             };
70              
71             sub _operands_ok
72             {
73 0     0     my ( $self, $op, @operands ) = @_;
74 0 0         $self->has_result_format or return 1;
75 0           my $s = shift @operands;
76 0           while (@operands)
77             {
78 0           my $b = shift @operands;
79 0           my $a = $s->_reduce;
80 0           $b = $b->_reduce;
81 0 0         $op eq "/" and $b = $b->_reciprocal;
82 0           $s = VulFrac->new(
83             num => int( $a_mult_b->( "*", $a->sign * $a->num, $b->sign * $b->num ) ),
84             denum => int( $a_mult_b->( "*", $a->denum, $b->denum ) )
85             );
86             }
87 0           my ( $max_num, $max_denum ) = ( @{ $_[0]->format } );
  0            
88 0           my %result_format = %{ $self->result_format };
  0            
89 0 0 0       $s->_gcd > 1 or return 0 if defined $result_format{reducable} and $result_format{reducable};
      0        
90 0           $s = $s->_reduce;
91 0 0 0       $s->num <= $max_num or return 0 if defined $result_format{keep} and $result_format{keep};
      0        
92 0 0 0       $s->denum <= $max_denum or return 0 if defined $result_format{keep} and $result_format{keep};
      0        
93 0           1;
94             }
95              
96             sub _build_exercises
97             {
98 0     0     my ($self) = @_;
99              
100 0           my (@tasks);
101 0           foreach my $i ( 1 .. $self->quantity )
102             {
103 0           my @line;
104 0           foreach my $j ( 0 .. 1 )
105             {
106 0           REDO: my ( $a, $b ) = $self->get_vulgar_fractions(2);
107 0 0         $self->_operands_ok( $j ? '/' : '*', $a, $b ) or goto REDO;
    0          
108 0           push @line, [ $a, $b ];
109             }
110 0           push @tasks, \@line;
111             }
112              
113 0           my $exercises = {
114             section => "Vulgar fraction multiplication / division",
115             caption => 'Fractions',
116             label => 'vulgar_fractions_multiplication',
117             header => [ [ 'Vulgar Fraction Multiplication', 'Vulgar Fraction Division' ] ],
118             solutions => [],
119             challenges => [],
120             };
121              
122 0           foreach my $line (@tasks)
123             {
124 0           my ( @solution, @challenge );
125              
126 0           foreach my $i ( 0 .. 1 )
127             {
128 0           my ( $a, $b ) = @{ $line->[$i] };
  0            
129 0 0         my $op = $i ? '/' : '*';
130 0           push @challenge, sprintf( '$ %s = $', $a_mult_b->( $op, $a, $b ) );
131              
132 0           my @way; # remember Frank Sinatra :)
133 0           push @way, $a_mult_b->( $op, $a, $b );
134              
135 0 0 0       ( $a, $b ) = ( $a->_reduce, $b = $b->_reduce ) and push @way, $a_mult_b->( $op, $a, $b )
      0        
136             if ( $a->_gcd > 1 or $b->_gcd > 1 );
137              
138 0 0         if ($i)
139             {
140 0           $b = $b->_reciprocal;
141 0           $op = '*';
142 0           push @way, $a_mult_b->( $op, $a, $b );
143             }
144              
145 0           my $s = VulFrac->new(
146             num => $a_mult_b->( $op, $a->sign * $a->num, $b->sign * $b->num ),
147             denum => $a_mult_b->( $op, $a->denum, $b->denum )
148             );
149 0           push @way, $s;
150 0           $s = VulFrac->new(
151             num => int( $s->num ),
152             denum => int( $s->denum ),
153             sign => $s->sign
154             );
155 0           push @way, $s;
156              
157 0 0 0       $s->_gcd > 1 and $s = $s->_reduce and push @way, $s;
158              
159 0 0 0       $s->num > $s->denum and $s->denum > 1 and push @way, $s->_stringify(1);
160              
161 0           push( @solution, '$ ' . join( " = ", @way ) . ' $' );
162             }
163              
164 0           push( @{ $exercises->{solutions} }, \@solution );
  0            
165 0           push( @{ $exercises->{challenges} }, \@challenge );
  0            
166             }
167              
168 0           $exercises;
169             }
170              
171             =head1 LICENSE AND COPYRIGHT
172              
173             Copyright 2010-2014 Jens Rehsack.
174              
175             This program is free software; you can redistribute it and/or modify it
176             under the terms of either: the GNU General Public License as published
177             by the Free Software Foundation; or the Artistic License.
178              
179             See http://dev.perl.org/licenses/ for more information.
180              
181             =cut
182              
183             1;