Consumes word_choice by adding it to best_choices, (taking ownership) if the certainty for word_choice is some distance of the best choice in best_choices, or by deleting the word_choice and returning false. The best_choices list is kept in sorted order by rating. Duplicates are removed, and the list is kept no longer than max_num_choices in length. Returns true if the word_choice is still a valid
| 610 | // removed, and the list is kept no longer than max_num_choices in length. |
| 611 | // Returns true if the word_choice is still a valid pointer. |
| 612 | bool WERD_RES::LogNewCookedChoice(int max_num_choices, bool debug, |
| 613 | WERD_CHOICE* word_choice) { |
| 614 | if (best_choice != NULL) { |
| 615 | // Throw out obviously bad choices to save some work. |
| 616 | // TODO(rays) Get rid of this! This piece of code produces different |
| 617 | // results according to the order in which words are found, which is an |
| 618 | // undesirable behavior. It would be better to keep all the choices and |
| 619 | // prune them later when more information is available. |
| 620 | float max_certainty_delta = |
| 621 | StopperAmbigThreshold(best_choice->adjust_factor(), |
| 622 | word_choice->adjust_factor()); |
| 623 | if (max_certainty_delta > -kStopperAmbiguityThresholdOffset) |
| 624 | max_certainty_delta = -kStopperAmbiguityThresholdOffset; |
| 625 | if (word_choice->certainty() - best_choice->certainty() < |
| 626 | max_certainty_delta) { |
| 627 | if (debug) { |
| 628 | STRING bad_string; |
| 629 | word_choice->string_and_lengths(&bad_string, NULL); |
| 630 | tprintf("Discarding choice \"%s\" with an overly low certainty" |
| 631 | " %.3f vs best choice certainty %.3f (Threshold: %.3f)\n", |
| 632 | bad_string.string(), word_choice->certainty(), |
| 633 | best_choice->certainty(), |
| 634 | max_certainty_delta + best_choice->certainty()); |
| 635 | } |
| 636 | delete word_choice; |
| 637 | return false; |
| 638 | } |
| 639 | } |
| 640 | |
| 641 | // Insert in the list in order of increasing rating, but knock out worse |
| 642 | // string duplicates. |
| 643 | WERD_CHOICE_IT it(&best_choices); |
| 644 | const STRING& new_str = word_choice->unichar_string(); |
| 645 | bool inserted = false; |
| 646 | int num_choices = 0; |
| 647 | if (!it.empty()) { |
| 648 | do { |
| 649 | WERD_CHOICE* choice = it.data(); |
| 650 | if (choice->rating() > word_choice->rating() && !inserted) { |
| 651 | // Time to insert. |
| 652 | it.add_before_stay_put(word_choice); |
| 653 | inserted = true; |
| 654 | if (num_choices == 0) |
| 655 | best_choice = word_choice; // This is the new best. |
| 656 | ++num_choices; |
| 657 | } |
| 658 | if (choice->unichar_string() == new_str) { |
| 659 | if (inserted) { |
| 660 | // New is better. |
| 661 | delete it.extract(); |
| 662 | } else { |
| 663 | // Old is better. |
| 664 | if (debug) { |
| 665 | tprintf("Discarding duplicate choice \"%s\", rating %g vs %g\n", |
| 666 | new_str.string(), word_choice->rating(), choice->rating()); |
| 667 | } |
| 668 | delete word_choice; |
| 669 | return false; |
no test coverage detected