code: function detailRange(cards) {
    if (cache.has(cards)) return cache.get(cards)
  
    var [ r1, r2, suitedness ] = cards
    if (r1 === r2) return addPairDetails(r1, new Set())
  
    if (ranks.indexOf(r1) > ranks.indexOf(r2)) {
      const tmp = r1; r1 = r2; r2 = tmp
    }
  
    var res
    if (suitedness === 's') res = addSuitedDetails(r1, r2, new Set())
    else if (suitedness === 'o') res = addOffsuitDetails(r1, r2, new Set())
    else res = addOffsuitAndSuitedDetails(r1, r2, new Set())
    cache.set(cards, res)
    return res
  }
docs: Provides all possible combinations of a given part of a card range.
  
  ```
  '99'  => '9h9s', '9h9d', '9h9c', '9s9d', '9s9c', '9d9c'
  
  'AKs' => 'AhKh', 'AsKs', 'AdKd', 'AcKc'
  
  'KQo' => 'KhQs', 'KhQd', 'KhQc', 'KsQh', 'KsQd', 'KsQc',
  'KdQh', 'KdQs', 'KdQc', 'KcQh', 'KcQs', 'KcQd'
  
  'JT'  => 'JhTh', 'JhTs', 'JhTd', 'JhTc', 'JsTh', 'JsTs', 'JsTd', 'JsTc',
  'JdTh', 'JdTs', 'JdTd', 'JdTc', 'JcTh', 'JcTs', 'JcTd', 'JcTc'
  ```
  @name detailRange
  @function
  @param {String} cards the cards for which to give a detailed combo range, i.e. 'AKs'
  Note: that AKs is considered the same as KAs and no duplicate combos will be included
  @return {Set} set of all possible combinations on how to hold the combo