124 lines
4.1 KiB
Python
124 lines
4.1 KiB
Python
import random
|
|
from functools import reduce
|
|
|
|
from tabulate import tabulate as tabu
|
|
from transitions import Machine
|
|
|
|
import heurams.kernel.particles as pt
|
|
import heurams.kernel.puzzles as puz
|
|
from heurams.services.logger import get_logger
|
|
|
|
from .states import FissionState, PhaserState
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
class Fission(Machine):
|
|
"""单原子调度展开器"""
|
|
|
|
def __init__(self, atom: pt.Atom, phase=PhaserState.RECOGNITION):
|
|
self.phase = phase
|
|
self.cursor = 0
|
|
self.atom = atom
|
|
self.current_puzzle_inf: dict
|
|
# phase 为 PhaserState 枚举实例, 需要获取其value
|
|
phase_value = phase.value
|
|
states = [
|
|
{"name": FissionState.EXAMMODE.value},
|
|
{"name": FissionState.RETRONLY.value},
|
|
]
|
|
|
|
transitions = [
|
|
{
|
|
"trigger": "finish",
|
|
"source": FissionState.EXAMMODE.value,
|
|
"dest": FissionState.RETRONLY.value,
|
|
},
|
|
]
|
|
if phase == PhaserState.FINISHED:
|
|
Machine.__init__(
|
|
self,
|
|
states=states,
|
|
transitions=transitions,
|
|
initial=FissionState.EXAMMODE.value,
|
|
)
|
|
return
|
|
orbital_schedule = atom.registry["orbital"]["phases"][phase_value] # type: ignore
|
|
orbital_puzzles = atom.registry["nucleon"]["puzzles"]
|
|
self.puzzles_inf = list()
|
|
self.min_ratings = []
|
|
for item, possibility in orbital_schedule: # type: ignore
|
|
logger.debug(f"开始处理: {item}")
|
|
if not isinstance(possibility, float):
|
|
possibility = float(possibility)
|
|
|
|
while possibility > 1:
|
|
self.puzzles_inf.append(
|
|
{
|
|
"puzzle": puz.puzzles[orbital_puzzles[item]["__origin__"]],
|
|
"alia": item,
|
|
}
|
|
)
|
|
possibility -= 1
|
|
|
|
if random.random() <= possibility:
|
|
self.puzzles_inf.append(
|
|
{
|
|
"puzzle": puz.puzzles[orbital_puzzles[item]["__origin__"]],
|
|
"alia": item,
|
|
}
|
|
)
|
|
self.current_puzzle_inf = self.puzzles_inf[0]
|
|
|
|
for i in range(len(self.puzzles_inf)):
|
|
self.min_ratings.append(0x3F3F3F3F)
|
|
|
|
Machine.__init__(
|
|
self,
|
|
states=states,
|
|
transitions=transitions,
|
|
initial=FissionState.EXAMMODE.value,
|
|
)
|
|
|
|
def get_puzzles_inf(self):
|
|
if self.state == "retronly":
|
|
return [{"puzzle": puz.puzzles["recognition"], "alia": "Recognition"}]
|
|
return self.puzzles_inf
|
|
|
|
def get_current_puzzle_inf(self):
|
|
if self.state == "retronly":
|
|
return {"puzzle": puz.puzzles["recognition"], "alia": "Recognition"}
|
|
return self.current_puzzle_inf
|
|
|
|
def report(self, rating):
|
|
self.min_ratings[self.cursor] = min(rating, self.min_ratings[self.cursor])
|
|
|
|
def get_quality(self):
|
|
if self.is_state("retronly", self):
|
|
return reduce(lambda x, y: min(x, y), self.min_ratings)
|
|
raise IndexError
|
|
|
|
def forward(self, step=1):
|
|
"""将谜题指针向前移动并依情况更新或完成"""
|
|
self.cursor += step
|
|
if self.cursor >= len(self.puzzles_inf):
|
|
if self.state != "retronly":
|
|
self.finish()
|
|
else:
|
|
self.current_puzzle_inf = self.puzzles_inf[self.cursor]
|
|
|
|
def __repr__(self, style="pipe", ends="\n") -> str:
|
|
from heurams.services.textproc import truncate
|
|
|
|
dic = [
|
|
{
|
|
"Type": "Fission",
|
|
"Atom": truncate(self.atom.ident),
|
|
"State": self.state,
|
|
"Progress": f"{self.cursor + 1} / {len(self.puzzles_inf)}",
|
|
"Queue": list(map(lambda f: truncate(f["alia"]), self.puzzles_inf)),
|
|
"Current Puzzle": f"{self.current_puzzle_inf['alia']}@{self.current_puzzle_inf['puzzle'].__name__}", # type: ignore
|
|
}
|
|
]
|
|
return str(tabu(dic, headers="keys", tablefmt=style)) + ends
|