#!/usr/bin/python3 """ Do some math for jewelry raw materials. We assume that silver has a consistent density, as do the stone(s). """ import sys def usage(exit_code: int) -> None: """Output a usage message.""" if exit_code == 0: file_ = sys.stdout else: file_ = sys.stderr print("Compute roughly how much silver and stone is in a given piece of jewelry.", file=file_) print( "We assume an idealized model where all the silver measured has the same density, and that the stone(s) do as well.", file=file_, ) print(file=file_) print("Masses are in grams", file=file_) print("Volumes are in milliliters", file=file_) print(file=file_) print(f"Usage: {sys.argv[0]}", file=file_) print(" --piece-of-jewelry-mass pojm", file=file_) print(" --bar-of-silver-mass bosm", file=file_) print(" --piece-of-jewelry-volume pojv", file=file_) print(" --bar-of-silver-volume bosv", file=file_) print(file=file_) print("If you do not enter those four command line options, you'll be prompted for them interactively") sys.exit(exit_code) class Masses: """Calculate approximately how much silver (in grams) and how much stone (again in grams) are used in a piece of jewelry.""" def __init__(self, *, j_mass: float, b_mass: float, j_volume: float, b_volume: float) -> None: """ Init. We could make assumptions about the theoretical density of pure silver, but this is probably more accurate, as not all silver is pure. j_mass is the total mass of the piece of finished jewelry. b_mass is the mass of a bar of silver of roughly equivalent density. j_volume is the total volume of the piece of finished jewelry. b_volume is the volume of a roughly-equivalent-density piece of silver. """ self.j_mass = j_mass self.b_mass = b_mass self.j_volume = j_volume self.b_volume = b_volume def calculate(self) -> None: """ Calculate a rough estimate of how many grams are stone, and how grams are silver, in a given, finished piece of jewelry. We know how many grams the piece of jewelry's mass is. We know how many grams the piece of silver's mass is. We know how many milliliters the piece of jewelry is. We know how much milliliters the piece of silver is. We want to know how many of the total grams are silver, and how many are stone. We know that: m = d * V mass = density * volume density = mass / volume | volume != 0 Most jewelry silver is measured in grams mass, not by volume. I pulled milliliters out of the air, but I think the units will cancel out anyway. """ silver_density = self.b_mass / self.b_volume # We don't need this one, but if we did: # jewel_density = self.j_mass / self.j_volume # stone_density + silver_density = self.j_mass / self.j_volume # stone_density + self.b_mass / self.b_volume = self.j_mass / self.j_volume # stone_density = self.j_mass / self.j_volume - self.b_mass / self.b_volume stone_density = self.j_mass / self.j_volume - self.b_mass / self.b_volume # We now have all 3 densities, 2 of the masses, and 2 of the volumes. # We'll use m = d * V again. # # self.j_mass = jewel_density * self.j_volume # self.b_mass = silver_density * self.b_volume # self.stone_mass = stone_density * (self.j_volume - self.b_volume) self.stone_mass = stone_density * (self.j_volume - self.b_volume) # m = d * V # m / d = V | d != 0 # V = m / d | d != 0 self.stone_volume = self.stone_mass / stone_density self.silver_mass = silver_density * (self.j_volume - self.stone_volume) def main() -> None: """Start the ball rolling.""" j_mass = None b_mass = None j_volume = None b_volume = None while sys.argv[1:]: if sys.argv[1] == "--piece-of-jewelry-mass": j_mass = float(sys.argv[2]) del sys.argv[1] elif sys.argv[1] == "--bar-of-silver-mass": b_mass = float(sys.argv[2]) del sys.argv[1] elif sys.argv[1] == "--piece-of-jewelry-volume": j_volume = float(sys.argv[2]) del sys.argv[1] elif sys.argv[1] == "--bar-of-silver-volume": b_volume = float(sys.argv[2]) del sys.argv[1] elif sys.argv[1] in ("--help", "-h"): usage(0) else: print(f"{sys.argv[0]}: unrecognized option: {sys.argv[1]}", file=sys.stderr) usage(1) del sys.argv[1] if j_mass is None: while True: line = input("Enter how many grams the finished piece of jewelry weighs: ") try: j_mass = float(line) except ValueError: print("Sorry, that does not look like a floating point number. Please try again") else: break if b_mass is None: while True: line = input("Enter how many grams a bar of the same, unworked silver, weighs: ") try: b_mass = float(line) except ValueError: print("Sorry, that does not look like a floating point number. Please try again") else: break if j_volume is None: while True: line = input("Enter how many milliliters the finished piece of jewelry occupies: ") try: j_volume = float(line) except ValueError: print("Sorry, that does not look like a floating point number. Please try again") else: break if b_volume is None: while True: line = input("Enter how many milliliters a bar of the same, unworked silver, occupies: ") try: b_volume = float(line) except ValueError: print("Sorry, that does not look like a floating point number. Please try again") else: break masses = Masses(j_mass=j_mass, b_mass=b_mass, j_volume=j_volume, b_volume=b_volume) masses.calculate() print(f"Your jewelry's silver mass in grams is {masses.silver_mass}") print(f"Your jewelry's stone mass in grams is {masses.stone_mass}") if __name__ == "__main__": main()