Feel free to localize it using the constants at the beginning. Adding the floating point left as an exercise for the reader.
#!/usr/bin/perl use warnings; use strict; use feature qw{ say }; use List::Util qw{ shuffle }; use Function::Parameters; use Tk; use constant { SEPARATOR => ',', OK => 'OK', TITLE => 'SI Units Conversions', DONE => 'Done', QUIT => 'Quit', ERRORS => 'Errors', }; push @ARGV, -font => 'sans 15'; fun prefixes (@prefixes) { +{ map +($_ => undef), "", @prefixes } } fun do_format ($x) { my $f = reverse $x; $f =~ s/(...)(?=.)/$1${\SEPARATOR}/g; return reverse $f } fun validate ($new_value, @) { $new_value =~ /^[0-9${\SEPARATOR}]*$/ } my %known = (l => prefixes(qw( m c d h )), m => prefixes(qw( m c d k ))); my %times = (m => 0.001, c => 0.01, d => 0.1, "" => 1, h => 100, k => 1000); my @exercises; for (1 .. shift) { my $unit = (keys %known)[rand keys %known]; my @prefixes = sort { $times{$a} <=> $times{$b} } (shuffle(keys %{ $known{$unit} }))[0, 1]; push @exercises, [ $unit, @prefixes, 1 + int rand 100 ]; $exercises[-1][-1] *= 10 for 1 .. rand 2; if (int rand 2) { my $times = $times{ $prefixes[1] } / $times{ $prefixes[0] }; $exercises[-1] = [ $unit, @prefixes[1, 0], $exercises[-1][-1] * $times ]; } } my (@solutions, @entries); my $errors = 0; my $mw = 'MainWindow'->new(title => TITLE); for my $i (0 .. $#exercises) { my $exercise = $exercises[$i]; my $f = $mw->Frame->pack; my $ratio = $times{ $exercise->[2] } / $times{ $exercise->[1] }; $f->Label(-text => do_format($exercise->[3] * $ratio) . " $exercise->[1]$exercise->[0] = ") ->pack(-side => 'left'); push @entries, $f->Entry(-textvariable => \$solutions[$i], -validate => 'all', -validatecommand => \&validate, )->pack(-side => 'left'); $f->Label(-text => " $exercise->[2]$exercise->[0]") ->pack(-side => 'left'); } my $f = $mw->Frame->pack; $f->Button(-text => DONE, -command => fun () { for my $i (0 .. $#solutions) { next if $entries[$i]->cget('-state') eq 'readonly'; my $value = ($solutions[$i] // "") =~ s/${\SEPARATO +R}//gr; if (($value || 0) == $exercises[$i][3]) { $entries[$i]->configure(-state => 'readonly' +, -validate => 'none'); $solutions[$i] = OK; } else { ++$errors; } } })->pack(-side => 'left'); $f->Button(-text => QUIT, -command => [$mw => 'destroy'])->pack(-side => 'left'); MainLoop(); say ERRORS, ": $errors";
It's been a practice for me, too, because of Function::Parameters.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Conversions of SI Units
by 1nickt (Canon) on Feb 17, 2019 at 00:45 UTC | |
by choroba (Cardinal) on Feb 17, 2019 at 16:30 UTC |