Click on the “Python Beginner to Advanced” public account, select “Star“
Essential content delivered promptly
[For reprints, please message the author]
Q: What’s the best way to learn to code?
A: Code daily! Welcome here!
First, welcome to the Python Mastery Program, I hope this is not just a challenge for you, but also a meaningful journey, and I wish you fruitful results. Have a pleasant journey.
⚡Forging the Temple of Memory | Refining the Elixir of Knowledge
🌟Review of Previous Sessions
In the training of Day 25, we learned:
✅Secure architecture of password managers
✅Core algorithms for encrypted storage
✅Advanced data presentation with Treeview
For those who missed the treasure chest of keys, pleaseclick to review[1]
🚀Core Objectives for This Session
Through this lesson, you will:
-
Implement a card flip animation effect
-
Master the principles of spaced repetition algorithms
-
Develop an intelligent memory management system
-
Generate visual reports of learning progress
1. Card Forging Technique (First Reshaping)
1.1 Dynamic Cards with Canvas
class FlashCard(tk.Canvas):
def __init__(self, master, front_text, back_text):
super().__init__(master, width=300, height=200, bg='white')
self.front_text = front_text
self.back_text = back_text
self.is_front = True
# Draw initial front
self.create_rectangle(5,5,295,195, outline='#4B8BBE', width=2)
self.text = self.create_text(150, 100, text=front_text,
font=('微软雅黑', 14), width=280)
self.bind("<Button-1>", self.flip)
def flip(self, event=None):
"""Card flip animation"""
for i in range(0, 90, 5):
self.configure(width=300*(1-abs(i-45)/45))
self.update()
self.master.after(20)
self.delete("all")
new_text = self.back_text if self.is_front else self.front_text
self.create_rectangle(5,5,295,195, outline='#4B8BBE', width=2)
self.create_text(150, 100, text=new_text,
font=('微软雅黑', 14), width=280)
self.is_front = not self.is_front
2. Core Memory Algorithm (Second Infusion)
2.1 SM-2 Spaced Repetition Algorithm
from datetime import datetime, timedelta
class SpacedRepetition:
def __init__(self):
self.quality_map = {
0: (0.0, 1.3), # Incorrect
1: (0.4, 1.3), # Difficult
2: (0.6, 1.5), # Average
3: (1.0, 2.0) # Easy
}
def update_card(self, card, quality):
"""Update card memory parameters"""
if quality < 0 or quality > 3:
raise ValueError("Quality rating must be between 0-3")
ease_factor = card.ease_factor
interval = card.interval
# Calculate new parameters
ease_delta, interval_mod = self.quality_map[quality]
new_ease = max(1.3, ease_factor + ease_delta)
new_interval = interval * new_ease * interval_mod
# Update card
card.interval = int(round(new_interval))
card.ease_factor = new_ease
card.next_review = datetime.now() + timedelta(days=card.interval)
3. System Integration (Third Fusion)
3.1 Main Interface Architecture
class FlashCardApp(tk.Tk):
def __init__(self):
super().__init__()
self.title("Memory Forge v1.0")
self.deck = self.load_deck()
self.current_card = None
# Control panel
control_frame = ttk.Frame(self)
control_frame.pack(pady=10)
ttk.Button(control_frame, text="Remember", command=lambda: self.rate_card(3)).pack(side='left', padx=5)
ttk.Button(control_frame, text="Vague", command=lambda: self.rate_card(2)).pack(side='left', padx=5)
ttk.Button(control_frame, text="Forget", command=lambda: self.rate_card(0)).pack(side='left', padx=5)
# Progress chart
self.figure = Figure(figsize=(5,3))
self.ax = self.figure.add_subplot(111)
self.canvas = FigureCanvasTkAgg(self.figure, self)
self.canvas.get_tk_widget().pack()
self.show_next_card()
def show_next_card(self):
"""Display the next card to review"""
due_cards = [c for c in self.deck if c.next_review <= datetime.now()]
if due_cards:
self.current_card = due_cards[0]
FlashCard(self, self.current_card.front, self.current_card.back).pack(pady=20)
else:
tk.messagebox.showinfo("Complete", "Today's review is finished!")
4. Complete Code (Mastery Achieved)
"""Memory Card Spaced Repetition System - Memory Forge v1.2
Author: This Traveler
Function Description:
1. A graphical interface application built with tkinter
2. Supports card front and back flip animation effects
3. Implements an improved spaced repetition algorithm based on SM-2
4. Memory curve visualization function
5. Automatic save/load learning progress"""
# Import necessary libraries
import tkinter as tk
from tkinter import ttk, messagebox
from datetime import datetime, timedelta
import json
import os
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
class FlashCard(tk.Canvas):
"""Flippable memory card component"""
def __init__(self, master, front_text, back_text, **kwargs):
"""
Initialize memory card
:param master: Parent container
:param front_text: Front text content
:param back_text: Back text content
"""
super().__init__(master, width=300, height=200, bg='white', **kwargs)
self.front_text = front_text # Card front content
self.back_text = back_text # Card back content
self.is_front = True # Current display is front
# Initialize drawing card front
self.draw_card(self.front_text)
# Bind click event
self.bind("<Button-1>", self.flip)
def draw_card(self, text):
"""Draw card content"""
self.delete("all") # Clear canvas
# Draw blue border
self.create_rectangle(5, 5, 295, 195, outline='#4B8BBE', width=2)
# Add text content (supports automatic line wrapping)
self.create_text(150, 100, text=text,
font=('微软雅黑', 14), width=280, tags="text")
def flip(self, event=None):
"""Execute card flip animation"""
# Use width change to simulate 3D flip effect
for i in range(0, 90, 5):
self.configure(width=300*(1-abs(i-45)/45)) # Dynamically adjust width
self.update()
self.master.after(20) # Control animation speed
# Switch display content
new_text = self.back_text if self.is_front else self.front_text
self.is_front = not self.is_front # Switch front and back state
self.draw_card(new_text)
class Card:
"""Memory card data model"""
def __init__(self, front, back):
"""
Initialize card data
:param front: Front content
:param back: Back content
"""
self.front = front # Card front question
self.back = back # Card back answer
self.interval = 1 # Current review interval (days)
self.ease_factor = 2.5 # Ease factor (for adjusting interval)
self.next_review = datetime.now() # Next review time
self.review_count = 0 # Total review count
self.history = [] # Review history record (date, rating)
class SpacedRepetition:
"""Spaced repetition scheduling algorithm (based on improved SM-2)"""
def update_card(self, card, quality):
"""
Update card memory parameters
:param card: Card object to update
:param quality: User rating (0-3)
"""
# Rating corresponding parameter mapping table (ease adjustment value, interval adjustment coefficient)
quality_map = {
0: (0.0, 0.8), # Forget
1: (0.4, 0.9), # Difficult
2: (0.6, 1.1), # Average
3: (1.0, 1.3) # Easy
}
# Get adjustment parameters
ease_delta, interval_mod = quality_map.get(quality, (0, 1))
# Adjust ease factor (minimum 1.3)
card.ease_factor = max(1.3, card.ease_factor + ease_delta)
# Calculate new interval (rounded)
card.interval = int(round(card.interval * card.ease_factor * interval_mod))
# Set next review time
card.next_review = datetime.now() + timedelta(days=card.interval)
card.review_count += 1 # Increase review count
# Record review history
card.history.append((datetime.now().strftime("%Y-%m-%d"), quality))
class FlashCardApp(tk.Tk):
"""Main application"""
def __init__(self):
super().__init__()
# Basic window settings
self.title("Memory Forge v1.2")
self.geometry("600x800")
self.scheduler = SpacedRepetition() # Initialize scheduler
self.deck = self.load_deck() # Load card data
self.current_card = None # Currently displayed card
# Initialize interface
self.create_widgets()
self.show_next_card() # Display the first card
# Set close event handling
self.protocol("WM_DELETE_WINDOW", self.on_close)
def create_widgets(self):
"""Create interface components"""
# Control button panel
control_frame = ttk.Frame(self)
control_frame.pack(pady=10, fill='x')
# Define rating button configuration
buttons = [
("Forget (0)", 0, '#FF6B6B'), # Red
("Difficult (1)", 1, '#FFD93D'), # Yellow
("Average (2)", 2, '#6C5CE7'), # Purple
("Remember (3)", 3, '#00B894') # Green
]
# Create and arrange rating buttons
for text, q, color in buttons:
btn = ttk.Button(
control_frame,
text=text,
command=lambda q=q: self.rate_card(q),
style=f'{color}.TButton'
)
btn.pack(side='left', padx=5, expand=True)
# Card display area
self.card_frame = ttk.Frame(self)
self.card_frame.pack(pady=20, fill='both', expand=True)
# Initialize statistics chart
self.figure = Figure(figsize=(5, 3), dpi=100)
self.ax = self.figure.add_subplot(111)
self.canvas = FigureCanvasTkAgg(self.figure, self)
self.canvas.get_tk_widget().pack(fill='both', expand=True)
# Configure button styles
self.style = ttk.Style()
self.style.configure('TButton', font=('微软雅黑', 10))
# Set colors for different buttons
for color in ['#FF6B6B', '#FFD93D', '#6C5CE7', '#00B894']:
self.style.configure(f'{color}.TButton', foreground='white', background=color)
def load_deck(self):
"""Load card data"""
# Default card data (used when file does not exist)
default_cards = [
{"front": "What is Python's GIL?", "back": "Global Interpreter Lock"},
{"front": "What is the purpose of @staticmethod?", "back": "Declare a static method that does not require an instance parameter"}
]
try:
# Attempt to load data from JSON file
with open('flashcards.json', 'r', encoding='utf-8') as f:
data = json.load(f)
return [Card(**item) for item in data]
except FileNotFoundError:
# Use default cards when file does not exist
return [Card(**item) for item in default_cards]
def save_deck(self):
"""Save card data to JSON file"""
data = []
for card in self.deck:
data.append({
"front": card.front,
"back": card.back,
"interval": card.interval,
"ease_factor": card.ease_factor,
"next_review": card.next_review.strftime("%Y-%m-%d %H:%M:%S"),
"review_count": card.review_count,
"history": card.history
})
# Write to JSON file
with open('flashcards.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
def show_next_card(self):
"""Display the next card to review"""
# Clear current card display area
for widget in self.card_frame.winfo_children():
widget.destroy()
# Filter cards that need to be reviewed (next review time has arrived)
due_cards = [c for c in self.deck if datetime.now() > c.next_review]
if due_cards:
self.current_card = due_cards[0]
# Create and display card component
FlashCard(self.card_frame, self.current_card.front, self.current_card.back).pack()
self.update_chart() # Update statistics chart
else:
self.update_chart()
messagebox.showinfo("Complete", "All cards have been reviewed today!")
def rate_card(self, quality):
"""Process user rating"""
if self.current_card:
self.scheduler.update_card(self.current_card, quality)
self.show_next_card()
def update_chart(self):
"""Update memory curve chart"""
self.ax.clear() # Clear old chart
# Collect all cards' historical data
dates = []
intervals = []
for card in self.deck:
if card.history:
# Get the most recent review date
last_date = datetime.strptime(card.history[-1][0], "%Y-%m-%d")
dates.append(last_date)
intervals.append(card.interval)
# Draw scatter plot
if dates and intervals:
self.ax.scatter(dates, intervals, c='#6C5CE7', alpha=0.7)
self.ax.set_title("Memory Interval Trend")
self.ax.set_ylabel("Next Review Interval (days)")
self.ax.grid(True)
self.figure.autofmt_xdate() # Automatically adjust date format
self.canvas.draw() # Redraw canvas
def on_close(self):
"""Handle window close event"""
self.save_deck() # Save data
self.destroy()
if __name__ == "__main__":
app = FlashCardApp()
app.mainloop()
Guidelines to Avoid Pitfalls
-
Animation Lag Optimization
# Incorrect approach (directly in the main thread loop)
for i in range(100):
update_animation()
time.sleep(0.1) # Will cause the interface to freeze
# Correct approach (using after method)
def animate(frame=0):
if frame < 90:
update_frame(frame)
self.after(20, animate, frame+1)
animate()
-
Timezone Handling Standards
# Incorrect approach (using naive time)
datetime.now() # May cause timezone confusion
# Correct approach (specifying timezone)
from datetime import timezone
datetime.now(timezone.utc).astimezone() # Get local timezone time
🔮Next Session Preview
Day 27: Time Sword – Date Management and Email Automation
⚡Advanced techniques of the datetime module
⚡Implementation of scheduled tasks
⚡Sending encrypted emails with smtplib
⚡Automatically generating daily reports
Core function preview:
# Email sending example
import smtplib
from email.mime.text import MIMEText
def send_email(subject, content):
msg = MIMEText(content, 'html')
msg['Subject'] = subject
msg['From'] = 'Daily Report <[email protected]>'
msg['To'] = '[email protected]'
with smtplib.SMTP_SSL('smtp.example.com', 465) as server:
server.login('user', 'password')
server.send_message(msg)
💬Practice Room
Share in the comments:
-
What knowledge area do you want to memorize the most?
-
Special animation effects for the designed flashcards. The top 3 liked will receive the “SuperMemo Memory Algorithm White Paper” + “Python Automation Secrets” e-books.
🚀Memory is eternal, the path remains forever
Click “♥” to mark your progress, and tomorrow at noon we will jointly wield the Time Sword!
#Previous Recommendations
Day 25: Treasure Chest of Keys – Password Management[2]
Day 24: Interface Mastery – Advanced Tkinter[3]
References
[1]
Click to review: Python Mastery Day 25: Treasure Chest of Keys – Practical Password Manager with Tkinter
[2]
Day 25: Treasure Chest of Keys – Password Management
[3]
Day 24: Interface Mastery – Advanced Tkinter
Complete Code:
https://github.com/Zesheng-Wang/100-days-python
Errata:
As I am not a seasoned programming expert, despite striving for accuracy while creating this content and consulting numerous resources, there may still be oversights. If you find any errors, please leave a message in the public account, and corrections are welcome.
You should secretly learn Python and amaze everyone.
-END-
Thank you all for your attention
Everything you care about is here