# GESP等级：二级 | GESP Python 二级考点
# -*- coding: utf-8 -*-
"""
06第2节4 — f-string格式化输出
GESP考点：#27b（格式化输出）、#27c（对齐与精度控制）
=====================================================
"""
import math

print("=" * 55)
print("【导入】太多小数位了！—— 用格式说明书整理输出")
print("=" * 55)

# 模拟海龟坐标场景
xcor_value = 120.000000
print(f"t.xcor() = {xcor_value}        ← 太多零了！")
print(f"t.xcor() = {xcor_value:.2f}            ← 清爽多了！")

# 进一步对比
PI = 3.1415926535
print()
print("对比展示：")
print(f"  格式化前：π ≈ {PI}")
print(f"  格式化后：π ≈ {PI:.2f}")

print()
print("=" * 55)
print("【知识点①】f-string 基础语法 — 用 { } 嵌入变量")
print("=" * 55)

name = "小明"
age = 10
print(f"我叫{name}，今年{age}岁")

# 转义花括号
value = 5
print(f"集合包含 {{ {value} }} 个元素  ← {{ 和 }} 是转义后的花括号")

print()
print("=" * 55)
print("【知识点②】{value:.2f} — 控制小数位数")
print("=" * 55)

score = 3.1415926535
print(f"原始值：{score}")
print(f"{{score:.1f}} → {score:.1f}   ← 保留1位")
print(f"{{score:.2f}} → {score:.2f}   ← 保留2位")
print(f"{{score:.3f}} → {score:.3f}  ← 保留3位（注意四舍五入！）")
print(f"{{score:.4f}} → {score:.4f}  ← 保留4位")
print(f"{{score:.0f}} → {score:.0f}     ← 保留0位（取整）")

print()
print("验证四舍五入：")
test_num = 2.71828
print(f"  2.71828 保留3位：{test_num:.3f}  ← 8进位了！")
print(f"  2.71828 保留2位：{test_num:.2f}  ← 8进位成 .72")
test_num2 = 2.71428
print(f"  2.71428 保留2位：{test_num2:.2f}  ← 4舍去，所以是 2.71")

print()
print("=" * 55)
print("【知识点③】{value:d} — 整数格式")
print("=" * 55)

num = 42
print(f"{{num:d}}       → {num:d}")

# 千位分隔符
big = 1000000
print(f"{{big}}         → {big}")
print(f"{{big:,d}}      → {big:,d}     ← 加了逗号好读！")

bigger = 1411750000
print(f"{{bigger}}      → {bigger}")
print(f"{{bigger:,d}}   → {bigger:,d}  ← 中国人口")

# 多组对比
test_ints = [56, 789, 1234, 98765, 1000000]
print()
print("多组对比：")
for n in test_ints:
    print(f"  {n:>8,d}  ← {{n:>8,d}}")

print()
print("[注意] :d 不能用于浮点数，下面的代码会报错：")
print("# print(f\"{{3.14:d}}\")  → ValueError")

print()
print("=" * 55)
print("【知识点④】{value:>10} — 右对齐")
print("=" * 55)

name = "小明"
print(f"|{{name:>10}}| → |{name:>10}|  ← 右对齐，宽度10")
print(f"|{{name:>6}}|  → |{name:>6}|  ← 右对齐，宽度6")
print(f"|{{name:>4}}|  → |{name:>4}|  ← 宽度不够也没关系")

# 数字右对齐
print()
print("数字右对齐效果：")
print(f"|{{95:>10}}|  → |{95:>10}|")
print(f"|{{88.5:>10}}| → |{88.5:>10}|")

print()
print("=" * 55)
print("【知识点⑤】{value:<10} 左对齐 & {value:^10} 居中对齐")
print("=" * 55)

name = "小明"
print(f"左对齐   |{{name:<10}}| → |{name:<10}|")
print(f"右对齐   |{{name:>10}}| → |{name:>10}|")
print(f"居中对齐 |{{name:^10}}| → |{name:^10}|")

