aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/infini
diff options
context:
space:
mode:
author简律纯 <i@jyunko.cn>2023-12-15 09:11:47 +0800
committer简律纯 <i@jyunko.cn>2023-12-15 09:11:47 +0800
commitbe8de118db913711eb72ae5187d26e54a0055727 (patch)
tree96cd6c012dafa3f4015e54edef90df5eaaab0ddb /src/infini
parent9b2d27ba1d91a0d5531bc9c0d52c3887a2dfb2aa (diff)
downloadinfini-be8de118db913711eb72ae5187d26e54a0055727.tar.gz
infini-be8de118db913711eb72ae5187d26e54a0055727.zip
refactor(docs): optmst `docs` dir & `deps`
Diffstat (limited to 'src/infini')
-rw-r--r--src/infini/__init__.py6
-rw-r--r--src/infini/cli.py45
-rw-r--r--src/infini/consts/__init__.py0
-rw-r--r--src/infini/consts/templates.py69
-rw-r--r--src/infini/event.py43
-rw-r--r--src/infini/exceptions.py6
-rw-r--r--src/infini/logging.py40
-rw-r--r--src/infini/manager.py18
-rw-r--r--src/infini/rule.py75
-rw-r--r--src/infini/settings.py1
-rw-r--r--src/infini/typing.py41
11 files changed, 344 insertions, 0 deletions
diff --git a/src/infini/__init__.py b/src/infini/__init__.py
new file mode 100644
index 00000000..9c88b4f9
--- /dev/null
+++ b/src/infini/__init__.py
@@ -0,0 +1,6 @@
+from infini.cli import Cli
+from infini.rule import Rule, Result, Dice
+from infini.typing import Config as ConfigTyping
+from infini.event import Event
+
+__all__ = ["Rule", "Cli", "Result", "Dice", "Event", "ConfigTyping"]
diff --git a/src/infini/cli.py b/src/infini/cli.py
new file mode 100644
index 00000000..e372b4b4
--- /dev/null
+++ b/src/infini/cli.py
@@ -0,0 +1,45 @@
+from pathlib import Path
+from .consts import templates
+from .logging import logger
+
+import argparse
+import os
+import sys
+import importlib
+
+
+class Cli:
+ def parse_args(self, argv: list[str] | None = None):
+ parser = argparse.ArgumentParser(description="HydroRoll 命令行工具")
+
+ parser.add_argument("--new", action="store_true", help="创建一个 HydroRoll 规则包模板")
+ parser.add_argument("--run", action="store_true", help="运行 HydroRoll 规则包")
+ parser.add_argument("--gui", action="store_true", help="显示弹窗")
+ parser.add_argument("--path", help="指定路径")
+
+ args = parser.parse_args(argv if argv else sys.argv[1:])
+
+ if args.gui:
+ logger.critical("选项[--gui]尚未被支持!")
+ sys.exit(1)
+
+ path = Path(args.path).resolve() if args.path else Path(os.getcwd()).resolve()
+ if args.new and args.run:
+ logger.error("无法确定的指令要求: 你同时指定了new与run指令。")
+ sys.exit(1)
+
+ if args.new:
+ if path.exists():
+ logger.error("指定的文件夹已经存在!")
+ sys.exit(1)
+
+ path.mkdir(parents=True, exist_ok=True)
+ (path / "rule.py").write_text(templates.RULE, encoding="utf-8")
+ (path / "event.py").write_text(templates.EVENT, encoding="utf-8")
+ (path / "dice.py").write_text(templates.DICE, encoding="utf-8")
+
+ logger.success("HydroRoll 规则包模板已创建!")
+
+ if args.run:
+ sys.path.append(str(path))
+ importlib.import_module("event")
diff --git a/src/infini/consts/__init__.py b/src/infini/consts/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/infini/consts/__init__.py
diff --git a/src/infini/consts/templates.py b/src/infini/consts/templates.py
new file mode 100644
index 00000000..e2edc2d6
--- /dev/null
+++ b/src/infini/consts/templates.py
@@ -0,0 +1,69 @@
+RULE = """from infini import Rule, Result, Dice
+
+
+class MyRule(Rule):
+ \"\"\"自设规则包\"\"\"
+
+ name = "MyRule"
+ priority: int = 0
+
+ def __init__(self) -> None:
+ \"\"\"初始化你的规则包\"\"\"
+
+ def check(self, dice: Dice) -> Result:
+ \"\"\"声明规则包检定方式\"\"\"
+ return Result("myevent.event1", True)
+"""
+
+EVENT = """from infini import Event
+
+__events__ = ["MyEvent"]
+
+
+class MyEvent(Event):
+ name = "event1"
+ output = "检定成功!"
+"""
+
+DICE = """from infini import Dice
+
+import random
+import re
+
+
+class BaseDice(Dice):
+ \"\"\"多面骰\"\"\"
+
+ def __init__(self, roll_string: str = "") -> None:
+ self.roll_string = roll_string
+ self.parse()
+
+ def parse(self) -> "Dice":
+ self.dices = []
+ split = re.split(r"[dD]", self.roll_string)
+
+ if split[0]:
+ self.a = int(split[0])
+ else:
+ self.a = 1
+
+ if split[1]:
+ self.b = int(split[1])
+ else:
+ self.b = 100
+
+ self.db = f"{self.a}D{self.b}"
+ self.dices += [f"D{self.b}"] * self.a
+ return self
+
+ def roll(self) -> int:
+ self.results = []
+
+ for _ in range(self.a):
+ result = random.randint(1, self.b)
+
+ self.results.append(result)
+
+ self.outcome = sum(self.results)
+ return self.outcome
+"""
diff --git a/src/infini/event.py b/src/infini/event.py
new file mode 100644
index 00000000..9ce34bd9
--- /dev/null
+++ b/src/infini/event.py
@@ -0,0 +1,43 @@
+from .typing import Dict
+from .logging import logger
+
+import re
+
+__all__ = ["Event", "events"]
+
+
+class Events:
+ """事件集合"""
+
+ _events: Dict[str, str] = {}
+
+ def regist(self, name: str, output: str) -> None:
+ self._events[name.lower()] = output
+
+ def process(self, name: str, **kwargs) -> str:
+ if string := self._events.get(name.lower()):
+ return self._format(string, **kwargs)
+ logger.warning(f"事件[{name.lower()}]不存在,将返回空字符串!")
+ return ""
+
+ def _format(self, string: str, **kwargs):
+ pattern = r"{(.*?)}"
+ values = re.findall(pattern, string)
+ for value in values:
+ kwarg = kwargs.get(value)
+ value = kwarg if kwarg else ""
+ string = re.sub(pattern, value, string)
+ return string
+
+
+class Event:
+ """事件基类"""
+
+ name: str
+ output: str
+
+ def __init_subclass__(cls) -> None:
+ events.regist(cls.name, cls.output)
+
+
+events = Events()
diff --git a/src/infini/exceptions.py b/src/infini/exceptions.py
new file mode 100644
index 00000000..62c88fa1
--- /dev/null
+++ b/src/infini/exceptions.py
@@ -0,0 +1,6 @@
+class HydroError(Exception):
+ """HydroRoll 异常基类"""
+
+
+class RuleLoadError(HydroError):
+ """规则导入错误"""
diff --git a/src/infini/logging.py b/src/infini/logging.py
new file mode 100644
index 00000000..a1458ef4
--- /dev/null
+++ b/src/infini/logging.py
@@ -0,0 +1,40 @@
+"""infini 日志。
+
+infini 使用 [loguru](https://github.com/Delgan/loguru) 来记录日志信息。
+自定义 logger 请参考 [loguru](https://github.com/Delgan/loguru) 文档。
+"""
+from datetime import datetime
+from multilogging import multilogger
+from pathlib import Path
+from .settings import DEBUG
+
+
+__all__ = ["logger", "error_or_exception"]
+
+logger = multilogger(
+ name="HydroRoll", payload="Core", level="DEBUG" if DEBUG else "INFO"
+)
+current_path = Path(__file__).resolve().parent
+LOG_PATH = current_path / "logs"
+if not LOG_PATH.exists():
+ LOG_PATH.mkdir(parents=True, exist_ok=True)
+logger.add(
+ sink=LOG_PATH / (datetime.now().strftime("%Y-%m-%d") + ".log"),
+ level="INFO",
+ rotation="10 MB",
+) # 每个日志文件最大为 10MB
+
+
+def error_or_exception(message: str, exception: Exception, verbose: bool = True):
+ # 弃用的方法
+ # logger.remove()
+ # logger.add(
+ # sys.stderr,
+ # format="<magenta>{time:YYYY-MM-DD HH:mm:ss.SSS}</magenta> <level>[{level}]</level> > <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
+ # )
+
+ if verbose:
+ logger.exception(exception)
+ logger.critical(message)
+ else:
+ logger.critical(f"{message} {exception!r}")
diff --git a/src/infini/manager.py b/src/infini/manager.py
new file mode 100644
index 00000000..42e79563
--- /dev/null
+++ b/src/infini/manager.py
@@ -0,0 +1,18 @@
+from .event import Events, events
+from .logging import logger
+from .typing import Dict
+
+
+class Manager:
+ """事件处理单元"""
+
+ events: Events
+
+ def __init__(self, _events: Events = None) -> None:
+ self.events = _events if _events else events
+
+ def roll(self):
+ ...
+
+
+manager = Manager()
diff --git a/src/infini/rule.py b/src/infini/rule.py
new file mode 100644
index 00000000..a1f04151
--- /dev/null
+++ b/src/infini/rule.py
@@ -0,0 +1,75 @@
+from abc import ABCMeta, abstractmethod
+from enum import Enum
+from .exceptions import HydroError
+from .typing import Dict
+
+__all__ = ["RuleLoadType", "Result", "Dice", "Rule"]
+
+
+class RuleLoadType(Enum):
+ """The Type Of Rules To Be Loaded"""
+
+ DIR = "dir"
+ NAME = "name"
+ FILE = "file"
+ CLASS = "class"
+
+
+class Result(metaclass=ABCMeta):
+ """规则检定结果基类"""
+
+ event: str
+ status: bool
+ exception: HydroError | None = None
+
+ def __init__(self, event: str, status: bool, exception: HydroError | None) -> None:
+ self.event = event
+ self.status = status
+ self.exception = exception
+
+ def ok(self):
+ """规则执行期间是否产生异常"""
+ return isinstance(self.exception, HydroError)
+
+
+class Dice(metaclass=ABCMeta):
+ """掷骰基类"""
+
+ roll_string: str
+ db: str
+ outcome: int
+
+ def __repr__(self) -> str:
+ return f'<HydroDice "{self.db.upper()}">'
+
+ def __str__(self) -> str:
+ return self.db.upper()
+
+ def __int__(self) -> int:
+ return self.outcome
+
+ @abstractmethod
+ def parse(self) -> "Dice":
+ """解析传入的掷骰字符串`roll_string`,返回一个`Dice`对象"""
+ raise NotImplementedError
+
+ @abstractmethod
+ def roll(self) -> int:
+ """掷骰方法,返回掷骰结果"""
+ raise NotImplementedError
+
+
+class Rule(metaclass=ABCMeta):
+ """规则基类"""
+
+ name: str
+ dices: Dict[str, str] = {}
+ priority: int = 0
+
+ @abstractmethod
+ def __init__(self) -> None:
+ raise NotImplementedError
+
+ @abstractmethod
+ def check(self, dice: Dice) -> Result:
+ raise NotImplementedError
diff --git a/src/infini/settings.py b/src/infini/settings.py
new file mode 100644
index 00000000..51c64dd2
--- /dev/null
+++ b/src/infini/settings.py
@@ -0,0 +1 @@
+DEBUG = True
diff --git a/src/infini/typing.py b/src/infini/typing.py
new file mode 100644
index 00000000..333a763b
--- /dev/null
+++ b/src/infini/typing.py
@@ -0,0 +1,41 @@
+from pydantic import BaseModel
+from typing import (
+ Dict as Dict,
+ TYPE_CHECKING as TYPE_CHECKING,
+ TypeVar as TypeVar,
+ Callable as Callable,
+ NoReturn as NoReturn,
+ Awaitable as Awaitable,
+)
+
+
+class Config(BaseModel):
+ rule_dir: list = []
+ rules: list = []
+
+
+class DiceConfig(BaseModel):
+ sides: int
+ counts: int
+ init_dice_pool: int
+
+
+class PlayerCard(BaseModel):
+ name: str
+ traits: list
+
+
+class Bonus(BaseModel):
+ level: int
+ cost: int
+
+
+class WikiPage(BaseModel):
+ title: str
+ content: str
+ tags: list = []
+
+
+class WikiModel:
+ class Setting(BaseModel):
+ desc: str