├── readme.md └── daiquiri-calc.py /readme.md: -------------------------------------------------------------------------------- 1 | # Imbalanced Daiquiri Batch Calculator 2 | 3 | ## Description 4 | 5 | This script calculates imbalanced daiquiri batch recipes (with dilution) for a craft cocktail class. The goal is to produce 3 imbalanced samples (a rum heavy, a lime heavy, and a syrup heavy example) to demonstrate imbalance, but the 3 examples can be combined in equal parts to achieve the classic 2:1:1 balance of a daiquiri. 6 | 7 | ## Usage 8 | 9 | Run the script from the command line: 10 | 11 | python3 daiquiri-science.py [serving_size] [num_sets] [dilution] 12 | 13 | ### Command-line Arguments 14 | 15 | 1. serving_size: Individual serving size in ounces after dilution (default: 1.0) 16 | 2. num_sets: Number of sets to prepare. Each set includes one sample of each variation (default: 30) 17 | 3. dilution: Target dilution as a decimal. For example, 0.3 represents 30% dilution (default: 0.3) 18 | 19 | ### Defaults 20 | 21 | If no arguments are provided, the script will use these default values: 22 | - Serving size: 1.0 oz 23 | - Number of sets: 30 24 | - Dilution: 0.3 (30%) 25 | 26 | ### Examples 27 | 28 | 1. Using default values: 29 | python3 daiquiri-science.py 30 | 31 | 2. Specifying all parameters: 32 | python3 daiquiri-science.py 1.5 40 0.25 33 | This calculates batches for 40 sets of 3 samples each, with each sample targeted to be 1.5 oz after dilution, and a 25% dilution target. 34 | 35 | ## Output 36 | 37 | The script provides: 38 | - Batch recipes for each Daiquiri variation 39 | - Total batch volumes 40 | - Number of complete sets and total individual samples 41 | - Combined totals of all ingredients 42 | - Final ratio of ingredients when all batches are combined 43 | 44 | ## Requirements 45 | 46 | - Python 3.6 or higher 47 | -------------------------------------------------------------------------------- /daiquiri-calc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ''' 4 | Adding a printed ratio for each batch, as well. 5 | ''' 6 | import math 7 | import argparse 8 | 9 | def round_up_to_quarter(value): 10 | return math.ceil(value * 4) / 4 11 | 12 | def calculate_batch(rum, syrup, lime, num_sets, serving_size, dilution): 13 | non_water_volume = serving_size * (1 - dilution) 14 | water_volume = serving_size * dilution 15 | 16 | return { 17 | 'rum': round_up_to_quarter(rum * non_water_volume * num_sets), 18 | 'syrup': round_up_to_quarter(syrup * non_water_volume * num_sets), 19 | 'lime': round_up_to_quarter(lime * non_water_volume * num_sets), 20 | 'water': round_up_to_quarter(water_volume * num_sets) 21 | } 22 | 23 | def main(): 24 | parser = argparse.ArgumentParser( 25 | description='Calculate cocktail batch recipes with dilution for a Daiquiri variation class.', 26 | epilog='This script helps prepare three variations of a Daiquiri (rum-heavy, syrup-heavy, and lime-heavy) ' 27 | 'for a cocktail balance class. It calculates the required amounts for each batch, accounting for ' 28 | 'the desired serving size, number of sets, and dilution.' 29 | ) 30 | 31 | parser.add_argument('serving_size', type=float, nargs='?', default=1.0, 32 | help='Individual serving size in ounces after dilution (default: 1.0)') 33 | parser.add_argument('num_sets', type=int, nargs='?', default=30, 34 | help='Number of sets to prepare. Each set includes one sample of each variation (default: 30)') 35 | parser.add_argument('dilution', type=float, nargs='?', default=0.3, 36 | help='Target dilution as a decimal. For example, 0.3 represents 30%% dilution (default: 0.3)') 37 | 38 | args = parser.parse_args() 39 | 40 | individual_serving = args.serving_size 41 | num_sets = args.num_sets 42 | dilution = args.dilution 43 | 44 | # Define the imbalanced recipes (proportions for non-water ingredients) 45 | rum_heavy_recipe = (0.5625, 0.21875, 0.21875) 46 | syrup_heavy_recipe = (0.46875, 0.3125, 0.21875) 47 | lime_heavy_recipe = (0.46875, 0.21875, 0.3125) 48 | 49 | # Calculate batches 50 | rum_heavy = calculate_batch(*rum_heavy_recipe, num_sets, individual_serving, dilution) 51 | syrup_heavy = calculate_batch(*syrup_heavy_recipe, num_sets, individual_serving, dilution) 52 | lime_heavy = calculate_batch(*lime_heavy_recipe, num_sets, individual_serving, dilution) 53 | 54 | print(f"Calculating batches for {num_sets} sets of 3 samples each (total {num_sets * 3} individual samples)") 55 | print(f"Each sample is targeted to be {individual_serving:.2f}oz after dilution") 56 | print(f"Target dilution: {dilution*100:.1f}%") 57 | 58 | print("\nBatch Recipes (in ounces, rounded up to nearest 1/4 oz):") 59 | print(f"Rum-heavy: {rum_heavy['rum']:.2f}oz rum, {rum_heavy['syrup']:.2f}oz syrup, {rum_heavy['lime']:.2f}oz lime, {rum_heavy['water']:.2f}oz water") 60 | print(f"Syrup-heavy: {syrup_heavy['rum']:.2f}oz rum, {syrup_heavy['syrup']:.2f}oz syrup, {syrup_heavy['lime']:.2f}oz lime, {syrup_heavy['water']:.2f}oz water") 61 | print(f"Lime-heavy: {lime_heavy['rum']:.2f}oz rum, {lime_heavy['syrup']:.2f}oz syrup, {lime_heavy['lime']:.2f}oz lime, {lime_heavy['water']:.2f}oz water") 62 | 63 | # Calculate total volume for each batch 64 | total_volume_rum_heavy = sum(rum_heavy.values()) 65 | total_volume_syrup_heavy = sum(syrup_heavy.values()) 66 | total_volume_lime_heavy = sum(lime_heavy.values()) 67 | 68 | print("\nTotal batch volumes:") 69 | print(f"Rum-heavy: {total_volume_rum_heavy:.2f}oz") 70 | print(f"Syrup-heavy: {total_volume_syrup_heavy:.2f}oz") 71 | print(f"Lime-heavy: {total_volume_lime_heavy:.2f}oz") 72 | 73 | # Calculate actual number of complete sets each batch will yield 74 | actual_sets_rum_heavy = math.floor(total_volume_rum_heavy / individual_serving) 75 | actual_sets_syrup_heavy = math.floor(total_volume_syrup_heavy / individual_serving) 76 | actual_sets_lime_heavy = math.floor(total_volume_lime_heavy / individual_serving) 77 | actual_complete_sets = min(actual_sets_rum_heavy, actual_sets_syrup_heavy, actual_sets_lime_heavy) 78 | 79 | print(f"\nEach batch will yield at least {actual_complete_sets} complete sets of samples") 80 | print(f"Total individual samples: {actual_complete_sets * 3}") 81 | 82 | # Verify the balance when combined 83 | combined_rum = rum_heavy['rum'] + syrup_heavy['rum'] + lime_heavy['rum'] 84 | combined_syrup = rum_heavy['syrup'] + syrup_heavy['syrup'] + lime_heavy['syrup'] 85 | combined_lime = rum_heavy['lime'] + syrup_heavy['lime'] + lime_heavy['lime'] 86 | combined_water = rum_heavy['water'] + syrup_heavy['water'] + lime_heavy['water'] 87 | 88 | print("\nCombined totals:") 89 | print(f"Rum: {combined_rum:.2f}oz") 90 | print(f"Syrup: {combined_syrup:.2f}oz") 91 | print(f"Lime: {combined_lime:.2f}oz") 92 | print(f"Water: {combined_water:.2f}oz") 93 | 94 | total_volume = combined_rum + combined_syrup + combined_lime + combined_water 95 | print(f"\nActual ratio when combined (rum:syrup:lime:water): {combined_rum/total_volume:.3f}:{combined_syrup/total_volume:.3f}:{combined_lime/total_volume:.3f}:{combined_water/total_volume:.3f}") 96 | 97 | if __name__ == "__main__": 98 | main() 99 | --------------------------------------------------------------------------------