Advertisement
Guest User

Decoding @webstockgame 2011

a guest
Feb 20th, 2011
2,514
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 27.20 KB | None | 0 0
  1. # Hacked together by Simon Green (@lumbarius) to decode the Webstock Game 2011 (@webstockgame).
  2. use strict;
  3. use Memoize;
  4.  
  5. memoize( 'Run', 'MotivationModifier', 'Time', 'Duration' );
  6.  
  7. my ($motivations_ref, $motivationCombos_ref, $units_ref, $foods_ref, $foodBoost_ref, $foodCombos_ref, $speakers_ref, $results_ref);
  8. my $best_ref = [0, undef, undef];
  9.  
  10. Main();
  11.  
  12. sub Main
  13. {
  14.     Initialise();
  15.     BruteForce();
  16.  
  17.     foreach my $time ( sort { $b <=> $a }
  18.                        keys %{$results_ref} )
  19.     {
  20.         print "$results_ref->{$time}\n";
  21.     }
  22.    
  23.     return;
  24. }
  25.  
  26. sub Initialise
  27. {
  28.     # http://twitter.com/webstockgame/status/37978363020713984 "LOLCats: + 2.2 km/h. It's either laughter or fear that gives your feet wings."
  29.     # http://twitter.com/webstockgame/status/37982147289550848 "TSA: +2.2 km/h. Get enough millimetre waves through your body and it'll turn into kilometres."
  30.     # http://twitter.com/webstockgame/status/38021097811087360 "Amanda Palmer album: +2.7 km/h. Because everyone likes Tasmania."
  31.     # http://twitter.com/webstockgame/status/38033677829013504 "API: +1.9 km/h. Because APIs help you come up to speed and click RUN."
  32.     # http://twitter.com/webstockgame/status/38324338209857536 "Accessibility: +3.1 km/h. Unfortunately not everyone cares about accessibility :-("
  33.     # http://twitter.com/webstockgame/status/38344478796419072 "Running tips: +1.4 mph. Unfortunately, spending 16 hours a day googling does not make an athlete."
  34.     # http://twitter.com/webstockgame/status/38397856910032896 "The ONYAs boost you 2.9 km/h. #scheduledtweetfail #webstock"
  35.     $motivations_ref = {
  36.         'LOLCats' => 2.2,
  37.         'TSA' => 2.2,
  38.         'Amanda Palmer Album' => 2.7,
  39.         'API' => 1.9,
  40.         'Accessibility' => 3.1,
  41.         'Running tips' => 1.4 * 1.61,
  42.         'Onyas Ticket' => 2.9,
  43.         };
  44.    
  45.     # http://twitter.com/webstockgame/status/38311297552617472 "You might have realised by now that food has different effects on each speaker. Might be anything between -30% to +30% on each 1000m sector."
  46.     $foodBoost_ref = {
  47.         'UMD' => 0.7,
  48.         'MD' => 0.8,
  49.         'SD' => 0.9,
  50.         'Y' => 1,
  51.         'SB' => 1.1,
  52.         'MB' => 1.2,
  53.         'UMB' => 1.3,
  54.         };
  55.    
  56.     # http://twitter.com/webstockgame/status/38311410115153920 "And having too much food of one kind is even worse..."
  57.     $foods_ref = {
  58.         'Coffee' => 3,
  59.         'Fish' => 99,
  60.         'IceCream' => 3,
  61.         'L&P' => 3,
  62.         'Marmite' => 2,
  63.         'Pavlova' => 2,
  64.         'Wine' => 3,
  65.         };
  66.    
  67.     # Josh Clark "A speaker's base speed is expressed in the common measurement units of their home country (according to Twitter)."
  68.     $units_ref = {
  69.         'kph' => 1,
  70.         'mph' => 1.61,
  71.         };
  72.    
  73.     # http://webstockgame.org/
  74.     # http://webstockgame.org/speakers.xml
  75.     $speakers_ref = {
  76.         'Amanda Palmer'      => { 'Initials' => 'AP',  'Profession' => [ 'Artist' ],         'BaseSpeed' => 10, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'SD', 'Fish' => 'Y', 'Wine' => 'SB', 'Pavlova' => 'MB', 'L&P' => 'UMB', 'Marmite' => 'UMD', 'IceCream' => 'MD' }, 'Glasses' => 0, 'American' => 1 },
  77.         'Charlie Bird'       => { 'Initials' => 'CB',  'Profession' => [ 'Organiser' ],      'BaseSpeed' => 13, 'Unit' => 'kph', 'Food' => { 'Coffee' => 'MD', 'Fish' => 'SD', 'Wine' => 'Y', 'Pavlova' => 'SB', 'L&P' => 'MB', 'Marmite' => 'UMB', 'IceCream' => 'UMD' }, 'Glasses' => 0, 'American' => 0 },
  78.         'Christine Perfetti' => { 'Initials' => 'CP',  'Profession' => [ 'Maven' ],          'BaseSpeed' => 15, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'Y', 'Fish' => 'SB', 'Wine' => 'MB', 'Pavlova' => 'UMB', 'L&P' => 'UMD', 'Marmite' => 'MD', 'IceCream' => 'SD' }, 'Glasses' => 0, 'American' => 1 },
  79.         'David McCandless'   => { 'Initials' => 'DMC', 'Profession' => [ 'Creative' ],       'BaseSpeed' => 13, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'UMD', 'Fish' => 'MD', 'Wine' => 'SD', 'Pavlova' => 'Y', 'L&P' => 'SB', 'Marmite' => 'MB', 'IceCream' => 'UMB' }, 'Glasses' => 1, 'American' => 0 },
  80.         'David Recordon'     => { 'Initials' => 'DR',  'Profession' => [ 'Maven' ],          'BaseSpeed' => 12, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'MB', 'Fish' => 'UMB', 'Wine' => 'UMD', 'Pavlova' => 'MD', 'L&P' => 'SD', 'Marmite' => 'Y', 'IceCream' => 'SB' }, 'Glasses' => 0, 'American' => 1 },
  81.         'Doug Bowman'        => { 'Initials' => 'DB',  'Profession' => [ 'Creative' ],       'BaseSpeed' => 11, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'SD', 'Fish' => 'Y', 'Wine' => 'SB', 'Pavlova' => 'MB', 'L&P' => 'UMB', 'Marmite' => 'UMD', 'IceCream' => 'MD' }, 'Glasses' => 1, 'American' => 1 },
  82.         'Frank Chimero'      => { 'Initials' => 'FC',  'Profession' => [ 'Creative' ],       'BaseSpeed' =>  9, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'SB', 'Fish' => 'MB', 'Wine' => 'UMB', 'Pavlova' => 'UMD', 'L&P' => 'MD', 'Marmite' => 'SD', 'IceCream' => 'Y' }, 'Glasses' => 1, 'American' => 1 },
  83.         'Glenda Sims'        => { 'Initials' => 'GS',  'Profession' => [ 'Maven' ],          'BaseSpeed' => 11, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'UMD', 'Fish' => 'MD', 'Wine' => 'SD', 'Pavlova' => 'Y', 'L&P' => 'SB', 'Marmite' => 'MB', 'IceCream' => 'UMB' }, 'Glasses' => 0, 'American' => 1 },
  84.         'Jason Cohen'        => { 'Initials' => 'JCO', 'Profession' => [ 'Maven' ],          'BaseSpeed' =>  8, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'UMD', 'Fish' => 'MD', 'Wine' => 'SD', 'Pavlova' => 'Y', 'L&P' => 'SB', 'Marmite' => 'MB', 'IceCream' => 'UMB' }, 'Glasses' => 0, 'American' => 1 },
  85.         'Jason Santa Maria'  => { 'Initials' => 'JSM', 'Profession' => [ 'Artist' ],         'BaseSpeed' => 10, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'UMB', 'Fish' => 'UMD', 'Wine' => 'MD', 'Pavlova' => 'SD', 'L&P' => 'Y', 'Marmite' => 'SB', 'IceCream' => 'MB' }, 'Glasses' => 1, 'American' => 1 },
  86.         'Jason Webley'       => { 'Initials' => 'JW',  'Profession' => [ 'Artist' ],         'BaseSpeed' => 10, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'SB', 'Fish' => 'MB', 'Wine' => 'UMB', 'Pavlova' => 'UMD', 'L&P' => 'MD', 'Marmite' => 'SD', 'IceCream' => 'Y' }, 'Glasses' => 0, 'American' => 1 },
  87.         'John Gruber'        => { 'Initials' => 'JG',  'Profession' => [ 'Coder' ],          'BaseSpeed' => 12, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'MD', 'Fish' => 'SD', 'Wine' => 'Y', 'Pavlova' => 'SB', 'L&P' => 'MB', 'Marmite' => 'UMB', 'IceCream' => 'UMD' }, 'Glasses' => 0, 'American' => 1 },
  88.         'Josh Clark'         => { 'Initials' => 'JC',  'Profession' => [ 'Maven' ],          'BaseSpeed' => 11, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'MB', 'Fish' => 'UMB', 'Wine' => 'UMD', 'Pavlova' => 'MD', 'L&P' => 'SD', 'Marmite' => 'Y', 'IceCream' => 'SB' }, 'Glasses' => 0, 'American' => 1 },
  89.         'Kristina Halvorson' => { 'Initials' => 'KH',  'Profession' => [ 'Maven' ],          'BaseSpeed' =>  7, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'SD', 'Fish' => 'Y', 'Wine' => 'SB', 'Pavlova' => 'MB', 'L&P' => 'UMB', 'Marmite' => 'UMD', 'IceCream' => 'MD' }, 'Glasses' => 1, 'American' => 1 },
  90.         'Marco Arment'       => { 'Initials' => 'MA',  'Profession' => [ 'Maven' ],          'BaseSpeed' => 10, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'UMD', 'Fish' => 'MD', 'Wine' => 'SD', 'Pavlova' => 'Y', 'L&P' => 'SB', 'Marmite' => 'MB', 'IceCream' => 'UMB' }, 'Glasses' => 0, 'American' => 1 },
  91.         'Mark Pilgram'       => { 'Initials' => 'MP',  'Profession' => [ 'Coder', 'Maven' ], 'BaseSpeed' => 13, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'SB', 'Fish' => 'MB', 'Wine' => 'UMB', 'Pavlova' => 'UMD', 'L&P' => 'MD', 'Marmite' => 'SD', 'IceCream' => 'Y' }, 'Glasses' => 1, 'American' => 1 },
  92.         'Merlin Mann'        => { 'Initials' => 'MM',  'Profession' => [ 'Maven' ],          'BaseSpeed' => 14, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'UMB', 'Fish' => 'UMD', 'Wine' => 'MD', 'Pavlova' => 'SD', 'L&P' => 'Y', 'Marmite' => 'SB', 'IceCream' => 'MB' }, 'Glasses' => 1, 'American' => 1 },
  93.         'Michael Koziarski'  => { 'Initials' => 'MK',  'Profession' => [ 'Coder' ],          'BaseSpeed' => 19, 'Unit' => 'kph', 'Food' => { 'Coffee' => 'Y', 'Fish' => 'SB', 'Wine' => 'MB', 'Pavlova' => 'UMB', 'L&P' => 'UMD', 'Marmite' => 'MD', 'IceCream' => 'SD' }, 'Glasses' => 0, 'American' => 0 },
  94.         'Michael Lopp'       => { 'Initials' => 'ML',  'Profession' => [ 'Coder', 'Maven' ], 'BaseSpeed' => 11, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'MB', 'Fish' => 'UMB', 'Wine' => 'UMD', 'Pavlova' => 'MD', 'L&P' => 'SD', 'Marmite' => 'Y', 'IceCream' => 'SB' }, 'Glasses' => 0, 'American' => 1 },
  95.         'Mike Brown'         => { 'Initials' => 'MB',  'Profession' => [ 'Organiser' ],      'BaseSpeed' => 23, 'Unit' => 'kph', 'Food' => { 'Coffee' => 'Y', 'Fish' => 'SB', 'Wine' => 'MB', 'Pavlova' => 'UMB', 'L&P' => 'UMD', 'Marmite' => 'MD', 'IceCream' => 'SD' }, 'Glasses' => 0, 'American' => 0 },
  96.         'Nicole Sullivan'    => { 'Initials' => 'NS',  'Profession' => [ 'Coder' ],          'BaseSpeed' => 12, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'Y', 'Fish' => 'SB', 'Wine' => 'MB', 'Pavlova' => 'UMB', 'L&P' => 'UMD', 'Marmite' => 'MD', 'IceCream' => 'SD' }, 'Glasses' => 0, 'American' => 1 },
  97.         'Peter Sunde'        => { 'Initials' => 'PS',  'Profession' => [ 'Coder' ],          'BaseSpeed' => 21, 'Unit' => 'kph', 'Food' => { 'Coffee' => 'SD', 'Fish' => 'Y', 'Wine' => 'SB', 'Pavlova' => 'MB', 'L&P' => 'UMB', 'Marmite' => 'UMD', 'IceCream' => 'MD' }, 'Glasses' => 0, 'American' => 0 },
  98.         'Scott McCloud'      => { 'Initials' => 'SMC', 'Profession' => [ 'Artist' ],         'BaseSpeed' => 12, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'MD', 'Fish' => 'SD', 'Wine' => 'Y', 'Pavlova' => 'SB', 'L&P' => 'MB', 'Marmite' => 'UMB', 'IceCream' => 'UMD' }, 'Glasses' => 1, 'American' => 1 },
  99.         'Steve Souders'      => { 'Initials' => 'SS',  'Profession' => [ 'Maven' ],          'BaseSpeed' => 12, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'MD', 'Fish' => 'SD', 'Wine' => 'Y', 'Pavlova' => 'SB', 'L&P' => 'MB', 'Marmite' => 'UMB', 'IceCream' => 'UMD' }, 'Glasses' => 0, 'American' => 1 },
  100.         'Tash Lampard'       => { 'Initials' => 'TL',  'Profession' => [ 'Organiser' ],      'BaseSpeed' => 16, 'Unit' => 'kph', 'Food' => { 'Coffee' => 'SB', 'Fish' => 'MB', 'Wine' => 'UMB', 'Pavlova' => 'UMD', 'L&P' => 'MD', 'Marmite' => 'SD', 'IceCream' => 'Y' }, 'Glasses' => 0, 'American' => 0 },
  101.         'Tom Coates'         => { 'Initials' => 'TC',  'Profession' => [ 'Maven' ],          'BaseSpeed' => 16, 'Unit' => 'mph', 'Food' => { 'Coffee' => 'UMB', 'Fish' => 'UMD', 'Wine' => 'MD', 'Pavlova' => 'SD', 'L&P' => 'Y', 'Marmite' => 'SB', 'IceCream' => 'MB' }, 'Glasses' => 0, 'American' => 1 },
  102.         };
  103.    
  104.     foreach my $speaker ( keys %{$speakers_ref} )
  105.     {
  106.         $speakers_ref->{$speaker}->{'Name'} = $speaker;
  107.        
  108.         # Convert boost names to values
  109.         foreach my $food ( keys %{$foods_ref} )
  110.         {
  111.             $speakers_ref->{$speaker}->{'Food'}->{$food} = $foodBoost_ref->{ $speakers_ref->{$speaker}->{'Food'}->{$food} };
  112.         }
  113.     }
  114.    
  115.     FriendOrFoe();
  116.  
  117.     # Combos originally built with the help of http://www.mathsisfun.com/combinatorics/combinations-permutations-calculator.html to save time and brain cycles
  118.     SafeFoodCombos();
  119.     MotivationCombos();
  120. }
  121.  
  122. sub FriendOrFoe
  123. {
  124.     foreach my $speaker1_ref ( values %{$speakers_ref} )
  125.     {
  126.         $speaker1_ref->{'Arch-Enemies'} = [];
  127.         $speaker1_ref->{'Buddies'} = [];
  128.  
  129.         # Scott McCloud: "Your duo is a team, but there's 'me' in 'team', and that's why speakers with the same first name would rather nuke their iPads than run together."
  130.         $speaker1_ref->{'Name'} =~ /^([^ ]+) /;
  131.         my $firstName = $1;
  132.        
  133.         foreach my $speaker2_ref ( grep { $speaker1_ref->{'Name'} != $_->{'Name'} &&
  134.                                       $_->{'Name'} =~ /^$firstName / &&
  135.                                       !$_->{'Arch-Enemies'} }
  136.                                values %{$speakers_ref} )
  137.         {
  138.             push @{$speaker1_ref->{'Arch-Enemies'}}, $speaker2_ref->{'Name'};
  139.             push @{$speaker2_ref->{'Arch-Enemies'}}, $speaker1_ref->{'Name'};
  140.         }
  141.    
  142.         # Amanda Palmer: "David Recordon's a big fan of the open seas. He'll friend anyone with a surname that begins with a 'C'!"
  143.         if ($speaker1_ref->{'Name'} == 'David Recordon')
  144.         {
  145.             foreach my $speaker2_ref (  grep { $_->{'Name'} != $speaker1_ref->{'Name'} &&
  146.                                            $_->{'Name'} =~ /^(?:[^ ]+) C/ }
  147.                                     values %{$speakers_ref} )
  148.             {
  149.                 push @{$speaker1_ref->{'Buddies'}}, $speaker2_ref->{'Name'};
  150.             }
  151.         }
  152.     }
  153.    
  154.     # Jason Cohen "Harry and Voldemort. Superman and Lex. Frank and Marco. Pilgrim and Perfetti. Clark and Coates. Palmer and Sims."
  155.     $speakers_ref->{'Frank Chimero'}->{'Arch-Enemies'} = [ 'Marco Arment' ];
  156.     $speakers_ref->{'Marco Arment'}->{'Arch-Enemies'} = [ 'Frank Chimero' ];
  157.     $speakers_ref->{'Mark Pilgram'}->{'Arch-Enemies'} = [ 'Christine Perfetti' ];
  158.     $speakers_ref->{'Christine Perfetti'}->{'Arch-Enemies'} = [ 'Mark Pilgram' ];
  159.     $speakers_ref->{'Josh Clark'}->{'Arch-Enemies'} = [ 'Tom Coates' ];
  160.     $speakers_ref->{'Tom Coates'}->{'Arch-Enemies'} = [ 'Josh Clark' ];
  161.     $speakers_ref->{'Amanda Palmer'}->{'Arch-Enemies'} = [ 'Glenda Sims' ];
  162.     $speakers_ref->{'Glenda Sims'}->{'Arch-Enemies'} = [ 'Amanda Palmer' ];
  163.  
  164.     # Michael Koziarski "Souders & Sullivan once worked together optimising a site. The final files were a negative size, resulting in a black hole. They must never team up again."
  165.     $speakers_ref->{'Steve Souders'}->{'Arch-Enemies'} = [ 'Nicole Sullivan' ];
  166.     $speakers_ref->{'Nicole Sullivan'}->{'Arch-Enemies'} = [ 'Steve Souders' ];
  167.  
  168.     # Kristina Halvorson "Abbott and Costello. Bret and Jemaine. Clark and McCandless. Palmer and Webley. Lopp and Gruber. Souders and Sunde."
  169.     $speakers_ref->{'Josh Clark'}->{'Buddies'} = [ 'David McCandless' ];
  170.     $speakers_ref->{'David McCandless'}->{'Buddies'} = [ 'Josh Clark' ];
  171.     $speakers_ref->{'Amanda Palmer'}->{'Buddies'} = [ 'Jason Webley' ];
  172.     $speakers_ref->{'Jason Webley'}->{'Buddies'} = [ 'Amanda Palmer' ];
  173.     $speakers_ref->{'Michael Lopp'}->{'Buddies'} = [ 'John Gruber' ];
  174.     $speakers_ref->{'John Gruber'}->{'Buddies'} = [ 'Michael Lopp' ];
  175.     $speakers_ref->{'Steve Souders'}->{'Buddies'} = [ 'Peter Sunde' ];
  176.     $speakers_ref->{'Peter Sunde'}->{'Buddies'} = [ 'Steve Souders' ];
  177.  
  178.     # Tom Coates "Frodo & Sam. Batman & Robin. Merlin & Doug. Frank and Tom. Tash, Mike % Charlie. Mark & Glenda."
  179.     $speakers_ref->{'Merlin Mann'}->{'Buddies'} = [ 'Doug Bowman' ];
  180.     $speakers_ref->{'Doug Bowman'}->{'Buddies'} = [ 'Merlin Mann' ];
  181.     $speakers_ref->{'Frank Chimero'}->{'Buddies'} = [ 'Tom Coates' ];
  182.     $speakers_ref->{'Tom Coates'}->{'Buddies'} = [ 'Frank Chimero' ];
  183.     $speakers_ref->{'Tash Lampard'}->{'Buddies'} = [ 'Charlie Bird', 'Mike Brown' ];
  184.     $speakers_ref->{'Mike Brown'}->{'Buddies'} = [ 'Charlie Bird', 'Tash Lampard' ];
  185.     $speakers_ref->{'Charlie Bird'}->{'Buddies'} = [ 'Mike Brown', 'Tash Lampard' ];
  186.     $speakers_ref->{'Mark Pilgram'}->{'Buddies'} = [ 'Glenda Sims' ];
  187.     $speakers_ref->{'Glenda Sims'}->{'Buddies'} = [ 'Mark Pilgram' ];
  188.  
  189.     # John Gruber: "Arment, Gilbert & Sullivan. Cohen & Koziarski. McCloud and Santa Maria Perfetti and Halvorson. Lemon and Paeroa."
  190.     $speakers_ref->{'Marco Arment'}->{'Buddies'} = [ 'Nicole Sullivan' ];
  191.     $speakers_ref->{'Nicole Sullivan'}->{'Buddies'} = [ 'Marco Arment' ];
  192.     $speakers_ref->{'Jason Cohen'}->{'Buddies'} = [ 'Michael Koziarski' ];
  193.     $speakers_ref->{'Michael Koziarski'}->{'Buddies'} = [ 'Jason Cohen' ];
  194.     $speakers_ref->{'Scott McCloud'}->{'Buddies'} = [ 'Jason Santa Maria' ];
  195.     $speakers_ref->{'Jason Santa Maria'}->{'Buddies'} = [ 'Scott McCloud' ];
  196.     $speakers_ref->{'Christine Perfetti'}->{'Buddies'} = [ 'Kristina Halvorson' ];
  197.     $speakers_ref->{'Kristina Halvorson'}->{'Buddies'} = [ 'Christine Perfetti' ];
  198.  
  199.     return;
  200. }
  201.  
  202. sub SafeFoodCombos
  203. {
  204.     my ($food, $foodCombo_ref, $foodComboInfo_ref) = @_;
  205.     # Mike Brown "Your submission should include no more than 5 food cards"
  206.  
  207.     if (!$food)
  208.     {
  209.         $foodCombos_ref = [];
  210.         foreach my $food2 ( keys %{$foods_ref} )
  211.         {
  212.             my @foodCombo = ();
  213.             my %foodComboInfo = ();
  214.             SafeFoodCombos($food2, \@foodCombo, \%foodComboInfo);
  215.         }
  216.     }
  217.     else
  218.     {
  219.         foreach my $food2 ( grep { ( $food le $_ ) &&
  220.                                    ( $foodComboInfo_ref->{$_} + 1 < $foods_ref->{$_} ) }
  221.                             keys %{$foods_ref} )
  222.         {
  223.             push @{$foodCombo_ref}, $food2;
  224.             $foodComboInfo_ref->{$food2}++;
  225.            
  226.             if ($#{$foodCombo_ref} < 4)
  227.             {
  228.                 SafeFoodCombos($food2, $foodCombo_ref, $foodComboInfo_ref);
  229.             }
  230.             else
  231.             {
  232.                 push @{$foodCombos_ref}, [ @{$foodCombo_ref} ];
  233.             }
  234.             pop @{$foodCombo_ref};
  235.             $foodComboInfo_ref->{$food2}--;
  236.         }
  237.     }
  238.    
  239.     return;
  240. }
  241.  
  242. sub MotivationCombos
  243. {
  244.     $motivationCombos_ref = [];
  245.    
  246.     # Charlie Bird "This is a relay race - if you don't provide a team of exactly two speakers, there's no way you'll even participate."
  247.     # Doug Bowman "Each speaker should have one motivation card, but be careful - both racers will be affected by both motivations."
  248.     foreach my $motivation1 ( keys %{$motivations_ref} )
  249.     {
  250.         foreach my $motivation2 ( grep {$_ gt $motivation1}
  251.                                   keys %{$motivations_ref} )
  252.         {
  253.             push @{$motivationCombos_ref}, [$motivation1, $motivation2];
  254.         }
  255.     }
  256.        
  257.     # http://twitter.com/kalena/status/38185965981929472 "@webstockgame Can you include duplicate motivation or food cards in your submission? Can't find the answer to this anywhere!"
  258.     # http://twitter.com/webstockgame/status/38305095099748352 "@kalena If there's no rule explicitly forbidding it, I think you could give it a try :)"
  259.     foreach my $motivation ( keys %{$motivations_ref} )
  260.     {
  261.         push @{$motivationCombos_ref}, [$motivation, $motivation];
  262.     }
  263. }
  264.  
  265. sub BruteForce
  266. {
  267.     foreach my $runner1_ref (
  268.         # sort {$a->{'Name'} cmp $b->{'Name'}}
  269.         values %{$speakers_ref} )
  270.     {
  271.         foreach my $runner2_ref (
  272.             # sort {$a->{'Name'} cmp $b->{'Name'}}
  273.             grep { $_->{'Name'} gt $runner1_ref->{'Name'} }
  274.             values %{$speakers_ref} )
  275.         {
  276.             Relay($runner1_ref, $runner2_ref);
  277.         }
  278.     }
  279. }
  280.  
  281. sub Relay
  282. {
  283.     my ($runner1_ref, $runner2_ref) = @_;
  284.     # Charlie Bird "This is a relay race - if you don't provide a team of exactly two speakers, there's no way you'll even participate."
  285.    
  286.     foreach my $runner1Profession ( @{$runner1_ref->{'Profession'}} )
  287.     {
  288.         # Tash Lampard "Bennifer and Brangelina - ah, popular portmanteaus! Write oue for your running buddies and stick it in with your entry. It's funny enough they'll get a 5% base speed bonus!"
  289.         my $runner1Modifier = 1.05;
  290.         my $runner2Modifier = 1.05;
  291.        
  292.         # David Recordon "Any American teamed up with a non-American gains a 10% base speed increase!"
  293.         $runner1Modifier *= ($runner1_ref->{'American'} && !$runner2_ref->{'American'}) ? 1.1 : 1;
  294.         $runner2Modifier *= ($runner2_ref->{'American'} && !$runner1_ref->{'American'}) ? 1.1 : 1;
  295.        
  296.         # Michael Lopp "Glasses - they focus your eyes. Surprisingly, they also focus your race mentality. FOUR EYES SPEAKER POWERUP: 10% base speed increase!"
  297.         $runner1Modifier *= ($runner1_ref->{'Glasses'}) ? 1.1 : 1;
  298.         $runner2Modifier *= ($runner2_ref->{'Glasses'}) ? 1.1 : 1;
  299.        
  300.         # http://twitter.com/webstockgame/status/38003315480469504 "Running with a racing buddy friend gives a speaker a 10% bonus on their base speed."
  301.         $runner1Modifier *= ("@{$runner1_ref->{'Buddies'}}" =~ /$runner2_ref->{'Name'}/) ? 1.1 : 1;
  302.         $runner2Modifier *= ("@{$runner2_ref->{'Buddies'}}" =~ /$runner1_ref->{'Name'}/) ? 1.1 : 1;
  303.        
  304.         # http://twitter.com/webstockgame/status/38003446254665728 "Running with an arch-enemy makes reduces their base speed by about 25%"
  305.         $runner1Modifier /= ("@{$runner1_ref->{'Arch-Enemies'}}" =~ /$runner2_ref->{'Name'}/) ? 1.25 : 1;
  306.         $runner2Modifier /= ("@{$runner2_ref->{'Arch-Enemies'}}" =~ /$runner1_ref->{'Name'}/) ? 1.25 : 1;
  307.        
  308.         # http://twitter.com/webstockgame/status/38044995223031808 "If a speaker has multiple archetypes, you a their coach can decide which one they're gonna be by circling it on the card."
  309.         foreach my $runner2Profession ( @{$runner2_ref->{'Profession'}} )
  310.         {
  311.             foreach my $motivationCombo_ref ( @{$motivationCombos_ref} )
  312.             {
  313.                 foreach my $foodCombo_ref ( @{$foodCombos_ref} )
  314.                 {
  315.                     my $runner1speed_ref = Run($runner1_ref->{'Name'}, $runner1Modifier, $runner1Profession, $motivationCombo_ref, $foodCombo_ref);
  316.                     my $runner2speed_ref = Run($runner2_ref->{'Name'}, $runner2Modifier, $runner2Profession, $motivationCombo_ref, $foodCombo_ref);
  317.                    
  318.                     my $runner1Time = Time( @{$runner1speed_ref} );
  319.                     my $runner2Time = Time( @{$runner2speed_ref} );
  320.                    
  321.                     my $time = $runner1Time + $runner2Time;
  322.                    
  323.                     if (!$best_ref->[0] || $time < $best_ref->[0])
  324.                     {
  325.                         $best_ref->[0] = $time if (!$best_ref->[0] || $time < $best_ref->[0]);
  326.                        
  327.                         my %m = ();
  328.                         foreach my $m ( @{$motivationCombo_ref} ) { $m{$m}++; }
  329.                        
  330.                         my %f = ();
  331.                         foreach my $f ( @{$foodCombo_ref} ) { $f{$f}++; }
  332.                        
  333.                         my $fGroup = join ', ', map { "$_" . ( $f{$_} > 1 ? " x $f{$_}" : '' ) } keys %f;
  334.                         my $mGroup = join ', ', map { "$_" . ( $m{$_} > 1 ? " x $m{$_}" : '' ) } keys %m;
  335.                        
  336.                         $best_ref = [$runner1Time + $runner2Time, Duration($best_ref->[0]) . " $runner1_ref->{'Name'} ($runner1Profession) & $runner2_ref->{'Name'} ($runner2Profession); $mGroup; $fGroup", $runner1_ref, $runner2_ref];
  337.                        
  338.                         $results_ref->{$time} = $best_ref->[1];
  339.                     }
  340.                 }
  341.             }
  342.         }
  343.     }
  344. }
  345.  
  346. sub Run
  347. {
  348.     my ($runnerName, $modifier, $profession, $motivationGroup_ref, $foodGroup_ref) = @_;
  349.    
  350.     my $runner_ref = $speakers_ref->{$runnerName};
  351.     my $motivationSpeed = 0;
  352.    
  353.     foreach my $motivation ( @{$motivationGroup_ref} )
  354.     {
  355.         $motivationSpeed += MotivationModifier($motivation, $profession);
  356.     }
  357.  
  358.     my @speed = ();
  359.    
  360.     # Merlin Mann "Each speaker runs 5000 metres. The five food cards affect how they run each 1000 metres of their race leg."
  361.     foreach my $food (@{$foodGroup_ref})
  362.     {
  363.         # Rules "When scoring we first calculate the speed of each of your speakers and apply any racing buddy modifications and other personal add-ons. Then we'll have a look at their motivation and finally we'll feed them, in that order. Got it?"
  364.         push @speed, ( $runner_ref->{'BaseSpeed'}
  365.                      * $units_ref->{$runner_ref->{'Unit'}}
  366.                      * $modifier
  367.                      + $motivationSpeed )
  368.                      * $runner_ref->{'Food'}->{$food}
  369.                      ;
  370.     }
  371.    
  372.     return \@speed;
  373. }
  374.  
  375. sub MotivationModifier
  376. {
  377.     my ($motivation, $profession) = @_;
  378.     # http://twitter.com/webstockgame/status/38003477846167553 "If you try to motivate speakers with something they hate, expect the benefit of the motivation card to be negated."
  379.            
  380.     # http://twitter.com/webstockgame/status/37970752279941120 "Coders are intrinsically motivated to the highest level. Each motivation card has just 50% of the positive effect it'd have on other people."
  381.     my $coderModifier = ($profession =~ /^Coder$/) ? 0.5 : 1;
  382.    
  383.     if ($motivation =~ /^Amanda Palmer Album$/)
  384.     {
  385.         # http://twitter.com/webstockgame/status/38349545591013376 "Music: often the lifeblood of creative people, and often another nascent trend to be harvested by Mavens."
  386.         if ($profession =~ /^(?:Creative|Maven)$/)
  387.         {
  388.             return $motivations_ref->{$motivation};
  389.         }
  390.     }
  391.     elsif ($motivation =~ /^LOLCats$/)
  392.     {
  393.         if ($profession =~ /^Artist$/)
  394.         {
  395.             # http://twitter.com/webstockgame/status/37987374608678912 "Every LOLcat picture is a work of art. It follows that every artist loves LOLcats, no?"
  396.             return $motivations_ref->{$motivation};
  397.         }
  398.         elsif ($profession =~ /^Organiser$/)
  399.         {
  400.             # Steve Souders: Organisers spend half their lives hearding kittens. Think it makes them happy?
  401.             return $motivations_ref->{$motivation} * -1;
  402.         }
  403.     }
  404.     elsif ($motivation =~ /^API$/)
  405.     {
  406.         # http://twitter.com/webstockgame/status/38055177172819968 "Mavens and APIs? Reeeallllly?"
  407.         if ($profession =~ /^Maven$/)
  408.         {
  409.             return $motivations_ref->{$motivation} * -1;
  410.         }
  411.     }
  412.     elsif ($motivation =~ /^TSA$/)
  413.     {
  414.         # http://twitter.com/webstockgame/status/38012371079266305 "Coders have strong opinions on everything, but being groped by underpaid security guards makes them worry about accessibility."
  415.         if ($profession =~ /^Coder$/)
  416.         {
  417.             return $motivations_ref->{$motivation} * -1 * $coderModifier;
  418.         }
  419.     }
  420.     elsif ($motivation =~ /^Accessibility$/)
  421.     {
  422.         # http://twitter.com/webstockgame/status/38068897210961920 "Organisers: they read a hell of a lot (when they're not alphabetising their book catalogue)!"
  423.         if ($profession =~ /^Organiser$/)
  424.         {
  425.             return $motivations_ref->{$motivation};
  426.         }
  427.     }
  428.     elsif ($motivation =~ /^Running tips$/)
  429.     {
  430.         # Glenda Sims: We know that artists and creatives are motivated by an eternay search for beauty and meaning. Surprisingly, so are coders.
  431.         if ($profession =~ /^(?:Artist|Coder|Creative)$/)
  432.         {
  433.             return $motivations_ref->{$motivation} * $coderModifier;
  434.         }
  435.     }
  436.     elsif ($motivation =~ /^Onyas Ticket$/)
  437.     {
  438.         # http://twitter.com/lumbarius/status/38367128251932672 "@webstockgame I haven't seen a rule for ONYAs... did I miss something?"
  439.         # http://twitter.com/webstockgame/status/38377248499314688 "@lumbarius doesn't everyone love the ONYAs ???? #Webstock"
  440.         return $motivations_ref->{$motivation} * $coderModifier;
  441.     }
  442.    
  443.     return 0;
  444. }
  445.  
  446. sub Time
  447. {
  448.     my $sum = 0;
  449.    
  450.     foreach my $val (@_)
  451.     {
  452.         $sum += 1 / $val * 3600;
  453.     }
  454.    
  455.     return $sum;
  456. }
  457.  
  458. sub Duration
  459. {
  460.     my ($seconds) = @_;
  461.    
  462.     my $decimal = (($2 + 0) * 10) + ($3 + 0) + (($4 + 0) >= 5 ? 1 : 0);
  463.    
  464.     my $minutes = int($seconds / 60);
  465.     $seconds -= ($minutes * 60);
  466.     $seconds =~ s/^(\d+(?:.\d{0,2})?).*$/$1/;
  467.    
  468.     return "$minutes:" . ($seconds < 10 ? '0' : '') . $seconds;
  469. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement