Śpiechu liczy zawartość alkoholu w drinkach

Zasta­na­wiało Was kiedyś o ile dokład­nie wzro­śnie całko­wita zawar­tość alko­holu gdy do piwa dodamy „u-boota” (50tkę wódki)? A o ile spad­nie gdy to piwo zbesz­cze­ścimy doda­niem soku mali­no­wego? Chodzi mi o dokładne warto­ści, a nie jakieś tam „no pewnie z 2% jak nic”. Dzisiaj się dowiecie :-)

Całość napi­sa­łem w Pytho­nie żeby się trochę wdro­żyć. Dla Windowsa jest bardzo fajna rzecz: Porta­ble Python. Insta­lu­jesz na pendraka i nieza­leż­nie od maszyny odpa­lasz inter­pre­ter. Do cało­ści dołą­czony jest całkiem zgrabny edytor PyScripter.

Dobra, do rzeczy. Potrzebna będzie wiedza przed­gim­na­zjalna — mnoże­nie, dzie­le­nie i trochę procen­tów. Wyni­kowy program obsłu­guje się tak:

#!/usr/bin/env python
 
from shaker import Shaker, ShakerDisplayer
 
shaker = Shaker()
shaker.addIngredient('piwo', 500, 5.7)
shaker.addIngredient('wodka', 50, 40)
shaker.addIngredient('sok malinowy', 25, 0)
 
ShakerDisplayer.displayShakerDetails(shaker, 89, True)

Otrzy­mamy poniż­szy tekst:

Sklad­niki drinka:
25.00ml sok mali­nowy
30.00ml wodka
48.50ml alco­hol
471.50ml piwo
Calko­wita zawar­tosc alko­holu w drinku: 8.43%
Calko­wita zawar­tosc alko­holu w drinku (wyra­zona w gramach): 38.32g
Praw­do­po­dobna liczba promili dla faceta o wadze 89kg wynosi 0.62‰

W pliku (module!) shaker.py stwo­rzymy sobie 2 klasy: ShakerShaker­Di­splayer. Jak linijki nie miesz­czą się w okienku to można prze­su­wać strzał­kami na klawiaturze ;-)

#!/usr/bin/env python
 
import unicodedata
from numbers import Number
 
class Shaker:
 
    def __init__(self, shakerCapacity = 1000000):
 
        # Zakladamy, ze pojemnosc shakera jest nieograniczona ;-)
        self._shakerCapacity = shakerCapacity
 
        # Inicjalizuje dictionary dla przechowywania klucz => wartosc
        # Klucz dla alkoholu jest w skladnikach zawsze
        self._drinkIngredients = {'alcohol' : 0}
 
    def addIngredient(self, name, amount, alcoholPercentage = 0):
 
        # Gdyby komus zachcialo sie wprowadzac inne wartosci niz numerki i wartosci dodatnie
        if not isinstance(amount, Number) or not isinstance(alcoholPercentage, Number) or alcoholPercentage < 0 or amount < 0:
 
            # Formatowanie za pomoca {} zadziala od Pythona 3.1+    
            raise ValueError('Podano {} i {} dla {}'.format(amount, alcoholPercentage, name))
 
        # Sprawdzam czy jest wystarczajaco duzo miejsca w shakerze
        spaceInShakerLeft = self._shakerCapacity - self.totalLiquidAmount()
        if spaceInShakerLeft >= amount:
            self._storeNewIngredient(name, amount, alcoholPercentage)
        else:
 
            # Jak za malo to dolewam tylko tyle ile sie zmiesci
            self._storeNewIngredient(name, spaceInShakerLeft, alcoholPercentage)
 
    def _storeNewIngredient(self, name, amount, alcoholPercentage):
 
        # Licze objetosc czystego alkoholu w plynie
        liquidAlcohol = 0
        if alcoholPercentage > 0:
            liquidAlcohol = (amount * alcoholPercentage) / 100
            self._drinkIngredients['alcohol'] += liquidAlcohol
 
        # Sprawdzam czy w drinku jest juz dany skladnik
        if self._drinkIngredients.get(name) == None:
            self._drinkIngredients[name] = amount - liquidAlcohol
        else:
            self._drinkIngredients[name] += amount - liquidAlcohol
 
    def getAllDrinkIngredients(self):
 
        # Wypluwam czysty dictionary ze skladnikami
        return self._drinkIngredients
 
    def totalLiquidAmount(self):
 
        # Zliczam objetosc wszystkich skladnikow w shakerze
        total = 0
        for value in self._drinkIngredients.values():
            total += value
        return total
 
    def getTotalLiquidAlcohol(self):
        return self._drinkIngredients['alcohol']
 
    def getTotalAlcoholPercentage(self):
 
        # Licze calkowity procent alkoholu w drinku
        return (self.getTotalLiquidAlcohol() / self.totalLiquidAmount()) * 100
 
    def getTotalAlcoholInGrams(self):
 
        # Przeliczam ml alkoholu na gramy
        return 0.79 * self.getTotalLiquidAlcohol()
 
    def computeAlcoholPromillesPerWeight(self, weight, man = True):
 
        # PRZYBLIZONA zawartosc procentowa plynow ustrojowych w zaleznosci od plci
        humanFluidsPercentage = 0.7 if man == True else 0.6
        return self.getTotalAlcoholInGrams() / (humanFluidsPercentage * weight)
 
    def pourOutDrink(self, amount):
        """
        Metoda wlasciwie niepotrzebna. Mozna wylac (wypic!) czesc zawartosci
        shakera i sobie potem dolewac kolejne skladniki.
        """
        if amount >= self.totalLiquidAmount():
            self._drinkIngredients = {'alcohol' : 0}
        else:
            percentage = amount / self.totalLiquidAmount()
            for key, value in self._drinkIngredients.items():
                self._drinkIngredients[key] -= self._drinkIngredients[key] * percentage

