1
0

feat: update legacy

This commit is contained in:
2026-06-16 19:57:15 +08:00
parent 1c81b24f74
commit 480e11dbf4
3 changed files with 252 additions and 35 deletions

View File

@@ -1,6 +1,6 @@
from typing import Iterable from typing import Iterable
from pathlib import Path from pathlib import Path
from .common import LcrConnException from common import LcrConnException
class Dataset: class Dataset:

View File

@@ -1,36 +1,245 @@
from .common import LcrConnException, Circuit, JointKind, to_human_readable_value 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)
def _get_joint_kind_symbol(joint_kind: JointKind) -> 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: match joint_kind:
case JointKind.SERIES: case JointKind.SERIES:
return "S" return "S"
case JointKind.PARALLEL: case JointKind.PARALLEL:
return "P" return "P"
def __illustrate_circuit(self, circuit: Circuit) -> None:
def _illustrate_circuit(circuit: Circuit) -> None: match circuit.device_scale:
match circuit.len_devices(): case CircuitDeviceScale.ONE:
case 1: dev1 = to_human_readable_value(circuit.first_device_value)
dev1 = to_human_readable_value(circuit.__first_device_value)
print(f"{dev1}") print(f"{dev1}")
case 2: case CircuitDeviceScale.TWO:
dev1 = to_human_readable_value(circuit.__first_device_value) dev1 = to_human_readable_value(circuit.first_device_value)
joint1 = circuit.joints[0] j2 = self.__get_joint_kind_symbol(circuit.second_device_joint)
j1 = _get_joint_kind_symbol(joint1.__joint_kind) dev2 = to_human_readable_value(circuit.second_device_value)
dev2 = to_human_readable_value(joint1.__device_value) print(f"[{j2}] ┬ {dev1}")
print(f"[{j1}] ┬ {dev1}")
print(f"{dev2}") print(f"{dev2}")
case 3: case CircuitDeviceScale.THREE:
dev1 = to_human_readable_value(circuit.__first_device_value) dev1 = to_human_readable_value(circuit.first_device_value)
joint1 = circuit.joints[0] j2 = self.__get_joint_kind_symbol(circuit.second_device_joint)
j1 = _get_joint_kind_symbol(joint1.__joint_kind) dev2 = to_human_readable_value(circuit.second_device_value)
dev2 = to_human_readable_value(joint1.__device_value) j3 = self.__get_joint_kind_symbol(circuit.third_device_joint)
joint2 = circuit.joints[1] dev3 = to_human_readable_value(circuit.third_device_value)
j2 = _get_joint_kind_symbol(joint2.__joint_kind) print(f"[{j3}] ┬ [{j2}] ┬ {dev1}")
dev3 = to_human_readable_value(joint2.__device_value)
print(f"[{j2}] ┬ [{j1}] ┬ {dev1}")
print(f" │ └ {dev2}") print(f" │ └ {dev2}")
print(f"{dev3}") print(f"{dev3}")
case _:
raise LcrConnException("Circuit too complex to illustrate")
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()

View File

@@ -2,7 +2,7 @@ import enum
from functools import cached_property from functools import cached_property
from dataclasses import dataclass from dataclasses import dataclass
from typing import Iterator from typing import Iterator
from .common import DeviceKind, Circuit from common import DeviceKind, Circuit
class ResponsePriority(enum.Enum): class ResponsePriority(enum.Enum):
@@ -103,7 +103,9 @@ class Response:
""" """
The collection of possible solutions given by the resolver. The collection of possible solutions given by the resolver.
For getting the response items, please use the iterator protocol. For getting the response items, please use `response[index]`.
For iterating the response items, please use the iterator protocol.
For getting the count of response items, please use the ``len`` function.
""" """
__sorted_items: list[ResponseItem] __sorted_items: list[ResponseItem]
@@ -125,5 +127,11 @@ class Response:
# Cut item by limit # Cut item by limit
self.__sorted_items = self.__sorted_items[:request.count_limit] self.__sorted_items = self.__sorted_items[:request.count_limit]
def __getitem__(self, index: int) -> ResponseItem:
return self.__sorted_items[index]
def __len__(self) -> int:
return len(self.__sorted_items)
def __iter__(self) -> Iterator[ResponseItem]: def __iter__(self) -> Iterator[ResponseItem]:
return iter(self.__sorted_items) return iter(self.__sorted_items)