import enum import argparse from dataclasses import dataclass from pathlib import Path from typing import TypeVar, cast from common import Circuit, CircuitDeviceScale, JointKind from dataset import ( DatasetCollection, to_human_readable_value, from_human_readable_value, ) from query import Response from resolver import Resolver, LutResolver, AStarResolver _T = TypeVar("_T", bound=str) class AppResolver(enum.StrEnum): """ The resolver for the app. """ LUT = "lut" """The look-up table resolver.""" ASTAR = "astar" """The A* resolver.""" @dataclass class AppConfig: """ The configuration for the app. """ resolver: AppResolver """The resolver for the app.""" resistor_dataset: Path """The path to the resistor dataset file.""" capacitor_dataset: Path """The path to the capacitor dataset file.""" inductor_dataset: Path """The path to the inductor dataset file.""" class App: """ The app. """ __config: AppConfig """The configuration for the app.""" __dataset: DatasetCollection """The dataset for the app.""" __resolver: Resolver """The resolver for the app.""" def __init__(self, config: AppConfig) -> None: self.__config = config self.__dataset = DatasetCollection.from_file( self.__config.resistor_dataset, self.__config.capacitor_dataset, self.__config.inductor_dataset, ) match self.__config.resolver: case AppResolver.LUT: self.__resolver = LutResolver(self.__dataset) case AppResolver.ASTAR: self.__resolver = AStarResolver(self.__dataset) def run(self) -> None: """ Run the app. """ print("LCR Connector") print('Type "help" for more info. Type "exit" to quit.') print("query: do a query.") print("help: show all command.") print("exit: exit this app.") while True: shit = self.__accept_command(("query", "help", "exit")) match self.__accept_command(("query", "help", "exit")): case "query": self.__op_query() case "help": print("LCR Connector Help:") print("") print("query: do a query.") print("help: show all command.") print("exit: exit this app.") case "exit": break def __op_query(self) -> None: pass def __op_page_viewer(self, response: Response) -> None: cnt = len(response) if cnt == 0: print("Sorry, no result!") print("Please consider adjusting your requirements and try again.") return ITEMS_PER_PAGE: int = 10 all_page = cnt // ITEMS_PER_PAGE current_page = 0 while True: # print list for i in range(ITEMS_PER_PAGE - 1): # build index and check it index = current_page * (ITEMS_PER_PAGE - 1) + i if index >= cnt: continue # fetch item and print it item = response[index] print( "Plan {0}\t{1}\t{2:.2%}".format( index + 1, to_human_readable_value(item.value), item.relative_difference, ) ) # print page footer print("") print("Page {} of {}.".format(current_page + 1, all_page + 1)) print("f: previous page. b: next page. q: quit this viewer.") # check command match self.__accept_command(("f", "b", "q")): case "f": current_page = max(0, current_page - 1) case "b": current_page = min(all_page, current_page + 1) case "q": break def __accept_command(self, valid_commands: tuple[_T, ...]) -> _T: while True: print("> ", end=None) words = input() words = words.strip() if words in valid_commands: return cast(_T, words) print("Unknown command, please try again.") def __accept_value_input(self) -> float: while True: words = input() try: pending = from_human_readable_value(words) except ValueError: print("Wrong value, please try again.") continue if pending > 0: return pending else: print("Value out of range, please try again.") def __get_joint_kind_symbol(self, joint_kind: JointKind) -> str: match joint_kind: case JointKind.SERIES: return "S" case JointKind.PARALLEL: return "P" def __illustrate_circuit(self, circuit: Circuit) -> None: match circuit.device_scale: case CircuitDeviceScale.ONE: dev1 = to_human_readable_value(circuit.first_device_value) print(f"{dev1}") case CircuitDeviceScale.TWO: dev1 = to_human_readable_value(circuit.first_device_value) j2 = self.__get_joint_kind_symbol(circuit.second_device_joint) dev2 = to_human_readable_value(circuit.second_device_value) print(f"[{j2}] ┬ {dev1}") print(f" └ {dev2}") case CircuitDeviceScale.THREE: dev1 = to_human_readable_value(circuit.first_device_value) j2 = self.__get_joint_kind_symbol(circuit.second_device_joint) dev2 = to_human_readable_value(circuit.second_device_value) j3 = self.__get_joint_kind_symbol(circuit.third_device_joint) dev3 = to_human_readable_value(circuit.third_device_value) print(f"[{j3}] ┬ [{j2}] ┬ {dev1}") print(f" │ └ {dev2}") print(f" └ {dev3}") if __name__ == "__main__": parser = argparse.ArgumentParser( prog="LCR Connector", description="Get the resistor, capacitor, or inductor circuit which has the closest value for your given value within at most 3 devices.", ) parser.add_argument( "-s", "--resolver", dest="resolver", action="store", type=AppResolver, choices=[resolver.value for resolver in AppResolver], required=True, help="The resolver you want to use", ) parser.add_argument( "-r", "--resistor", dest="resistor_dataset", action="store", type=Path, required=True, help="The path to the resistor dataset file", metavar="RESISTOR.TXT", ) parser.add_argument( "-l", "--inductor", dest="inductor_dataset", action="store", type=Path, required=True, help="The path to the inductor dataset file", metavar="INDUCTOR.TXT", ) parser.add_argument( "-c", "--capacitor", dest="capacitor_dataset", action="store", type=Path, required=True, help="The path to the capacitor dataset file", metavar="CAPACITOR.TXT", ) args = parser.parse_args() app_config = AppConfig( resolver=args.resolver, resistor_dataset=args.resistor_dataset, capacitor_dataset=args.capacitor_dataset, inductor_dataset=args.inductor_dataset, ) app = App(app_config) app.run()