Klasa powy­żej poli­czy to co trzeba. Wyli­cze­nia doty­czące promili w orga­ni­zmie należy trak­to­wać jako mocno przy­bli­żone. Całej dawki alko­holu nie przyj­mu­jemy w końcu w 1 sekun­dzie, orga­nizm na bieżąco spala truci­znę. Poza tym zależy czy i co się jadło itp. itd., nie wiem, nie znam się.
Teraz jesz­cze klasa, która zajmie się wyświe­tla­niem (a raczej metoda statyczna).

class ShakerDisplayer:
 
    def displayShakerDetails(shaker, weight, man = True):
        if not isinstance(shaker, Shaker):
            raise ValueError('Podano argument klasy {}'.format(shaker.__class__))
 
        print('Skladniki drinka:')
        for key,value in shaker.getAllDrinkIngredients().items():
            # Zaokraglamy i wymuszamy 2 miejsca po przecinku
            print('{:.2f}ml {}'.format(value,key))
 
        print('Calkowita zawartosc alkoholu w drinku: {:.2f}%'.format(shaker.getTotalAlcoholPercentage()))
        print('Calkowita zawartosc alkoholu w drinku (wyrazona w gramach): {:.2f}g'.format(shaker.getTotalAlcoholInGrams()))
 
        # Nie znam lepszej metody na wyswietlenie znaku promila niz unicodedata.lookup('PER MILLE SIGN')
        # Ma ktos lepszy pomysl?
        print('Prawdopodobna liczba promili dla {} o wadze {}kg wynosi {:.2f}{}'.format('faceta' if man == True else 'kobiety', weight, shaker.computeAlcoholPromillesPerWeight(weight,man), unicodedata.lookup('PER MILLE SIGN')))

Gdyby potrak­to­wać nasz żołą­dek jak taki shaker, to po wpisa­niu pół litra wódki + 2 piwa + litrowy sprite da nam:

Sklad­niki drinka:
300.00ml wodka
257.00ml alco­hol
1000.00ml sprite
943.00ml piwo
Calko­wita zawar­tosc alko­holu w drinku: 10.28%
Calko­wita zawar­tosc alko­holu w drinku (wyra­zona w gramach): 203.03g
Praw­do­po­dobna liczba promili dla faceta o wadze 89kg wynosi 3.26‰

No nic, na zdro­wie i pozdro dla wszyst­kich Pytho­now­ców! Leniu­chom podaję link do goto­wych plików.

Podobne wpisy:

  1. Mój pierw­szy raz… z Javą :-)
  2. Śpie­chu certyfikowany
  3. Śpie­chu goes Hyper Threading
  4. Śpie­chu pisze testy jednostkowe

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.

Możesz użyć następujących tagów oraz atrybutów HTML-a: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <p> <pre lang="" line="" escaped=""> <q cite=""> <strike> <strong>