+sub exam()
+{
+ my @exam=keys(%exam);
+ for (;;) {
+ reschedule() if !$opt_fast;
+ my $besthashref=best();
+ my $r=$besthashref->{"r"};
+ my $exam_from=$besthashref->{"exam_from"};
+ my $exam_to=$exam{$exam_from}{"to"};
+ print word_out($r->{$exam_from}).": ";
+ my $got=<STDIN>;
+ chomp $got;
+ my $want=$r->{$exam_to};
+ my $got_chk=to_chk($got,$exam_to);
+ my @want_chk=map(to_chk($_,$exam_to),map((!ref($_)?$_:@$_),$want));
+ my $ok;
+ my $substr;
+ for my $want_chk (@want_chk) {
+ next if !$want_chk; # discard patterns like: /(P)/
+ $ok=1 if $got_chk eq $want_chk;
+ $substr=1 if $want_chk=~/\Q$got_chk\E/;
+ }
+ my $aliased;
+ if (!$ok && $exam_from eq "english" && $exam_to eq "kana"
+ && (my $arrref=$kana_to_r{$got})) {
+ my %chk_english_from=map((to_chk($_,"english")=>1),@{$r->{"english"}});
+ my $intended;
+ for my $kana_alias (@$arrref) {
+ for my $kana_alias_english (@{$kana_alias->{"english"}}) {
+ my $chk_english=to_chk $kana_alias_english,"english" or next;
+ next if !$chk_english_from{$chk_english};
+ print "intended ----> ".$r->{"orig"}."\n" if !$intended++;
+ print "OK if alias -> ".$kana_alias->{"orig"}."\n";
+ $ok=1;
+ $aliased=1;
+ }
+ }
+ }
+ print "-------------> ".word_out($want)."\n" if !$aliased;
+ if (!$ok) {
+ if ($exam_to eq "english" && $got=~/\S/ && $substr) {
+ my $key;
+ do {
+ print STDERR "Is your answer correct? [y/n] ";
+ sub restore
+ {
+ Term::ReadKey::ReadMode(0);
+ }
+ local $SIG{"__DIE__"}=\&restore;
+ Term::ReadKey::ReadMode(4);
+ $key=Term::ReadKey::ReadKey(0);
+ print STDERR "\n"; # no echo
+ restore();
+ die if $key eq "\x03"; # ctrl-c
+ $ok=1 if $key eq "y";
+ $ok=0 if $key eq "n";
+ } while (!defined $ok);
+ }
+ }
+ $ok||=0;
+ if (!$aliased) {
+ result $r,$exam_from,$ok,"write"=>1;
+ print STDERR "result: ".($ok ? "ok" : "WRONG");
+ schedule $r,$exam_from;
+ print "\n";
+ }
+ print STDERR join(" * ",map("WRONG",1..8))."\n" if !$ok;
+ }
+}
+