补全9月11日至13日课评:为13名学生创建请假文档,为5个班级创建总结文档
This commit is contained in:
1120
.claude/memory/temp/_pre_inject/0830.html
Normal file
1120
.claude/memory/temp/_pre_inject/0830.html
Normal file
File diff suppressed because it is too large
Load Diff
883
.claude/memory/temp/_pre_inject/1400.html
Normal file
883
.claude/memory/temp/_pre_inject/1400.html
Normal file
@@ -0,0 +1,883 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>第1周周六下午CSP04班课评</title>
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;600;700&family=Noto+Sans+SC:wght@300;400;500;600&display=swap');
|
||||
|
||||
:root {
|
||||
--coral: #e85d4c;
|
||||
--coral-light: #f5a99e;
|
||||
--coral-dark: #c44738;
|
||||
--amber: #f0a84a;
|
||||
--amber-light: #f5d08a;
|
||||
--ink: #2c2420;
|
||||
--ink-soft: #5a524e;
|
||||
--paper: #faf6f1;
|
||||
--paper-warm: #f5efe8;
|
||||
--cream: #fffdf9;
|
||||
--border: #e8e0d8;
|
||||
--shadow-soft: rgba(44, 36, 32, 0.06);
|
||||
--shadow-medium: rgba(44, 36, 32, 0.10);
|
||||
--shadow-card: rgba(44, 36, 32, 0.08);
|
||||
}
|
||||
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
html { scroll-behavior: smooth; }
|
||||
|
||||
body {
|
||||
font-family: 'Noto Sans SC', -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
background: var(--paper);
|
||||
min-height: 100vh;
|
||||
color: var(--ink);
|
||||
background-image:
|
||||
radial-gradient(circle at 20% 50%, rgba(240, 168, 74, 0.03) 0%, transparent 50%),
|
||||
radial-gradient(circle at 80% 20%, rgba(232, 93, 76, 0.02) 0%, transparent 50%),
|
||||
radial-gradient(circle at 50% 80%, rgba(240, 168, 74, 0.02) 0%, transparent 40%);
|
||||
}
|
||||
|
||||
.topbar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
background: rgba(250, 246, 241, 0.92);
|
||||
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding: 14px 28px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.topbar-title {
|
||||
font-family: 'Noto Serif SC', serif;
|
||||
font-size: 1.05em;
|
||||
font-weight: 600;
|
||||
color: var(--ink);
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.topbar-meta {
|
||||
font-size: 0.8em;
|
||||
color: var(--ink-soft);
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.topbar-actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 8px 18px;
|
||||
border-radius: 10px;
|
||||
font-size: 0.85em;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.25s ease;
|
||||
border: none;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.btn-outline {
|
||||
background: transparent;
|
||||
border: 1.5px solid var(--border);
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
|
||||
.btn-outline:hover {
|
||||
border-color: var(--coral);
|
||||
color: var(--coral);
|
||||
background: rgba(232, 93, 76, 0.05);
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
background: var(--coral);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-success:hover {
|
||||
background: var(--coral-dark);
|
||||
}
|
||||
|
||||
.main {
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
padding: 28px 20px 160px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.course-hero {
|
||||
background: linear-gradient(135deg, var(--cream) 0%, var(--paper-warm) 100%);
|
||||
border-radius: 20px;
|
||||
padding: 36px 32px 32px;
|
||||
margin-bottom: 24px;
|
||||
border: 1px solid var(--border);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 8px var(--shadow-soft), 0 8px 32px var(--shadow-card);
|
||||
}
|
||||
|
||||
.course-hero::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -60px;
|
||||
right: -40px;
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, rgba(232, 93, 76, 0.08) 0%, transparent 70%);
|
||||
}
|
||||
|
||||
.course-hero::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -40px;
|
||||
left: -30px;
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, rgba(240, 168, 74, 0.06) 0%, transparent 70%);
|
||||
}
|
||||
|
||||
.hero-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
background: linear-gradient(135deg, var(--coral) 0%, var(--amber) 100%);
|
||||
color: white;
|
||||
font-size: 0.75em;
|
||||
font-weight: 600;
|
||||
padding: 6px 16px;
|
||||
border-radius: 20px;
|
||||
margin-bottom: 16px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-family: 'Noto Serif SC', serif;
|
||||
font-size: 2.2em;
|
||||
font-weight: 700;
|
||||
color: var(--ink);
|
||||
line-height: 1.3;
|
||||
margin-bottom: 8px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.hero-subtitle {
|
||||
font-size: 0.95em;
|
||||
color: var(--ink-soft);
|
||||
margin-bottom: 20px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.hero-divider {
|
||||
width: 60px;
|
||||
height: 3px;
|
||||
background: linear-gradient(90deg, var(--coral), var(--amber));
|
||||
border-radius: 2px;
|
||||
margin-bottom: 20px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.hero-info {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.hero-info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 0.85em;
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
|
||||
.hero-info-item .icon { font-size: 1.1em; }
|
||||
|
||||
.goals-section {
|
||||
background: var(--cream);
|
||||
border-radius: 16px;
|
||||
padding: 24px;
|
||||
margin-bottom: 28px;
|
||||
border: 1px solid var(--border);
|
||||
box-shadow: 0 2px 12px var(--shadow-soft);
|
||||
}
|
||||
|
||||
.goals-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.goals-title {
|
||||
font-family: 'Noto Serif SC', serif;
|
||||
font-size: 1em;
|
||||
font-weight: 600;
|
||||
color: var(--ink);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.goals-title .title-icon { font-size: 1.2em; }
|
||||
|
||||
.goals-toggle {
|
||||
font-size: 0.78em;
|
||||
color: var(--ink-soft);
|
||||
cursor: pointer;
|
||||
background: var(--paper-warm);
|
||||
border: 1px solid var(--border);
|
||||
font-family: inherit;
|
||||
padding: 5px 12px;
|
||||
border-radius: 8px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.goals-toggle:hover {
|
||||
background: var(--coral);
|
||||
color: white;
|
||||
border-color: var(--coral);
|
||||
}
|
||||
|
||||
.goals-list {
|
||||
list-style: none;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.goals-list.collapsed { display: none; }
|
||||
|
||||
.goals-list li {
|
||||
padding: 12px 16px;
|
||||
background: var(--paper);
|
||||
border-radius: 10px;
|
||||
margin-bottom: 10px;
|
||||
font-size: 0.9em;
|
||||
color: var(--ink-soft);
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
border-left: 3px solid transparent;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.goals-list li:hover {
|
||||
border-left-color: var(--coral);
|
||||
background: var(--cream);
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.goals-list li:last-child { margin-bottom: 0; }
|
||||
|
||||
.goal-num {
|
||||
background: linear-gradient(135deg, var(--coral) 0%, var(--amber) 100%);
|
||||
color: white;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.78em;
|
||||
font-weight: 600;
|
||||
flex-shrink: 0;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.goal-text { flex: 1; line-height: 1.6; }
|
||||
|
||||
.cards-slider-wrapper {
|
||||
position: relative;
|
||||
border-radius: 16px;
|
||||
margin-bottom: 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.cards-slider {
|
||||
position: relative;
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.student-card { display: none; }
|
||||
|
||||
.student-card.active { display: block; position: relative; pointer-events: auto; }
|
||||
|
||||
|
||||
|
||||
.student-card:hover {
|
||||
box-shadow: 0 8px 32px var(--shadow-medium);
|
||||
}
|
||||
|
||||
.card-header {
|
||||
padding: 18px 24px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: linear-gradient(135deg, rgba(250, 246, 241, 0.5) 0%, rgba(245, 239, 232, 0.5) 100%);
|
||||
border-radius: 16px 16px 0 0;
|
||||
}
|
||||
|
||||
.student-name {
|
||||
font-family: 'Noto Serif SC', serif;
|
||||
font-size: 1.15em;
|
||||
font-weight: 600;
|
||||
color: var(--ink);
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.card-badge {
|
||||
font-size: 0.75em;
|
||||
padding: 5px 12px;
|
||||
border-radius: 20px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.badge-normal { background: #e8f5e9; color: #2e7d32; }
|
||||
.badge-makeup { background: linear-gradient(135deg, #fff3e0 0%, #ffe0b2 100%); color: #e65100; }
|
||||
.badge-absent { background: #fce4ec; color: #c2185b; }
|
||||
|
||||
.card-body { padding: 24px; }
|
||||
|
||||
.feedback-content {
|
||||
font-size: 0.92em;
|
||||
line-height: 2;
|
||||
color: var(--ink-soft);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.feedback-content[contenteditable="true"] { outline: none; border: 2px dashed transparent; border-radius: 10px; padding: 10px; margin: -10px; transition: all 0.2s ease; }
|
||||
.feedback-content[contenteditable="true"]:hover { border-color: var(--border); background: var(--paper); }
|
||||
.feedback-content[contenteditable="true"]:focus { border-color: var(--coral); background: rgba(232, 93, 76, 0.03); }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.side-nav-btn {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
z-index: 90;
|
||||
width: 52px;
|
||||
height: 80px;
|
||||
border: none;
|
||||
background: rgba(250, 246, 241, 0.85);
|
||||
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.4em;
|
||||
color: var(--ink-soft);
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 16px var(--shadow-medium);
|
||||
}
|
||||
|
||||
.side-nav-btn:hover:not(:disabled) { background: var(--cream); color: var(--coral); width: 60px; box-shadow: 0 6px 24px rgba(232, 93, 76, 0.15); }
|
||||
.side-nav-btn:disabled { opacity: 0.25; cursor: not-allowed; }
|
||||
|
||||
.side-nav-btn.prev-btn { left: 0; border-radius: 0 12px 12px 0; border-right: 1px solid var(--border); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); padding-right: 4px; }
|
||||
.side-nav-btn.next-btn { right: 0; border-radius: 12px 0 0 12px; border-left: 1px solid var(--border); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); padding-left: 4px; }
|
||||
.side-nav-btn .arrow { transition: transform 0.3s ease; }
|
||||
.side-nav-btn:hover .arrow.prev-arrow { transform: translateX(-3px); }
|
||||
.side-nav-btn:hover .arrow.next-arrow { transform: translateX(3px); }
|
||||
|
||||
.nav-controls { display: flex; justify-content: center; align-items: center; gap: 20px; margin-bottom: 16px; }
|
||||
.page-indicator { font-family: 'Noto Serif SC', serif; font-size: 0.95em; color: var(--ink-soft); font-weight: 500; min-width: 70px; text-align: center; letter-spacing: 1px; }
|
||||
.progress-dots { display: flex; justify-content: center; gap: 10px; margin-top: 4px; }
|
||||
.progress-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--border); cursor: pointer; transition: all 0.3s ease; position: relative; }
|
||||
.progress-dot.active { background: var(--coral); width: 28px; border-radius: 4px; }
|
||||
.progress-dot:hover:not(.active) { background: var(--coral-light); transform: scale(1.3); }
|
||||
|
||||
.bottom-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: rgba(250, 246, 241, 0.95);
|
||||
|
||||
border-top: 1px solid var(--border);
|
||||
padding: 14px 24px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.toast {
|
||||
position: fixed;
|
||||
bottom: 80px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%) translateY(20px);
|
||||
background: var(--ink);
|
||||
color: white;
|
||||
padding: 12px 28px;
|
||||
border-radius: 10px;
|
||||
font-size: 0.85em;
|
||||
opacity: 0;
|
||||
transition: all 0.3s ease;
|
||||
pointer-events: none;
|
||||
z-index: 200;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
|
||||
|
||||
.edit-mode-badge {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 80px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
|
||||
color: #92400e;
|
||||
padding: 8px 20px;
|
||||
border-radius: 20px;
|
||||
font-size: 0.8em;
|
||||
font-weight: 500;
|
||||
z-index: 200;
|
||||
border: 1px solid #fcd34d;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
.edit-mode-badge.show { display: block; }
|
||||
|
||||
.footer { text-align: center; padding: 36px 20px; color: #bbb; font-size: 0.78em; font-family: 'Noto Serif SC', serif; letter-spacing: 1px; }
|
||||
|
||||
.oj-section { margin-top: 20px; border-radius: 12px; border: 1px solid var(--border); overflow: hidden; background: var(--paper); }
|
||||
.oj-header { display: flex; align-items: center; gap: 8px; padding: 12px 16px; background: linear-gradient(135deg, rgba(232, 93, 76, 0.06) 0%, rgba(240, 168, 74, 0.04) 100%); border-bottom: 1px solid var(--border); font-size: 0.85em; font-weight: 600; color: var(--ink); }
|
||||
.oj-table { width: 100%; border-collapse: collapse; font-size: 0.82em; }
|
||||
.oj-table thead th { padding: 10px 14px; text-align: left; font-weight: 600; color: var(--ink-soft); background: var(--cream); border-bottom: 1px solid var(--border); font-size: 0.9em; }
|
||||
.oj-table thead th:first-child { width: 45%; }
|
||||
.oj-table thead th:nth-child(2) { width: 18%; }
|
||||
.oj-table thead th:nth-child(3) { width: 16%; text-align: center; }
|
||||
.oj-table thead th:last-child { width: 21%; text-align: center; }
|
||||
.oj-table tbody td { padding: 10px 14px; border-bottom: 1px solid rgba(232, 228, 222, 0.5); color: var(--ink); vertical-align: middle; }
|
||||
.oj-table tbody tr:last-child td { border-bottom: none; }
|
||||
.oj-table tbody tr:hover td { background: rgba(232, 93, 76, 0.02); }
|
||||
|
||||
.oj-status { display: inline-flex; align-items: center; gap: 5px; padding: 3px 10px; border-radius: 20px; font-size: 0.88em; font-weight: 500; }
|
||||
.oj-status.ac { background: #e8f5e9; color: #2e7d32; }
|
||||
.oj-status.wa { background: #fff3e0; color: #e65100; }
|
||||
.oj-status.re { background: #fce4ec; color: #c2185b; }
|
||||
.oj-status.tle { background: #e3f2fd; color: #1565c0; }
|
||||
.oj-status.pending { background: #f5f5f5; color: #9e9e9e; }
|
||||
.oj-status-icon { font-size: 1.1em; line-height: 1; }
|
||||
.oj-submit-count { text-align: center; font-weight: 500; color: var(--ink-soft); }
|
||||
.oj-submit-count.highlight { color: var(--coral); font-weight: 600; }
|
||||
.oj-pattern { text-align: center; font-size: 0.9em; color: var(--ink-soft); }
|
||||
|
||||
.oj-summary { display: flex; align-items: center; gap: 12px; padding: 10px 16px; background: var(--cream); border-top: 1px solid var(--border); font-size: 0.82em; color: var(--ink-soft); }
|
||||
.oj-summary .oj-summary-item { display: flex; align-items: center; gap: 4px; }
|
||||
.oj-summary .oj-summary-num { font-weight: 600; color: var(--ink); }
|
||||
|
||||
@media (max-width: 768px){
|
||||
.hero-title { font-size: 1.7em; }
|
||||
.side-nav-btn { width: 40px; height: 60px; font-size: 1.1em; }
|
||||
.main { padding: 20px 16px 160px; }
|
||||
.course-hero { padding: 28px 20px 24px; }
|
||||
.oj-table { font-size: 0.78em; }
|
||||
.oj-table tbody td, .oj-table thead th { padding: 8px 10px; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 顶部导航 -->
|
||||
<div class="topbar">
|
||||
<div>
|
||||
<div class="topbar-title">第1周 · CSP04班课评</div>
|
||||
<div class="topbar-meta">2026年9月5日 · 《基础回顾·OJ五题精讲》 · 橙子老师</div>
|
||||
</div>
|
||||
<div class="topbar-actions">
|
||||
<button class="btn btn-outline" onclick="toggleEdit()" id="editBtn">✏️ 编辑</button>
|
||||
<button class="btn btn-outline" onclick="exportText()">📋 导出</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 编辑模式提示 -->
|
||||
<div class="edit-mode-badge" id="editBadge">📝 编辑模式 · 点击文字即可修改</div>
|
||||
|
||||
<!-- 侧边翻页按钮 -->
|
||||
<button class="side-nav-btn prev-btn" id="sidePrevBtn" onclick="prevCard()" title="上一张">
|
||||
<span class="arrow prev-arrow">‹</span>
|
||||
</button>
|
||||
<button class="side-nav-btn next-btn" id="sideNextBtn" onclick="nextCard()" title="下一张">
|
||||
<span class="arrow next-arrow">›</span>
|
||||
</button>
|
||||
|
||||
<!-- 主内容 -->
|
||||
<div class="main">
|
||||
<!-- 课程封面区域 -->
|
||||
<div class="course-hero">
|
||||
<div class="hero-badge">📚 本周课程</div>
|
||||
<h1 class="hero-title">《基础回顾·OJ五题精讲》</h1>
|
||||
<p class="hero-subtitle">C++信息奥赛 · 第1课</p>
|
||||
<div class="hero-divider"></div>
|
||||
<div class="hero-info">
|
||||
<div class="hero-info-item"><span class="icon">📅</span><span>2026年9月5日</span></div>
|
||||
<div class="hero-info-item"><span class="icon">⏰</span><span>周六 14:00-16:00</span></div>
|
||||
<div class="hero-info-item"><span class="icon">👩🏫</span><span>橙子老师</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 学习目标 -->
|
||||
<div class="goals-section">
|
||||
<div class="goals-header">
|
||||
<span class="goals-title"><span class="title-icon">🎯</span>本周知识点</span>
|
||||
<button class="goals-toggle" onclick="toggleGoals()">收起</button>
|
||||
</div>
|
||||
<ul class="goals-list" id="goalsList"><li><span class="goal-num">1</span><span class="goal-text">字符串处理与回文判断(ASCII大小写转换、双指针)</span></li><li><span class="goal-num">2</span><span class="goal-text">数组有序去重(快慢指针)</span></li><li><span class="goal-num">3</span><span class="goal-text">进制转换(除K取余、映射表0123456789ABCDEF)</span></li><li><span class="goal-num">4</span><span class="goal-text">二进制与位运算(拆位数1、2的幂/幸运数)</span></li><li><span class="goal-num">5</span><span class="goal-text">模拟与状态标记(约瑟夫报数游戏)</span></li></ul>
|
||||
</div>
|
||||
|
||||
<!-- 学生卡片滑动区 -->
|
||||
<div class="cards-slider-wrapper">
|
||||
<div class="cards-slider" id="cardsSlider">
|
||||
|
||||
<div class="student-card active">
|
||||
<div class="card-header">
|
||||
<span class="student-name">郑子煜</span>
|
||||
<span class="card-badge badge-normal">正常上课</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="feedback-content" data-student="郑子煜">新学期第一课态度认真、跟住老师节奏;尝试回文串和进制数位两道题都还差一点没通,假期后基础需要重新拾起,多复习基础概念、留意语法细节会更稳~</div>
|
||||
|
||||
<div class="oj-section" data-oj-section="郑子煜">
|
||||
<div class="oj-header"><span>📊</span><span>OJ 做题数据 · 题目解析与错因</span></div>
|
||||
<table class="oj-table">
|
||||
<thead><tr><th>题目</th><th>状态</th><th style="text-align:center">提交次数</th><th style="text-align:center">思考模式</th><th>解析 / 为什么错</th></tr></thead>
|
||||
<tbody><tr><td>S0401P1 小杨的回文串</td><td><span class="oj-status wa"><span class="oj-status-icon">✗</span>CE</span></td><td class="oj-submit-count highlight">2</td><td class="oj-pattern">遇到困难</td><td>编译错误——分号/括号/变量名等语法细节未检查,先在本地编译通过</td></tr><tr><td>S0401P2 小杨有序去重</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>未提交(课上未做)</td></tr><tr><td>S0401P3 小杨的进制数位</td><td><span class="oj-status wa"><span class="oj-status-icon">✗</span>WA</span></td><td class="oj-submit-count">1</td><td class="oj-pattern">遇到困难</td><td>答案错误——进制转换"除K取余、余数倒序拼+0特判"细节未掌握</td></tr><tr><td>S0401A6 基础回顾-选择</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>未提交(课上未做)</td></tr><tr><td>S0401A7 基础回顾-判断</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>未提交(课上未做)</td></tr><tr><td>S0401P4 小杨的幸运数字</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>未提交(课上未做)</td></tr><tr><td>S0401P5 小杨的报数游戏</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>未提交(课上未做)</td></tr></tbody>
|
||||
</table>
|
||||
<div class="oj-summary">
|
||||
<div class="oj-summary-item"><span>完成:</span><span class="oj-summary-num">0/2</span></div>
|
||||
<div class="oj-summary-item"><span>AC:</span><span class="oj-summary-num">0</span></div>
|
||||
<div class="oj-summary-item"><span>总提交:</span><span class="oj-summary-num">3</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><div class="student-card">
|
||||
<div class="card-header">
|
||||
<span class="student-name">张雨禾</span>
|
||||
<span class="card-badge badge-normal">正常上课</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="feedback-content" data-student="张雨禾">专注、坐得住,态度认真;尝试5题共10次提交,仅进制数位一次通过,其余多为审题粗心和语法小错,每天复习、写完自查会更好~</div>
|
||||
|
||||
<div class="oj-section" data-oj-section="张雨禾">
|
||||
<div class="oj-header"><span>📊</span><span>OJ 做题数据 · 题目解析与错因</span></div>
|
||||
<table class="oj-table">
|
||||
<thead><tr><th>题目</th><th>状态</th><th style="text-align:center">提交次数</th><th style="text-align:center">思考模式</th><th>解析 / 为什么错</th></tr></thead>
|
||||
<tbody><tr><td>S0401P1 小杨的回文串</td><td><span class="oj-status wa"><span class="oj-status-icon">✗</span>WA</span></td><td class="oj-submit-count highlight">2</td><td class="oj-pattern">遇到困难</td><td>答案错误——先数原串大小写个数再转,别转完再统计</td></tr><tr><td>S0401P2 小杨有序去重</td><td><span class="oj-status wa"><span class="oj-status-icon">✗</span>CE</span></td><td class="oj-submit-count highlight">2</td><td class="oj-pattern">遇到困难</td><td>编译错误——语法细节未检查</td></tr><tr><td>S0401P3 小杨的进制数位</td><td><span class="oj-status ac"><span class="oj-status-icon">✓</span>AC</span></td><td class="oj-submit-count">1</td><td class="oj-pattern">一气呵成</td><td>进制数位一次过,掌握扎实</td></tr><tr><td>S0401A6 基础回顾-选择</td><td><span class="oj-status wa"><span class="oj-status-icon">✗</span>WA</span></td><td class="oj-submit-count highlight">3</td><td class="oj-pattern">反复调试</td><td>答案错误——选择/判断题多审题粗心、概念没记牢</td></tr><tr><td>S0401A7 基础回顾-判断</td><td><span class="oj-status wa"><span class="oj-status-icon">✗</span>WA</span></td><td class="oj-submit-count highlight">2</td><td class="oj-pattern">遇到困难</td><td>答案错误——判断题细节记牢</td></tr><tr><td>S0401P4 小杨的幸运数字</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>未提交(课上未做)</td></tr><tr><td>S0401P5 小杨的报数游戏</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>未提交(课上未做)</td></tr></tbody>
|
||||
</table>
|
||||
<div class="oj-summary">
|
||||
<div class="oj-summary-item"><span>完成:</span><span class="oj-summary-num">1/5</span></div>
|
||||
<div class="oj-summary-item"><span>AC:</span><span class="oj-summary-num">1</span></div>
|
||||
<div class="oj-summary-item"><span>总提交:</span><span class="oj-summary-num">10</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><div class="student-card">
|
||||
<div class="card-header">
|
||||
<span class="student-name">苏俊宇</span>
|
||||
<span class="card-badge badge-normal">正常上课</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="feedback-content" data-student="苏俊宇">认真专注,逻辑思维出色;回文串、有序去重两题一次通过、一气呵成,基础很扎实!把这份思路多落实到手上,再多写几题会更棒~</div>
|
||||
|
||||
<div class="oj-section" data-oj-section="苏俊宇">
|
||||
<div class="oj-header"><span>📊</span><span>OJ 做题数据 · 题目解析与错因</span></div>
|
||||
<table class="oj-table">
|
||||
<thead><tr><th>题目</th><th>状态</th><th style="text-align:center">提交次数</th><th style="text-align:center">思考模式</th><th>解析 / 为什么错</th></tr></thead>
|
||||
<tbody><tr><td>S0401P1 小杨的回文串</td><td><span class="oj-status ac"><span class="oj-status-icon">✓</span>AC</span></td><td class="oj-submit-count">1</td><td class="oj-pattern">一气呵成</td><td>回文判断一次过,思路清晰</td></tr><tr><td>S0401P2 小杨有序去重</td><td><span class="oj-status ac"><span class="oj-status-icon">✓</span>AC</span></td><td class="oj-submit-count">1</td><td class="oj-pattern">一气呵成</td><td>快慢指针去重一次过,掌握扎实</td></tr><tr><td>S0401P3 小杨的进制数位</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>未提交(课上未做)</td></tr><tr><td>S0401A6 基础回顾-选择</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>未提交(课上未做)</td></tr><tr><td>S0401A7 基础回顾-判断</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>未提交(课上未做)</td></tr><tr><td>S0401P4 小杨的幸运数字</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>未提交(课上未做)</td></tr><tr><td>S0401P5 小杨的报数游戏</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>未提交(课上未做)</td></tr></tbody>
|
||||
</table>
|
||||
<div class="oj-summary">
|
||||
<div class="oj-summary-item"><span>完成:</span><span class="oj-summary-num">2/2</span></div>
|
||||
<div class="oj-summary-item"><span>AC:</span><span class="oj-summary-num">2</span></div>
|
||||
<div class="oj-summary-item"><span>总提交:</span><span class="oj-summary-num">2</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><div class="student-card">
|
||||
<div class="card-header">
|
||||
<span class="student-name">鲍佳音</span>
|
||||
<span class="card-badge badge-normal">正常上课</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="feedback-content" data-student="鲍佳音">欢迎佳音加入CSP04班!第一次上课就很投入、态度认真;主动尝试5题共10次提交,进制数位一次通过,思维底子不错,继续加油~</div>
|
||||
|
||||
<div class="oj-section" data-oj-section="鲍佳音">
|
||||
<div class="oj-header"><span>📊</span><span>OJ 做题数据 · 题目解析与错因</span></div>
|
||||
<table class="oj-table">
|
||||
<thead><tr><th>题目</th><th>状态</th><th style="text-align:center">提交次数</th><th style="text-align:center">思考模式</th><th>解析 / 为什么错</th></tr></thead>
|
||||
<tbody><tr><td>S0401P1 小杨的回文串</td><td><span class="oj-status wa"><span class="oj-status-icon">✗</span>WA</span></td><td class="oj-submit-count highlight">2</td><td class="oj-pattern">遇到困难</td><td>答案错误——先数原串大小写个数再转</td></tr><tr><td>S0401P2 小杨有序去重</td><td><span class="oj-status wa"><span class="oj-status-icon">✗</span>WA</span></td><td class="oj-submit-count highlight">2</td><td class="oj-pattern">遇到困难</td><td>答案错误——快慢指针细节待练</td></tr><tr><td>S0401P3 小杨的进制数位</td><td><span class="oj-status ac"><span class="oj-status-icon">✓</span>AC</span></td><td class="oj-submit-count">1</td><td class="oj-pattern">一气呵成</td><td>进制数位一次过,基础不错</td></tr><tr><td>S0401A6 基础回顾-选择</td><td><span class="oj-status wa"><span class="oj-status-icon">✗</span>WA</span></td><td class="oj-submit-count highlight">3</td><td class="oj-pattern">反复调试</td><td>答案错误——概念/审题细节</td></tr><tr><td>S0401A7 基础回顾-判断</td><td><span class="oj-status wa"><span class="oj-status-icon">✗</span>WA</span></td><td class="oj-submit-count highlight">2</td><td class="oj-pattern">遇到困难</td><td>答案错误——判断题细节</td></tr><tr><td>S0401P4 小杨的幸运数字</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>未提交(课上未做)</td></tr><tr><td>S0401P5 小杨的报数游戏</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>未提交(课上未做)</td></tr></tbody>
|
||||
</table>
|
||||
<div class="oj-summary">
|
||||
<div class="oj-summary-item"><span>完成:</span><span class="oj-summary-num">1/5</span></div>
|
||||
<div class="oj-summary-item"><span>AC:</span><span class="oj-summary-num">1</span></div>
|
||||
<div class="oj-summary-item"><span>总提交:</span><span class="oj-summary-num">10</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><div class="student-card">
|
||||
<div class="card-header">
|
||||
<span class="student-name">卢华琛</span>
|
||||
<span class="card-badge badge-absent">请假</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="feedback-content" data-student="卢华琛">本周因事请假未到课。请在家复习上学期基础知识,有空到OJ看看《基础回顾》题目,为下节课做好准备;如需补课可联系老师安排。</div>
|
||||
|
||||
<div class="oj-section" data-oj-section="卢华琛">
|
||||
<div class="oj-header"><span>📊</span><span>OJ 做题数据 · 题目解析与错因</span></div>
|
||||
<table class="oj-table">
|
||||
<thead><tr><th>题目</th><th>状态</th><th style="text-align:center">提交次数</th><th style="text-align:center">思考模式</th><th>解析 / 为什么错</th></tr></thead>
|
||||
<tbody><tr><td>S0401P1 小杨的回文串</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>请假未到课</td></tr><tr><td>S0401P2 小杨有序去重</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>请假未到课</td></tr><tr><td>S0401P3 小杨的进制数位</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>请假未到课</td></tr><tr><td>S0401A6 基础回顾-选择</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>请假未到课</td></tr><tr><td>S0401A7 基础回顾-判断</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>请假未到课</td></tr><tr><td>S0401P4 小杨的幸运数字</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>请假未到课</td></tr><tr><td>S0401P5 小杨的报数游戏</td><td><span class="oj-status pending">未提交</span></td><td class="oj-submit-count">0</td><td class="oj-pattern">-</td><td>请假未到课</td></tr></tbody>
|
||||
</table>
|
||||
<div class="oj-summary">
|
||||
<div class="oj-summary-item"><span>完成:</span><span class="oj-summary-num">0/0</span></div>
|
||||
<div class="oj-summary-item"><span>AC:</span><span class="oj-summary-num">0</span></div>
|
||||
<div class="oj-summary-item"><span>总提交:</span><span class="oj-summary-num">0</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 导航控制 -->
|
||||
<div class="nav-controls">
|
||||
<span class="page-indicator" id="pageIndicator">1 / N</span>
|
||||
</div>
|
||||
|
||||
<!-- 进度点 -->
|
||||
<div class="progress-dots" id="progressDots">
|
||||
<div class="progress-dot active" onclick="goToCard(0)"></div><div class="progress-dot" onclick="goToCard(1)"></div><div class="progress-dot" onclick="goToCard(2)"></div><div class="progress-dot" onclick="goToCard(3)"></div><div class="progress-dot" onclick="goToCard(4)"></div>
|
||||
</div>
|
||||
|
||||
<div class="footer">穹狼科创 · CSP04班 · 橙子老师</div>
|
||||
</div>
|
||||
|
||||
<!-- 底部操作栏 -->
|
||||
<div class="bottom-bar" id="bottomBar" style="display: none;">
|
||||
<button class="btn btn-outline" onclick="cancelEdit()">取消</button>
|
||||
<button class="btn btn-success" onclick="saveEdit()">✓ 保存修改</button>
|
||||
</div>
|
||||
|
||||
<!-- 提示条 -->
|
||||
<div class="toast" id="toast"></div>
|
||||
|
||||
<script>
|
||||
let currentCard = 0;
|
||||
const totalCards = 5;
|
||||
const allCards = document.querySelectorAll('.student-card');
|
||||
const sidePrevBtn = document.getElementById('sidePrevBtn');
|
||||
const sideNextBtn = document.getElementById('sideNextBtn');
|
||||
const pageIndicator = document.getElementById('pageIndicator');
|
||||
const progressDots = document.querySelectorAll('.progress-dot');
|
||||
|
||||
function updateSlider() {
|
||||
allCards.forEach(function(card, i) {
|
||||
card.classList.remove('active', 'prev');
|
||||
if (i === currentCard) { card.classList.add('active'); }
|
||||
else if (i < currentCard) { card.classList.add('prev'); }
|
||||
});
|
||||
pageIndicator.textContent = (currentCard + 1) + ' / ' + totalCards;
|
||||
sidePrevBtn.disabled = currentCard === 0;
|
||||
sideNextBtn.disabled = currentCard === totalCards - 1;
|
||||
progressDots.forEach(function(dot, i) { dot.classList.toggle('active', i === currentCard); });
|
||||
}
|
||||
|
||||
function nextCard() { if (currentCard < totalCards - 1) { currentCard++; updateSlider(); } }
|
||||
function prevCard() { if (currentCard > 0) { currentCard--; updateSlider(); } }
|
||||
function goToCard(i) { currentCard = i; updateSlider(); }
|
||||
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'ArrowLeft') prevCard();
|
||||
if (e.key === 'ArrowRight') nextCard();
|
||||
});
|
||||
|
||||
var touchStartX = 0;
|
||||
var sliderEl = document.getElementById('cardsSlider');
|
||||
sliderEl.addEventListener('touchstart', function(e) { touchStartX = e.changedTouches[0].screenX; });
|
||||
sliderEl.addEventListener('touchend', function(e) {
|
||||
var dx = e.changedTouches[0].screenX;
|
||||
if (touchStartX - dx > 50) nextCard();
|
||||
if (dx - touchStartX > 50) prevCard();
|
||||
});
|
||||
|
||||
updateSlider();
|
||||
|
||||
|
||||
function toggleGoals() {
|
||||
var list = document.getElementById('goalsList');
|
||||
var btn = document.querySelector('.goals-toggle');
|
||||
list.classList.toggle('collapsed');
|
||||
btn.textContent = list.classList.contains('collapsed') ? '展开' : '收起';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var originalContent = {};
|
||||
var originalMetrics = {};
|
||||
var isEditMode = false;
|
||||
|
||||
function toggleEdit() {
|
||||
isEditMode = !isEditMode;
|
||||
var feedbacks = document.querySelectorAll('.feedback-content');
|
||||
var metricComments = document.querySelectorAll('.metric-comment');
|
||||
var starRatings = document.querySelectorAll('.star-rating');
|
||||
var editBtn = document.getElementById('editBtn');
|
||||
var editBadge = document.getElementById('editBadge');
|
||||
var bottomBar = document.getElementById('bottomBar');
|
||||
|
||||
if (isEditMode) {
|
||||
feedbacks.forEach(function(el) { originalContent[el.dataset.student] = el.innerHTML; });
|
||||
metricComments.forEach(function(el) {
|
||||
var key = el.closest('.student-card').querySelector('.student-name').textContent + '-' + el.dataset.metricComment;
|
||||
originalMetrics[key] = { text: el.innerHTML, score: 0 };
|
||||
});
|
||||
starRatings.forEach(function(el) {
|
||||
var key = el.closest('.student-card').querySelector('.student-name').textContent + '-' + el.closest('.metric-item').dataset.metric;
|
||||
if (originalMetrics[key]) originalMetrics[key].score = el.dataset.score;
|
||||
});
|
||||
|
||||
feedbacks.forEach(function(el) { el.contentEditable = true; });
|
||||
metricComments.forEach(function(el) { el.contentEditable = true; });
|
||||
starRatings.forEach(function(el) { el.classList.add('editable'); });
|
||||
editBtn.textContent = '✏️ 退出编辑';
|
||||
editBadge.classList.add('show');
|
||||
bottomBar.style.display = 'flex';
|
||||
showToast('编辑模式已开启,点击文字或星星即可修改');
|
||||
} else {
|
||||
feedbacks.forEach(function(el) { el.contentEditable = false; });
|
||||
metricComments.forEach(function(el) { el.contentEditable = false; });
|
||||
starRatings.forEach(function(el) { el.classList.remove('editable'); });
|
||||
editBtn.textContent = '✏️ 编辑';
|
||||
editBadge.classList.remove('show');
|
||||
bottomBar.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function saveEdit() {
|
||||
isEditMode = false;
|
||||
document.querySelectorAll('.feedback-content').forEach(function(el) { el.contentEditable = false; });
|
||||
document.querySelectorAll('.metric-comment').forEach(function(el) { el.contentEditable = false; });
|
||||
document.querySelectorAll('.star-rating').forEach(function(el) { el.classList.remove('editable'); });
|
||||
document.getElementById('editBtn').textContent = '✏️ 编辑';
|
||||
document.getElementById('editBadge').classList.remove('show');
|
||||
document.getElementById('bottomBar').style.display = 'none';
|
||||
originalContent = {};
|
||||
originalMetrics = {};
|
||||
showToast('✓ 修改已保存');
|
||||
}
|
||||
|
||||
function cancelEdit() {
|
||||
isEditMode = false;
|
||||
document.querySelectorAll('.feedback-content').forEach(function(el) {
|
||||
if (originalContent[el.dataset.student]) el.innerHTML = originalContent[el.dataset.student];
|
||||
el.contentEditable = false;
|
||||
});
|
||||
document.querySelectorAll('.metric-comment').forEach(function(el) {
|
||||
var key = el.closest('.student-card').querySelector('.student-name').textContent + '-' + el.dataset.metricComment;
|
||||
if (originalMetrics[key]) el.innerHTML = originalMetrics[key].text;
|
||||
el.contentEditable = false;
|
||||
});
|
||||
document.querySelectorAll('.star-rating').forEach(function(el) {
|
||||
var key = el.closest('.student-card').querySelector('.student-name').textContent + '-' + el.closest('.metric-item').dataset.metric;
|
||||
if (originalMetrics[key]) setStarRating(el, parseInt(originalMetrics[key].score));
|
||||
el.classList.remove('editable');
|
||||
});
|
||||
document.getElementById('editBtn').textContent = '✏️ 编辑';
|
||||
document.getElementById('editBadge').classList.remove('show');
|
||||
document.getElementById('bottomBar').style.display = 'none';
|
||||
originalContent = {};
|
||||
originalMetrics = {};
|
||||
showToast('已恢复原始内容');
|
||||
}
|
||||
|
||||
function exportText() {
|
||||
var text = '第1周周六下午CSP04班课评\n';
|
||||
text += '2026年9月5日 · 《基础回顾·OJ五题精讲》 · 橙子老师\n';
|
||||
text += '═══════════════════════════════════════\n\n';
|
||||
text += '🎯 本周知识点\n';
|
||||
text += '─────────────────────────────────────\n';
|
||||
text += '1. 字符串处理与回文判断(ASCII大小写转换、双指针)\n2. 数组有序去重(快慢指针)\n3. 进制转换(除K取余、映射表0123456789ABCDEF)\n4. 二进制与位运算(拆位数1、2的幂/幸运数)\n5. 模拟与状态标记(约瑟夫报数游戏)\n\n';
|
||||
text += '═══════════════════════════════════════\n\n';
|
||||
|
||||
document.querySelectorAll('.student-card').forEach(function(card) {
|
||||
var name = card.querySelector('.student-name').textContent;
|
||||
var badge = card.querySelector('.card-badge').textContent;
|
||||
var feedback = card.querySelector('.feedback-content').innerText;
|
||||
text += '【' + name + '】' + badge + '\n';
|
||||
text += '─────────────────────────────────\n';
|
||||
text += feedback + '\n\n';
|
||||
|
||||
card.querySelectorAll('.metric-item').forEach(function(m) {
|
||||
var label = m.querySelector('.metric-label').textContent;
|
||||
var rating = m.querySelector('.star-rating');
|
||||
var score = parseInt(rating.dataset.score);
|
||||
var scoreLabels = ['未评', '⭐', '⭐⭐', '⭐⭐⭐', '⭐⭐⭐⭐', '⭐⭐⭐⭐⭐'];
|
||||
var stars = scoreLabels[score] || '未评';
|
||||
var comment = m.querySelector('.metric-comment').innerText.trim();
|
||||
if (comment === '点击编辑评语...') comment = '';
|
||||
text += ' ' + label + ':' + stars;
|
||||
if (comment) text += '(' + comment + ')';
|
||||
text += '\n';
|
||||
});
|
||||
text += '\n';
|
||||
});
|
||||
|
||||
navigator.clipboard.writeText(text).then(function() {
|
||||
showToast('✓ 已复制到剪贴板,可直接粘贴发送');
|
||||
}).catch(function() {
|
||||
var ta = document.createElement('textarea');
|
||||
ta.value = text; document.body.appendChild(ta); ta.select();
|
||||
document.execCommand('copy'); document.body.removeChild(ta);
|
||||
showToast('✓ 已复制到剪贴板');
|
||||
});
|
||||
}
|
||||
|
||||
function showToast(msg) {
|
||||
var toast = document.getElementById('toast');
|
||||
toast.textContent = msg;
|
||||
toast.classList.add('show');
|
||||
setTimeout(function() { toast.classList.remove('show'); }, 2000);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
107
.claude/memory/temp/build_0812_0813_page.py
Normal file
107
.claude/memory/temp/build_0812_0813_page.py
Normal file
@@ -0,0 +1,107 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# 将第33周综合课评页替换为 8月12-13日 两天专属(4课)
|
||||
import io
|
||||
|
||||
path = 'output/课评汇总/第33周穹狼传奇&小龙虾综合课评_0812-0813.html'
|
||||
|
||||
block1 = ''' <!-- ═══════ 区块1:穹狼传奇 8-12 第3课 ═══════ -->
|
||||
<div class="course-block">
|
||||
<div class="course-hero">
|
||||
<div class="hero-badge">🐺 穹狼传奇班</div>
|
||||
<h1 class="hero-title">《精灵图动作播放器与小怪素材》</h1>
|
||||
<p class="hero-subtitle">AI创意编程 · 第3课</p>
|
||||
<div class="hero-divider"></div>
|
||||
<div class="hero-info">
|
||||
<div class="hero-info-item"><span class="icon">📅</span><span>2026年8月12日</span></div>
|
||||
<div class="hero-info-item"><span class="icon">⏰</span><span>上午 09:00</span></div>
|
||||
<div class="hero-info-item"><span class="icon">👩🏫</span><span>橙子老师</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="goals-section"><div class="goals-header"><span class="goals-title"><span class="title-icon">🎯</span>本周知识点</span><button class="goals-toggle" onclick="toggleGoals(this)">收起</button></div><ul class="goals-list"><li><span class="goal-num">1</span><span class="goal-text">让AI写需求文档:用"计划模式"(先出方案、不写代码)规划功能,审核后再开工</span></li><li><span class="goal-num">2</span><span class="goal-text">精灵图布局规范:图片两排排列、尺寸统一</span></li><li><span class="goal-num">3</span><span class="goal-text">精灵图动作播放器:上传素材即可预览动作播放</span></li><li><span class="goal-num">4</span><span class="goal-text">生成小怪素材:用提示词让AI生图、AI抠图去背景</span></li><li><span class="goal-num">5</span><span class="goal-text">素材精修归档:提示词放创作台精修,素材统一管理</span></li></ul></div>
|
||||
<div class="cards-slider-wrapper">
|
||||
<div class="cards-slider">
|
||||
<div class="student-card active" data-key="haolin-0812"><div class="card-header"><span class="student-name">卢皓霖</span><span class="card-badge badge-normal">正常上课</span></div><div class="card-body"><div class="feedback-content" data-student="卢皓霖">皓霖家长好,本周学习的内容是《精灵图动作播放器与小怪素材》:<br>1. 让AI写需求文档:用"计划模式"(先出方案、不写代码)规划功能,审核后再开工<br>2. 精灵图布局规范:图片两排排列、尺寸统一<br>3. 精灵图动作播放器:上传素材即可预览动作播放<br>4. 生成小怪素材:用提示词让AI生图、AI抠图去背景<br>5. 素材精修归档:提示词放创作台精修,素材统一管理<br><br>昨天皓霖一口气做了22种动作精灵图,今天就把它们用起来啦~开始做"精灵图动作播放器",还学会让AI先写需求文档、审核之后再动手,做事的流程感越来越强!💪<br><br>今天还挑战了新任务:生成游戏的小怪角色!他让AI生成了"橘子怪",学会用AI抠图把背景去掉。遇到白底没抠干净,皓霖一点不慌,老师一提醒就自己调整过来了——这种不怕小麻烦的好心态,学编程特别珍贵!还学会把生图提示词放到创作台(AI生图的编辑工作区)里精修,素材越做越精致。😊<br><br>课堂上偶尔聊到游戏会走神,不过老师一提醒,皓霖马上就能回到任务上,这份"能收回来"的能力很棒!下次我们把任务切成两三小步,每完成一步击个掌,专注一小段、歇一小段,效率会更稳哟~<br><br>回家可以请皓霖打开"橘子怪"给你们看看,让他讲讲怎么让AI生图、又怎么把白底抠掉的——能讲清楚,就说明真的学会啦~明天做第一关地图,把精灵和小怪都用起来!老师会继续关注皓霖的表现,期待看到更多精彩!🌟💡</div><div class="metrics"><div class="metric-item" data-metric="课堂互动"><div class="metric-label">课堂互动</div><div class="star-rating editable" data-score="4"><span class="star" data-val="1">★</span><span class="star" data-val="2">★</span><span class="star" data-val="3">★</span><span class="star" data-val="4">★</span><span class="star" data-val="5">★</span><span class="star-score">优秀</span></div><div class="metric-comment" data-metric-comment="课堂互动">学会"计划模式"让AI先写需求文档,主动和老师配合打磨素材;聊到游戏会走神,但一提醒能收回</div></div><div class="metric-item" data-metric="专注度"><div class="metric-label">专注度</div><div class="star-rating editable" data-score="3"><span class="star" data-val="1">★</span><span class="star" data-val="2">★</span><span class="star" data-val="3">★</span><span class="star" data-val="4">★</span><span class="star" data-val="5">★</span><span class="star-score">良好</span></div><div class="metric-comment" data-metric-comment="专注度">偶尔聊游戏走神,老师提醒后能马上回到任务</div></div><div class="metric-item" data-metric="作品完成"><div class="metric-label">作品完成</div><div class="star-rating editable" data-score="4"><span class="star" data-val="1">★</span><span class="star" data-val="2">★</span><span class="star" data-val="3">★</span><span class="star" data-val="4">★</span><span class="star" data-val="5">★</span><span class="star-score">优秀</span></div><div class="metric-comment" data-metric-comment="作品完成">把22种精灵图做成动作播放器,还生成"橘子怪"素材、学会AI抠图去背景</div></div><div class="metric-item" data-metric="知识点掌握"><div class="metric-label">知识点掌握</div><div class="star-rating editable" data-score="4"><span class="star" data-val="1">★</span><span class="star" data-val="2">★</span><span class="star" data-val="3">★</span><span class="star" data-val="4">★</span><span class="star" data-val="5">★</span><span class="star-score">优秀</span></div><div class="metric-comment" data-metric-comment="知识点掌握">掌握需求文档先行、AI抠图、提示词精修;素材统一归档还需巩固</div></div></div></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
'''
|
||||
|
||||
block2 = ''' <!-- ═══════ 区块2:小龙虾 8-12 第3课 ═══════ -->
|
||||
<div class="course-block">
|
||||
<div class="course-hero">
|
||||
<div class="hero-badge">🦞 AICODE小龙虾班</div>
|
||||
<h1 class="hero-title">《AI创意写作·修仙爽文《战临九天》》</h1>
|
||||
<p class="hero-subtitle">AI创意编程 · 第3课</p>
|
||||
<div class="hero-divider"></div>
|
||||
<div class="hero-info">
|
||||
<div class="hero-info-item"><span class="icon">📅</span><span>2026年8月12日</span></div>
|
||||
<div class="hero-info-item"><span class="icon">⏰</span><span>下午</span></div>
|
||||
<div class="hero-info-item"><span class="icon">👩🏫</span><span>橙子老师</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="goals-section"><div class="goals-header"><span class="goals-title"><span class="title-icon">🎯</span>本周知识点</span><button class="goals-toggle" onclick="toggleGoals(this)">收起</button></div><ul class="goals-list"><li><span class="goal-num">1</span><span class="goal-text">故事设定共创:把想要的题材、主角、金手指(随身空间+前世记忆)用清晰的话告诉AI,AI帮忙整理成大纲</span></li><li><span class="goal-num">2</span><span class="goal-text">力量体系设计:给故事定"武道八境"境界体系(武者→武师→武灵→武王→武宗→武尊→武圣→武帝),让世界规则自洽</span></li><li><span class="goal-num">3</span><span class="goal-text">角色与伏笔设计:废柴主角、随身老爷爷、部族覆灭之谜、天赋被父亲封印,每个角色背后都藏着钩子</span></li><li><span class="goal-num">4</span><span class="goal-text">剧情逻辑自查:发现设定前后矛盾就大胆提出质疑,核对原文、修改设定,让故事经得起推敲</span></li><li><span class="goal-num">5</span><span class="goal-text">作品网页化:把写好的小说做成单文件阅读网页,目录导航、明暗主题、字号调节,新章节随时加</span></li></ul></div>
|
||||
<div class="cards-slider-wrapper">
|
||||
<div class="cards-slider">
|
||||
<div class="student-card active" data-key="junmian-0812"><div class="card-header"><span class="student-name">赵俊棉</span><span class="card-badge badge-normal">正常上课</span></div><div class="card-body"><div class="feedback-content" data-student="赵俊棉">俊棉家长好,本周学习的内容是《AI创意写作·修仙爽文《战临九天》》:<br>1. 故事设定共创:把想要的题材、主角、金手指(随身空间+前世记忆)用清晰的话告诉AI,AI帮忙整理成大纲<br>2. 力量体系设计:给故事定"武道八境"境界体系(武者→武师→武灵→武王→武宗→武尊→武圣→武帝),让世界规则自洽<br>3. 角色与伏笔设计:废柴主角、随身老爷爷、部族覆灭之谜、天赋被父亲封印,每个角色背后都藏着钩子<br>4. 剧情逻辑自查:发现设定前后矛盾就大胆提出质疑,核对原文、修改设定,让故事经得起推敲<br>5. 作品网页化:把写好的小说做成单文件阅读网页,目录导航、明暗主题、字号调节,新章节随时加<br><br>俊棉今天从"网页主编"升级成"故事主笔",书名、主角名、"武道八境"境界体系都是他自己拍板的,主人翁意识特别强~📖<br><br>最让老师惊喜的是他把"较真"用在了剧情逻辑上:第一章里他发现"16岁便突破炼气九层"和"先测灵根再修炼"的设定对不上(按故事设定,修炼要先测灵根、再一步步突破境界),直接提出"这个地方是不是不太对?",老师当场把第一章原文调出来一起核对修正——会自己审查自己故事逻辑,这就是作者思维💡<br><br>下午他一句"继续",AI就连着写出了第4-6章:破境武师、大比一拳镇场、硬抗武灵楚枫,一波接一波的爽快反转;他还把小说做成了网页版,目录导航、明暗主题、字号调节都有~<br><br>比起第2课"做完要检查、让AI迭代",这一课他更进一层,会主动找剧情漏洞,进步很明显~下节课老师想请俊棉当"小编剧",把《战临九天》的开篇讲给您听~<br><br>回家可以玩一个小游戏:让俊棉当"作者"、您当"读者",读完一段问他"下一章会发生什么",看他把伏笔怎么接回来~<br><br>老师会继续关注俊棉的表现,期待看到更多精彩!🌟💡</div><div class="metrics"><div class="metric-item" data-metric="课堂互动"><div class="metric-label">课堂互动</div><div class="star-rating editable" data-score="5"><span class="star" data-val="1">★</span><span class="star" data-val="2">★</span><span class="star" data-val="3">★</span><span class="star" data-val="4">★</span><span class="star" data-val="5">★</span><span class="star-score">超棒</span></div><div class="metric-comment" data-metric-comment="课堂互动">主人翁意识强,书名、主角、"武道八境"全自己拍板,主动质疑剧情设定</div></div><div class="metric-item" data-metric="专注度"><div class="metric-label">专注度</div><div class="star-rating editable" data-score="5"><span class="star" data-val="1">★</span><span class="star" data-val="2">★</span><span class="star" data-val="3">★</span><span class="star" data-val="4">★</span><span class="star" data-val="5">★</span><span class="star-score">超棒</span></div><div class="metric-comment" data-metric-comment="专注度">整节课全程主导故事创作,专注投入</div></div><div class="metric-item" data-metric="作品完成"><div class="metric-label">作品完成</div><div class="star-rating editable" data-score="5"><span class="star" data-val="1">★</span><span class="star" data-val="2">★</span><span class="star" data-val="3">★</span><span class="star" data-val="4">★</span><span class="star" data-val="5">★</span><span class="star-score">超棒</span></div><div class="metric-comment" data-metric-comment="作品完成">完成《战临九天》世界观设定+续写第4-6章+网页版阅读器</div></div><div class="metric-item" data-metric="知识点掌握"><div class="metric-label">知识点掌握</div><div class="star-rating editable" data-score="5"><span class="star" data-val="1">★</span><span class="star" data-val="2">★</span><span class="star" data-val="3">★</span><span class="star" data-val="4">★</span><span class="star" data-val="5">★</span><span class="star-score">超棒</span></div><div class="metric-comment" data-metric-comment="知识点掌握">把"剧情逻辑自查"用到极致,会审查自己故事逻辑</div></div></div></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
'''
|
||||
|
||||
block3 = ''' <!-- ═══════ 区块3:穹狼传奇 8-13 第4课 ═══════ -->
|
||||
<div class="course-block">
|
||||
<div class="course-hero">
|
||||
<div class="hero-badge">🐺 穹狼传奇班</div>
|
||||
<h1 class="hero-title">《AI生成游戏地图——橙城第一关》</h1>
|
||||
<p class="hero-subtitle">AI创意编程 · 第4课</p>
|
||||
<div class="hero-divider"></div>
|
||||
<div class="hero-info">
|
||||
<div class="hero-info-item"><span class="icon">📅</span><span>2026年8月13日</span></div>
|
||||
<div class="hero-info-item"><span class="icon">⏰</span><span>上午 09:00</span></div>
|
||||
<div class="hero-info-item"><span class="icon">👩🏫</span><span>橙子老师</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="goals-section"><div class="goals-header"><span class="goals-title"><span class="title-icon">🎯</span>本周知识点</span><button class="goals-toggle" onclick="toggleGoals(this)">收起</button></div><ul class="goals-list"><li><span class="goal-num">1</span><span class="goal-text">用文字向AI描述想要的地图场景(横版过关、草原、关卡设计)</span></li><li><span class="goal-num">2</span><span class="goal-text">让AI先给出地图提示词,再用于生图</span></li><li><span class="goal-num">3</span><span class="goal-text">把提示词粘贴到游戏工坊的背景生成功能出图</span></li><li><span class="goal-num">4</span><span class="goal-text">一张一张生成地图(先生成第一关)</span></li><li><span class="goal-num">5</span><span class="goal-text">把生成好的地图图片分类保存好</span></li></ul></div>
|
||||
<div class="cards-slider-wrapper">
|
||||
<div class="cards-slider">
|
||||
<div class="student-card active" data-key="haolin-0813"><div class="card-header"><span class="student-name">卢皓霖</span><span class="card-badge badge-normal">正常上课</span></div><div class="card-body"><div class="feedback-content" data-student="卢皓霖">皓霖家长好,本周学习的内容是《AI生成游戏地图——橙城第一关》:<br>1. 用文字向AI描述想要的地图场景(横版过关、草原、关卡设计)<br>2. 让AI先给出地图提示词,再用于生图<br>3. 把提示词粘贴到游戏工坊的背景生成功能出图<br>4. 一张一张生成地图(先生成第一关)<br>5. 把生成好的地图图片分类保存好<br><br>今天皓霖继续"穹狼传奇"游戏开发,第一关"橙城"地图终于做出来啦~前几课做的精灵图和小怪素材,这下有了自己的舞台!他学会先向AI描述想要的地图("在草原上,前面是一个城"),让AI先给提示词、再粘贴到背景生成里出图。😊<br><br>"让AI先给提示词"这步今天刚突破——一开始还没摸到方法,我们一起试了两三次就找到了,遇到卡壳不放弃、反复调整。这节课完全是皓霖自己在动手,老师只在旁边递工具,说明他已经能独立走通"描述→提示词→生图"的完整流程啦!💪<br><br>作品特别完整:第一关"橙城"加5张场景图都分门别类放好了,还做成"橙城·第一关 地图陈列"展示页,闯关页面也有雏形,越来越有模有样!🌟<br><br>课堂小提醒:皓霖偶尔会坐不住、爱聊游戏,但老师一提醒马上能回到任务。下节课让角色真正走进"橙城"地图走起来!<br><br>🏠 回家任务(2分钟):打开地图陈列页,让皓霖讲讲地图怎么一步步做出来的,重点说说"先要提示词"这步;再问问他第一关为什么选草原~<br><br>老师会继续关注皓霖的表现,期待看到更多精彩!🌟💡</div><div class="metrics"><div class="metric-item" data-metric="课堂互动"><div class="metric-label">课堂互动</div><div class="star-rating editable" data-score="4"><span class="star" data-val="1">★</span><span class="star" data-val="2">★</span><span class="star" data-val="3">★</span><span class="star" data-val="4">★</span><span class="star" data-val="5">★</span><span class="star-score">优秀</span></div><div class="metric-comment" data-metric-comment="课堂互动">整节课基本独立动手,老师只在旁边递工具</div></div><div class="metric-item" data-metric="专注度"><div class="metric-label">专注度</div><div class="star-rating editable" data-score="3"><span class="star" data-val="1">★</span><span class="star" data-val="2">★</span><span class="star" data-val="3">★</span><span class="star" data-val="4">★</span><span class="star" data-val="5">★</span><span class="star-score">良好</span></div><div class="metric-comment" data-metric-comment="专注度">偶尔坐不住、爱聊游戏,但老师一提醒能回到任务</div></div><div class="metric-item" data-metric="作品完成"><div class="metric-label">作品完成</div><div class="star-rating editable" data-score="5"><span class="star" data-val="1">★</span><span class="star" data-val="2">★</span><span class="star" data-val="3">★</span><span class="star" data-val="4">★</span><span class="star" data-val="5">★</span><span class="star-score">超棒</span></div><div class="metric-comment" data-metric-comment="作品完成">完成"橙城"第一关地图+5张场景图+地图陈列展示页+闯关页雏形</div></div><div class="metric-item" data-metric="知识点掌握"><div class="metric-label">知识点掌握</div><div class="star-rating editable" data-score="4"><span class="star" data-val="1">★</span><span class="star" data-val="2">★</span><span class="star" data-val="3">★</span><span class="star" data-val="4">★</span><span class="star" data-val="5">★</span><span class="star-score">优秀</span></div><div class="metric-comment" data-metric-comment="知识点掌握">突破"让AI先给提示词",独立走通"描述→提示词→生图"完整流程</div></div></div></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
'''
|
||||
|
||||
block4 = ''' <!-- ═══════ 区块4:小龙虾 8-13 第4课 ═══════ -->
|
||||
<div class="course-block">
|
||||
<div class="course-hero">
|
||||
<div class="hero-badge">🦞 AICODE小龙虾班</div>
|
||||
<h1 class="hero-title">《AI作品集·我的个人主页》</h1>
|
||||
<p class="hero-subtitle">AI创意编程 · 第4课</p>
|
||||
<div class="hero-divider"></div>
|
||||
<div class="hero-info">
|
||||
<div class="hero-info-item"><span class="icon">📅</span><span>2026年8月13日</span></div>
|
||||
<div class="hero-info-item"><span class="icon">⏰</span><span>下午</span></div>
|
||||
<div class="hero-info-item"><span class="icon">👩🏫</span><span>橙子老师</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="goals-section"><div class="goals-header"><span class="goals-title"><span class="title-icon">🎯</span>本周知识点</span><button class="goals-toggle" onclick="toggleGoals(this)">收起</button></div><ul class="goals-list"><li><span class="goal-num">1</span><span class="goal-text">需求表达:用清晰的话告诉AI"我要一个介绍自己的主页",把想法说具体</span></li><li><span class="goal-num">2</span><span class="goal-text">个人介绍组织:把"我是谁、我喜欢做什么"整理成给AI的素材</span></li><li><span class="goal-num">3</span><span class="goal-text">作品集导航:一个主页集中放项目卡片,点击即可跳转到猜名字/冷笑话/小说等作品</span></li><li><span class="goal-num">4</span><span class="goal-text">页面优化迭代:让AI调背景图、加内容、改布局,多轮打磨到满意</span></li><li><span class="goal-num">5</span><span class="goal-text">项目串联:把前3课的游戏、网页、故事串成一个完整的个人作品集</span></li></ul></div>
|
||||
<div class="cards-slider-wrapper">
|
||||
<div class="cards-slider">
|
||||
<div class="student-card active" data-key="junmian-0813"><div class="card-header"><span class="student-name">赵俊棉</span><span class="card-badge badge-normal">正常上课</span></div><div class="card-body"><div class="feedback-content" data-student="赵俊棉">俊棉家长好,本周学习的内容是《AI作品集·我的个人主页》:<br>1. 需求表达:用清晰的话告诉AI"我要一个介绍自己的主页",把想法说具体<br>2. 个人介绍组织:把"我是谁、我喜欢做什么"整理成给AI的素材<br>3. 作品集导航:一个主页集中放项目卡片,点击即可跳转到猜名字/冷笑话/小说等作品<br>4. 页面优化迭代:让AI调背景图、加内容、改布局,多轮打磨到满意<br>5. 项目串联:把前3课的游戏、网页、故事串成一个完整的个人作品集<br><br>俊棉今天当上了"作品集策展人"——把前3天做的猜名字游戏、冷笑话网页和《战临九天》小说,全部收进一个属于自己的个人主页,点卡片就能跳转,再也不用翻文件夹啦~🎉<br><br>主页处处是细节:首页是"你好呀,我是土逗"(俊棉给自己起的名字)的自我介绍,往下是6张特质卡,用小龙虾红的暗色主题、滚动入场动画和手机端适配,连网页图标都是一只小龙虾🦞;他还把"鱼航员嘉年华"图片做成了猜名字游戏的背景,让旧作品焕然一新~<br><br>今天他的"作品力"也在涨:一句"继续",AI就把《战临九天》从第6章写到第13章,越写越起劲;"较真"也跟着升级——第2课对玩法较真、第3课对剧情较真,这一课较真到了代码上:小说封面(初版)显示"0章"、点不进去,他和老师一起排查,发现是章节简介里的引号把代码截断了,修好后还总结出"以后加章节要检查引号"的小规则——从"用AI做内容"到"会修AI生成的网页",工程思维在悄悄发芽💪<br><br>下节课老师想请俊棉当"首席讲解员",打开作品集把这4天的成长讲给家长听;回家可以先来一场"策展人导览":让孩子从主页点进3个作品,每件用一句话介绍"这是什么、我怎么做出来的",家长当观众、问"这个怎么玩""哪件最得意"就好~平时在家,也多让俊棉自己开口把想法说给AI听,新点子都会从他嘴里长出来~<br><br>老师会继续关注俊棉的表现,期待看到更多精彩!🌟💡</div><div class="metrics"><div class="metric-item" data-metric="课堂互动"><div class="metric-label">课堂互动</div><div class="star-rating editable" data-score="5"><span class="star" data-val="1">★</span><span class="star" data-val="2">★</span><span class="star" data-val="3">★</span><span class="star" data-val="4">★</span><span class="star" data-val="5">★</span><span class="star-score">超棒</span></div><div class="metric-comment" data-metric-comment="课堂互动">当"作品集策展人",主动排查修复代码bug并总结规则</div></div><div class="metric-item" data-metric="专注度"><div class="metric-label">专注度</div><div class="star-rating editable" data-score="5"><span class="star" data-val="1">★</span><span class="star" data-val="2">★</span><span class="star" data-val="3">★</span><span class="star" data-val="4">★</span><span class="star" data-val="5">★</span><span class="star-score">超棒</span></div><div class="metric-comment" data-metric-comment="专注度">整节课专注打磨个人主页,细节拉满</div></div><div class="metric-item" data-metric="作品完成"><div class="metric-label">作品完成</div><div class="star-rating editable" data-score="5"><span class="star" data-val="1">★</span><span class="star" data-val="2">★</span><span class="star" data-val="3">★</span><span class="star" data-val="4">★</span><span class="star" data-val="5">★</span><span class="star-score">超棒</span></div><div class="metric-comment" data-metric-comment="作品完成">完成个人作品集主页(个人介绍+6特质卡+作品跳转)+续写小说第7-13章</div></div><div class="metric-item" data-metric="知识点掌握"><div class="metric-label">知识点掌握</div><div class="star-rating editable" data-score="5"><span class="star" data-val="1">★</span><span class="star" data-val="2">★</span><span class="star" data-val="3">★</span><span class="star" data-val="4">★</span><span class="star" data-val="5">★</span><span class="star-score">超棒</span></div><div class="metric-comment" data-metric-comment="知识点掌握">从"用AI做内容"到"会修AI生成的网页",工程思维悄悄发芽</div></div></div></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
'''
|
||||
|
||||
new_blocks = block1 + block2 + block3 + block4
|
||||
|
||||
s = io.open(path, encoding='utf-8').read()
|
||||
start = s.index('<!-- ═══════ 区块1')
|
||||
end = s.index(' <div class="footer">')
|
||||
s2 = s[:start] + new_blocks + s[end:]
|
||||
io.open(path, 'w', encoding='utf-8', newline='').write(s2)
|
||||
print('replaced bytes:', end - start, '->', len(new_blocks))
|
||||
print('ok')
|
||||
72
.claude/memory/temp/build_problems_meta.py
Normal file
72
.claude/memory/temp/build_problems_meta.py
Normal file
@@ -0,0 +1,72 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Assemble per-problem teaching data (题目 statement + 参考答案 + 解析要点) for
|
||||
CSP04 lesson 01. Reference code read from C++代码/CSP04/01/*.cpp (GBK)."""
|
||||
import json, io
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent.parent.parent
|
||||
CODE_DIR = ROOT / 'C++代码' / 'CSP04' / '01'
|
||||
|
||||
def read_code(fname):
|
||||
for enc in ('gbk', 'gb18030', 'utf-8'):
|
||||
try:
|
||||
p = CODE_DIR / fname
|
||||
if not p.exists():
|
||||
return ''
|
||||
return io.open(p, encoding=enc).read().strip()
|
||||
except Exception:
|
||||
continue
|
||||
return ''
|
||||
|
||||
# 每题:题目在问什么 + 关键点(解析)
|
||||
PROBLEMS = {
|
||||
'S0401P1': {
|
||||
'title': '小杨的回文串',
|
||||
'statement': '给定一个只含英文字母、大小写混合的字符串,问三件事:①把所有字母统一转小写后,它是不是回文串(是Yes/否No);②原串里有多少个大写字母;③原串里有多少个小写字母。回文就是正读倒读一样,如 abba、abcba。',
|
||||
'key_points': '先统计后转换(统计的是原串的大写/小写个数);大写字母 +32 = 小写字母;用双指针 l/r 向中间夹,发现一次不相等就判否;三行输出顺序是 回文结果/大写个数/小写个数。',
|
||||
'code_file': '小杨的回文串.cpp',
|
||||
},
|
||||
'S0401P2': {
|
||||
'title': '小杨有序去重',
|
||||
'statement': '给定一份非降序的成绩单(相邻可能相等),去掉连续的重复成绩,得到“出现过的不同成绩”列表。用双指针在数组上原地完成:慢指针 j 指向已保留部分的末尾,快指针 i 向后扫,遇到 a[i] ≠ a[j] 就把 a[i] 复制到 a[j+1]。输出两行:去重后的列表;不同成绩的个数。',
|
||||
'key_points': '前提是“有序”,只去相邻重复;比较对象是 a[j](保留区末尾),不是 a[i-1];j 从 1 开始、i 从 2 开始(第一个数无条件保留);n 最大 1e5,必须一遍扫完。',
|
||||
'code_file': '小杨有序去重.cpp',
|
||||
},
|
||||
'S0401P3': {
|
||||
'title': '小杨的进制数位',
|
||||
'statement': '把十进制数 n 转换成 k 进制(2≤k≤16),并统计表示里的字符构成:①k 进制表示(超过 9 的数位用大写 A~F 表示 10~15);②表示中数字字符(0~9)的个数;③表示中字母字符(A~F)的个数。',
|
||||
'key_points': '除 k 取余、余数倒着拼(out = S[余数] + out);查表 “0123456789ABCDEF”;n=0 要特判输出 0;统计的是 k 进制表示里的字符,不是十进制原数。',
|
||||
'code_file': '小杨的进制数位.cpp',
|
||||
},
|
||||
'S0401P4': {
|
||||
'title': '小杨的幸运数字',
|
||||
'statement': '有些正整数的二进制表示里恰好只有 1 个 1(如 1=1、2=10、8=1000),这样的数叫“幸运数”,也就是 2 的幂。给 n 个正整数,统计:①这 n 个数里幸运数的个数;②这 n 个数的二进制表示中 1 的总个数。',
|
||||
'key_points': '对每个数单独数它的 1 的个数(cnt1 每轮要清零);sum 累计的是“1 的个数”,cnt 累计的是“满足条件的数”,别混;1(=2^0)也是幸运数;进阶可用 n&(n-1)==0 判断/__builtin_popcount 数 1。',
|
||||
'code_file': '小杨的幸运数字.cpp',
|
||||
},
|
||||
'S0401P5': {
|
||||
'title': '小杨的报数游戏',
|
||||
'statement': 'n 个小朋友围成一圈,编号 1~n。从 1 号开始沿顺时针从 1 报数,报到 k 的小朋友出列,出列者下一位重新从 1 报数……直到全部出列。按出列顺序输出编号(约瑟夫问题)。',
|
||||
'key_points': '数组 arr[i] 记状态(0 在场/1 出列);只有 arr[idx]==0 的人才报数;报满 k 出列后 cnt 归零、p--;idx 越界就回绕 idx>n→idx=1;边界 k=1 依次出列 1 2 3…n。',
|
||||
'code_file': '小杨的报数游戏.cpp',
|
||||
},
|
||||
}
|
||||
|
||||
out = {}
|
||||
for pid, meta in PROBLEMS.items():
|
||||
code = read_code(meta['code_file'])
|
||||
out[pid] = {
|
||||
'key': pid + ' ' + meta['title'],
|
||||
'title': meta['title'],
|
||||
'statement': meta['statement'],
|
||||
'key_points': meta['key_points'],
|
||||
'code_file': meta['code_file'],
|
||||
'ref_code': code,
|
||||
}
|
||||
|
||||
dest = ROOT / '.claude' / 'memory' / 'temp' / 'problems_meta.json'
|
||||
dest.parent.mkdir(parents=True, exist_ok=True)
|
||||
dest.write_text(json.dumps(out, ensure_ascii=False, indent=2), encoding='utf-8')
|
||||
print('SAVED ->', dest)
|
||||
for pid, meta in out.items():
|
||||
print(pid, 'ref_code_len=', len(meta['ref_code']))
|
||||
140
.claude/memory/temp/fetch_student_code.py
Normal file
140
.claude/memory/temp/fetch_student_code.py
Normal file
@@ -0,0 +1,140 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Fetch final submission code per (student, problem) for CSP04 lesson 01 (基础回顾).
|
||||
Targets both CSP04 sections (0830 & 1400). Saves to JSON.
|
||||
"""
|
||||
import io, sys, json, re, httpx
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
|
||||
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent.parent
|
||||
env = {}
|
||||
for line in (PROJECT_ROOT / '.env').read_text(encoding='utf-8').split('\n'):
|
||||
line = line.strip()
|
||||
if line and not line.startswith('#') and '=' in line:
|
||||
k, v = line.split('=', 1)
|
||||
env[k] = v
|
||||
|
||||
base = env.get('OJ_BASE_URL', 'https://oj.qonnwolf.com')
|
||||
TID = '6a8c6a8b8499477a04169f85' # CSP04 lesson 01 基础回顾 (A包)
|
||||
|
||||
# 数字题目 -> 展示名(参考课件 OJ ID)
|
||||
PID_MAP = {
|
||||
6775: 'S0401P1 小杨的回文串',
|
||||
6776: 'S0401P2 小杨有序去重',
|
||||
6777: 'S0401P3 小杨的进制数位',
|
||||
6968: 'S0401P4 小杨的幸运数字',
|
||||
6969: 'S0401P5 小杨的报数游戏',
|
||||
}
|
||||
|
||||
CLASSES = {
|
||||
'0830': ['欧俊宇', '汪子杰', '谢明泓', '王佳琳', '魏铭轩', '张立坤'],
|
||||
'1400': ['郑子煜', '张雨禾', '苏俊宇', '卢华琛', '鲍佳音'],
|
||||
}
|
||||
ALL_TARGETS = sorted({n for lst in CLASSES.values() for n in lst})
|
||||
|
||||
STATUS_NAMES = {1: 'AC', 2: 'WA', 3: 'CE', 4: 'RE', 5: 'TLE', 6: 'MLE', 7: 'PE', 8: 'OLE'}
|
||||
|
||||
client = httpx.Client(base_url=base, follow_redirects=True, timeout=30)
|
||||
r = client.post('/login', json={'uname': env.get('OJ_USERNAME'), 'password': env.get('OJ_PASSWORD')})
|
||||
ok = any(c.name == 'sid' for c in client.cookies.jar)
|
||||
print('LOGIN:', 'OK' if ok else 'FAIL')
|
||||
if not ok:
|
||||
raise SystemExit('login failed')
|
||||
|
||||
# 1. fetch all records for the homework
|
||||
records = []
|
||||
seen = set()
|
||||
for page in range(1, 40):
|
||||
r = client.get(f'/d/system/record?tid={TID}&page={page}', headers={'Accept': 'application/json'})
|
||||
if r.status_code != 200:
|
||||
break
|
||||
try:
|
||||
rdocs = r.json().get('rdocs', [])
|
||||
except Exception:
|
||||
break
|
||||
if not rdocs:
|
||||
break
|
||||
for rec in rdocs:
|
||||
rid = rec.get('_id')
|
||||
if rid in seen:
|
||||
continue
|
||||
seen.add(rid)
|
||||
records.append({
|
||||
'rid': rid, 'uid': rec.get('uid'), 'pid': rec.get('pid'),
|
||||
'status': rec.get('status'), 'score': rec.get('score', 0),
|
||||
'judgeAt': rec.get('judgeAt', ''), 'lang': rec.get('lang'),
|
||||
})
|
||||
if len(rdocs) < 100:
|
||||
break
|
||||
print('TOTAL RECORDS:', len(records))
|
||||
|
||||
# 2. build uid -> name
|
||||
uids = {rec['uid'] for rec in records}
|
||||
uid_name = {}
|
||||
for uid in sorted(uids):
|
||||
try:
|
||||
rr = client.get(f'/user/{uid}')
|
||||
m = re.search(r'<title>([^<]+)</title>', rr.text)
|
||||
if m:
|
||||
nm = m.group(1).split(' - ')[0].strip()
|
||||
uid_name[uid] = nm
|
||||
except Exception:
|
||||
pass
|
||||
print('UID->NAME mapped:', len(uid_name))
|
||||
for rec in records:
|
||||
rec['name'] = uid_name.get(rec['uid'], '')
|
||||
|
||||
# 3. for each target student, per problem pick the LAST submission (max judgeAt by iso)
|
||||
last_by_key = {}
|
||||
for rec in records:
|
||||
if rec['name'] not in ALL_TARGETS:
|
||||
continue
|
||||
if rec['pid'] not in PID_MAP:
|
||||
continue
|
||||
key = (rec['name'], rec['pid'])
|
||||
if key not in last_by_key or rec['judgeAt'] > last_by_key[key]['judgeAt']:
|
||||
last_by_key[key] = rec
|
||||
print('LAST-SUB keys:', len(last_by_key))
|
||||
|
||||
# 4. fetch code per (name, pid)
|
||||
result = {}
|
||||
sample_shown = 0
|
||||
for (name, pid), rec in last_by_key.items():
|
||||
try:
|
||||
rr = client.get(f"/d/system/record/{rec['rid']}", headers={'Accept': 'application/json'})
|
||||
j = rr.json()
|
||||
rdoc = j.get('rdoc', {})
|
||||
code = rdoc.get('code', '')
|
||||
lang = rdoc.get('lang') or rec.get('lang')
|
||||
except Exception as e:
|
||||
code = ''
|
||||
lang = None
|
||||
entry = {
|
||||
'key': PID_MAP[pid],
|
||||
'code': code,
|
||||
'lang': lang,
|
||||
'status': STATUS_NAMES.get(rec['status'], '?'),
|
||||
'score': rec.get('score'),
|
||||
'attempts': sum(1 for x in records if x['name'] == name and x['pid'] == pid),
|
||||
'judgeAt': rec.get('judgeAt'),
|
||||
}
|
||||
result.setdefault(name, {})[str(pid)] = entry
|
||||
if sample_shown < 2 and code:
|
||||
sample_shown += 1
|
||||
print(f"SAMPLE CODE [{name} / {PID_MAP[pid]}] lang={lang}:\n{code[:300]}")
|
||||
|
||||
client.close()
|
||||
|
||||
out = {
|
||||
'tid': TID,
|
||||
'classes': CLASSES,
|
||||
'pid_map': {str(k): v for k, v in PID_MAP.items()},
|
||||
'students': result,
|
||||
}
|
||||
out_path = PROJECT_ROOT / '.claude' / 'memory' / 'temp' / 'student_code_CSP04_L01.json'
|
||||
out_path.write_text(json.dumps(out, ensure_ascii=False, indent=2), encoding='utf-8')
|
||||
print('SAVED ->', out_path)
|
||||
print('students with code:', sorted(result.keys()))
|
||||
134
.claude/memory/temp/fix_star_slider.py
Normal file
134
.claude/memory/temp/fix_star_slider.py
Normal file
@@ -0,0 +1,134 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Batch fix for 课评汇总 class pages:
|
||||
1) Remove the 评星 (star rating) feature: strip each <div class="metrics">…</div> block,
|
||||
delete star/metric CSS rules, and remove the dead star JS functions.
|
||||
2) Fix the 翻页卡死 (pagination freeze) on carousel pages: switch slides from
|
||||
absolute-stacked opacity to display:none for inactive cards (only the active
|
||||
card is ever laid out/painted), and remove backdrop-filter blur (compositing cost).
|
||||
|
||||
Only applied to the first-week pages when <target> is the folder.
|
||||
"""
|
||||
import os, re, sys
|
||||
|
||||
# ------------- balanced <div class="metrics"> removal -------------
|
||||
def remove_metrics(html):
|
||||
marker = '<div class="metrics">'
|
||||
res = []
|
||||
i = 0
|
||||
n = len(html)
|
||||
while True:
|
||||
idx = html.find(marker, i)
|
||||
if idx == -1:
|
||||
res.append(html[i:])
|
||||
break
|
||||
res.append(html[i:idx])
|
||||
depth = 1
|
||||
j = idx + len(marker)
|
||||
while depth > 0 and j < n:
|
||||
oi = html.find('<div', j)
|
||||
ci = html.find('</div>', j)
|
||||
if ci == -1:
|
||||
j = n
|
||||
break
|
||||
if oi != -1 and oi < ci:
|
||||
depth += 1
|
||||
j = oi + 4
|
||||
else:
|
||||
depth -= 1
|
||||
j = ci + 6
|
||||
i = j
|
||||
return ''.join(res)
|
||||
|
||||
# ------------- balanced CSS block parser -------------
|
||||
def strip_css(css, is_carousel):
|
||||
out = []
|
||||
i = 0
|
||||
n = len(css)
|
||||
while i < n:
|
||||
m = re.match(r'\s+', css[i:])
|
||||
if m:
|
||||
out.append(m.group(0)); i += m.end(); continue
|
||||
m = re.match(r'/\*.*?\*/', css[i:], re.S)
|
||||
if m:
|
||||
out.append(m.group(0)); i += m.end(); continue
|
||||
brace = css.find('{', i)
|
||||
if brace == -1:
|
||||
out.append(css[i:]); break
|
||||
sel = css[i:brace]
|
||||
depth = 1
|
||||
j = brace + 1
|
||||
while depth > 0 and j < n:
|
||||
if css[j] == '{': depth += 1
|
||||
elif css[j] == '}': depth -= 1
|
||||
j += 1
|
||||
body = css[brace+1:j-1]
|
||||
full = css[i:j]
|
||||
selnorm = sel.strip()
|
||||
if selnorm.startswith('@media') or selnorm.startswith('@supports'):
|
||||
out.append(selnorm + '{' + strip_css(body, is_carousel) + '}')
|
||||
elif re.search(r'\.(?:metric|star)', selnorm):
|
||||
pass # drop star / metric rules
|
||||
elif is_carousel and re.match(r'^\.student-card', selnorm):
|
||||
if '.prev' in selnorm:
|
||||
pass # drop the now-unneeded prev-state rule
|
||||
elif '.active' in selnorm:
|
||||
out.append('.student-card.active { display: block; position: relative; pointer-events: auto; }')
|
||||
elif re.match(r'^\.student-card\s*$', selnorm):
|
||||
out.append('.student-card { display: none; }')
|
||||
else:
|
||||
out.append(full) # .student-card:hover
|
||||
else:
|
||||
out.append(full)
|
||||
i = j
|
||||
return ''.join(out)
|
||||
|
||||
def process_styles(html, is_carousel):
|
||||
def repl(m):
|
||||
css = strip_css(m.group(2), is_carousel)
|
||||
css = re.sub(r'backdrop-filter\s*:\s*blur\([^)]*\);?', '', css)
|
||||
return m.group(1) + css + m.group(3)
|
||||
return re.sub(r'(<style[^>]*>)(.*?)(</style>)', repl, html, flags=re.S)
|
||||
|
||||
# ------------- dead star JS removal -------------
|
||||
def remove_function(js, name):
|
||||
pat = re.compile(r'function\s+' + re.escape(name) + r'\s*\(')
|
||||
m = pat.search(js)
|
||||
if not m:
|
||||
return js
|
||||
brace = js.find('{', m.end())
|
||||
if brace == -1:
|
||||
return js
|
||||
depth = 1
|
||||
j = brace + 1
|
||||
n = len(js)
|
||||
while depth > 0 and j < n:
|
||||
if js[j] == '{': depth += 1
|
||||
elif js[j] == '}': depth -= 1
|
||||
j += 1
|
||||
return js[:m.start()] + js[j:]
|
||||
|
||||
def remove_call(js, name):
|
||||
return re.sub(r'^[ \t]*' + re.escape(name) + r'\(\).*?$', '', js, flags=re.M)
|
||||
|
||||
def fix(html):
|
||||
is_carousel = 'id="cardsSlider"' in html
|
||||
html = remove_metrics(html)
|
||||
html = process_styles(html, is_carousel)
|
||||
if 'function initStarRatings' in html and 'initStarRatings' in html:
|
||||
html = remove_call(html, 'initStarRatings')
|
||||
html = remove_function(html, 'initStarRatings')
|
||||
html = remove_function(html, 'setStarRating')
|
||||
return html
|
||||
|
||||
def main(files):
|
||||
for path in files:
|
||||
with open(path, encoding='utf-8') as f:
|
||||
html = f.read()
|
||||
out = fix(html)
|
||||
changed = out != html
|
||||
with open(path, 'w', encoding='utf-8') as f:
|
||||
f.write(out)
|
||||
print(('CHANGED ' if changed else 'same ') + os.path.basename(path))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv[1:])
|
||||
155
.claude/memory/temp/inject_prob_details.py
Normal file
155
.claude/memory/temp/inject_prob_details.py
Normal file
@@ -0,0 +1,155 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Inject a collapsible 题目讲解 panel (题目 / 孩子代码 / 答案 / 解析) into each
|
||||
student's OJ section on the two CSP04 class pages (0830 & 1400). Additive only.
|
||||
|
||||
Usage: python inject_prob_details.py <page1.html> <page2.html> ...
|
||||
"""
|
||||
import sys, os, json, html, re, copy
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent.parent.parent
|
||||
TMP = ROOT / '.claude' / 'memory' / 'temp'
|
||||
CODE = json.load(open(TMP / 'student_code_CSP04_L01.json', encoding='utf-8'))
|
||||
META = json.load(open(TMP / 'problems_meta.json', encoding='utf-8'))
|
||||
|
||||
# display prefix -> numeric pid (as used in fetched codes)
|
||||
PIDNUM = {v.split(' ')[0]: k for k, v in CODE['pid_map'].items()}
|
||||
PROB_ORDER = ['S0401P1', 'S0401P2', 'S0401P3', 'S0401P4', 'S0401P5']
|
||||
|
||||
STATUS_TXT = {'AC': '✅ 已通过 AC', 'WA': '❌ 答案错误 WA', 'CE': '❌ 编译错误 CE',
|
||||
'RE': '❌ 运行错误 RE', 'TLE': '❌ 超时 TLE', 'PE': '⚠️ 格式错误 PE', 'MLE': '❌ 超内存 MLE'}
|
||||
|
||||
CSS_BLOCK = '''
|
||||
/* ===== 题目讲解(题目/孩子代码/答案/解析) ===== */
|
||||
.oj-explains{margin-top:16px;}
|
||||
.oj-explains-title{font-size:0.9em;font-weight:600;color:var(--ink);margin-bottom:8px;display:flex;align-items:center;gap:6px;}
|
||||
.prob-detail{border:1px solid var(--border);border-radius:10px;margin-bottom:8px;overflow:hidden;background:var(--cream);}
|
||||
.prob-head{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:10px 14px;cursor:pointer;font-size:0.85em;}
|
||||
.prob-head:hover{background:var(--paper-warm);}
|
||||
.prob-title{font-weight:600;color:var(--ink);}
|
||||
.prob-sub{font-size:0.74em;color:var(--ink-soft);flex:1;text-align:right;}
|
||||
.prob-caret{font-size:0.85em;color:var(--ink-soft);transition:transform 0.2s ease;}
|
||||
.prob-detail.open .prob-caret{transform:rotate(90deg);}
|
||||
.prob-body{display:none;padding:12px 14px;border-top:1px solid var(--border);}
|
||||
.prob-detail.open .prob-body{display:block;}
|
||||
.prob-sec{margin-bottom:12px;}
|
||||
.prob-sec:last-child{margin-bottom:0;}
|
||||
.prob-sec-h{font-size:0.78em;font-weight:700;color:var(--ink-soft);margin-bottom:5px;}
|
||||
.prob-sec-c{font-size:0.83em;line-height:1.75;color:var(--ink-soft);background:var(--paper);border-radius:8px;padding:8px 11px;}
|
||||
.prob-code{background:#1b2733;color:#e6eef7;border-radius:8px;padding:10px 12px;font-size:0.76em;line-height:1.6;overflow:auto;white-space:pre;max-height:240px;font-family:Consolas,'Courier New',monospace;}
|
||||
/* 未提交 -> 课后作业(不展开、不做分析) */
|
||||
.prob-detail.homework{background:var(--paper-warm);border-style:dashed;}
|
||||
.prob-detail.homework .prob-head{cursor:default;}
|
||||
.prob-detail.homework .prob-sub{color:#a8842c;font-weight:600;}
|
||||
'''
|
||||
|
||||
JS_BLOCK = '\n function toggleProb(el){el.classList.toggle("open");var c=el.querySelector(".prob-caret");if(c)c.textContent=el.classList.contains("open")?"▼":"▶";}\n'
|
||||
|
||||
|
||||
def esc(t):
|
||||
return html.escape(str(t))
|
||||
|
||||
|
||||
def build_panels(student):
|
||||
panels = ['<div class="oj-explains">',
|
||||
'<div class="oj-explains-title">📖 题目讲解(已提交的题 · 题目 / 孩子代码 / 参考答案 / 解析)</div>']
|
||||
codes = CODE['students'].get(student, {})
|
||||
for pid in PROB_ORDER:
|
||||
meta = META.get(pid)
|
||||
if not meta:
|
||||
continue
|
||||
entry = codes.get(PIDNUM.get(pid, ''), {})
|
||||
code = entry.get('code', '')
|
||||
status = entry.get('status', '')
|
||||
attempts = entry.get('attempts', 0)
|
||||
if code:
|
||||
sub = '%s · %d次提交' % (STATUS_TXT.get(status, status), attempts)
|
||||
panels.append(
|
||||
'<div class="prob-detail" onclick="toggleProb(this)">'
|
||||
'<div class="prob-head">'
|
||||
'<span class="prob-title">%s</span>'
|
||||
'<span class="prob-sub">%s</span>'
|
||||
'<span class="prob-caret">▶</span>'
|
||||
'</div>'
|
||||
'<div class="prob-body">'
|
||||
'<div class="prob-sec"><div class="prob-sec-h">📋 题目</div><div class="prob-sec-c">%s</div></div>'
|
||||
'<div class="prob-sec"><div class="prob-sec-h">👦 孩子的代码</div><pre class="prob-code">%s</pre></div>'
|
||||
'<div class="prob-sec"><div class="prob-sec-h">✅ 参考答案</div><pre class="prob-code">%s</pre></div>'
|
||||
'<div class="prob-sec"><div class="prob-sec-h">💡 解析</div><div class="prob-sec-c">%s</div></div>'
|
||||
'</div></div>' % (esc(meta['key']), sub, esc(meta['statement']), esc(code), esc(meta['ref_code']), esc(meta['key_points'])))
|
||||
else:
|
||||
# 未提交 -> 只标为课后作业,不做分析
|
||||
panels.append(
|
||||
'<div class="prob-detail homework">'
|
||||
'<div class="prob-head">'
|
||||
'<span class="prob-title">%s</span>'
|
||||
'<span class="prob-sub">📚 未提交 · 课后作业</span>'
|
||||
'</div></div>' % esc(meta['key']))
|
||||
panels.append('</div>')
|
||||
return '\n'.join(panels)
|
||||
|
||||
|
||||
def find_oj_section(html, start):
|
||||
"""Return end index (after the matching </div>) for the oj-section starting at `start`."""
|
||||
n = len(html)
|
||||
depth = 1
|
||||
i = start + len('<div class="oj-section"')
|
||||
while depth > 0 and i < n:
|
||||
o = html.find('<div', i)
|
||||
c = html.find('</div>', i)
|
||||
if c == -1:
|
||||
return -1
|
||||
if o != -1 and o < c:
|
||||
depth += 1
|
||||
i = o + 4
|
||||
else:
|
||||
depth -= 1
|
||||
i = c + 6
|
||||
return i
|
||||
|
||||
|
||||
def inject_style(html, css):
|
||||
idx = html.rfind('</style>')
|
||||
if idx == -1:
|
||||
return html
|
||||
return html[:idx] + css + html[idx:]
|
||||
|
||||
|
||||
def inject_script(html, js):
|
||||
idx = html.rfind('</script>')
|
||||
if idx == -1:
|
||||
return html
|
||||
return html[:idx] + js + html[idx:]
|
||||
|
||||
|
||||
def process(html):
|
||||
# inject CSS/JS once
|
||||
if '.prob-detail' not in html:
|
||||
html = inject_style(html, CSS_BLOCK)
|
||||
if 'function toggleProb' not in html:
|
||||
html = inject_script(html, JS_BLOCK)
|
||||
# inject panels per student oj-section (insert RIGHT-TO-LEFT so earlier
|
||||
# positions stay valid after the html string changes length)
|
||||
pat = re.compile(r'<div class="oj-section" data-oj-section="([^"]+)">')
|
||||
matches = [(m.group(1), m.start()) for m in pat.finditer(html)]
|
||||
for name, start in reversed(matches):
|
||||
end = find_oj_section(html, start)
|
||||
if end == -1:
|
||||
continue
|
||||
closing = end - 6 # position of the </div> that closes oj-section
|
||||
panels = build_panels(name)
|
||||
html = html[:closing] + panels + '\n' + html[closing:]
|
||||
return html
|
||||
|
||||
|
||||
def main(files):
|
||||
for p in files:
|
||||
orig = open(p, encoding='utf-8').read()
|
||||
out = process(orig)
|
||||
changed = out != orig
|
||||
open(p, 'w', encoding='utf-8').write(out)
|
||||
print(('CHANGED ' if changed else 'same ') + os.path.basename(p))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv[1:])
|
||||
62
.claude/memory/temp/oj_probe.py
Normal file
62
.claude/memory/temp/oj_probe.py
Normal file
@@ -0,0 +1,62 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Probe OJ: login, list records for lesson-01 tid, and test whether a single
|
||||
record exposes the submission code. Prints discoveries."""
|
||||
import io, sys, re, json, httpx
|
||||
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
|
||||
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
|
||||
from pathlib import Path
|
||||
|
||||
env = {}
|
||||
for line in (Path('.env')).read_text(encoding='utf-8').split('\n'):
|
||||
line = line.strip()
|
||||
if line and not line.startswith('#') and '=' in line:
|
||||
k, v = line.split('=', 1)
|
||||
env[k] = v
|
||||
|
||||
base = env.get('OJ_BASE_URL', 'https://oj.qonnwolf.com')
|
||||
TID = '6a8c6a8b8499477a04169f85' # CSP04 lesson 01 基础回顾
|
||||
|
||||
client = httpx.Client(base_url=base, follow_redirects=True, timeout=30)
|
||||
r = client.post('/login', json={'uname': env.get('OJ_USERNAME'), 'password': env.get('OJ_PASSWORD')})
|
||||
ok = any(c.name == 'sid' for c in client.cookies.jar)
|
||||
print('LOGIN:', 'OK' if ok else 'FAIL', 'status', r.status_code)
|
||||
if not ok:
|
||||
raise SystemExit('login failed')
|
||||
|
||||
# 1. record list via JSON API
|
||||
r = client.get(f'/d/system/record?tid={TID}&page=1', headers={'Accept': 'application/json'})
|
||||
print('RECORD LIST status', r.status_code)
|
||||
try:
|
||||
data = r.json()
|
||||
except Exception as e:
|
||||
print('NOT JSON:', r.text[:300])
|
||||
data = {}
|
||||
rdocs = data.get('rdocs', [])
|
||||
print('rdocs count', len(rdocs))
|
||||
if rdocs:
|
||||
rec = rdocs[0]
|
||||
print('RECORD KEYS:', sorted(rec.keys()))
|
||||
for k in ('_id','uid','pid','score','status','judgeAt','code'):
|
||||
print(' ', k, '=', repr(rec.get(k))[:80])
|
||||
# pick the record that has a code-like field or pick any
|
||||
sample = rec
|
||||
rid = sample.get('_id')
|
||||
print('USING rid =', rid, 'pid =', sample.get('pid'))
|
||||
# 2. try single-record detail endpoints
|
||||
for ep in (f'/d/system/record/{rid}', f'/record/{rid}', f'/d/system/submission/{rid}'):
|
||||
try:
|
||||
rr = client.get(ep, headers={'Accept': 'application/json'})
|
||||
txt = rr.text
|
||||
has_code = 'code' in txt or '"code"' in txt
|
||||
print(f'DETAIL {ep} status={rr.status_code} has_code_field={has_code} len={len(txt)}')
|
||||
try:
|
||||
j = rr.json()
|
||||
keys = sorted(j.keys()) if isinstance(j, dict) else 'list'
|
||||
print(' detail keys:', keys if isinstance(keys, list) else keys)
|
||||
if isinstance(j, dict) and 'code' in j:
|
||||
print(' CODE snippet:', repr(j['code'])[:200])
|
||||
except Exception:
|
||||
print(' (not json) snippet:', txt[:160].replace('\n',' '))
|
||||
except Exception as e:
|
||||
print(' DETAIL err', ep, e)
|
||||
client.close()
|
||||
42
.claude/memory/temp/problems_meta.json
Normal file
42
.claude/memory/temp/problems_meta.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"S0401P1": {
|
||||
"key": "S0401P1 小杨的回文串",
|
||||
"title": "小杨的回文串",
|
||||
"statement": "给定一个只含英文字母、大小写混合的字符串,问三件事:①把所有字母统一转小写后,它是不是回文串(是Yes/否No);②原串里有多少个大写字母;③原串里有多少个小写字母。回文就是正读倒读一样,如 abba、abcba。",
|
||||
"key_points": "先统计后转换(统计的是原串的大写/小写个数);大写字母 +32 = 小写字母;用双指针 l/r 向中间夹,发现一次不相等就判否;三行输出顺序是 回文结果/大写个数/小写个数。",
|
||||
"code_file": "小杨的回文串.cpp",
|
||||
"ref_code": "#include <bits/stdc++.h>\n#define endl '\\n'\nusing namespace std;\n\nstring s;\nint cnt1, cnt2; // cnt1大写 cnt2小写 \n\nint main(){\n\tcin >> s;\n\t\n\tint len = s.size();\n\tfor(int i = 0; i < len; i++){\n\t\t// 先数小写的个数 \n\t\tif(islower(s[i])){\n\t\t\tcnt2++;\n\t\t} \n\t\t// 再数大写的个数 \n\t\tif(isupper(s[i])){\n\t\t\tcnt1++;\n\t\t\t// 转换成小写\n\t\t\ts[i] = s[i] + 32; \n\t\t}\n\t}\n\t\n\tint l = 0, r = len - 1;\n\tbool ok = true;\n\twhile(l <= r){\n\t\tif(s[l] != s[r]){\n\t\t\tok = false;\n\t\t\tbreak;\n\t\t}\n\t\tl++, r--;\n\t}\n\t\n\tif(ok){\n\t\tcout << \"Yes\";\n\t} else {\n\t\tcout << \"No\";\n\t}\n\t\n\tcout << endl << cnt1 << endl << cnt2;\n\treturn 0;\n}"
|
||||
},
|
||||
"S0401P2": {
|
||||
"key": "S0401P2 小杨有序去重",
|
||||
"title": "小杨有序去重",
|
||||
"statement": "给定一份非降序的成绩单(相邻可能相等),去掉连续的重复成绩,得到“出现过的不同成绩”列表。用双指针在数组上原地完成:慢指针 j 指向已保留部分的末尾,快指针 i 向后扫,遇到 a[i] ≠ a[j] 就把 a[i] 复制到 a[j+1]。输出两行:去重后的列表;不同成绩的个数。",
|
||||
"key_points": "前提是“有序”,只去相邻重复;比较对象是 a[j](保留区末尾),不是 a[i-1];j 从 1 开始、i 从 2 开始(第一个数无条件保留);n 最大 1e5,必须一遍扫完。",
|
||||
"code_file": "小杨有序去重.cpp",
|
||||
"ref_code": "#include <bits/stdc++.h>\n#define endl '\\n'\nusing namespace std;\n\nconst int MAXN = 100010;\nint n;\nint arr[MAXN];\n\nint main(){\n\n cin >> n;\n for(int i = 1; i <= n; i++){\n cin >> arr[i];\n }\n\n if(n == 0){\n cout << endl << 0 << endl;\n return 0;\n }\n \t\n\tint j = 1; // 慢指针\n\tfor(int i = 2; i <= n; i++){\n\t\t// i表示快指针,一直向后移动\n\t\tif(arr[i] == arr[j]) continue;\n\t\t// 如果不相同\n\t\tarr[j+1] = arr[i];\n\t\tj++; \n\t} \n\t\n\tfor(int i = 1; i <= j; i++){\n\t\tcout << arr[i] << \" \";\n\t}\n\tcout << endl << j;\n return 0;\n}"
|
||||
},
|
||||
"S0401P3": {
|
||||
"key": "S0401P3 小杨的进制数位",
|
||||
"title": "小杨的进制数位",
|
||||
"statement": "把十进制数 n 转换成 k 进制(2≤k≤16),并统计表示里的字符构成:①k 进制表示(超过 9 的数位用大写 A~F 表示 10~15);②表示中数字字符(0~9)的个数;③表示中字母字符(A~F)的个数。",
|
||||
"key_points": "除 k 取余、余数倒着拼(out = S[余数] + out);查表 “0123456789ABCDEF”;n=0 要特判输出 0;统计的是 k 进制表示里的字符,不是十进制原数。",
|
||||
"code_file": "小杨的进制数位.cpp",
|
||||
"ref_code": "#include <bits/stdc++.h>\n#define endl '\\n'\nusing namespace std;\n\nint num, k;\nstring out;\nstring S = \"0123456789ABCDEF\";\nint cnt1 = 0,cnt2 = 0;\n\nint main(){\n\tcin >> num >> k;\n\t\n\tif(num == 0){\n\t\tcout << 0 << endl << 1 << endl << 0;\n\t\treturn 0;\n\t}\n\t\n\tint t = num;\n\twhile(t > 0){\n\t\tint g = t % k;\n\t\t\n\t\tout = S[g] + out;\n\t\t\n\t\tt /= k;\n\t}\n\t\n\tfor(char c : out){\n\t\tif(isupper(c)){\n\t\t\tcnt2++;\n\t\t}else if(isdigit(c)){\n\t\t\tcnt1++;\n\t\t}\n\t}\n\tcout << out << endl << cnt1 << endl << cnt2;\n\treturn 0;\n}"
|
||||
},
|
||||
"S0401P4": {
|
||||
"key": "S0401P4 小杨的幸运数字",
|
||||
"title": "小杨的幸运数字",
|
||||
"statement": "有些正整数的二进制表示里恰好只有 1 个 1(如 1=1、2=10、8=1000),这样的数叫“幸运数”,也就是 2 的幂。给 n 个正整数,统计:①这 n 个数里幸运数的个数;②这 n 个数的二进制表示中 1 的总个数。",
|
||||
"key_points": "对每个数单独数它的 1 的个数(cnt1 每轮要清零);sum 累计的是“1 的个数”,cnt 累计的是“满足条件的数”,别混;1(=2^0)也是幸运数;进阶可用 n&(n-1)==0 判断/__builtin_popcount 数 1。",
|
||||
"code_file": "小杨的幸运数字.cpp",
|
||||
"ref_code": "#include <bits/stdc++.h>\n#define endl '\\n'\nusing namespace std;\n\nint n, num, cnt = 0, sum = 0;\nstring str = \"01\";\n\nint main() {\n\tcin >> n;\n\n\tfor(int i = 1; i <= n; i++) {\n\t\tcin >> num;\n\t\tint t = num;\n\t\t\n\t\tstring out = \"\";\n\t\tint cnt1 = 0;// 判断1的个数 \n\t\t\n\t\twhile(t > 0) {\n\t\t\tint g = t % 2;\n\t\t\t\n\t\t\tif(g == 1){\n\t\t\t\tsum++; // 总数加一 \n\t\t\t\tcnt1++; // 个数加一 \n\t\t\t}\n\t\t\t\n\t\t\tout = str[g] + out;\n\t\t\tt /= 2;\n\t\t}\n\t\t\n\t\tif(cnt1 == 1){\n\t\t\tcnt++; \n\t\t} \n\t}\n\t\n\tcout << cnt << endl << sum;\n\n\n\treturn 0;\n}"
|
||||
},
|
||||
"S0401P5": {
|
||||
"key": "S0401P5 小杨的报数游戏",
|
||||
"title": "小杨的报数游戏",
|
||||
"statement": "n 个小朋友围成一圈,编号 1~n。从 1 号开始沿顺时针从 1 报数,报到 k 的小朋友出列,出列者下一位重新从 1 报数……直到全部出列。按出列顺序输出编号(约瑟夫问题)。",
|
||||
"key_points": "数组 arr[i] 记状态(0 在场/1 出列);只有 arr[idx]==0 的人才报数;报满 k 出列后 cnt 归零、p--;idx 越界就回绕 idx>n→idx=1;边界 k=1 依次出列 1 2 3…n。",
|
||||
"code_file": "小杨的报数游戏.cpp",
|
||||
"ref_code": "#include <iostream>\nusing namespace std;\n\nint main() {\n\tint n, k;\n\tcin >> n >> k;\n\tint arr[110] = {0}; // 0表示当前这个同学还在,1表示这个同学出列了\n\tint idx = 1; // 表示当前这个叫到第几个同学\n\tint cnt = 0; // 本轮报数的计数器\n\tint p = n; // 当前人数 \n\t\n\twhile(p != 0){\n\t\t// 先判断当前这个人是不是出列了\n\t\tif(arr[idx] == 0){\n\t\t\tcnt++;\n\t\t\tif(cnt == k){\n\t\t\t\t// 这个人出列\n\t\t\t\tcout << idx << \" \"; // 当前这个人出列\n\t\t\t\tarr[idx] = 1; // 修改当前这个人出列状态\n\t\t\t\tp--;\n\t\t\t\tcnt = 0; \n\t\t\t}\n\t\t} \n\t\tidx++;\n\t\tif(idx > n){\n\t\t\tidx = 1;\n\t\t}\n\t} \n\treturn 0;\n}"
|
||||
}
|
||||
}
|
||||
11
.claude/memory/temp/spotcheck.py
Normal file
11
.claude/memory/temp/spotcheck.py
Normal file
@@ -0,0 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import io, re, sys
|
||||
f = sys.argv[1]; name = sys.argv[2]
|
||||
c = io.open(f, encoding='utf-8').read()
|
||||
i = c.find('data-oj-section="%s"' % name)
|
||||
j = c.find('oj-explains', i)
|
||||
seg = c[j:j+1800]
|
||||
seg = re.sub(r'<[^>]+>', ' ', seg)
|
||||
seg = re.sub(r'\s+', ' ', seg)
|
||||
print('--- %s 题目讲解(前段) ---' % name)
|
||||
print(seg)
|
||||
330
.claude/memory/temp/student_code_CSP04_L01.json
Normal file
330
.claude/memory/temp/student_code_CSP04_L01.json
Normal file
@@ -0,0 +1,330 @@
|
||||
{
|
||||
"tid": "6a8c6a8b8499477a04169f85",
|
||||
"classes": {
|
||||
"0830": [
|
||||
"欧俊宇",
|
||||
"汪子杰",
|
||||
"谢明泓",
|
||||
"王佳琳",
|
||||
"魏铭轩",
|
||||
"张立坤"
|
||||
],
|
||||
"1400": [
|
||||
"郑子煜",
|
||||
"张雨禾",
|
||||
"苏俊宇",
|
||||
"卢华琛",
|
||||
"鲍佳音"
|
||||
]
|
||||
},
|
||||
"pid_map": {
|
||||
"6775": "S0401P1 小杨的回文串",
|
||||
"6776": "S0401P2 小杨有序去重",
|
||||
"6777": "S0401P3 小杨的进制数位",
|
||||
"6968": "S0401P4 小杨的幸运数字",
|
||||
"6969": "S0401P5 小杨的报数游戏"
|
||||
},
|
||||
"students": {
|
||||
"汪子杰": {
|
||||
"6968": {
|
||||
"key": "S0401P4 小杨的幸运数字",
|
||||
"code": "#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n int n;\n cin >> n;\n int sum1 = 0, sum2 = 0;\n for (int i = 0; i < n; i++) {\n int x = 0;\n cin >> x;\n \n \n int t = x;\n while (t % 2 == 0) {\n t /= 2;\n }\n if (t == 1) sum1++;\n \n while (x > 0) {\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n sum2 += x & 1;\n x >>= 1;\n }\n }\n cout<<sum1<<endl;\n cout<<sum2<<endl;\n return 0;\n}\n\n\n\n\n\n\n",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 2,
|
||||
"judgeAt": "2026-09-06T05:54:19.538Z"
|
||||
},
|
||||
"6777": {
|
||||
"key": "S0401P3 小杨的进制数位",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\nstring s;\nint n,k;\nint sh,z;\nstring str=\"0123456789ABCDEF\";\nint main(){\n\tcin>>n>>k;\n\tint t=n;\n\tif(n==0){\n\t\tcout<<0<<endl<<1<<endl<<0;\n\t\treturn 0;\n\t}\n\twhile(t>0){\n\t\tint g=t%k;\n\t\tif(g<=9){\n\t\t\tsh++;\t\n\t\t}else{\n\t\t\tz++;\n\t\t}\n\t\ts=str[g]+s;\n\t\tt/=k;\n\t}\n\tcout<<s<<endl;\n\tcout<<sh<<endl;\n\tcout<<z;\n\treturn 0;\n}",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 2,
|
||||
"judgeAt": "2026-09-05T02:54:53.592Z"
|
||||
},
|
||||
"6776": {
|
||||
"key": "S0401P2 小杨有序去重",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\nint n;\nint a[101000];\nint cnt1=0,cnt2=0;\nint main(){\n\tcin>>n;\n\tfor(int i=1;i<=n;i++){\n\t\tcin>>a[i];\n\t}\n\tint j=1;\n\tfor(int i=2;i<=n;i++){\n\t\tif(a[i]!=a[j]){\n\t\t\ta[j+1]=a[i];\n\t\t\tj++;\n\t\t}\n\t\t\n\t}\n\tfor(int i=1;i<=j;i++){\n\t\tcout<<a[i]<<\" \"; \n\t}\n\t\n\tcout<<endl<<j;\n\t\n\treturn 0;\n}\n",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 2,
|
||||
"judgeAt": "2026-09-05T02:25:01.427Z"
|
||||
},
|
||||
"6775": {
|
||||
"key": "S0401P1 小杨的回文串",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\nstring s;\nstring neww;\nint cnt1=0,cnt2=0;\nint main(){\n\tcin>>s;\n\tint n=s.size();\n\tfor(int i=0;i<=n-1;i++){\n\t\tchar c=s[i];\n\t\tif(c>='A'&&c<='Z'){\n\t\t\tcnt1++;\n\t\t\tc=c+32;\n\t\t}else if(c>='a'&&c<='z'){\n\t\t\tcnt2++; \n\t\t}\n\t\tneww+=c;\n\t}\n\n\t\n\tint l=0,r=s.size()-1;\n\tbool ok=true;\n\twhile(l<=r){\n\t\tif(neww[l]!=neww[r]){\n\t\t\tok=false;\n\t\t\tbreak;\n\t\t}\n\t\tl++,r--;\n\t}\n\t\n\t\n\tif(ok!=0){\n\t\tcout<<\"Yes\"<<endl;\n\t}else{\n\t\tcout<<\"No\"<<endl;\n\t}\n\tcout<<cnt1<<endl;\n\tcout<<cnt2;\n\t\n\t\n\treturn 0;\n}",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 3,
|
||||
"judgeAt": "2026-09-05T01:54:20.081Z"
|
||||
}
|
||||
},
|
||||
"卢华琛": {
|
||||
"6777": {
|
||||
"key": "S0401P3 小杨的进制数位",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\nint n,k,c1 = 0,c2 = 0;\nstring str = \"0123456789ABCDEF\" , s; \nint main(){\n\tcin >> n >> k;\n\tif(n == 0){\n\t\tcout << 0 << endl;\n\t\tcout << 1 << endl;\n\t\tcout << 0 << endl;\n\t\treturn 0;\n\t}\n\tint t = n;\n\twhile(t > 0){\n\t\tint g = t % k;\n\t\tif(g >= 10){\n\t\t\tc1++;\n\t\t}else{\n\t\t\tc2++;\n\t\t}\n\t\ts = str[g] + s;\n\t\tt /= k;\n\t}\n\tcout << s << endl;\n\tcout << c2 << endl;\n\tcout << c1 << endl;\n\treturn 0;\n}",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 2,
|
||||
"judgeAt": "2026-09-06T04:27:56.437Z"
|
||||
},
|
||||
"6776": {
|
||||
"key": "S0401P2 小杨有序去重",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\nint n;\nint arr[100010];\nint main(){\n\tcin >> n;\n\tfor(int i = 1; i <= n; i++){\n\t\tcin >> arr[i];\n\t}\n\tint j = 1;\n\tfor(int i = 2; i <= n; i++){\n\t\tif(arr[j] != arr [i]){\n\t\t\tarr[j + 1] = arr[i];\n\t\t\tj++;\n\t\t}\n\t}\n\tfor(int i = 1; i <= j; i++){\n\t\tcout << arr[i] << \" \";\n\t}\n\tcout << endl << j;\n\treturn 0;\n}",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 1,
|
||||
"judgeAt": "2026-09-06T03:45:54.958Z"
|
||||
},
|
||||
"6775": {
|
||||
"key": "S0401P1 小杨的回文串",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\nstring s;\nint a1 = 0, a2 = 0;\nint main(){\n\tcin >> s;\n\tint len = s.size(); \n\tfor(int i = 0;i <= len - 1;i++){\n\t\tchar c = s[i];\n\t\tif(c >= 'A' && c <= 'Z'){\n\t\t\ta1++;\n\t\t\ts[i] = c - 'A' + 'a';\n\t\t}else if(c >= 'a' && c <= 'z'){\n\t\t\ta2++;\n\t\t}\n\t}\n\tint l = 0, r = len - 1;\n\tbool o = true;\n\twhile(l <= r){\n\t\tif(s[l] != s[r]){\n\t\to = false;\n\t\tbreak;\n\t\t}\n\t\tl++,r--;\n\t}\n\tif(o == true){\n\t\tcout << \"Yes\" << endl;\n\t}else{\n\t\tcout << \"No\" << endl;\n\t}\n\tcout << a1 << endl;\n\tcout << a2 << endl;\n\treturn 0;\n}",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 1,
|
||||
"judgeAt": "2026-09-06T03:20:43.028Z"
|
||||
}
|
||||
},
|
||||
"欧俊宇": {
|
||||
"6969": {
|
||||
"key": "S0401P5 小杨的报数游戏",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\nint main(){\n int a,b;\n cin>>a>>b;\n int d[110];\n for(int i=0;i<=a-1;i++){\n \td[i]=i+1;\n\t}\n\tint l=a; \n int p=0;\n\twhile(l>0){\n p=(p+b-1)%l;\n cout<<d[p]<<\" \";\n\n \n for(int i=p;i<=l-2;i++){\n d[i]=d[i+1];\n }\n l--;\n }\n \n\treturn 0;\n}\n",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 1,
|
||||
"judgeAt": "2026-09-05T12:23:44.711Z"
|
||||
},
|
||||
"6968": {
|
||||
"key": "S0401P4 小杨的幸运数字",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\nint main(){\n int n;\n cin>>n;\n int lucky=0; \n int one=0; \n for(int i=1;i<=n;i++){\n int x;\n cin>>x;\n\n int c=0; \n int t=x;\n\n while(t>0){\n if(t%2==1){\n c=c+1;\n }\n t/=2; \n }\n\n one=one+c; \n\n if(c==1){\n lucky+=1;\n }\n }\n\n cout<<lucky<<endl<<one;\n \n return 0;\n}\n",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 1,
|
||||
"judgeAt": "2026-09-05T11:53:23.849Z"
|
||||
},
|
||||
"6777": {
|
||||
"key": "S0401P3 小杨的进制数位",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\nint n,k;\nstring s;\nint sh,z;\nstring str=\"0123456789ABCDEFG\";\nint main(){\n cin>>n>>k;\n int t=n;\n if(n==0){\n \tcout<<0<<endl<<1<<endl<<0;\n \treturn 0;\n\t}\n while(t>0){\n \tint g=t%k;\n\t\tif(g<=9){\n\t\t\tsh++;\n\t\t} else{\n\t\t\tz++;\n\t\t}\n\t\ts=str[g]+s;\n\t\tt/=k;\n\t}\n\tcout<<s<<endl;\n\tcout<<sh<<endl;\n\tcout<<z;\n\treturn 0;\n}\n",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 1,
|
||||
"judgeAt": "2026-09-05T02:56:50.501Z"
|
||||
},
|
||||
"6776": {
|
||||
"key": "S0401P2 小杨有序去重",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\nint n,a[110000];\nint main(){\n\tcin>>n;\n\tfor(int i=1;i<=n;i++){\n\t\tcin>>a[i];\n\t}\n\tint j=1;\n\tfor(int i=2;i<=n;i++){\n\t\tif(a[i]!=a[j]){\n\t\t\ta[j+1]=a[i];\n\t\t\tj++;\n\t\t}\n\t}\n\tfor(int i=1;i<=j;i++){\n\t\tcout<<a[i]<<\" \";\n\t}\n\tcout<<endl<<j;\n\treturn 0;\n}\n",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 2,
|
||||
"judgeAt": "2026-09-05T02:30:47.942Z"
|
||||
},
|
||||
"6775": {
|
||||
"key": "S0401P1 小杨的回文串",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\nint main(){\n\tstring a;\n\tcin>>a;\n\tint b=a.size()-1;\n\tbool c=true;\n\tint ad=0;\n\tint ax=0;\n\tfor(int i=0;i<=b;i++){\n\t\tif(a[i]>='a'&&a[i]<='z'){\n\t\t\tax++;\n\t\t}\n\t\tif(a[i]>='A'&&a[i]<='Z'){\n\t\t\tad++;\n\t\t}\n\t\tif(a[i]>='A'&&a[i]<='Z'){\n\t\t\ta[i]+=32;\n\t\t}\n\t}\n\t\n\t\n\tfor(int j=0;j<=b/2;j++){\n\t\tint n=a[j];\n\t\tint m=a[b-j];\n\t\tif(n!=m){\n\t\t\tc=false;\n\t\t\t\n\t\t}\n\t}\n\tif(c==1){\n\t\tcout<<\"Yes\"<<endl;\n\t}else{\n\t\tcout<<\"No\"<<endl;\n\t}\n\tcout<<ad<<endl;\n\tcout<<ax;\n\treturn 0;\n}\n",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 2,
|
||||
"judgeAt": "2026-09-05T01:42:05.562Z"
|
||||
}
|
||||
},
|
||||
"张雨禾": {
|
||||
"6777": {
|
||||
"key": "S0401P3 小杨的进制数位",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\nint n;\nint main(){\n\tint n,k,cnt1=0,cnt2=0;\n\tstring s;\n\tstring str=\"0123456789ABCDEF0\";\n\tcin>>n>>k;\n\t\n\tif(n==0){\n\t\tcout<<0<<endl<<1<<endl<<0;\n\t\treturn 0;\n\t}\n\t\n\tint t=n;\n\tint g;\n\twhile(t>0){\n\t\t g=t%k;\n\t\tif(g>9){\n\t\t\tcnt2++;\n\t\t}else{\n\t\t\tcnt1++;\n\t\t}\n\t\ts=str[g]+s;\n\t\n\tt/=k;\n\t\n\t}\n\t\n\tcout<<s<<endl<<cnt1<<endl<<cnt2;\n\t\n\treturn 0;\n}",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 1,
|
||||
"judgeAt": "2026-09-05T08:00:02.371Z"
|
||||
},
|
||||
"6776": {
|
||||
"key": "S0401P2 小杨有序去重",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\nint n;\nint arr[1000100]; \n \nint main(){\n\tcin>>n;\n\tfor(int i=1;i<=n;i++){\n\t\tcin>>arr[i];\n\t}\n\t\n\tint j=1;\n\tfor(int i=2;i<=n;i++){\n\t\tif(arr[i]!=arr[j]){\n\t\t\tarr[j+1]=arr[i];\n\t\t\tj++;\n\t\t}\n\t}\n\t\n\t\n\tfor(int i=1;i<=j;i++){\n\t\tcout<<arr[i]<<\" \";\n\t}\n\tcout<<endl<<j;\n\treturn 0;\n}",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 2,
|
||||
"judgeAt": "2026-09-05T07:21:43.279Z"
|
||||
},
|
||||
"6775": {
|
||||
"key": "S0401P1 小杨的回文串",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\nstring s;\nint da,xiao;\n\nint main(){\n\tcin>>s;\n\tint len = s.size();\n\tfor(int i = 0;i < len; i++){\n\t\tchar c=s[i];\n\t\tif(c>='A'&&c<='Z'){\n\t\t\tda++;\n\t\t\ts[i]=c-'A'+'a'; \n\t\t}else if(c>='a'&&c<='z'){\n\t\t\txiao++;\n\t\t}\n\t}\n\t\n\t\n\tint l=0,r=len-1;\n\tbool ok=true;\n\twhile(l<=r){\n\t\tif(s[l] !=s[r]){\n\t\t\tok=false;\n\t\t\tbreak;\n\t\t}\n\t\tr--,l++;\n\t}\n\t\n\tif(ok==true){\n\t\tcout<<\"Yes\";\n\t}else{\n\t\tcout<<\"No\";\n\t}\n\tcout<<endl;\n\tcout<<da<<endl;\n\tcout<<xiao<<endl;\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\n\treturn 0;\n}",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 2,
|
||||
"judgeAt": "2026-09-05T06:43:25.148Z"
|
||||
}
|
||||
},
|
||||
"郑子煜": {
|
||||
"6777": {
|
||||
"key": "S0401P3 小杨的进制数位",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\nstring op=\"123456789ABCDEF\";\nint main (){\n\tint x, y, num = 0;\n\tstring n;\n\tcin >> x >> y >> n;\n\tint len = n.size();\n\tfor(int i=0; i<len; i++){\n\t\tint g;\n\t\tif(n[i] >= 'A'){\n\t\t\tg = n[i] - 'A'+10;\n\t\t}\n\t\telse{\n\t\t\tg = n[i]-'0';\n\t\t}\n\t\tnum = num*x + g;\n\t}\n\tint t=num;\n\tstring ans = \" \";\n\twhile(t > 0){\n\t\tint g= t % y;\n\t\tans = op[g] + ans;\n\t\tt/=y;\n\t}\n\tcout << ans;\n\treturn 0;\n}",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "WA",
|
||||
"score": 0,
|
||||
"attempts": 1,
|
||||
"judgeAt": "2026-09-05T07:58:50.666Z"
|
||||
},
|
||||
"6775": {
|
||||
"key": "S0401P1 小杨的回文串",
|
||||
"code": "#include <bits/stdc++.h>\nusing namespace std;\n\nint main()\n{\n\tint cnt1=0,cnt2=0;\n\tstring s;\n\tcin >> s;\n int len = s.size();\n for(int i = 0; i < len;i++){\n \tchar c = s[i];\n \tif(c >= 'A' && c <= 'Z'){\n \t\tcnt1++;\n \t\ts[i] = c - 'A' + 'a';\n\t\t}else if(c >= 'a' && c <= 'z'){\n\t\t\tcnt2++;\n\t\t}\n\t\t\n\t}\n\tint l = 0,r = len - 1;\n\tbool ok = true;\n\twhile(l <= r ){\n\t\t\tif(s[l] != s[r]){\n\t\t\t\tok = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tl++,r--;\n\t\t}\n\tif(ok){\n\t\tcout << \"Yes\";\n\t}else\n\t \tcout << \"No\";\n\t \tcout << endl;\n\t \tcout << cnt1 << endl;\n\t\tcout << cnt2 << endl;\n return 0;\n\n} \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 2,
|
||||
"judgeAt": "2026-09-05T07:55:11.601Z"
|
||||
}
|
||||
},
|
||||
"鲍佳音": {
|
||||
"6777": {
|
||||
"key": "S0401P3 小杨的进制数位",
|
||||
"code": "#include <bits/stdc++.h>\nusing namespace std;\nint n,k,c1,c2;\nstring s,s1=\"0123456789ABCDEF\";\nint main(){\n\tcin>>n>>k;\n\tif(n==0){\n\t\tcout<<0<<endl<<1<<endl<<0;\n\t\treturn 0;\n\t}\n\tint t=n;\n\twhile(t>0){\n\t\tint g=t%k;\n\t\tif(g>9){\n\t\t\tc2++;\n\t\t}else{\n\t\t\tc1++;\n\t\t}\n\t\ts=s1[g]+s;\n\t\tt/=k;\n\t}\n cout<<s<<endl<<c1<<endl<<c2;\n return 0;\n}",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 1,
|
||||
"judgeAt": "2026-09-05T07:55:31.183Z"
|
||||
},
|
||||
"6776": {
|
||||
"key": "S0401P2 小杨有序去重",
|
||||
"code": "#include <bits/stdc++.h>\nusing namespace std;\nint a[1000010],n,js;\nint main(){\n\tcin>>n;\n\tfor(int i=1;i<=n;i++){\n\t\tcin>>a[i];\n\t}\n\tint j=1;\n\tfor(int i=2;i<=n;i++){\n\t\tif(a[i]!=a[j]){\n\t\t\ta[j+1]=a[i];\n\t\t\tj++;\n\t }\n\t}\n\t\n\tfor(int i=1;i<=j;i++){\n\t\tcout<<a[i]<<\" \";\n\t}\n\tcout<<endl<<j;\n\treturn 0;\n}",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 2,
|
||||
"judgeAt": "2026-09-05T07:21:35.839Z"
|
||||
},
|
||||
"6775": {
|
||||
"key": "S0401P1 小杨的回文串",
|
||||
"code": "#include <bits/stdc++.h>\nusing namespace std;\nint d,x;\nstring s,a; \nint main(){\n\tcin>>s;\n\tfor(int i=0;i<s.size();i++){\n\t\tif(s[i]>='a'&&s[i]<='z') x++;\n\t\telse if(s[i]>='A'&&s[i]<='Z'){\n\t\t\td++;\n\t\t\ts[i]=s[i]-'A'+'a';\n\t\t};\n\t}\n\ta=s;\n\treverse(a.begin(),a.end());\n\tif(s==a){\n\t\tcout<<\"Yes\"<<endl;\n\t}else{\n\t\tcout<<\"No\"<<endl;\n\t}\n\tcout<<d<<endl<<x;\n\n\treturn 0;\n}",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 2,
|
||||
"judgeAt": "2026-09-05T06:35:05.876Z"
|
||||
}
|
||||
},
|
||||
"苏俊宇": {
|
||||
"6776": {
|
||||
"key": "S0401P2 小杨有序去重",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\nint n;\nint arr[1000100];\nint main(){\n\tcin>>n;\n\tfor(int i=1;i<=n;i++){\n\t\tcin>>arr[i];\n\t}\n\t\n\tint j=1;\n\tfor(int i=2;i<=n;i++){\n\t\tif(arr[i]!=arr[j]){\n\t\t\tarr[j+1]=arr[i];\n\t\t\tj++; \n\t\t}\n\t}\n\t\n\tfor(int i=1;i<=j;i++){\n\t\tcout<<arr[i]<<\" \";\n\t}\n\tcout<<endl<<j;\n\treturn 0;\n} ",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 1,
|
||||
"judgeAt": "2026-09-05T07:33:04.703Z"
|
||||
},
|
||||
"6775": {
|
||||
"key": "S0401P1 小杨的回文串",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\nint cnt1,cnt2;\nstring s;\nint main(){\n\tcin>>s;\n\tint len=s.size();\n\t\n\tfor(int i=0;i<len;i++){\n\t\tchar c=s[i];\n\t\tif(c>='A'&&'Z'>=c){\n\t\t\tcnt1++;\n\t\t\ts[i]=c-'A'+'a'; \n\t\t}else if('a'<=c&&'z'>=c){\n\t\t\tcnt2++;\n\t\t}\n\t}\n\t\n\tint l=0,r=len-1;\n\tbool ok=true;\n\twhile(l<=r){\n\t\tif(s[l]!=s[r]){\n\t\t\tok=false;\n\t\t\tbreak;\n\t\t}\n\t\tl++,r--;\n\t}\n\t\n\tif(ok){\n\t\tcout<<\"Yes\"<<endl<<cnt1<<endl<<cnt2;\n\t}else{\n\t\tcout<<\"No\"<<endl<<cnt1<<endl<<cnt2;\n\t}\n\treturn 0;\n} ",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 1,
|
||||
"judgeAt": "2026-09-05T07:15:29.944Z"
|
||||
}
|
||||
},
|
||||
"王佳琳": {
|
||||
"6777": {
|
||||
"key": "S0401P3 小杨的进制数位",
|
||||
"code": "#include <bits/stdc++.h> \nusing namespace std;\nint n,k,cnt1=0,cnt2=0;\nstring s;\nstring str=\"0123456789ABCDEF\";\nint main(){\n\tcin>>n>>k;\n\tif(n==0){\n\t\tcout<<0<<endl<<1<<endl<<0;\n\t\treturn 0;\n\t}\n\tint t=n;\n\twhile(t>0){\n\t\tint g=t%k;\n\t\tif(g<=9){\n\t\t\tcnt1++;\n\t\t}else{\n\t\t\tcnt2++;\n\t\t}\n\t\ts=str[g]+s;\n\t\tt/=k;\n\t}\n\tcout<<s<<endl;\n\tcout<<cnt1<<endl<<cnt2;\n\treturn 0;\n}\n\t\n\t\t\n\t",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 3,
|
||||
"judgeAt": "2026-09-05T03:18:13.216Z"
|
||||
},
|
||||
"6776": {
|
||||
"key": "S0401P2 小杨有序去重",
|
||||
"code": "#include <bits/stdc++.h> \nusing namespace std;\nint n;\nint arr[100010];\nint main(){\n\tcin>>n;\n\tfor(int i=1;i<=n;i++){\n\t\tcin>>arr[i];\n\t}\n\tint j=1;\n\tfor(int i=2;i<=n;i++){\n\t\tif(arr[i] != arr[j]){\n\t\t\tarr[j+1]=arr[i];\n\t\t\tj++;\n\t\t}\n\t}\n\tfor(int i=1; i<=j;i++){\n\t\n\t\tcout<<arr[i]<<\" \";\n\t}\n\tcout<<endl<<j;\n}\n\t\n\t\t\n\t",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 5,
|
||||
"judgeAt": "2026-09-05T02:48:35.600Z"
|
||||
},
|
||||
"6775": {
|
||||
"key": "S0401P1 小杨的回文串",
|
||||
"code": "#include <bits/stdc++.h> \nusing namespace std;\nstring n,t;\nint cnt1,cnt2;\nint main(){\n\t\n\tcin>>n;\n\tfor(int i=0;i<n.size();i++){\n\t\tchar c=n[i];\n\t\tif(n[i]>='A' && n[i]<='Z'){\n\t\t\tcnt1++;\n\t\t\tc=c-'A'+'a';\n\t\t\t\n\t\t}else if(n[i]>='a' && n[i]<='z'){\n\t\t\tcnt2++;\n\t\t}\n\t\tt+=c;\n\t}\n\tint l=0,r=n.size()-1;\n\tbool ok=true;\n\twhile(l<=r){\n\t\tif(t[l] != t[r]){\n\t\t\tok=0;\n\t\t\tbreak;\n\t\t}\n\t\tl++,r--;\n\t}\n\tif(ok){\n\t\tcout<<\"Yes\"<<endl;\n\t}else{\n\t\tcout<<\"No\"<<endl;\n\t}\n\t\n\tcout<<cnt1<<endl;\n\tcout<<cnt2<<endl;\n}",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 2,
|
||||
"judgeAt": "2026-09-05T02:03:00.115Z"
|
||||
}
|
||||
},
|
||||
"谢明泓": {
|
||||
"6777": {
|
||||
"key": "S0401P3 小杨的进制数位",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\n\nint main(){\n int n,k;\n cin >> n >> k;\n if(n == 0){\n \tcout << 0 << endl << 1 << endl << 0;\n \treturn 0;\n\t}\n string s = \"\";\n string st = \"0123456789ABCDEF\";\n int t = n,sum = 0,cnt = 0;\n while(t){\n \tint g = t%k;\n \tif(g <= 9)sum++;\n \telse cnt++;\n \ts = st[g] + s;\n \tt /= k;\n\t}cout << s << endl << sum << endl << cnt;\n\treturn 0;\n}",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 5,
|
||||
"judgeAt": "2026-09-05T02:49:29.829Z"
|
||||
},
|
||||
"6776": {
|
||||
"key": "S0401P2 小杨有序去重",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\nint l[100100];\nint main(){\n int n;\n cin >> n;\n for(int i = 1;i <= n;i++)\n \tcin >> l[i];\n int j = 1;\n for(int i = 2;i <= n;i++){\n \tif(l[i] != l[j]){\n \t\tl[j+1] = l[i];\n \t\tj++;\n\t\t}\n\t}\n\tfor(int i = 1;i <= j;i++)\n\t\tcout << l[i] << \" \";\n\tcout << endl << j;\n\treturn 0;\n}",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 1,
|
||||
"judgeAt": "2026-09-05T02:20:26.121Z"
|
||||
},
|
||||
"6775": {
|
||||
"key": "S0401P1 小杨的回文串",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\n\nint main(){\n\tstring s;\n\tcin >> s;\n\tint sum = 0,cnt = 0;\n\tstring n = s;\n\tfor(int i = 0;i < s.size();i++){\n\t\tif(isupper(s[i])){\t\n\t\t\ts[i] = tolower(s[i]);\n\t\t\tsum++;\n\t\t}\n\t\telse if(islower(s[i]))cnt++;\n\t}\n\tbool b = true;\n\tfor(int i = 0;i <= s.size()/2;i++){\n\t\tif(s[i] != s[s.size()-1-i]){\n\t\t\tb = false;\n\t\t\tcout << \"No\" << endl;\n\t\t\tbreak;\n\t\t}\n\t}if(b)cout << \"Yes\" << endl;\n\tcout << sum << endl << cnt;\n\treturn 0;\n}",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 1,
|
||||
"judgeAt": "2026-09-05T01:48:24.232Z"
|
||||
}
|
||||
},
|
||||
"张立坤": {
|
||||
"6776": {
|
||||
"key": "S0401P2 小杨有序去重",
|
||||
"code": "#include <bits/stdc++.h>\nusing namespace std;\nint d,x,n,a[100010];\nint main(){\n\tcin>>n;\n\tfor(int i=1;i<=n;i++){\n\t\tcin>>a[i];\n\t}\n\tint j=1;\n\tfor(int i=2;i<=n;i++){\n\t\tif(a[i]!=a[j]){\n\t\t\ta[j+1]=a[i];\n\t\t\tj++;\n\t\t}\n\t}\n\tfor(int i=1;i<=j;i++){\n\t\tcout<<a[i]<<\" \";\n\t}\n\tcout<<endl<<j;\n} ",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 2,
|
||||
"judgeAt": "2026-09-05T02:21:21.152Z"
|
||||
},
|
||||
"6775": {
|
||||
"key": "S0401P1 小杨的回文串",
|
||||
"code": "#include <bits/stdc++.h>\nusing namespace std;\nstring s,a;\nint d,x;\nint main(){\n\tcin>>s;\n\tfor(int i=0;i<=s.size()-1;i++){\n\t\tif(char(s[i])>='A'&&char(s[i])<='Z'){\n\t\t\td++;\n\t\t\ts[i]=char(int(s[i])+32);\n\t\t}\n\t\telse if(char(s[i])>='a'&&char(s[i])<='z'){\n\t\t\tx++;\n\t\t}\n\t}\n\tint l=0,r=s.size()-1;\n\tbool ok=true;\n\twhile(l<=r){\n\t\tif(s[l]!=s[r]){\n\t\t\tok=false;\n\t\t\tbreak;\n\t\t}\n\t\tl++,r--;\n\t}\n\tif(ok==1){\n\t\tcout<<\"Yes\"<<endl<<d<<endl<<x;\n\t}\n\telse{\n\t\tcout<<\"No\"<<endl<<d<<endl<<x;\n\t}\n\t\n} ",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "AC",
|
||||
"score": 100,
|
||||
"attempts": 3,
|
||||
"judgeAt": "2026-09-05T01:47:08.198Z"
|
||||
}
|
||||
},
|
||||
"魏铭轩": {
|
||||
"6775": {
|
||||
"key": "S0401P1 小杨的回文串",
|
||||
"code": "#include<bits/stdc++.h>\nusing namespace std;\nint cnt2=0;\nint cnt1=0;\nstring neww;\nchar ch[1010];\nstring s;\nint main(){\n\tgetline(cin,s);\n\tint len=s.size();\n\tfor(int i=0;i<len;i++){\n\t\tchar S=s[i];\n\t\tif(S>='A'&&S<='Z'){\n\t\t\tS=S+32;\n\t\t\tcnt1++;\n\t\t}else if(S>='a'&&S<='z'){\n\t\t\tcnt2++;\n\t\t}\n\t\tneww+=s;\n\t}\n\tint l=0,r=s.size()-1\n\tbool ok=tyue;\n\twhile(l<=r){\n\t\tif(neww[l]!=neww[r]){\n\t\t\tok=fales;\n\t\t\tbreak;\n\t\t}\n\t\t\n\n\t\t\n\t}\n\tl++,r--;\n\tcout<<ok;",
|
||||
"lang": "cc.cc14o2",
|
||||
"status": "PE",
|
||||
"score": 0,
|
||||
"attempts": 1,
|
||||
"judgeAt": "2026-09-05T02:00:56.839Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
24
.claude/memory/temp/verify_final_csp.py
Normal file
24
.claude/memory/temp/verify_final_csp.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import io, re, sys
|
||||
for f in sys.argv[1:]:
|
||||
c = io.open(f, encoding='utf-8').read()
|
||||
print('===', f.replace('\\', '/').split('/')[-1])
|
||||
print(' oj-explains:', c.count('class="oj-explains"'),
|
||||
'| prob-detail:', c.count('class="prob-detail"'),
|
||||
'| prob-sec-h:', c.count('class="prob-sec-h"'))
|
||||
print(' ★star leftover:', c.count('star-rating'), c.count('class="star '),
|
||||
'| backdrop-filter:', c.count('backdrop-filter'))
|
||||
print(' student-card display:none:', '.student-card { display: none; }' in c,
|
||||
'| active block:', '.student-card.active { display: block; position: relative; pointer-events: auto; }' in c)
|
||||
opens = c.count('<div'); closes = c.count('</div>')
|
||||
print(' div balance:', opens, '/', closes, 'OK' if opens == closes else 'MISMATCH')
|
||||
mjs = re.search(r'<script[^>]*>(.*)</script>', c, re.S)
|
||||
js = mjs.group(1)
|
||||
print(' js braces:', js.count('{'), '/', js.count('}'),
|
||||
'parens:', js.count('('), '/', js.count(')'))
|
||||
print(' toggleProb present:', 'function toggleProb' in c)
|
||||
# which student owns first panel
|
||||
m = re.search(r'data-oj-section="([^"]+)">', c)
|
||||
first_stu = m.group(1) if m else '?'
|
||||
idx = c.find(first_stu)
|
||||
print(' first student:', first_stu)
|
||||
18
.claude/memory/temp/verify_fix.py
Normal file
18
.claude/memory/temp/verify_fix.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os, sys, re
|
||||
folder = os.path.abspath(sys.argv[1]) if len(sys.argv) > 1 else os.getcwd()
|
||||
files = [f for f in os.listdir(folder) if f.endswith('.html') and f != '总览.html']
|
||||
for name in sorted(files):
|
||||
p = os.path.join(folder, name)
|
||||
with open(p, encoding='utf-8') as f:
|
||||
c = f.read()
|
||||
star_html = (len(c.split('<div class="metrics">')) - 1) + c.count('class="star ') + c.count('class="star-rating')
|
||||
star_css = len(re.findall(r'\.star-rating \{|\.metric-item \{|\.metric-label \{|\.star \{|\.star\.filled|\.half-filled\.', c))
|
||||
star_js = len(re.findall(r'function initStarRatings|function setStarRating|initStarRatings\(\);', c))
|
||||
bf = c.count('backdrop-filter')
|
||||
car = 'id="cardsSlider"' in c
|
||||
sc_dn = '.student-card { display: none; }' in c
|
||||
opens = c.count('<div'); closes = c.count('</div>')
|
||||
bal = 'OK' if opens == closes else 'MISMATCH %d/%d' % (opens, closes)
|
||||
print('%-46s carousel=%-5s starHTML=%d starCSS=%d starJS=%d backdrop=%d scdn=%s div=%s' % (
|
||||
name, car, star_html, star_css, star_js, bf, sc_dn if car else 'n/a(scroll)', bal))
|
||||
18
.claude/memory/temp/verify_inject.py
Normal file
18
.claude/memory/temp/verify_inject.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import io, re, sys
|
||||
for f in sys.argv[1:]:
|
||||
c = io.open(f, encoding='utf-8').read()
|
||||
opens = c.count('<div'); closes = c.count('</div>')
|
||||
print('===', f.replace('\\', '/').split('/')[-1])
|
||||
print(' oj-explains blocks:', c.count('class="oj-explains"'))
|
||||
print(' prob-detail panels:', c.count('class="prob-detail"'))
|
||||
print(' oj-sections:', c.count('data-oj-section='))
|
||||
print(' CSS present:', '.prob-detail {' in c)
|
||||
print(' toggleProb:', 'function toggleProb' in c)
|
||||
print(' prob-sec-h count:', c.count('class="prob-sec-h"'))
|
||||
print(' div balance:', opens, '/', closes, 'OK' if opens == closes else 'MISMATCH')
|
||||
# sample first panel body
|
||||
m = re.search(r'<div class="oj-explains">(.*?)</div>\s*\n', c, re.S)
|
||||
if m:
|
||||
blk = m.group(1)
|
||||
print(' sample has 题目:', '📋 题目' in blk, '| 孩子代码:', '👦 孩子的代码' in blk, '| 答案:', '✅ 参考答案' in blk, '| 解析:', '💡 解析' in blk)
|
||||
23
.claude/memory/temp/verify_inject2.py
Normal file
23
.claude/memory/temp/verify_inject2.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import io, sys
|
||||
for f in sys.argv[1:]:
|
||||
c = io.open(f, encoding='utf-8').read()
|
||||
print('===', f.replace('\\', '/').split('/')[-1])
|
||||
for label, needle in [
|
||||
('CSS .prob-detail', '.prob-detail{border'),
|
||||
('CSS .prob-body', '.prob-body{display:none'),
|
||||
('CSS .prob-code', '.prob-code{background'),
|
||||
('📋 题目', '📋 题目'),
|
||||
('👦 孩子的代码', '👦 孩子的代码'),
|
||||
('✅ 参考答案', '✅ 参考答案'),
|
||||
('💡 解析', '💡 解析'),
|
||||
('题目讲解标题', '题目讲解'),
|
||||
]:
|
||||
print(' %-18s count=%d' % (label, c.count(needle)))
|
||||
# show a real panel sample (find first prob-body, strip tags for a peek)
|
||||
import re
|
||||
m = re.search(r'<div class="prob-body">(.*?)</div></div></div>', c, re.S)
|
||||
if m:
|
||||
txt = re.sub(r'<[^>]+>', ' ', m.group(1))
|
||||
txt = re.sub(r'\s+', ' ', txt)
|
||||
print(' first-panel text snippet:', txt[:180])
|
||||
41
.claude/memory/temp/verify_structure.py
Normal file
41
.claude/memory/temp/verify_structure.py
Normal file
@@ -0,0 +1,41 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import io, re, sys
|
||||
|
||||
def find_oj_section(html, start):
|
||||
n = len(html)
|
||||
depth = 1
|
||||
i = start + len('<div class="oj-section"')
|
||||
while depth > 0 and i < n:
|
||||
o = html.find('<div', i)
|
||||
c = html.find('</div>', i)
|
||||
if c == -1:
|
||||
return -1
|
||||
if o != -1 and o < c:
|
||||
depth += 1
|
||||
i = o + 4
|
||||
else:
|
||||
depth -= 1
|
||||
i = c + 6
|
||||
return i
|
||||
|
||||
for f in sys.argv[1:]:
|
||||
c = io.open(f, encoding='utf-8').read()
|
||||
pat = re.compile(r'<div class="oj-section" data-oj-section="([^"]+)">')
|
||||
print('===', f.replace('\\', '/').split('/')[-1])
|
||||
total_panels = 0
|
||||
bad = []
|
||||
for m in pat.finditer(c):
|
||||
name = m.group(1)
|
||||
end = find_oj_section(c, m.start())
|
||||
blk = c[m.start():end]
|
||||
expl = blk.count('class="oj-explains"')
|
||||
panels = blk.count('class="prob-detail"')
|
||||
total_panels += panels
|
||||
if expl != 1 or panels != 5:
|
||||
bad.append('%s: expl=%d panels=%d' % (name, expl, panels))
|
||||
print(' oj-sections:', c.count('data-oj-section='), '| total prob-detail:', total_panels)
|
||||
if bad:
|
||||
print(' MISMATCH blocks:', bad)
|
||||
else:
|
||||
print(' OK: every student has exactly 1 题目讲解 block with 5 panels')
|
||||
print(' div balance:', c.count('<div'), '/', c.count('</div>'))
|
||||
36
.claude/memory/temp/verify_structure2.py
Normal file
36
.claude/memory/temp/verify_structure2.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import io, re, sys
|
||||
|
||||
def find_oj_section(html, start):
|
||||
n = len(html)
|
||||
depth = 1
|
||||
i = start + len('<div class="oj-section"')
|
||||
while depth > 0 and i < n:
|
||||
o = html.find('<div', i)
|
||||
c = html.find('</div>', i)
|
||||
if c == -1:
|
||||
return -1
|
||||
if o != -1 and o < c:
|
||||
depth += 1
|
||||
i = o + 4
|
||||
else:
|
||||
depth -= 1
|
||||
i = c + 6
|
||||
return i
|
||||
|
||||
for f in sys.argv[1:]:
|
||||
c = io.open(f, encoding='utf-8').read()
|
||||
pat = re.compile(r'<div class="oj-section" data-oj-section="([^"]+)">')
|
||||
print('===', f.replace('\\', '/').split('/')[-1])
|
||||
for m in pat.finditer(c):
|
||||
name = m.group(1)
|
||||
end = find_oj_section(c, m.start())
|
||||
blk = c[m.start():end]
|
||||
expl = blk.count('class="oj-explains"')
|
||||
full = blk.count('class="prob-detail" onclick')
|
||||
hw = blk.count('class="prob-detail homework"')
|
||||
mark = 'OK' if (expl == 1 and full + hw == 5) else 'BAD'
|
||||
print(' %-4s expl=%d full=%d homework=%d %s' % (name, expl, full, hw, mark))
|
||||
print(' total homework-note count:', c.count('未提交 · 课后作业'))
|
||||
print(' div balance:', c.count('<div'), '/', c.count('</div>'),
|
||||
'OK' if c.count('<div') == c.count('</div>') else 'MISMATCH')
|
||||
Reference in New Issue
Block a user