Function bodies 29 total
apply_ux function · python · L70-L109 (40 LOC)apply_elearning_ux.py
def apply_ux():
# 1. Create the custom SCSS file
with open("custom_elearning.scss", "w", encoding="utf-8") as f:
f.write(scss_content)
print("Created custom_elearning.scss")
# 2. Update _quarto.yml
if os.path.exists("_quarto.yml"):
with open("_quarto.yml", "r", encoding="utf-8") as f:
lines = f.readlines()
new_lines = []
in_html_section = False
css_added = False
nav_added = False
for line in lines:
new_lines.append(line)
if line.strip() == "html:":
in_html_section = True
if in_html_section:
# Add CSS reference if not exists
if line.strip().startswith("theme:") and not css_added:
new_lines.append(" css: custom_elearning.scss\n")
css_added = True
# Add page-navigation if not exists
if line.strip().startswith("toc:") and not nav_added:
getProgress function · javascript · L41-L46 (6 LOC)custom.js
function getProgress() {
try {
const raw = localStorage.getItem(STORAGE_KEY);
return raw ? JSON.parse(raw) : {};
} catch (_) { return {}; }
}markWeekDone function · javascript · L48-L56 (9 LOC)custom.js
function markWeekDone(weekId) {
try {
const p = getProgress();
if (!p[weekId]) {
p[weekId] = { done: true, ts: Date.now() };
localStorage.setItem(STORAGE_KEY, JSON.stringify(p));
}
} catch (_) {}
}getCompletedCount function · javascript · L58-L60 (3 LOC)custom.js
function getCompletedCount() {
return Object.keys(getProgress()).length;
}isWeekDone function · javascript · L62-L64 (3 LOC)custom.js
function isWeekDone(weekId) {
return !!getProgress()[weekId];
}detectWeekId function · javascript · L67-L75 (9 LOC)custom.js
function detectWeekId() {
const path = window.location.pathname;
for (const [folder, id] of Object.entries(WEEK_MAP)) {
if (path.includes(folder)) return id;
}
// Fallback: match Week_NN pattern
const m = path.match(/Week_(\d{2})/);
return m ? `week_${m[1]}` : null;
}loadConfetti function · javascript · L78-L87 (10 LOC)custom.js
function loadConfetti() {
return new Promise((resolve) => {
if (window.confetti) { resolve(window.confetti); return; }
const s = document.createElement('script');
s.src = CONFETTI_CDN;
s.onload = () => resolve(window.confetti);
s.onerror = () => resolve(null); // graceful degradation
document.head.appendChild(s);
});
}Repobility (the analyzer behind this table) · https://repobility.com
fireCelebration function · javascript · L90-L117 (28 LOC)custom.js
async function fireCelebration() {
const confetti = await loadConfetti();
if (!confetti) return;
const defaults = { zIndex: 9999, disableForReducedMotion: true };
function burst(ratio, opts) {
confetti(Object.assign({}, defaults, opts, {
particleCount: Math.floor(200 * ratio),
}));
}
burst(0.25, { spread: 26, startVelocity: 55, origin: { y: 0.6 } });
burst(0.20, { spread: 60, origin: { y: 0.65 } });
burst(0.35, { spread: 100, decay: 0.91, scalar: 0.8, origin: { y: 0.7 } });
burst(0.10, { spread: 120, startVelocity: 25, decay: 0.92, scalar: 1.2, origin: { y: 0.75 } });
burst(0.10, { spread: 120, startVelocity: 45, origin: { y: 0.6 } });
// Bonus side bursts
setTimeout(() => {
confetti(Object.assign({}, defaults, {
particleCount: 60, angle: 60, spread: 55, origin: { x: 0, y: 0.65 }
}));
confetti(Object.assign({}, defaults, {
particleCount: 60, angle: 120, spread: 55, origin: { x: burst function · javascript · L96-L100 (5 LOC)custom.js
function burst(ratio, opts) {
confetti(Object.assign({}, defaults, opts, {
particleCount: Math.floor(200 * ratio),
}));
}buildProgressBar function · javascript · L120-L139 (20 LOC)custom.js
function buildProgressBar(compact = false) {
const done = getCompletedCount();
const pct = Math.round((done / TOTAL_WEEKS) * 100);
const stars = done >= 22 ? ' 🌟' : done >= 15 ? ' ⭐' : done >= 7 ? ' 🔥' : '';
return `
<div id="econlab-progress-container">
<div id="econlab-progress-header">
<span id="econlab-progress-label">📊 ההתקדמות שלך${stars}</span>
<span id="econlab-progress-text">${done}/${TOTAL_WEEKS} שבועות</span>
</div>
<div id="econlab-progress-bar-bg">
<div id="econlab-progress-bar" style="width:${pct}%"></div>
</div>
<div id="econlab-progress-footer">
<span>${pct === 0 ? 'בואו נתחיל! 💪' : pct === 100 ? '🎉 השלמת את הקורס!' : `${pct}% הושלם`}</span>
<span style="opacity:0.75;font-size:0.7rem">מתאפס עם ניקוי Cache</span>
</div>
</div>`;
}injectProgressBar function · javascript · L142-L169 (28 LOC)custom.js
function injectProgressBar() {
// Don't double-inject
if (document.getElementById('econlab-progress-container')) return;
const html = buildProgressBar();
const wrap = document.createElement('div');
wrap.innerHTML = html;
// Try sidebar first, then fallback positions
const targets = [
'#quarto-sidebar .sidebar-menu-container',
'#quarto-sidebar',
'.sidebar-nav',
'.sidebar',
];
for (const sel of targets) {
const el = document.querySelector(sel);
if (el) {
el.insertBefore(wrap.firstElementChild, el.firstChild);
return;
}
}
// Last resort: top of page
const main = document.querySelector('#quarto-content') || document.querySelector('main');
if (main) main.insertBefore(wrap.firstElementChild, main.firstChild);
}injectGlobalProgressBar function · javascript · L172-L176 (5 LOC)custom.js
function injectGlobalProgressBar() {
const wrapper = document.getElementById('econlab-global-progress-wrapper');
if (!wrapper) return;
wrapper.innerHTML = buildProgressBar();
}refreshProgressUI function · javascript · L179-L195 (17 LOC)custom.js
function refreshProgressUI() {
const done = getCompletedCount();
const pct = Math.round((done / TOTAL_WEEKS) * 100);
const bar = document.getElementById('econlab-progress-bar');
const text = document.getElementById('econlab-progress-text');
const foot = document.querySelector('#econlab-progress-footer span:first-child');
const label = document.getElementById('econlab-progress-label');
if (bar) bar.style.width = pct + '%';
if (text) text.textContent = `${done}/${TOTAL_WEEKS} שבועות`;
if (foot) foot.textContent = pct === 100 ? '🎉 השלמת את הקורס!' : `${pct}% הושלם`;
if (label) {
const stars = done >= 22 ? ' 🌟' : done >= 15 ? ' ⭐' : done >= 7 ? ' 🔥' : '';
label.textContent = `📊 ההתקדמות שלך${stars}`;
}
}buildFinishButton function · javascript · L198-L215 (18 LOC)custom.js
function buildFinishButton(weekId) {
const done = isWeekDone(weekId);
return `
<div id="econlab-finish-container">
<hr style="margin-bottom:1.5rem;opacity:0.15;">
${done ? `
<button id="econlab-finish-btn" class="completed" disabled>
✅ שבוע זה הושלם!
</button>
<p class="econlab-completed-msg">כל הכבוד! המשיכו לשבוע הבא 🚀</p>
` : `
<button id="econlab-finish-btn" onclick="window.__econlab.finishWeek()">
✅ סיימתי את השבוע!
</button>
<p class="econlab-finish-desc">לחצו לאחר השלמת כל המשימות — תקבלו ציון ו-XP!</p>
`}
</div>`;
}injectFinishButton function · javascript · L218-L242 (25 LOC)custom.js
function injectFinishButton() {
if (document.getElementById('econlab-finish-container')) return;
const weekId = detectWeekId();
if (!weekId) return;
const html = buildFinishButton(weekId);
const wrap = document.createElement('div');
wrap.innerHTML = html;
const targets = [
'.page-navigation',
'#quarto-content',
'main .container-fluid',
'main',
];
for (const sel of targets) {
const el = document.querySelector(sel);
if (el) {
el.parentNode.insertBefore(wrap.firstElementChild, el);
return;
}
}
}Want fix-PRs on findings? Install Repobility's GitHub App · github.com/apps/repobility-bot
handleFinishWeek function · javascript · L245-L275 (31 LOC)custom.js
async function handleFinishWeek() {
const weekId = detectWeekId();
if (!weekId || isWeekDone(weekId)) return;
markWeekDone(weekId);
// Update button immediately
const btn = document.getElementById('econlab-finish-btn');
const container = document.getElementById('econlab-finish-container');
if (btn) {
btn.disabled = true;
btn.textContent = '✅ שבוע זה הושלם!';
btn.classList.add('completed');
}
if (container) {
const desc = container.querySelector('.econlab-finish-desc');
if (desc) desc.remove();
if (!container.querySelector('.econlab-completed-msg')) {
const msg = document.createElement('p');
msg.className = 'econlab-completed-msg';
msg.textContent = 'כל הכבוד! המשיכו לשבוע הבא 🚀';
container.appendChild(msg);
}
}
refreshProgressUI();
await fireCelebration();
}enhanceCodeCopyButtons function · javascript · L278-L292 (15 LOC)custom.js
function enhanceCodeCopyButtons() {
// Quarto renders copy buttons; we add a tooltip/title override
document.querySelectorAll('.code-copy-button').forEach((btn) => {
if (!btn.dataset.econlabPatched) {
btn.title = 'העתק קוד';
btn.dataset.econlabPatched = 'true';
btn.addEventListener('click', () => {
const original = btn.innerHTML;
btn.innerHTML = '✓ הועתק!';
setTimeout(() => { btn.innerHTML = original; }, 2000);
});
}
});
}highlightActiveSidebarItem function · javascript · L295-L301 (7 LOC)custom.js
function highlightActiveSidebarItem() {
const active = document.querySelector('.sidebar-item.active a, .active.nav-link');
if (active) {
active.style.fontWeight = '700';
active.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
}
}animateProgressBarEntrance function · javascript · L304-L314 (11 LOC)custom.js
function animateProgressBarEntrance() {
const bar = document.getElementById('econlab-progress-bar');
if (!bar) return;
const targetWidth = bar.style.width;
bar.style.width = '0%';
requestAnimationFrame(() => {
requestAnimationFrame(() => {
bar.style.width = targetWidth;
});
});
}isAssignmentPage function · javascript · L317-L321 (5 LOC)custom.js
function isAssignmentPage() {
const path = window.location.pathname;
return Object.keys(WEEK_MAP).some((folder) => path.includes(folder)) ||
/Week_\d{2}/.test(path);
}init function · javascript · L324-L339 (16 LOC)custom.js
function init() {
injectProgressBar();
injectGlobalProgressBar();
animateProgressBarEntrance();
if (isAssignmentPage()) {
injectFinishButton();
}
enhanceCodeCopyButtons();
highlightActiveSidebarItem();
// Re-patch copy buttons if code blocks load lazily
const obs = new MutationObserver(() => enhanceCodeCopyButtons());
obs.observe(document.body, { childList: true, subtree: true });
}fix_file function · python · L4-L31 (28 LOC)fix_hr.py
def fix_file(filepath):
with open(filepath, 'r', encoding='utf-8') as f:
lines = f.readlines()
new_lines = []
changed = 0
i = 0
while i < len(lines):
line = lines[i]
if line.rstrip() == '---':
# Check if it's a Setext heading (previous non-empty line exists)
prev = lines[i-1].rstrip() if i > 0 else ''
if prev != '':
# This is a Setext h2 heading underline — keep it
new_lines.append(line)
else:
# Plain horizontal rule — replace with *** to avoid YAML confusion
new_lines.append('***\n')
changed += 1
else:
new_lines.append(line)
i += 1
if changed:
with open(filepath, 'w', encoding='utf-8') as f:
f.writelines(new_lines)
print(f"Fixed {changed} occurrences in {filepath}")
return changedinject_videos function · python · L65-L105 (41 LOC)inject_validated_videos.py
def inject_videos():
base_dir = "Assignments"
for root, dirs, files in os.walk(base_dir):
for file in files:
if file.endswith("README.md") or file.endswith(".qmd"):
file_path = os.path.join(root, file)
folder_name = os.path.basename(root)
# Check if the folder matches one of our defined weeks
week_key = next((key for key in videos.keys() if key in folder_name), None)
if week_key:
with open(file_path, "r", encoding="utf-8") as f:
content = f.read()
# Clean up old video blocks or placeholders if they exist
content = re.sub(r"### 🎥 סרטוני הדרכה.*?(?=\n#|\Z)", "", content, flags=re.DOTALL)
content = re.sub(r"### 🎥 סרטון.*?(?=\n#|\Z)", "", content, flags=re.DOTALL)
# Construct the new tabset block
vids = videos[week_key]
Open data scored by Repobility · https://repobility.com
main function · python · L12-L60 (49 LOC)Members/_template/intro.py
def main():
# ===== ערוך כאן =====
name = "Your Name" # שמך באנגלית
degree = "B.A. Economics" # התואר שלך
university = "Your University" # שם האוניברסיטה
year_of_study = "2nd year" # שנת לימודים
economic_interests = [
"כתוב כאן תחום כלכלי שמעניין אותך",
"תחום נוסף",
"תחום שלישי",
]
why_econlab = (
"כתוב כאן במשפט אחד למה הצטרפת ל-EconLab PPE "
"ומה אתה מקווה ללמוד."
)
# ====================
print("=" * 50)
print(" EconLab PPE | היכרות ראשונה")
print("=" * 50)
print(f" שם: {name}")
print(f" תואר: {degree}")
print(f" אוניברסיטה: {university}")
print(f" שנה: {year_of_study}")
print()
print(" תחומי עניין כלכליים:")
for i, interest in enumerate(economic_interests, start=1):
print(f" {i}. {interest}")
print()
print(" למה EconLab?")
print(f" {why_econlab}")
print("=" *main function · python · L4-L36 (33 LOC)Members/yehuda_saadya/intro.py
def main():
name = "השם שלך באנגלית"
degree = "התואר שלך (למשל: B.A Economics / M.A Public Policy)"
location = "Israel"
goal = (
"להתמקצע בכלים תכנותיים לכלכלנים דרך עבודה מסודרת בניהול פרויקטים, "
"כדי להבין באמת בפרקטיקה ולבנות יכולת ללמד אחרים."
)
mission = (
"להקים 'סיירת כלכלנים' שיודעת לקחת נתונים ציבוריים, לנקות, לנתח, "
"לבנות מודלים וכלים, ולהפיק תוצרים שמסייעים בקבלת החלטות."
)
focus_areas = [
"Python לדאטה ואוטומציה (pandas, visualization)",
"R לאקונומטריקה (regression, DiD, time series)",
"SQL להבנת מסדי נתונים ושאילתות",
"ניתוח תקציב המדינה ונתוני מאקרו (בנק ישראל, למ״ס, OECD)",
]
print("=== EconLab PPE | Intro ===")
print(f"Name: {name}")
print(f"Degree: {degree}")
print(f"Location: {location}")
print()
print("Why I'm here:")
print(goal)
print()
print("My mission:")
print(mission)
print()
print("Focus areas:")
for i, itemgenerate function · python · L4-L46 (43 LOC)scripts/generate_leaderboard.py
def generate():
members_dir = "Members"
scores = {}
# Check if Members directory exists
if os.path.exists(members_dir):
# Iterate over student folders
for student in os.listdir(members_dir):
student_path = os.path.join(members_dir, student)
if os.path.isdir(student_path):
# Count unique assignment folders submitted by the student
assignments = [d for d in os.listdir(student_path) if os.path.isdir(os.path.join(student_path, d))]
scores[student] = len(assignments)
# Sort students by score descending
sorted_scores = sorted(scores.items(), key=lambda x: x[1], reverse=True)
# Generate Markdown content for Quarto
md = [
"---",
"title: '🏆 לוח תוצאות'",
"comments: false",
"---",
"",
"כאן תוכלו לראות את ההתקדמות של חברי הקהילה! הלוח מתעדכן אוטומטית בכל פעם שסטודנט מגיש מחברת פתורה לתיקייה שלו.",
"",
"| מיקום | write_file function · python · L15-L20 (6 LOC)setup_repo.py
def write_file(path: str, content: str) -> None:
"""יוצר קובץ עם תוכן בקידוד UTF-8 (יוצר תיקיות ביניים במידת הצורך)."""
os.makedirs(os.path.dirname(path) if os.path.dirname(path) else ".", exist_ok=True)
with open(path, "w", encoding="utf-8") as fh:
fh.write(content)
print(f" [+] {path}")make_dir function · python · L23-L26 (4 LOC)setup_repo.py
def make_dir(path: str) -> None:
"""יוצר תיקייה (כולל הורים) אם לא קיימת."""
os.makedirs(path, exist_ok=True)
print(f" [d] {path}/")main function · python · L593-L634 (42 LOC)setup_repo.py
def main() -> None:
print("\n========================================")
print(" EconLab PPE – Repository Initializer")
print("========================================\n")
# --- Root files ---
print("[1/6] Root files...")
write_file("README.md", ROOT_README)
write_file("CONTRIBUTING.md", CONTRIBUTING)
write_file(".gitignore", GITIGNORE)
# --- Cookbook ---
print("\n[2/6] Cookbook/...")
make_dir("Cookbook")
for path, content in COOKBOOK_FILES.items():
write_file(path, content)
# --- Notebooks ---
print("\n[3/6] Notebooks/...")
for folder, readme_content in NOTEBOOK_FOLDERS.items():
make_dir(folder)
write_file(os.path.join(folder, "README.md"), readme_content)
# --- Projects ---
print("\n[4/6] Projects/...")
for folder, readme_content in PROJECT_FOLDERS.items():
make_dir(folder)
write_file(os.path.join(folder, "README.md"), readme_content)
# --- Members ---
print("\