Skip to content

Commit a9b0b84

Browse files
authored
Add vicutils section
1 parent 1d3d94c commit a9b0b84

1 file changed

Lines changed: 69 additions & 51 deletions

File tree

index.html

Lines changed: 69 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<head>
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6-
<title>Python Solutions - LeetCode & Kattis</title>
6+
<title>Python Solutions - LeetCode, Kattis & VicUtils</title>
77
<link rel="icon" href="VN.ico">
88
<style>
99
* {
@@ -80,7 +80,7 @@
8080

8181
.platforms {
8282
display: grid;
83-
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
83+
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
8484
gap: 2rem;
8585
margin-bottom: 3rem;
8686
}
@@ -134,6 +134,7 @@
134134

135135
.leetcode-icon { background: #ffa116; }
136136
.kattis-icon { background: #1e40af; }
137+
.vicutils-icon { background: #10b981; }
137138

138139
.platform-card p {
139140
color: #666;
@@ -229,7 +230,7 @@
229230
}
230231

231232
.problem-item.html-page::before {
232-
background: #10b981; /* Green for full HTML pages */
233+
background: #10b981;
233234
}
234235

235236
.problem-item.png-page {
@@ -238,7 +239,7 @@
238239
}
239240

240241
.problem-item.png-page::before {
241-
background: #f59e0b; /* Orange for PNG pages */
242+
background: #f59e0b;
242243
}
243244

244245
.problem-item.code-only {
@@ -247,7 +248,11 @@
247248
}
248249

249250
.problem-item.code-only::before {
250-
background: #6b7280; /* Gray for code-only pages */
251+
background: #6b7280;
252+
}
253+
254+
.problem-item.util-script::before {
255+
background: #10b981;
251256
}
252257

253258
.problem-name {
@@ -310,7 +315,6 @@
310315
font-style: italic;
311316
}
312317

313-
/* Generated page styles */
314318
.generated-page {
315319
background: white;
316320
min-height: 100vh;
@@ -483,12 +487,12 @@
483487

484488
<header>
485489
<h1>PythonSolutions</h1>
486-
<p class="subtitle">LeetCode & Kattis Problem Solutions with Interactive Pages</p>
490+
<p class="subtitle">LeetCode & Kattis Solutions + Utility Scripts</p>
487491
</header>
488492

489493
<div id="loading" class="loading">
490494
<div class="spinner"></div>
491-
<span>Scanning repository for solutions...</span>
495+
<span>Scanning repository...</span>
492496
</div>
493497

494498
<div id="main-view" class="platforms" style="display: none;">
@@ -509,6 +513,15 @@ <h2>
509513
<p>Competitive programming solutions with detailed walkthroughs</p>
510514
<div class="problem-count" id="kattis-count">Loading...</div>
511515
</div>
516+
517+
<div class="platform-card" onclick="showProblems('vicutils')">
518+
<h2>
519+
<div class="platform-icon vicutils-icon">🛠️</div>
520+
VicUtils
521+
</h2>
522+
<p>Useful utility scripts and helper functions</p>
523+
<div class="problem-count" id="vicutils-count">Loading...</div>
524+
</div>
512525
</div>
513526

514527
<div id="problems-view" class="problems-view">
@@ -525,11 +538,12 @@ <h2 id="problems-title"></h2>
525538
<script>
526539
let problemsData = {
527540
leetcode: [],
528-
kattis: []
541+
kattis: [],
542+
vicutils: []
529543
};
530544

531545
async function scanForProblems() {
532-
const platforms = ['leetcode', 'kattis'];
546+
const platforms = ['leetcode', 'kattis', 'vicutils'];
533547

534548
for (const platform of platforms) {
535549
try {
@@ -540,30 +554,49 @@ <h2 id="problems-title"></h2>
540554
continue;
541555
}
542556

543-
const directories = await response.json();
557+
const items = await response.json();
544558
const problems = [];
545559

546-
for (const dir of directories) {
547-
if (dir.type === 'dir') {
560+
if (platform === 'vicutils') {
561+
// For vicutils, treat .py files directly (not directories)
562+
for (const item of items) {
563+
if (item.type === 'file' && item.name.endsWith('.py') && item.name !== '__init__.py') {
564+
problems.push({
565+
name: item.name,
566+
displayName: item.name.replace('.py', '').replace(/_/g, ' '),
567+
type: 'util-script',
568+
hasPage: true,
569+
hasHtml: false,
570+
hasPng: false,
571+
hasPy: true,
572+
mainPyFile: item,
573+
htmlFiles: [],
574+
pngFiles: [],
575+
pyFiles: [item]
576+
});
577+
}
578+
}
579+
} else {
580+
// For leetcode and kattis, process directories
581+
const directories = items.filter(item => item.type === 'dir');
582+
583+
for (const dir of directories) {
548584
try {
549585
const dirResponse = await fetch(`https://api.github.com/repos/${getRepoPath()}/contents/${platform}/${dir.name}`);
550586
if (dirResponse.ok) {
551587
const files = await dirResponse.json();
552588

553-
// Look for any .html file that matches the directory name
554589
const hasHtml = files.some(file =>
555590
file.name.endsWith('.html') &&
556591
file.name.toLowerCase().includes(dir.name.toLowerCase().replace(/\s+/g, ''))
557592
);
558593

559-
// Look for any .vn.png files (not tied to directory name)
560594
const pngFiles = files.filter(file =>
561595
file.name.endsWith('.vn.png') ||
562596
file.name.match(/\.vn\.\d+\.png$/)
563597
);
564598
const hasPng = pngFiles.length > 0;
565599

566-
// Look for any .vn.py files
567600
const pyFiles = files.filter(file => file.name.endsWith('.vn.py'));
568601
const hasPy = pyFiles.length > 0;
569602

@@ -579,12 +612,11 @@ <h2 id="problems-title"></h2>
579612
hasPage = true;
580613
} else if (hasPy) {
581614
type = 'code-only';
582-
hasPage = true; // We'll generate a page for code-only too
615+
hasPage = true;
583616
}
584617

585-
// Find the main .vn.py file (there should typically be one)
586618
if (pyFiles.length > 0) {
587-
mainPyFile = pyFiles[0]; // Take the first .vn.py file
619+
mainPyFile = pyFiles[0];
588620
}
589621

590622
if (hasHtml || hasPng || hasPy) {
@@ -599,7 +631,6 @@ <h2 id="problems-title"></h2>
599631
mainPyFile: mainPyFile,
600632
htmlFiles: files.filter(file => file.name.endsWith('.html')),
601633
pngFiles: pngFiles.sort((a, b) => {
602-
// Sort PNG files by number if they have one
603634
const aNum = a.name.match(/\.(\d+)\.png$/) ? parseInt(a.name.match(/\.(\d+)\.png$/)[1]) : 0;
604635
const bNum = b.name.match(/\.(\d+)\.png$/) ? parseInt(b.name.match(/\.(\d+)\.png$/)[1]) : 0;
605636
return aNum - bNum;
@@ -635,26 +666,27 @@ <h2 id="problems-title"></h2>
635666
document.getElementById('loading').style.display = 'none';
636667
document.getElementById('main-view').style.display = 'grid';
637668

638-
for (const platform of ['leetcode', 'kattis']) {
669+
for (const platform of ['leetcode', 'kattis', 'vicutils']) {
639670
const problems = problemsData[platform];
640671
const totalProblems = problems.length;
672+
const label = platform === 'vicutils' ? 'scripts' : 'problems';
641673

642-
document.getElementById(`${platform}-count`).textContent = `${totalProblems} problems`;
674+
document.getElementById(`${platform}-count`).textContent = `${totalProblems} ${label}`;
643675
}
644676
}
645677

646678
function showProblems(platform) {
647679
const problems = problemsData[platform];
648-
const title = platform.charAt(0).toUpperCase() + platform.slice(1);
680+
const title = platform === 'vicutils' ? 'VicUtils' : platform.charAt(0).toUpperCase() + platform.slice(1);
649681

650682
document.getElementById('main-view').style.display = 'none';
651683
document.getElementById('problems-view').style.display = 'block';
652-
document.getElementById('problems-title').textContent = `${title} Problems`;
684+
document.getElementById('problems-title').textContent = platform === 'vicutils' ? 'Utility Scripts' : `${title} Problems`;
653685

654686
const container = document.getElementById('problems-container');
655687

656688
if (problems.length === 0) {
657-
container.innerHTML = '<div class="no-problems">No problems found for this platform yet.</div>';
689+
container.innerHTML = '<div class="no-problems">No items found for this section yet.</div>';
658690
return;
659691
}
660692

@@ -668,14 +700,15 @@ <h2 id="problems-title"></h2>
668700
let icon = '';
669701
if (problem.type === 'html') icon = '🌐';
670702
else if (problem.type === 'png') icon = '🖼️';
703+
else if (problem.type === 'util-script') icon = '🛠️';
671704
else icon = '💻';
672705

673706
item.innerHTML = `
674707
<div class="problem-name">
675708
<span class="problem-type-icon">${icon}</span>
676709
${problem.displayName}
677710
</div>
678-
<div class="problem-path">${platform}/${problem.name}/</div>
711+
<div class="problem-path">${platform}/${problem.name}</div>
679712
`;
680713

681714
if (problem.hasHtml && problem.htmlFiles.length > 0) {
@@ -697,35 +730,29 @@ <h2 id="problems-title"></h2>
697730
}
698731

699732
async function generatePage(platform, problem) {
700-
// Instead of opening a new window, we'll create a URL hash-based system
701-
// This allows for shareable links
702733
const problemId = encodeURIComponent(`${platform}/${problem.name}`);
703734
const newUrl = `${window.location.origin}${window.location.pathname}#view/${problemId}`;
704735
window.location.href = newUrl;
705736
}
706737

707738
async function renderProblemPage(platform, problemName) {
708-
// Find the problem data
709739
const problem = problemsData[platform]?.find(p => p.name === problemName);
710740
if (!problem) {
711-
document.body.innerHTML = '<div class="error">Problem not found</div>';
741+
document.body.innerHTML = '<div class="error">Item not found</div>';
712742
return;
713743
}
714744

715-
// Create a new page content
716745
let problemUrl = '';
717746
let pythonCode = '';
718747

719-
// Try to get the problem URL from the .vn.py file
720748
if (problem.hasPy && problem.mainPyFile) {
721749
try {
722-
const pyResponse = await fetch(`https://api.github.com/repos/${getRepoPath()}/contents/${platform}/${problem.name}/${problem.mainPyFile.name}`);
750+
const pyResponse = await fetch(`https://api.github.com/repos/${getRepoPath()}/contents/${platform === 'vicutils' ? platform : `${platform}/${problem.name}`}/${problem.mainPyFile.name}`);
723751
if (pyResponse.ok) {
724752
const pyData = await pyResponse.json();
725753
const content = atob(pyData.content);
726754
pythonCode = content;
727755

728-
// Extract URL from first comment
729756
const urlMatch = content.match(/^#.*?(https:\/\/[^\s]+)/m);
730757
if (urlMatch) {
731758
problemUrl = urlMatch[1];
@@ -736,12 +763,12 @@ <h2 id="problems-title"></h2>
736763
}
737764
}
738765

739-
// Generate the page HTML
740766
const pageTitle = problem.displayName.replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
741-
const platformTitle = platform.charAt(0).toUpperCase() + platform.slice(1);
767+
const platformTitle = platform === 'vicutils' ? 'VicUtils' : platform.charAt(0).toUpperCase() + platform.slice(1);
742768

743-
// Get GitHub repo URL for the folder
744-
const repoUrl = `https://github.com/${getRepoPath()}/tree/main/${platform}/${problem.name}`;
769+
const repoUrl = platform === 'vicutils'
770+
? `https://github.com/${getRepoPath()}/blob/main/${platform}/${problem.name}`
771+
: `https://github.com/${getRepoPath()}/tree/main/${platform}/${problem.name}`;
745772

746773
let pageContent = `
747774
<div class="generated-page">
@@ -756,14 +783,11 @@ <h2 id="problems-title"></h2>
756783
</div>
757784
758785
<h1 class="page-title">${pageTitle}</h1>
759-
<p class="page-subtitle">${platformTitle} Problem Solution</p>
786+
<p class="page-subtitle">${platformTitle}${platform === 'vicutils' ? ' Script' : ' Problem Solution'}</p>
760787
`;
761788

762-
// Add images if available
763789
if (problem.hasPng && problem.pngFiles.length > 0) {
764-
pageContent += `
765-
<div class="images-grid">
766-
`;
790+
pageContent += `<div class="images-grid">`;
767791

768792
problem.pngFiles.forEach((pngFile, index) => {
769793
const imageUrl = `${platform}/${problem.name}/${pngFile.name}`;
@@ -780,25 +804,20 @@ <h1 class="page-title">${pageTitle}</h1>
780804
pageContent += `</div>`;
781805
}
782806

783-
// Add code section (always show if available, even with images)
784807
if (pythonCode) {
785808
pageContent += `
786809
<div class="code-section">
787-
<h3>Python Solution</h3>
810+
<h3>Python ${platform === 'vicutils' ? 'Script' : 'Solution'}</h3>
788811
<div class="code-content">${escapeHtml(pythonCode)}</div>
789812
</div>
790813
`;
791814
}
792815

793816
pageContent += `</div>`;
794817

795-
// Replace the body content with the generated page
796818
document.body.innerHTML = pageContent;
797-
798-
// Update page title and favicon
799819
document.title = `${pageTitle} - ${platformTitle}`;
800820

801-
// Add favicon if not already present
802821
if (!document.querySelector('link[rel="icon"]')) {
803822
const link = document.createElement('link');
804823
link.rel = 'icon';
@@ -813,7 +832,6 @@ <h3>Python Solution</h3>
813832
return div.innerHTML;
814833
}
815834

816-
// Add navigation enhancement to problem pages
817835
function addNavigationToCurrentPage() {
818836
const path = window.location.pathname;
819837
const isLeetCodeProblem = path.includes('/leetcode/') && path.endsWith('.html');
@@ -892,7 +910,7 @@ <h3>Python Solution</h3>
892910
// Handle platform navigation
893911
window.addEventListener('load', () => {
894912
const simpleHash = window.location.hash.substring(1);
895-
if (simpleHash === 'leetcode' || simpleHash === 'kattis') {
913+
if (simpleHash === 'leetcode' || simpleHash === 'kattis' || simpleHash === 'vicutils') {
896914
setTimeout(() => showProblems(simpleHash), 1000);
897915
}
898916
});

0 commit comments

Comments
 (0)