You've already forked HeurAMS-Classic
build: 修改依赖并引入外部库
This commit is contained in:
Vendored
+167
@@ -0,0 +1,167 @@
|
||||
"""
|
||||
fsrs.card
|
||||
---------
|
||||
|
||||
This module defines the Card and State classes.
|
||||
|
||||
Classes:
|
||||
Card: Represents a flashcard in the FSRS system.
|
||||
State: Enum representing the learning state of a Card object.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timezone
|
||||
import time
|
||||
import json
|
||||
from typing import TypedDict
|
||||
from typing_extensions import Self
|
||||
from fsrs.state import State
|
||||
|
||||
|
||||
class CardDict(TypedDict):
|
||||
"""
|
||||
JSON-serializable dictionary representation of a Card object.
|
||||
"""
|
||||
|
||||
card_id: int
|
||||
state: int
|
||||
step: int | None
|
||||
stability: float | None
|
||||
difficulty: float | None
|
||||
due: str
|
||||
last_review: str | None
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class Card:
|
||||
"""
|
||||
Represents a flashcard in the FSRS system.
|
||||
|
||||
Attributes:
|
||||
card_id: The id of the card. Defaults to the epoch milliseconds of when the card was created.
|
||||
state: The card's current learning state.
|
||||
step: The card's current learning or relearning step or None if the card is in the Review state.
|
||||
stability: Core mathematical parameter used for future scheduling.
|
||||
difficulty: Core mathematical parameter used for future scheduling.
|
||||
due: The date and time when the card is due next.
|
||||
last_review: The date and time of the card's last review.
|
||||
"""
|
||||
|
||||
card_id: int
|
||||
state: State
|
||||
step: int | None
|
||||
stability: float | None
|
||||
difficulty: float | None
|
||||
due: datetime
|
||||
last_review: datetime | None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
card_id: int | None = None,
|
||||
state: State = State.Learning,
|
||||
step: int | None = None,
|
||||
stability: float | None = None,
|
||||
difficulty: float | None = None,
|
||||
due: datetime | None = None,
|
||||
last_review: datetime | None = None,
|
||||
) -> None:
|
||||
if card_id is None:
|
||||
# epoch milliseconds of when the card was created
|
||||
card_id = int(datetime.now(timezone.utc).timestamp() * 1000)
|
||||
# wait 1ms to prevent potential card_id collision on next Card creation
|
||||
time.sleep(0.001)
|
||||
self.card_id = card_id
|
||||
|
||||
self.state = state
|
||||
|
||||
if self.state == State.Learning and step is None:
|
||||
step = 0
|
||||
self.step = step
|
||||
|
||||
self.stability = stability
|
||||
self.difficulty = difficulty
|
||||
|
||||
if due is None:
|
||||
due = datetime.now(timezone.utc)
|
||||
self.due = due
|
||||
|
||||
self.last_review = last_review
|
||||
|
||||
def to_dict(self) -> CardDict:
|
||||
"""
|
||||
Returns a dictionary representation of the Card object.
|
||||
|
||||
Returns:
|
||||
CardDict: A dictionary representation of the Card object.
|
||||
"""
|
||||
|
||||
return {
|
||||
"card_id": self.card_id,
|
||||
"state": self.state.value,
|
||||
"step": self.step,
|
||||
"stability": self.stability,
|
||||
"difficulty": self.difficulty,
|
||||
"due": self.due.isoformat(),
|
||||
"last_review": self.last_review.isoformat() if self.last_review else None,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, source_dict: CardDict) -> Self:
|
||||
"""
|
||||
Creates a Card object from an existing dictionary.
|
||||
|
||||
Args:
|
||||
source_dict: A dictionary representing an existing Card object.
|
||||
|
||||
Returns:
|
||||
Self: A Card object created from the provided dictionary.
|
||||
"""
|
||||
|
||||
return cls(
|
||||
card_id=int(source_dict["card_id"]),
|
||||
state=State(int(source_dict["state"])),
|
||||
step=source_dict["step"],
|
||||
stability=(
|
||||
float(source_dict["stability"]) if source_dict["stability"] else None
|
||||
),
|
||||
difficulty=(
|
||||
float(source_dict["difficulty"]) if source_dict["difficulty"] else None
|
||||
),
|
||||
due=datetime.fromisoformat(source_dict["due"]),
|
||||
last_review=(
|
||||
datetime.fromisoformat(source_dict["last_review"])
|
||||
if source_dict["last_review"]
|
||||
else None
|
||||
),
|
||||
)
|
||||
|
||||
def to_json(self, indent: int | str | None = None) -> str:
|
||||
"""
|
||||
Returns a JSON-serialized string of the Card object.
|
||||
|
||||
Args:
|
||||
indent: Equivalent argument to the indent in json.dumps()
|
||||
|
||||
Returns:
|
||||
str: A JSON-serialized string of the Card object.
|
||||
"""
|
||||
return json.dumps(self.to_dict(), indent=indent)
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, source_json: str) -> Self:
|
||||
"""
|
||||
Creates a Card object from a JSON-serialized string.
|
||||
|
||||
Args:
|
||||
source_json: A JSON-serialized string of an existing Card object.
|
||||
|
||||
Returns:
|
||||
Self: A Card object created from the JSON string.
|
||||
"""
|
||||
|
||||
source_dict: CardDict = json.loads(source_json)
|
||||
return cls.from_dict(source_dict=source_dict)
|
||||
|
||||
|
||||
__all__ = ["Card"]
|
||||
Reference in New Issue
Block a user