# 不同长度字符串的对齐效果
print()
print("不同长度字符串对齐效果：")
words = ["甲", "小明", "程序员", "中华人民共和国"]
for w in words:
    print(f"  |{w:<10}|  |{w:^10}|  |{w:>10}|  ← {w}")

print()
print("=" * 55)
print("【组合使用】格式化表格输出")
print("=" * 55)

# 学生成绩表
print("学生成绩表：")
print("-" * 40)
print(f"| {'姓名':>6} | {'语文':>6} | {'数学':>6} | {'英语':>6} |")
print("-" * 40)
print(f"| {'小明':>6} | {95:>6} | {88.5:>6.1f} | {92:>6.1f} |")
print(f"| {'小红':>6} | {92:>6} | {96:>6} | {89.5:>6.1f} |")
print(f"| {'小刚':>6} | {80:>6} | {76.5:>6.1f} | {85:>6.1f} |")
print("-" * 40)

# 另一种表头居中、数字右对齐
print()
print("商品价格表（表头居中，价格右对齐）：")
print("-" * 35)
print(f"| {'商品':^10} | {'单价':^8} | {'数量':^8} |")
print("-" * 35)
print(f"| {'苹果':>8} | {5.5:>8.2f} | {3:>8} |")
print(f"| {'香蕉':>8} | {3.0:>8.2f} | {5:>8} |")
print(f"| {'草莓':>8} | {12.8:>8.2f} | {2:>8} |")
print("-" * 35)

print()
print("=" * 55)
print("【演示①】π 的格式化")
print("=" * 55)

print("π的原始值：")
print(f"  math.pi = {math.pi}")
print()
print("格式化后：")
print(f"  {{math.pi:.1f}} → {math.pi:.1f}   ← 保留1位")
print(f"  {{math.pi:.2f}} → {math.pi:.2f}   ← 保留2位（3.14）")
print(f"  {{math.pi:.3f}} → {math.pi:.3f}  ← 保留3位")
print(f"  {{math.pi:.4f}} → {math.pi:.4f}  ← 保留4位（3.1416，四舍五入！）")
print(f"  {{math.pi:.5f}} → {math.pi:.5f}  ← 保留5位")
print(f"  {{math.pi:.0f}} → {math.pi:.0f}     ← 保留0位（输出 3）")

print()
print("=" * 55)
print("【演示②】多列对齐输出")
print("=" * 55)

# 带边框的漂亮表格
header = f"| {'姓名':^8} | {'语文':^8} | {'数学':^8} | {'英语':^8} |"
sep = "+" + "-" * 10 + "+" + "-" * 10 + "+" + "-" * 10 + "+" + "-" * 10 + "+"

print(sep)
print(header)
print(sep)
data = [
    ("小明", 95, 88.5, 92.0),
    ("小红", 92, 96, 89.5),
    ("小刚", 80, 76.5, 85.0),
    ("小华", 88, 91.0, 87.5),
]
for n, c, m, e in data:
    print(f"| {n:^8} | {c:^8} | {m:^8.1f} | {e:^8.1f} |")
print(sep)

print()
print("=" * 55)
print("【演示③】千位分隔符 ,d 的妙用")
print("=" * 55)

numbers = [
    1234,
    56789,
    1000000,
    1411750000,
    9876543210,
]
for n in numbers:
    print(f"  {n:>15,d}   ← {{n:>15,d}}")

print()
print("对比（不加逗号 vs 加逗号）：")
for n in [1000, 1000000, 1000000000]:
    print(f"  {n:>12}   →   {n:>12,d}")

print()
print("=" * 55)
print("【实操①】格式配对填空 — 验证")
print("=" * 55)

score = 3.14159
print(f"原始值 score = {score}")
print()
print("配对验证：")
print(f"  A. {{score:.1f}} → {score:.1f}    ← 对应 ② 3.1")
print(f"  B. {{score:.2f}} → {score:.2f}    ← 对应 ① 3.14")
print(f"  C. {{score:.3f}} → {score:.3f}   ← 对应 ④ 3.142")
print(f"  D. {{score:.0f}} → {score:.0f}      ← 对应 ③ 3")

