1
0
Files
LCRConnector/legacy/lcr_connector.py
2026-06-16 19:57:15 +08:00

246 lines
7.6 KiB
Python

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()