77
88package Parser::Legacy::ObjectWithUnits ;
99
10+ # Refrences to problem specific copies of %Units::fundamental_units
11+ # and %Units::known_units. These should be passed to any Units function call.
12+ # They are set by the initializeUnits sub
13+ my $fundamental_units = ' ' ;
14+ my $known_units = ' ' ;
15+
1016sub name {' object' };
1117sub cmp_class {' an Object with Units' };
1218sub makeValue {
@@ -15,10 +21,46 @@ sub makeValue {
1521 Value::makeValue($value ,%options );
1622}
1723
24+ sub initializeUnits {
25+ $fundamental_units = shift ;
26+ $known_units = shift ;
27+ }
28+
1829sub new {
1930 my $self = shift ; my $class = ref ($self ) || $self ;
2031 my $context = (Value::isContext($_ [0]) ? shift : $self -> context);
21- my $num = shift ; my $units = shift ;
32+ my $num = shift ;
33+ # we need to check if units is the options hash
34+ my $units = shift ;
35+ my $options ;
36+
37+ if (ref ($units ) eq ' HASH' ) {
38+ $options = $units ;
39+ $units = ' ' ;
40+ } else {
41+ $options = shift ;
42+ }
43+
44+ # register a new unit/s if needed
45+ if (defined ($options -> {newUnit })) {
46+ my @newUnits ;
47+ if (ref ($options -> {newUnit }) eq ' ARRAY' ) {
48+ @newUnits = @{$options -> {newUnit }};
49+ } else {
50+ @newUnits = ($options -> {newUnit });
51+ }
52+
53+ foreach my $newUnit (@newUnits ) {
54+ if (ref ($newUnit ) eq ' HASH' ) {
55+ add_unit($newUnit -> {name }, $newUnit -> {conversion });
56+ } else {
57+ add_unit($newUnit );
58+ }
59+ }
60+ }
61+
62+
63+
2264 Value::Error(" You must provide a " .$self -> name) unless defined ($num );
2365 ($num ,$units ) = splitUnits($num ) unless $units ;
2466 Value::Error(" You must provide units for your " .$self -> name) unless $units ;
@@ -37,17 +79,18 @@ sub new {
3779#
3880# Find the units for the formula and split that off
3981#
40- my $aUnit = ' (?:' .getUnitNames().' )(?:\s*(?:\^|\*\*)\s*[-+]?\d+)?' ;
41- my $unitPattern = $aUnit .' (?:\s*[/* ]\s*' .$aUnit .' )*' ;
42- my $unitSpace = " ($aUnit ) +($aUnit )" ;
4382sub splitUnits {
83+ my $aUnit = ' (?:' .getUnitNames().' )(?:\s*(?:\^|\*\*)\s*[-+]?\d+)?' ;
84+ my $unitPattern = $aUnit .' (?:\s*[/* ]\s*' .$aUnit .' )*' ;
85+ my $unitSpace = " ($aUnit ) +($aUnit )" ;
4486 my $string = shift ;
45- my ($num ,$units ) = $string =~ m ! ^(.*?(?:[)}\] 0-9a-z]|\d\. ))\s *($unitPattern )\s *$ ! o ;
87+ my ($num ,$units ) = $string =~ m ! ^(.*?(?:[)}\] 0-9a-z]|\d\. ))\s *($unitPattern )\s *$ ! ;
4688 if ($units ) {
4789 while ($units =~ s / $unitSpace/ $1 *$2 / ) {};
4890 $units =~ s / // g ;
4991 $units =~ s /\*\* / ^/ g ;
5092 }
93+
5194 return ($num ,$units );
5295}
5396
@@ -57,18 +100,29 @@ sub splitUnits {
57100#
58101sub getUnitNames {
59102 local ($a ,$b );
103+ my $units = \%Units::known_units ;
104+ if ($known_units ) {
105+ $units = $known_units ;
106+ }
60107 join (' |' ,sort {
61108 return length ($b ) <=> length ($a ) if length ($a ) != length ($b );
62109 return $a cmp $b ;
63- } keys (%Units::known_units ));
110+ } keys (%$units ));
64111}
65112
66113#
67114# Get the units hash and fix up the errors
68115#
69116sub getUnits {
70117 my $units = shift ;
71- my %Units = Units::evaluate_units($units );
118+ my $options = {};
119+ if ($fundamental_units ) {
120+ $options -> {fundamental_units } = $fundamental_units ;
121+ }
122+ if ($known_units ) {
123+ $options -> {known_units } = $known_units ;
124+ }
125+ my %Units = Units::evaluate_units($units ,$options );
72126 if ($Units {ERROR }) {
73127 $Units {ERROR } =~ s / at ([^ ]+) line \d +(\n |.)*// ;
74128 $Units {ERROR } =~ s / ^UNIT ERROR:? *// ;
@@ -104,6 +158,7 @@ sub cmp_parse {
104158 #
105159 # Check that the units are defined and legal
106160 #
161+
107162 my ($num ,$units ) = splitUnits($ans -> {student_ans });
108163 unless (defined ($num ) && defined ($units ) && $units ne ' ' ) {
109164 $self -> cmp_Error($ans ," Your answer doesn't look like " .lc ($self -> cmp_class));
@@ -157,6 +212,31 @@ sub adjustCorrectValue {
157212
158213sub cmp_reparse {Value::cmp_parse(@_ )}
159214
215+ sub add_fundamental_unit {
216+ my $unit = shift ;
217+ $fundamental_units -> {$unit } = 0;
218+ }
219+
220+ sub add_unit {
221+ my $unit = shift ;
222+ my $hash = shift ;
223+
224+ unless (ref ($hash ) eq ' HASH' ) {
225+ $hash = {' factor' => 1,
226+ " $unit " => 1 };
227+ }
228+
229+ # make sure that if this unit is defined in terms of any other units
230+ # then those units are fundamental units.
231+ foreach my $subUnit (keys %$hash ) {
232+ if (!defined ($fundamental_units -> {$subUnit })) {
233+ add_fundamental_unit($subUnit );
234+ }
235+ }
236+
237+ $known_units -> {$unit } = $hash ;
238+ }
239+
160240# #####################################################################
161241
162242#
0 commit comments