1
0
Files
LCRConnector/legacy/lcr_connector.py

246 lines
7.6 KiB
Python
Raw Normal View History

2026-06-16 19:57:15 +08:00
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()