def calculate_final_scores(history):   # ➊
    """returns a tuple of 4 integers: 
           sum_upper_section,
           upper_section_bonus,
           sum_lower_section,
           yahtzee_bonus
    """                                # ➋
    sum_upper_section = 0              # ➌
    sum_lower_section = 0
    upper_section_bonus = 0
    yahtzee_bonus = 0
    allow_yahtzee_bonus = False
    for name in history:               # ➍     
        scored = history[name][0]      # ➎
        dice = history[name][1]        # ➏
        # is upper section?            # ➐
        if name in ("Ones", "Twos", "Threes",
                    "Fours", "Fives", "Sixes"):
            sum_upper_section += scored
        else:
            sum_lower_section += scored
        # is Yahtzee?                  # ➑
        if len(set(dice)) == 1: 
            # enable Yahtzee bonus ?
            if scored == 50 and not allow_yahtzee_bonus:
                allow_yahtzee_bonus = True
            elif allow_yahtzee_bonus:
                yahtzee_bonus += 100
    if sum_upper_section >= 63:        # ➒
        upper_section_bonus = 35
    return sum_upper_section, upper_section_bonus, sum_lower_section, yahtzee_bonus

# testing

if __name__ == "__main__":             # ➓       
    print("testing...")
    # example 1:
    # get upper section bonus of 35
    # because sum(upper_section) > 63
    history = {"Ones":  (5, [1,1,1,1,1]),
               "Twos":  (10,[2,2,2,2,2]),
               "Threes":(15,[3,3,3,3,3]),
               "Fours": (20,[4,4,4,4,4]),
               "Fives": (15,[5,5,5,1,1]),
               "Sixes": (0,[1,2,6,6,3]),
               }
    assert sum(calculate_final_scores(history)) == 100
    # test the upper section bonus  directly
    # it's the second element of the return value 
    # a second element in python has the index 1
    assert calculate_final_scores(history)[1] == 35
    # example 2:
    # get yahtzee bonus of 100:
    history = {"Ones":   (5, [1,1,1,1,1]),
               "Yahtzee":(50, [2,2,2,2,2]),
               "Twos":   (10, [2,2,2,2,2])}        
    assert sum(calculate_final_scores(history)) == 165        
    # example 3
    # get yahtzee bonus of 200:
    history = {"Ones":   (5, [1,1,1,1,1]),
               "Yahtzee":(50, [2,2,2,2,2]),
               "Twos":   (10, [2,2,2,2,2]),
               "Threes": (15, [3,3,3,3,3])}        
    assert sum(calculate_final_scores(history)) == 280        
    # example4: 
    # don't get yahtzee bonus because Yahtzee
    # because Yahtzee was played (used up) with
    # zero points already:
    history = {"Ones":(5, [1,1,1,1,1]),
               "Yahtzee":(0, [3,4,2,2,2]),
               "Twos":(10, [2,2,2,2,2])}        
    assert sum(calculate_final_scores(history)) == 15        
    
    print("all tests passed")