ankigammon 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ankigammon might be problematic. Click here for more details.
- ankigammon/__init__.py +7 -0
- ankigammon/__main__.py +6 -0
- ankigammon/analysis/__init__.py +13 -0
- ankigammon/analysis/score_matrix.py +373 -0
- ankigammon/anki/__init__.py +6 -0
- ankigammon/anki/ankiconnect.py +224 -0
- ankigammon/anki/apkg_exporter.py +123 -0
- ankigammon/anki/card_generator.py +1307 -0
- ankigammon/anki/card_styles.py +1034 -0
- ankigammon/gui/__init__.py +8 -0
- ankigammon/gui/app.py +209 -0
- ankigammon/gui/dialogs/__init__.py +10 -0
- ankigammon/gui/dialogs/export_dialog.py +597 -0
- ankigammon/gui/dialogs/import_options_dialog.py +163 -0
- ankigammon/gui/dialogs/input_dialog.py +776 -0
- ankigammon/gui/dialogs/note_dialog.py +93 -0
- ankigammon/gui/dialogs/settings_dialog.py +384 -0
- ankigammon/gui/format_detector.py +292 -0
- ankigammon/gui/main_window.py +1071 -0
- ankigammon/gui/resources/icon.icns +0 -0
- ankigammon/gui/resources/icon.ico +0 -0
- ankigammon/gui/resources/icon.png +0 -0
- ankigammon/gui/resources/style.qss +394 -0
- ankigammon/gui/resources.py +26 -0
- ankigammon/gui/widgets/__init__.py +8 -0
- ankigammon/gui/widgets/position_list.py +193 -0
- ankigammon/gui/widgets/smart_input.py +268 -0
- ankigammon/models.py +322 -0
- ankigammon/parsers/__init__.py +7 -0
- ankigammon/parsers/gnubg_parser.py +454 -0
- ankigammon/parsers/xg_binary_parser.py +870 -0
- ankigammon/parsers/xg_text_parser.py +729 -0
- ankigammon/renderer/__init__.py +5 -0
- ankigammon/renderer/animation_controller.py +406 -0
- ankigammon/renderer/animation_helper.py +221 -0
- ankigammon/renderer/color_schemes.py +145 -0
- ankigammon/renderer/svg_board_renderer.py +824 -0
- ankigammon/settings.py +239 -0
- ankigammon/thirdparty/__init__.py +7 -0
- ankigammon/thirdparty/xgdatatools/__init__.py +17 -0
- ankigammon/thirdparty/xgdatatools/xgimport.py +160 -0
- ankigammon/thirdparty/xgdatatools/xgstruct.py +1032 -0
- ankigammon/thirdparty/xgdatatools/xgutils.py +118 -0
- ankigammon/thirdparty/xgdatatools/xgzarc.py +260 -0
- ankigammon/utils/__init__.py +13 -0
- ankigammon/utils/gnubg_analyzer.py +431 -0
- ankigammon/utils/gnuid.py +622 -0
- ankigammon/utils/move_parser.py +239 -0
- ankigammon/utils/ogid.py +335 -0
- ankigammon/utils/xgid.py +419 -0
- ankigammon-1.0.0.dist-info/METADATA +370 -0
- ankigammon-1.0.0.dist-info/RECORD +56 -0
- ankigammon-1.0.0.dist-info/WHEEL +5 -0
- ankigammon-1.0.0.dist-info/entry_points.txt +2 -0
- ankigammon-1.0.0.dist-info/licenses/LICENSE +21 -0
- ankigammon-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"""Export XG decisions to Anki .apkg file using genanki."""
|
|
2
|
+
|
|
3
|
+
import genanki
|
|
4
|
+
import random
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import List
|
|
7
|
+
|
|
8
|
+
from ankigammon.models import Decision
|
|
9
|
+
from ankigammon.anki.card_generator import CardGenerator
|
|
10
|
+
from ankigammon.anki.card_styles import MODEL_NAME, CARD_CSS
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ApkgExporter:
|
|
14
|
+
"""
|
|
15
|
+
Export XG decisions to Anki .apkg file.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, output_dir: Path, deck_name: str = "My AnkiGammon Deck"):
|
|
19
|
+
"""
|
|
20
|
+
Initialize the APKG exporter.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
output_dir: Directory for output files
|
|
24
|
+
deck_name: Name of the Anki deck
|
|
25
|
+
"""
|
|
26
|
+
self.output_dir = Path(output_dir)
|
|
27
|
+
self.output_dir.mkdir(parents=True, exist_ok=True)
|
|
28
|
+
self.deck_name = deck_name
|
|
29
|
+
|
|
30
|
+
# Generate unique IDs
|
|
31
|
+
self.deck_id = random.randrange(1 << 30, 1 << 31)
|
|
32
|
+
self.model_id = random.randrange(1 << 30, 1 << 31)
|
|
33
|
+
|
|
34
|
+
# Create model
|
|
35
|
+
self.model = self._create_model()
|
|
36
|
+
|
|
37
|
+
# Create deck
|
|
38
|
+
self.deck = genanki.Deck(self.deck_id, self.deck_name)
|
|
39
|
+
|
|
40
|
+
def _create_model(self) -> genanki.Model:
|
|
41
|
+
"""Create the Anki note model."""
|
|
42
|
+
return genanki.Model(
|
|
43
|
+
self.model_id,
|
|
44
|
+
MODEL_NAME,
|
|
45
|
+
fields=[
|
|
46
|
+
{'name': 'Front'},
|
|
47
|
+
{'name': 'Back'},
|
|
48
|
+
],
|
|
49
|
+
templates=[
|
|
50
|
+
{
|
|
51
|
+
'name': 'Card 1',
|
|
52
|
+
'qfmt': '{{Front}}',
|
|
53
|
+
'afmt': '{{Back}}',
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
css=CARD_CSS
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
def export(
|
|
60
|
+
self,
|
|
61
|
+
decisions: List[Decision],
|
|
62
|
+
output_file: str = "xg_deck.apkg",
|
|
63
|
+
show_options: bool = False,
|
|
64
|
+
color_scheme: str = "classic",
|
|
65
|
+
interactive_moves: bool = False,
|
|
66
|
+
orientation: str = "counter-clockwise",
|
|
67
|
+
progress_callback: callable = None
|
|
68
|
+
) -> str:
|
|
69
|
+
"""
|
|
70
|
+
Export decisions to an APKG file.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
decisions: List of Decision objects
|
|
74
|
+
output_file: Output filename
|
|
75
|
+
show_options: Show multiple choice options (text-based)
|
|
76
|
+
color_scheme: Board color scheme name
|
|
77
|
+
interactive_moves: Enable interactive move visualization
|
|
78
|
+
orientation: Board orientation ("clockwise" or "counter-clockwise")
|
|
79
|
+
progress_callback: Optional callback(message: str) for progress updates
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
Path to generated APKG file
|
|
83
|
+
"""
|
|
84
|
+
# Create renderer with color scheme
|
|
85
|
+
from ankigammon.renderer.color_schemes import get_scheme
|
|
86
|
+
from ankigammon.renderer.svg_board_renderer import SVGBoardRenderer
|
|
87
|
+
|
|
88
|
+
scheme = get_scheme(color_scheme)
|
|
89
|
+
renderer = SVGBoardRenderer(color_scheme=scheme, orientation=orientation)
|
|
90
|
+
|
|
91
|
+
# Create card generator
|
|
92
|
+
card_gen = CardGenerator(
|
|
93
|
+
output_dir=self.output_dir,
|
|
94
|
+
show_options=show_options,
|
|
95
|
+
interactive_moves=interactive_moves,
|
|
96
|
+
renderer=renderer,
|
|
97
|
+
progress_callback=progress_callback
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# Generate cards
|
|
101
|
+
for i, decision in enumerate(decisions):
|
|
102
|
+
if progress_callback:
|
|
103
|
+
progress_callback(f"Position {i+1}/{len(decisions)}: Starting...")
|
|
104
|
+
card_data = card_gen.generate_card(decision, card_id=f"card_{i}")
|
|
105
|
+
|
|
106
|
+
# Create note
|
|
107
|
+
note = genanki.Note(
|
|
108
|
+
model=self.model,
|
|
109
|
+
fields=[card_data['front'], card_data['back']],
|
|
110
|
+
tags=card_data['tags']
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Add to deck
|
|
114
|
+
self.deck.add_note(note)
|
|
115
|
+
|
|
116
|
+
# Create package (no media files needed - SVG is embedded)
|
|
117
|
+
output_path = self.output_dir / output_file
|
|
118
|
+
package = genanki.Package(self.deck)
|
|
119
|
+
|
|
120
|
+
# Write APKG
|
|
121
|
+
package.write_to_file(str(output_path))
|
|
122
|
+
|
|
123
|
+
return str(output_path)
|