anchor.diff:    Runs = lists:map(fun (Hand) -> new_run_record(Hand, TrumpSuit) end, Hands),
     Runs.
   
  -% TODO: could use split_runs before score_suit to make it cleaner
  -% TODO: move score out of best_run, add new record with cards
   new_run_record(Cards, TrumpSuit) ->
     SortedCards = sort_cards_by_value(Cards),
  -  SplitBySuit = split_by_suit(SortedCards),
  -  {CardsBySuit, Suits} = lists:unzip(SplitBySuit),
  +  CardsBySuit = split_by_suit(SortedCards),
   
  -  _CardsToShow = lists:flatten(lists:foldl(fun lists:append/2,
  -      lists:map(fun split_runs/1, CardsBySuit))),
  +  SplitByRuns = lists:reverse(lists:foldl(fun lists:append/2, [],
  +    lists:map(fun split_runs/1, CardsBySuit))),
   
  -  % {suit, #best_fun{}}
  -  Runs = lists:zip(Suits, lists:map(fun score_suit/1, CardsBySuit)),
  +  SortBySize = sort_runs(SplitByRuns, TrumpSuit),
   
  -  Folder = fun({Suit, Run}, Acc) -> fold_runs(Suit, Run, Acc, TrumpSuit) end,
  -  NoRun = {nosuit, #best_run{type=none, high=0, score=0, trump=false}},
  -
  -  _BestRun = lists:foldl(Folder, NoRun, Runs),
  -
  -  #run_record{twenty=false,
  -              fifty=false,
  -              bella=false,
  -              best_run=none,
  -              score=0}.
  +  CardsToShow = lists:flatten(SortBySize),
  +  Score = score_runs(SplitByRuns),
  +  BestRun = make_best(SortBySize, TrumpSuit),
  +  #run_record{best_run=BestRun, score=Score, to_show=CardsToShow}.
   
   % This sorts top to bottom by values to make run finding easier
   sort_cards_by_value2(#card{suit=Suit, value=V1},
  
positive.code:     ?_assertEqual([],
        split_runs(ML([14, 13, 11, 10, 8, 7])))
    ].
  
  % J, Q, K, A --> 11, 12, 13, 14
  score_suit_test_() ->
    M = fun (Value) -> #card{value=Value} end,
    ML = fun (VList) -> lists:map(M, VList) end,
    MB = fun ({Type, High, Score}) -> make_best_run(Type, High, Score) end,
  
    [
      ?_assertEqual(MB({none, 0, 0}), score_suit(ML([12, 10, 9, 7, 6]))),
      ?_assertEqual(MB({none, 0, 0}), score_suit(ML([12]))),
  
      ?_assertEqual(MB({twenty, 8, 20}), score_suit(ML([8, 7, 6]))),
      ?_assertEqual(MB({twenty, 8, 20}), score_suit(ML([13, 12, 10, 8, 7, 6]))),
      ?_assertEqual(MB({twenty, 13, 20}), score_suit(ML([13, 12, 11, 9, 7, 6]))),
  
      % Double twenty:
      ?_assertEqual(MB({twenty, 14, 40}), score_suit(ML([14, 13, 12, 10, 9, 8, 6]))),
  
      ?_assertEqual(MB({fifty, 9,  50}), score_suit(ML([9, 8, 7, 6]))),
      ?_assertEqual(MB({fifty, 12, 70}), score_suit(ML([12, 11, 10, 9, 8, 7, 6]))),
  
      % Double fifty:
      ?_assertEqual(MB({fifty, 14, 100}),
        score_suit(ML([14, 13, 12, 11, 10, 9, 8, 7, 6])))
    ].
  
  fold_runs_test_() ->
    FiftyA50 = #best_run{type=fifty, high=14, score=50, trump=false},
    FiftyJ50 = #best_run{type=fifty, high=11, score=50, trump=false},
  
    TwentyA  = #best_run{type=twenty, high=14, score=20, trump=false},
  
    Best50NT = #best_run{type=fifty, high=14, score=50, trump=false},
    Best20NT = #best_run{type=twenty, high=14, score=40, trump=false},
  
  %-record(best_run, {type, high, score, trump}).
    [
      % Test Trump equal beats non-trump:
      ?_assertEqual(Best50NT#best_run{score=100, trump=true},
        fold_runs(trump, FiftyA50, Best50NT, trump)),
  
      ?_assertEqual(Best20NT#best_run{score=60, trump=true},
        fold_runs(trump, TwentyA, Best20NT, trump)),
  
      % Test lower trump does not:
      ?_assertEqual(Best50NT#best_run{score=100},
        fold_runs(trump, FiftyJ50, Best50NT, trump)),
  
      % Fifty beats twenty, even if twenty was trump and had a high card
      ?_assertEqual(Best50NT#best_run{high=11, score=90},
        fold_runs(nontrump, FiftyJ50, Best20NT#best_run{trump=true}, trump)),
  
      % Twenty doesn't beat fifty, even trump with higher card:
      ?_assertEqual(Best50NT#best_run{high=11, score=70},
        fold_runs(trump, TwentyA, Best50NT#best_run{high=11}, trump))
  
    ].
  
negative.code: sort_cards_by_value(Cards) ->
    lists:sort(fun sort_cards_by_value2/2, Cards).
  
  sort_runs(Run1, Run2, _Trump)
    when length(Run1) =/= length(Run2) ->
      not(length(Run1) =< length(Run2));
  
  sort_runs([#card{value=V1}|_], [#card{value=V2}|_], _Trump)
    when V1 =/= V2 ->
      not(V1 =< V2);
  
  sort_runs(_Run1, [#card{suit=S1}|_], Trump) ->
    not(S1 == Trump).
  
  sort_runs(Runs, Trump) ->
    lists:sort(fun (X, Y) -> sort_runs(X, Y, Trump) end, Runs).
  
  make_best([], _Trump) ->
    #best_run{type=none, high=0, trump=false};
  
  make_best([[#card{value=V1, suit=S1}|_] = Run |_], Trump) when length(Run) == 4 ->
    #best_run{type=fifty, high=V1, trump=(S1 == Trump)};
  
  make_best([[#card{value=V1, suit=S1}|_]|_], Trump) ->
    #best_run{type=twenty, high=V1, trump=(S1 == Trump)}.
  
  score_runs([], Score) ->
    Score;
  
  score_runs([Run|Rest], Score) when length(Run) == 4 ->
    score_runs(Rest, Score + 50);
  
  score_runs([_Run|Rest], Score) ->
    score_runs(Rest, Score + 20).
  
  score_runs(Runs) ->
    score_runs(Runs, 0).
  
  split_by_suit([], Cards, _Suit, Lists) ->
    lists:reverse([lists:reverse(Cards)|Lists]);
  
  split_by_suit([#card{suit=Suit} = Card|Rest], Cards, Suit, Lists) ->
    split_by_suit(Rest, [Card|Cards], Suit, Lists);
  
  split_by_suit([Card|Rest], Cards, _Suit, Lists) ->
    split_by_suit(Rest, [Card], Card#card.suit, [lists:reverse(Cards)|Lists]).
  
  % Stable split to keep sorted
  split_by_suit([Card|Rest]) ->
    split_by_suit(Rest, [Card], Card#card.suit, []).
  
  % Split them into 4's and 3's:
  
  