print()
print("=" * 55)
print("【实操②】补全 f-string 格式")
print("=" * 55)

# 题目1
price = 99.5
print(f"题目1：价格：{price:.2f}元    ← {{price:.2f}}")

# 题目2-4
name = "小林"
print(f"题目2：|{{name:<12}}| → |{name:<12}|  ← 左对齐")
print(f"题目3：|{{name:>12}}| → |{name:>12}|  ← 右对齐")
print(f"题目4：|{{name:^12}}| → |{name:^12}|  ← 居中对齐")

# 题目5
big = 1000000
print(f"题目5：{{big:,d}} → {big:,d}  ← 千位分隔符")

print()
print("=" * 55)
print("【实操③】乌龟状态仪表盘（模拟版）")
print("=" * 55)

# 模拟海龟状态（不依赖真实的 turtle 图形窗口）
# 模拟 t.forward(120), t.right(45), t.forward(80) 后的状态
sim_x = round(120 + 80 * math.cos(math.radians(-45)), 2)
sim_y = round(80 * math.sin(math.radians(45)), 2)
sim_heading = 45.0

print("=" * 38)
print(f"| {'乌龟状态仪表盘':^30} |")
print("=" * 38)
print(f"| {'x坐标':>10} | {sim_x:>12.2f} |")
print(f"| {'y坐标':>10} | {sim_y:>12.2f} |")
print(f"| {'朝向角度':>10} | {sim_heading:>12.1f} |")
print("=" * 38)

# 更简洁的版本
print()
print("简洁仪表盘：")
print("  ┌─────────────────────────┐")
print(f"  │ [龟] x={sim_x:>8.2f}  y={sim_y:>8.2f}  │")
print(f"  │    角度={sim_heading:>6.1f}°              │")
print("  └─────────────────────────┘")

print()
print("=" * 55)
print("【小测验证】")
print("=" * 55)

# 题目1
print(f"题目1：{{3.14159:.2f}} = {3.14159:.2f}     ← 选 A（3.14）")

# 题目2
print(f"题目2：|{{'abc':>8}}| = |{'abc':>8}|  ← 选 B（右对齐）")

# 题目3
print(f"题目3：{{123:d}} = {123:d}               ← 选 A（整数格式）")

# 题目4
print(f"题目4：{{1234567:,d}} = {1234567:,d}  ← 选 B（千位分隔符）")

# 题目5
print(f"题目5：{{{{ 转义为 }}  → 输出 {{          ← 选 C")

print()
print("=" * 55)
print("【额外挑战】组合格式控制")
print("=" * 55)

# 挑战1：同时控制对齐和精度
print("挑战1：对齐 + 精度组合")
vals = [3.14159, 2.71828, 1.41421, 0.57721]
for v in vals:
    print(f"  |{v:>12.4f}|  ← {{v:>12.4f}}")

# 挑战2：各种格式的混合
print()
print("挑战2：混合格式一行")
print(f"{'名称':>10} {'整数':>8} {'浮点数':>10} {'百分比':>10}")
items = [("苹果", 3, 5.5), ("香蕉", 5, 3.0), ("草莓", 2, 12.8)]
for name, qty, price in items:
    total = qty * price
    print(f"{name:>10} {qty:>8d} {price:>10.2f} {total:>10.2f}")

# 挑战3：用 f-string 做进度条
print()
print("挑战3：简单进度条")
progress = 0.65  # 65%
bar_len = 20
filled = int(bar_len * progress)
bar = "#" * filled + "-" * (bar_len - filled)
print(f"进度：[{bar}] {progress:.0%}")

print()
print("=" * 55)
print("【课堂口诀】")
print("=" * 55)
print("f-string 冒号后，格式说明书在手")
print(":.2f 管小数，几位由你来定")
print(":d 管整数，带个逗号更好读")
print(":>10 右对齐，:<10 左对齐")
print(":^10 居中间，整整齐齐真好看")
print()
print("记忆钩子：")
print("f-string冒号后控格式：:.2f管小数 :d管整数 :>10管对齐")
print("=" * 55)
