feat: update legacy
This commit is contained in:
@@ -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:
|
||||||
|
|||||||
@@ -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):
|
||||||
match joint_kind:
|
"""
|
||||||
case JointKind.SERIES:
|
The resolver for the app.
|
||||||
return "S"
|
"""
|
||||||
case JointKind.PARALLEL:
|
|
||||||
return "P"
|
LUT = "lut"
|
||||||
|
"""The look-up table resolver."""
|
||||||
|
ASTAR = "astar"
|
||||||
|
"""The A* resolver."""
|
||||||
|
|
||||||
|
|
||||||
def _illustrate_circuit(circuit: Circuit) -> None:
|
@dataclass
|
||||||
match circuit.len_devices():
|
class AppConfig:
|
||||||
case 1:
|
"""
|
||||||
dev1 = to_human_readable_value(circuit.__first_device_value)
|
The configuration for the app.
|
||||||
print(f"{dev1}")
|
"""
|
||||||
case 2:
|
|
||||||
dev1 = to_human_readable_value(circuit.__first_device_value)
|
resolver: AppResolver
|
||||||
joint1 = circuit.joints[0]
|
"""The resolver for the app."""
|
||||||
j1 = _get_joint_kind_symbol(joint1.__joint_kind)
|
|
||||||
dev2 = to_human_readable_value(joint1.__device_value)
|
resistor_dataset: Path
|
||||||
print(f"[{j1}] ┬ {dev1}")
|
"""The path to the resistor dataset file."""
|
||||||
print(f" └ {dev2}")
|
capacitor_dataset: Path
|
||||||
case 3:
|
"""The path to the capacitor dataset file."""
|
||||||
dev1 = to_human_readable_value(circuit.__first_device_value)
|
inductor_dataset: Path
|
||||||
joint1 = circuit.joints[0]
|
"""The path to the inductor dataset file."""
|
||||||
j1 = _get_joint_kind_symbol(joint1.__joint_kind)
|
|
||||||
dev2 = to_human_readable_value(joint1.__device_value)
|
|
||||||
joint2 = circuit.joints[1]
|
class App:
|
||||||
j2 = _get_joint_kind_symbol(joint2.__joint_kind)
|
"""
|
||||||
dev3 = to_human_readable_value(joint2.__device_value)
|
The app.
|
||||||
print(f"[{j2}] ┬ [{j1}] ┬ {dev1}")
|
"""
|
||||||
print(f" │ └ {dev2}")
|
|
||||||
print(f" └ {dev3}")
|
__config: AppConfig
|
||||||
case _:
|
"""The configuration for the app."""
|
||||||
raise LcrConnException("Circuit too complex to illustrate")
|
__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()
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user