File Coverage

blib/lib/Text/Phonetic/VideoGame.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Text::Phonetic::VideoGame;
2 3     3   3401 use warnings;
  3         5  
  3         91  
3 3     3   15 use strict;
  3         6  
  3         108  
4 3     3   19 use base 'Text::Phonetic';
  3         7  
  3         3743  
5              
6 3     3   12240 use String::Nysiis;
  0            
  0            
7             use Roman ();
8             use Lingua::EN::Inflect::Number qw( to_S );
9             use List::MoreUtils qw( uniq );
10              
11             our $VERSION = '0.05';
12             my %ordinal = (
13             '1st' => 'first',
14             '2nd' => 'second',
15             '3rd' => 'third',
16             '4th' => 'fourth',
17             '5th' => 'fifth',
18             '6th' => 'sixth',
19             '7th' => 'seventh',
20             '8th' => 'eighth',
21             '9th' => 'ninth',
22             );
23             my %abbreviation = (
24             breathe => 'breath', # NYSIIS handles this case poorly
25             bros => 'brothers',
26             csi => 'crime scene investigation',
27             ddr => 'dance dance revolution',
28             doa => 'dead or alive',
29             dora => 'dora the explorer',
30             ff => 'final fantasy',
31             gta => 'grand theft auto',
32             iss => 'international superstar soccer',
33             kotr => 'knights of the old republic',
34             le => 'limited edition',
35             mlb => 'major league baseball',
36             motocross => 'motorcross',
37             mr => 'mister',
38             nam => 'vietnam',
39             ny => 'new york',
40             pbr => 'pro bull riders',
41             pgr => 'project gotham racing',
42             rabbids => 'raving rabbids',
43             spongebob => 'spongebob squarepants',
44             spyro => 'legend spyro',
45             t2 => 'terminator 2',
46             tmnt => 'teenage mutant ninja turtles',
47             w => 'with', # w/ before removing slashes becomes w
48             wwf => 'wwe',
49             xtreme => 'extreme',
50             zelda => 'the legend of zelda',
51              
52              
53             # easier than using a words to numbers module
54             eighteen => 18,
55              
56             # easier than using split_compound_word
57             bustamove => 'bust a move',
58             davinci => 'da vinci',
59             fzero => 'f zero',
60             motogp => 'moto gp',
61             mysims => 'my sims',
62             proam => 'pro am',
63             rtype => 'r type',
64             xmen => 'x men',
65             );
66             my $publishers = join '|', (
67             'disney',
68             'disneys',
69             'ea',
70             'hasbro',
71             'james camerons',
72             'sega',
73             'tom clancys',
74             'mobile suit', # not a publisher. commonly omitted "gundam" prefix
75             );
76              
77             sub _do_encode {
78             my $self = shift;
79             my $string = lc shift;
80             my $original = $string;
81              
82             $string =~ s{[-/:]}{ }g; # dashes, slashes are like spaces
83             $string =~ s/[&.'",]//g; # most punctuation can be ignored
84              
85             # remove useless publisher names (usually found at the front)
86             $string =~ s/^(?:$publishers)\b//;
87              
88             # expand some common abbreviations
89             my $abbr = join '|', keys(%abbreviation);
90             $string =~ s/\b($abbr)\b/$abbreviation{$1}/ge;
91              
92             $string =~ s/sk8/skate/g;
93             $string =~ s/\b([1-9])(st|nd|rd|th)\b/$ordinal{"$1$2"}/ge;
94             $string =~ s/\bv(\d)\b/volume $1/g;
95             $string =~ s/\b(\d+)gb\b/$1 gb/g; # 40GB -> 40 GB
96             $string =~ s/\b2k([0-9])\b/200$1/ig; # 2K4 -> 2004
97             $string =~ s/\b(\d+)k\b/${1}000/g; # 40K -> 40000
98             $string =~ s/(\D)(\d)/$1 $2/g; # "xbox360", "kombat4", etc
99              
100             # remove some noise words
101             $string =~ s/\b(videogame|video game|as|ds|3d)\b//g;
102             $string =~ s/\b(n|a|an|the|and|of|vs|at|in|for|if|game only|with)\b//g;
103             $string =~ s/\b(edition|volume|vol|versus|game|games|used)\b//g;
104              
105             $string =~ s/\s+/ /g;
106             $string =~ s/^\s+|\s+$//g; # remove leading/trailing spaces
107              
108             # do some in-place substitutions
109             my @words = map { $self->split_compound_word($_) } split / /, $string;
110             for my $word (@words) {
111             $word = $self->word2num($word);
112             next if $word eq 'mix'; # looks Roman but is rarely meant that way
113             $word = Roman::arabic($word) if Roman::isroman($word);
114             }
115              
116             my @encodings = map { /^\d+$/ ? $_ : String::Nysiis::nysiis($_) } @words;
117             $string = join ' ', @encodings;
118              
119             # normalize numbers that might be years
120             $string =~ s/\b(7|8|9)([0-9])\b/19$1$2/g; # 97 -> 1997
121             $string =~ s/\b(0|1|2)([0-9])\b/20$1$2/g; # 03 -> 2003
122              
123             # remove redundant words
124             $string =~ s/\b(\d+)\s\1\b/$1/g; # 2 2 -> 2
125             for ($string) {
126             s/\bNANTAND\b// if $original =~ /\bds\b/; # Nintendo <- DS
127             s/\bNANTAND\b// if $original =~ /\bwii\b/; # Nintendo <- Wii
128             s/\bSACAR\b// if $original =~ /\bfifa\b/; # soccer <- FIFA
129             s/\bBASCATBAL\b// if $original =~ /\bnba\b/; # basketball <- NBA
130             s/\bFAT BAL\b// if $original =~ /\bnfl\b/; # football <- NFL
131             s/\bHACY\b// if $original =~ /\bnhl\b/; # hockey <- NHL
132             }
133             for ($string) {
134             s/\bNFL\b// if /\bMAD DAN\b/; # NFL <- Madden
135             s/\bGALF\b// if /\bTAGAR WAD\b/; # golf <- Tiger Woods
136             s/\bFAT BAL\b// if /\bBLAT\b/; # football <- blitz
137             s/\bHAGAG\b// if /\bSANAC\b/; # hedgehog <- Sonic
138             s/\bCABAL\b// if /\bDANGAR HAN\b/; # Cabela's <- Dangerous Hunts
139             s/\bBNX\b// if /\bDAV MAR\b/; # BMX <- Dave Mirra
140             s/\bW\b// if /\bRASTL MAN\b/; # WWE <- Wrestlemania
141             s/\bS\b// if /\bRAN STANPY\b/; # Show <- Ren & Stimpy
142             s/\bSPANG BAB\b// if /\bSGAR PAN\b/; # Sponge Bob <- Square Pants
143             s/\bRASC RANGAR\b// if /\bCAP DAL\b/; # Rescue Rangers <- Chip & Dale
144             s/\bLAR CRAFT\b// if /\bTANB RADAR\b/; # Lara Croft <- Tomb Raider
145             }
146              
147             $string =~ s/X\b/C/g; # "TANX" -> "TANC" etc
148             $string =~ s/\bCRASN\b/CRASAN/g;
149             $string =~ s/\s+/ /g;
150             $string =~ s/^\s+|\s+$//g; # remove leading/trailing spaces
151              
152             # remove duplicates and sort
153             @words = uniq sort split /\s+/, $string;
154             return join ' ', @words;
155             }
156              
157             # returns an arabic numeral representation of number word
158             # ("five" -> 5). If the word is not a number word, returns the word.
159             sub word2num {
160             my ($self, $word) = @_;
161             my %words = (
162             zero => 0,
163             one => 1,
164             two => 2,
165             three => 3,
166             four => 4,
167             five => 5,
168             six => 6,
169             seven => 7,
170             eight => 8,
171             nine => 9,
172             );
173             return $words{$word} if exists $words{$word};
174             return $word;
175             }
176              
177             sub split_compound_word {
178             my ( $self, $word ) = @_;
179              
180             # don't produce subwords less than 3 characters
181             my $length = length $word;
182             return $word if $length < 6;
183              
184             # try to split the word into smaller two smaller words
185             for my $i ( 3 .. $length-3 ) {
186             my $front = substr $word, 0, $i;
187             my $back = substr $word, $i;
188             return ( $front, $back )
189             if $self->is_word($front)
190             and $self->is_word($back);
191             return ( $front, $back )
192             if $self->is_word( to_S $front )
193             and $self->is_word( to_S $back );
194             }
195              
196             return $word;
197             }
198              
199             # a hand picked dictionary of short nouns and adjectives
200             my %dictionary = map { $_ => 1 } qw(
201             acid
202             acme
203             acne
204             acre
205             act
206             aeon
207             aero
208             after
209             age
210             aid
211             air
212             all
213             alpha
214             ammo
215             anal
216             andreas
217             anti
218             apex
219             aqua
220             arch
221             area
222             arm
223             arms
224             army
225             ash
226             assault
227             astro
228             atom
229             aunt
230             aura
231             axe
232             axes
233             axle
234             axon
235             baby
236             back
237             bad
238             bag
239             bail
240             bain
241             bait
242             bald
243             bale
244             ball
245             band
246             bane
247             bang
248             bank
249             bar
250             barb
251             bark
252             barn
253             baru
254             base
255             bass
256             bath
257             bats
258             battle
259             bead
260             beam
261             bean
262             bear
263             beat
264             beef
265             beer
266             beet
267             bell
268             belt
269             best
270             big
271             bike
272             bird
273             bite
274             blade
275             blast
276             blind
277             blob
278             blood
279             blue
280             boar
281             boat
282             bob
283             body
284             bomb
285             bomber
286             bond
287             bone
288             book
289             boom
290             boot
291             boss
292             bot
293             bound
294             bow
295             boy
296             brain
297             brat
298             bread
299             break
300             brew
301             buck
302             bud
303             bull
304             bump
305             bunk
306             burger
307             burner
308             bush
309             bust
310             butt
311             cage
312             cake
313             caliber
314             calibur
315             call
316             camp
317             cane
318             car
319             card
320             cart
321             cat
322             chip
323             chrome
324             chum
325             city
326             clay
327             clod
328             clown
329             club
330             coal
331             coaster
332             coat
333             cog
334             coke
335             comb
336             cook
337             corn
338             corp
339             corps
340             craft
341             crew
342             crib
343             crop
344             cross
345             crow
346             cry
347             cube
348             cup
349             cyan
350             dam
351             dart
352             dash
353             data
354             date
355             dawn
356             day
357             days
358             dead
359             deaf
360             debt
361             deck
362             den
363             dent
364             diet
365             dime
366             dino
367             dock
368             dog
369             dogs
370             donkey
371             doo
372             dope
373             dorm
374             double
375             down
376             drag
377             dragon
378             dream
379             drip
380             drop
381             dry
382             dual
383             duck
384             duct
385             dude
386             due
387             duel
388             dump
389             dust
390             duty
391             ear
392             earth
393             east
394             eat
395             edit
396             eel
397             egg
398             elf
399             elk
400             elm
401             end
402             epic
403             ever
404             excite
405             exit
406             extra
407             eye
408             face
409             fad
410             fake
411             fall
412             fan
413             far
414             fare
415             fat
416             fear
417             feat
418             fest
419             field
420             fighter
421             film
422             fire
423             fit
424             flag
425             flat
426             fly
427             foal
428             foil
429             fold
430             food
431             fool
432             foot
433             force
434             fort
435             fox
436             francisco
437             free
438             front
439             fuel
440             fun
441             fury
442             fuse
443             game
444             garb
445             gash
446             gate
447             geek
448             gem
449             gene
450             germ
451             ghost
452             gig
453             girl
454             glen
455             glue
456             gnat
457             goal
458             goat
459             god
460             gold
461             golden
462             golf
463             good
464             goof
465             grad
466             gram
467             grave
468             gray
469             green
470             grey
471             grid
472             grog
473             ground
474             grub
475             gun
476             guy
477             gym
478             hair
479             halo
480             hand
481             hang
482             harm
483             hat
484             hawk
485             head
486             heart
487             heat
488             heel
489             helm
490             help
491             herb
492             herd
493             high
494             hiss
495             hit
496             hive
497             hobo
498             holy
499             home
500             hot
501             hounds
502             hour
503             house
504             howl
505             hub
506             hunter
507             hurt
508             hymn
509             ice
510             idea
511             idol
512             inch
513             iris
514             isle
515             ivy
516             jade
517             jaw
518             jazz
519             jeep
520             jig
521             jive
522             job
523             joke
524             jot
525             jug
526             jump
527             junk
528             kart
529             keel
530             keep
531             kill
532             king
533             kong
534             kingdom
535             kit
536             kite
537             knob
538             lacy
539             lady
540             lake
541             lamb
542             lamp
543             land
544             lane
545             lank
546             lap
547             law
548             lead
549             leaf
550             leg
551             life
552             light
553             lily
554             limb
555             lime
556             lip
557             list
558             loaf
559             loan
560             lock
561             locked
562             long
563             loot
564             loud
565             love
566             low
567             mad
568             mail
569             man
570             mania
571             mario
572             master
573             mate
574             maze
575             mech
576             mega
577             melt
578             mesh
579             mess
580             metal
581             metroid
582             milk
583             mint
584             mix
585             moat
586             monk
587             monkey
588             moon
589             moss
590             mote
591             motor
592             mud
593             myth
594             name
595             navy
596             night
597             nine
598             ninja
599             north
600             nuke
601             oak
602             oar
603             odd
604             odor
605             off
606             ogre
607             old
608             one
609             out
610             owl
611             pac
612             pack
613             page
614             palm
615             pant
616             paper
617             parents
618             park
619             pawn
620             pay
621             peer
622             pilot
623             ping
624             pint
625             pixy
626             play
627             poem
628             poet
629             pole
630             poll
631             pong
632             power
633             pray
634             prey
635             prime
636             pro
637             puck
638             puff
639             pug
640             pump
641             pun
642             punch
643             pure
644             quiz
645             race
646             rag
647             rage
648             rain
649             ranger
650             rant
651             rap
652             rare
653             rayne
654             realm
655             red
656             rich
657             ride
658             rig
659             riot
660             road
661             rock
662             roll
663             roller
664             roof
665             rook
666             room
667             root
668             rope
669             rose
670             row
671             ruby
672             rump
673             rust
674             rye
675             sack
676             sale
677             salt
678             san
679             sanity
680             sash
681             scab
682             scooby
683             seal
684             seam
685             seat
686             sect
687             self
688             sew
689             shadow
690             shell
691             shift
692             ship
693             shock
694             shoot
695             shore
696             sick
697             side
698             sign
699             silk
700             silo
701             sim
702             sink
703             six
704             skin
705             skit
706             slam
707             slug
708             slum
709             smart
710             smash
711             smog
712             snow
713             soap
714             sock
715             sofa
716             soft
717             soul
718             sound
719             soup
720             sour
721             south
722             speed
723             spider
724             splitter
725             sponge
726             spot
727             spy
728             square
729             star
730             start
731             station
732             steel
733             stem
734             step
735             stew
736             stool
737             story
738             street
739             strike
740             stunt
741             super
742             swim
743             switch
744             tail
745             take
746             talk
747             tall
748             tank
749             tanx
750             task
751             tax
752             team
753             tear
754             tech
755             teck
756             teen
757             temp
758             text
759             thin
760             thru
761             thunder
762             tick
763             tide
764             tiger
765             time
766             toad
767             toe
768             toll
769             tomb
770             tome
771             tot
772             toy
773             trap
774             tree
775             tropic
776             tube
777             tusk
778             twin
779             ultra
780             under
781             user
782             vain
783             veil
784             vein
785             vest
786             vial
787             visa
788             vote
789             vow
790             wage
791             waker
792             walker
793             war
794             ward
795             ware
796             wario
797             warp
798             wart
799             wasp
800             wave
801             weak
802             weal
803             web
804             west
805             wet
806             wheel
807             whip
808             wick
809             wii
810             wind
811             wine
812             wing
813             wise
814             wolf
815             womb
816             wonder
817             wood
818             world
819             worm
820             wrestle
821             yard
822             yarn
823             year
824             york
825             zero
826             zone
827             zoom
828             );
829             sub is_word {
830             my ($self, $word) = @_;
831             return $dictionary{ lc $word };
832             }
833              
834             1;
835              
836             =head1 NAME
837              
838             Text::Phonetic::VideoGame - phonetic encoding for video game titles
839              
840             =head1 SYNOPSIS
841              
842             use Text::Phonetic::VideoGame;
843             my $phonetic = Text::Phonetic::VideoGame->new;
844             my $first = $phonetic->encode('super smash brothers');
845             my $second = $phonetic->encode('Super Smash Bros.');
846             warn "They match\n" if $first eq $second;
847              
848             warn "They match\n" if $phonetic->compare('ff 7', 'final fantasy vii');
849              
850             This module implements a phonetic algorithm for the comparison of video game
851             titles. It uses L to disambiguate common English typos and
852             adds additional rules which apply specifically to typos in video game titles.
853              
854             The module implements the L interface. See that documentation
855             for details about the interface.
856              
857             =head1 METHODS
858              
859             See L.
860              
861             =head1 VARIATIONS HANDLED
862              
863             =head2 Common English Typos
864              
865             L handles common English typos such as misspellings of proper
866             names which makes titles like "adams family" match "addams family".
867              
868             =head2 Punctuation Variants
869              
870             Most punctuation and its variants are handled correctly. For instance "tom &
871             jerry" and "tom and jerry" or "Lord of the Rings: Two Towers" with and without
872             the colon.
873              
874             =head2 Common Abbreviations
875              
876             Abbreviations such as "bros" for "brothers" and "TMNT" for "Teenage Mutant
877             Ninja Turtles".
878              
879             =head2 Canonical Years
880              
881             The titles "NFL 2004", "NFL '04" and "NFL 2K4" all hash to the same code.
882              
883             =head2 Canonical Numbers
884              
885             Roman numerals, ordinal numbers and spelled out numbers are recognized as
886             being equal.
887              
888             =head2 Compound Words
889              
890             The game titles "mega man" and "megaman" are recognized as being identical.
891              
892             =head2 Word Order
893              
894             The order of certain parts of a title are often confused. For instance,
895             "Sonic Adventure 2: Battle" and "Sonic Adventure: Battle 2" both indicate the
896             same game.
897              
898             =head1 AUTHOR
899              
900             Michael Hendricks, C<< >>
901              
902             =head1 BUGS
903              
904             Please report any bugs or feature requests to C
905             rt.cpan.org>, or through the web interface at
906             L. I
907             will be notified, and then you'll automatically be notified of progress on
908             your bug as I make changes.
909              
910             The source code is available on GitHub:
911             L Patches and pull requests
912             are welcome.
913              
914             =head1 ACKNOWLEDGEMENTS
915              
916             Thanks to JJGames (L) and Video Game Price Charts
917             (L) for sponsoring development of this module.
918              
919             =head1 COPYRIGHT & LICENSE
920              
921             Copyright 2009 Michael Hendricks, all rights reserved.
922              
923             This program is released under the following license: MIT