|
#!/usr/bin/env python3 |
|
|
|
import argparse |
|
import collections |
|
import csv |
|
import dataclasses |
|
import glob |
|
import io |
|
import random |
|
|
|
# List of ingredient files to use. |
|
INGREDIENT_FILES = glob.glob('*.csv') |
|
|
|
# Entry represents an individual row from an ingredient file. |
|
@dataclasses.dataclass |
|
class Entry: |
|
name: str = "" |
|
weight: str = "" |
|
|
|
# Field names for the ingredient files. |
|
FIELDS = ['name', 'weight'] |
|
|
|
# Returns a new weight for the entry if selected. |
|
def new_weight(entry): |
|
return entry.weight // 2 |
|
|
|
|
|
# Generator func that yields Entry instances for all entries in the ingredient file. |
|
def read_csv(path): |
|
with io.open(path, 'r') as csvfile: |
|
for row in csv.DictReader(csvfile): |
|
# print(row) |
|
yield Entry(**row) |
|
|
|
|
|
# Write ingredient data back to a file. For the entry that was selected |
|
# in this round, we'll store its new weight value to reduce likelihood of it being |
|
# selected soon. |
|
def update_entry_weight_from(path, entries, selection, selection_weight): |
|
with io.open(path, 'w') as csvfile: |
|
writer = csv.DictWriter(csvfile, fieldnames=FIELDS) |
|
writer.writeheader() |
|
for entry in entries: |
|
if entry.name == selection.name: |
|
entry.weight = selection_weight |
|
writer.writerow(dict(name=entry.name, weight=entry.weight)) |
|
|
|
|
|
# Load ingredient file and make a (weighted) random selection of its entries. |
|
def random_selection_from(entries, k): |
|
population = [e.name for e in entries] |
|
weights = [int(e.weight) for e in entries] |
|
|
|
for name in random.choices(population, weights, k=k): |
|
yield Entry(name, weights[population.index(name)]) |
|
|
|
|
|
def main(): |
|
parser = argparse.ArgumentParser( |
|
prog='ingredient_selector', |
|
description='Randomly select ingredients from dataset files for #club-cooking challenge!', |
|
) |
|
parser.add_argument( |
|
'-k', |
|
action='store', |
|
default=1, |
|
type=int, |
|
help='Number of random values to return.' |
|
) |
|
parser.add_argument( |
|
'-u', |
|
'--update', |
|
action='store_true', |
|
help='Flag indicating if ingredient weights should be updated.' |
|
) |
|
|
|
args = parser.parse_args() |
|
|
|
for path in INGREDIENT_FILES: |
|
entries = list(read_csv(path)) |
|
|
|
for entry in random_selection_from(entries, args.k): |
|
print(f'{path}: Selected {entry.name} at weight {entry.weight}') |
|
|
|
if args.update: |
|
entry_weight = new_weight(entry) |
|
update_entry_weight_from(path, entries, entry, entry_weight) |
|
|
|
print(f'{path}: Updated {entry.name} to weight {entry_weight}') |
|
print() |
|
|
|
if __name__ == '__main__': |
|
main() |