def _printChangedPositions(self): """Print all bottles that have had their positions changed.""" lastStack = None lastRow = None for bottle in sorted( self._bottlePositions, key=lambda b: (b.coordinate[0], b.coordinate[1], -b.coordinate[2])): if bottle.boldness_coord != None or bottle.price_coord != None or bottle.hold_coord != None: if bottle.boldness_coord != lastStack: print( stylize( Fore.GREEN, '\n-------- Stack %d --------------------------------' % bottle.boldness_coord)) elif bottle.price_coord != lastRow: print('') lastStack = bottle.boldness_coord lastRow = bottle.price_coord print("%s %s %s" % (stylize(Fore.BLUE, "Move"), stylize(Style.BRIGHT, bottle.label.description), stylize( Fore.BLUE, "to (%d, %d, %d)" % (bottle.boldness_coord, bottle.price_coord, bottle.hold_coord))))
def _printNewWineries(self): """Print all wineries that have been added this session""" for winery in self._newWineries: print("%s %s in %s" % (stylize(Fore.GREEN, "Create New Winery:"), stylize(Style.BRIGHT, winery.name), stylize(Style.BRIGHT, winery.region.description)))
def _printNewVarietals(self): """Print all varietals that have been added this session""" for varietal in self._newVarietals: print("%s %s, boldness %s" % (stylize(Fore.GREEN, "Create New Varietal:"), stylize(Style.BRIGHT, varietal.name), stylize(Style.BRIGHT, str(varietal.boldness))))
def _printNewLabels(self): """Print all labels that have been added this session""" for label in self._newLabels: print("%s %s, %s, %s%% abv" % (stylize(Fore.GREEN, "Create New Label:"), stylize(Style.BRIGHT, label.description), stylize(Style.BRIGHT, label.varietalDescription), stylize(Style.BRIGHT, ("%.1f" % label.abv))))
def _printChangedWineries(self): """Print all labels that have had their wineries changed. Includes the region, since this is expected to be used when splitting a region""" for label in self._labelWineries: print("%s %s (%s)" % (stylize(Fore.GREEN, "Change Winery:"), stylize(Style.BRIGHT, label.description), stylize(Style.DIM, label.winery.region.description)))
def _printClearedPositions(self): """Print all bottles that have had their positions cleared. This indicates the bottle is no longer stored in any particular location of the cellar. Such bottles are likely errors in the placement algorihms, so this output is highlighted in red. """ for bottle in self._bottlePositions: if bottle.boldness_coord == None and bottle.price_coord == None and bottle.hold_coord == None: print("%s %s" % (stylize(Fore.RED, "Clear position for"), stylize(Style.BRIGHT, bottle.label.description)))
def disambiguateRegion(repo, matchingWineries): """This selects which winery among multiples with the same name""" print("\nMultiple Regions for %s:" % stylize(Style.BRIGHT, matchingWineries[0].name)) for winery in matchingWineries: print(" " + stylize(Style.DIM, winery.region.description)) print() region = getRegion(repo) for winery in matchingWineries: if winery.region is region: return winery return repo.addWinery(winery, region)
def __init__(self): self.options = '' self.long_options = [] self.usageHead = 'usage: ' + stylize(Style.BRIGHT, os.path.basename(main.__file__)) self.usageOpts = [] self.usageDesc = [] self.maxLen = 0
def getVarietalPortions(repo): """This prompts the user to create the appropriate blend of grape varietals""" varietalPortions = [] remaining = 100 while remaining > 0: idx, varietalName = textEntry(" Varietal> ", [varietal.name for varietal in repo.varietals]) if idx is not None: varietal = repo.varietals[idx] else: boldness = None while boldness is None: boldnessStr = textEntry(" Boldness (? to list current)> ", [])[1]; if boldnessStr == '?': for varietal in sorted(repo.varietals, key=attrgetter('boldness'), reverse=True): print(' %s %s' % ( stylize(Fore.BLUE, '%2d' % varietal.boldness), stylize(Style.BRIGHT, '%s' % varietal.name))) else: boldness = int(boldnessStr) varietal = repo.addVarietal(varietalName, boldness) portionStr = textEntry(" Percentage (* for remainder)> ", [])[1]; if portionStr == '*': portion = remaining else: portion = min(remaining, int(portionStr)) varietalPortions.append((varietal, portion)) remaining -= portion; if remaining > 0: print() return varietalPortions
def _printNewBottles(self): """Print all bottles that have been added this session""" currentYear = date.today().year needSeparator = False for label, bottles in self._splitByLabel(self._newBottles).items(): if needSeparator: print() needSeparator = True print("%s %s" % (stylize(Fore.GREEN, ("Create New Bottle%s" % ("" if len(bottles) == 1 else "s"))), stylize(Style.BRIGHT, label.description))) counts = self._countHoldYears(bottles) for holdYear in sorted(counts): holdAmt = counts[holdYear] print( stylize( Fore.BLUE, " %d bottle%s to %s" % (holdAmt, ("" if holdAmt == 1 else "s"), "Drink Now" if holdYear == currentYear else ("Hold Until %d" % holdYear))))
def _printBottleConsumptions(self): """Print all bottles that have been consumed""" for bottle in self._bottleConsumptions: print("%s %s, %s %s, %s %s" % (stylize(Fore.RED, "Consumed"), stylize(Style.BRIGHT, bottle.label.description), stylize(Fore.RED, "stored at"), stylize( Style.BRIGHT, "(%d, %d, %d)" % (bottle.boldness_coord, bottle.price_coord, bottle.hold_coord)), stylize(Fore.RED, "on"), stylize(Style.BRIGHT, bottle.consumption.strftime('%Y-%m-%d'))))
def getWinery(repo): """This prompts the user to select a winery from the list of all current wineries, or to enter a new one. """ idx, winery = textEntry("Winery> ", [winery.name for winery in repo.wineries]) if idx is not None: # Check to see if multiple wineries have the same name (happens when a # winery is split into multiple regions) matchingWineries = [] for w in repo.wineries: if w.name == winery: matchingWineries.append(w) if len(matchingWineries) == 1: print(" " + stylize(Style.DIM, repo.wineries[idx].region.description)) return repo.wineries[idx] return disambiguateRegion(repo, matchingWineries) print('\n*** New Winery ***') return repo.addWinery(winery, getRegion(repo))
def parseArguments(definitions): """This parses the command line arguments based on the supplied definitions. The definitions are expected to be an array of tuples, each tuple either of these form: (shortOpt, longOpt, desc) (shortOpt, longOpt, param, desc) These arguments are provided to the OptionDefinition class depending on their type. The returned array will include the values for each definition, in the same order as the definitions were provided. Every three-value definition will get a True or False value (option present or not). Every four-value will get either None (option not present) or the parsed value as a string. """ optDef = OptionDefinition() optDef.addSimpleOption('h', 'help', 'Show this message') for defn in definitions: if len(defn) == 3: optDef.addSimpleOption(defn[0], defn[1], defn[2]) elif len(defn) == 4: optDef.addParameterizedOption(defn[0], defn[1], defn[2], defn[3]) else: raise Exception("Bad Argument Definition") # -------------------- try: (optlist, args) = getopt.getopt(sys.argv[1:], optDef.options, optDef.long_options) except getopt.GetoptError as err: print(stylize(Fore.RED, str(err)) + '\n\n' + optDef.usage()) sys.exit(1) for parsed in optlist: if parsed[0] == '-h' or parsed[0] == '--help': print(optDef.usage()) sys.exit(0) # -------------------- results = [] for defn in definitions: optval = None for parsed in optlist: if parsed[0] == '-' + defn[0] or parsed[0] == '--' + defn[1]: optval = parsed[1] # For options without arguments, use True / False for present / absent # Otherwise, return the value (or None for absent) if len(defn) == 3: optval = (optval != None) results.append(optval) return results
# -------------------------------------------------------------------------------- from colorama import Fore, Back, Style from datetime import date from backend.cellar import Cellar from scripts.styling import stylize from scripts.options import parseArguments [showCosts] = parseArguments([('c', 'cost', 'Also show bottle costs')]) cellar = Cellar() currentYear = date.today().year for label in sorted(cellar.labels, key=lambda l: l.weightedBoldness, reverse=True): labelDesc = "%s %s %s" % ( stylize(Style.BRIGHT, label.description), stylize(Fore.BLUE, label.varietalDescription), stylize(Style.DIM, label.winery.region.description)) if showCosts: labelDesc += " " + stylize(Style.DIM + Fore.GREEN, "$%.2f" % label.averagePrice(True)) print(labelDesc) inventoryByYear = label.inventoryByYear() for holdYear in sorted(inventoryByYear): holdAmt = inventoryByYear[holdYear] print(stylize(Fore.GREEN, ' %d bottle%s to %s' % ( holdAmt, '' if holdAmt == 1 else 's', 'drink now' if holdYear == currentYear else ('hold until %d' % holdYear))))
regionWidth = 0 longestHold = 0 currentYear = date.today().year for bottle in cellar.bottles: longestHold = max(longestHold, bottle.hold_until) byRegion = cellar.byRegion() for data in byRegion: for region in data['regions']: regionWidth = max(regionWidth, len(region['region'].name)) firstRegion = True for data in byRegion: print('%s %s' % (stylize( Fore.GREEN, '%2d bottle%s' % (len(data['bottles']), ' ' if len(data['bottles']) == 1 else 's')), stylize(Style.BRIGHT, '%-*s' % (regionWidth + 8, data['country']))), end='') if firstRegion: for year in range(currentYear, longestHold + 1): print(stylize(Style.BRIGHT, '%d ' % year), end='') firstRegion = False print() for region in data['regions']: print('%8d bottle%s %s' % (len(region['bottles']),
for bottle in cellar.bottles: longestHold = max(longestHold, bottle.hold_until) byVarietal = cellar.byVarietal() for bucket in byVarietal: for data in bucket['data']: varietalWidth = max(varietalWidth, len(data['varietal'].name)) firstBucket = True for bucket in byVarietal: bucketCount = 0 for data in bucket['data']: bucketCount += data['totalCount'] print('%s %s' % (stylize(Fore.GREEN, '%4.1f bottles' % bucketCount), stylize(Style.BRIGHT, '%-*s' % (varietalWidth + 5, bucket['bucketName']))), end='') if firstBucket: for year in range(currentYear, longestHold + 1): print(stylize(Style.BRIGHT, ' %d' % year), end='') print(stylize(Style.BRIGHT, ' |'), end='') for year in range(currentYear, longestHold + 1): print(stylize(Style.BRIGHT, ' %d' % year), end='') firstBucket = False
def _printNewRegions(self): """Print all regions that have been added this session""" for region in self._newRegions: print("%s %s" % (stylize(Fore.GREEN, "Create New Region:"), stylize(Style.BRIGHT, region.description)))
while True: idx, winery = textEntry("Winery> ", [winery.name for winery in repo.wineries]) if idx is not None: return repo.wineries[idx] print("Unknown entry. Try again") # -------------------------------------------------------------------------------- [showCosts] = parseArguments([('c', 'cost', 'Also show bottle costs')]) repo = Repository() wineryName = getWinery(repo).name print() print(stylize(Style.BRIGHT, "Current Regions:")) matchingWineries = [] labels = [] for winery in repo.wineries: if winery.name == wineryName: print(" " + winery.region.description) matchingWineries.append(winery) labels += winery.labels for label in labels: print() print("%s %s %s" % (stylize(Style.BRIGHT, label.description), stylize(Fore.BLUE, label.varietalDescription), stylize(Style.DIM, label.winery.region.description)))
# -------------------------------------------------------------------------------- [showCosts] = parseArguments([('c', 'cost', 'Also show bottle costs')]) repo = Repository() wineryName = getWinery(repo).name labels = [] for winery in repo.wineries: if winery.name == wineryName: labels += winery.labels print() currentYear = date.today().year for label in sorted(labels, key=lambda l: l.weightedBoldness, reverse=True): labelDesc = "%s %s %s" % (stylize(Style.BRIGHT, label.description), stylize(Fore.BLUE, label.varietalDescription), stylize(Style.DIM, label.winery.region.description)) if showCosts: labelDesc += " " + stylize(Style.DIM + Fore.GREEN, "$%.2f" % label.averagePrice(False)) print(labelDesc) consumed = label.numberConsumed if (consumed > 0): print( stylize( Style.DIM, ' %d bottle%s consumed' %
def fmtLong(longOpt, *args): """Format a long option for the usage text""" fmt = stylize(Fore.BLUE, '--' + longOpt) if len(args) > 0: fmt += '=' + stylize(Fore.GREEN, args[0]) return fmt
def fmtShort(shortOpt, *args): """Format a short option for the usage text""" fmt = stylize(Fore.BLUE, '-' + shortOpt) if len(args) > 0: fmt += ' ' + stylize(Fore.GREEN, args[0]) return fmt
from scripts.styling import stylize from scripts.options import parseArguments [showCosts] = parseArguments([('c', 'cost', 'Also show bottle costs')]) cellar = Cellar() bottlesByYear = cellar.bottlesByYear for year in sorted(bottlesByYear): bottles = bottlesByYear[year] count = len(bottles) yearCost = 0 labels = {} for bottle in bottles: labelDesc = "%s %s %s" % ( stylize(Style.BRIGHT, bottle.label.description), stylize(Fore.BLUE, bottle.label.varietalDescription), stylize(Style.DIM, bottle.label.winery.region.description)) if showCosts: avgPrice = bottle.label.averagePrice(True) labelDesc += " " + stylize(Style.DIM + Fore.GREEN, "$%.2f" % avgPrice) yearCost += avgPrice if labelDesc not in labels: labels[labelDesc] = 1 else: labels[labelDesc] += 1 yearDesc = "%s: %s" % ( stylize(Fore.BLUE, "%d" % year),
import calendar [verbose, showCosts] = parseArguments([('v', 'verbose', 'Also show specific bottles'), ('c', 'cost', 'Also show bottle costs')]) cellar = Cellar() consumption = cellar.consumptionByMonth() for year in sorted(consumption): for month in sorted(consumption[year]): count = len(consumption[year][month]) monthSummary = ( "%s: %s" % (stylize(Fore.BLUE, "%s %d" % (calendar.month_abbr[month], year)), stylize(Fore.GREEN, '%d bottle%s' % (count, ' ' if count == 1 else 's')))) if showCosts: totalCost = 0 for bottle in consumption[year][month]: totalCost += bottle.cost monthSummary += " " + stylize(Style.DIM + Fore.GREEN, "$%.2f" % totalCost) print(monthSummary) if verbose: for bottle in consumption[year][month]: