Spaces:
Running
Running
File size: 14,458 Bytes
5ed3bc5 8f3f71c 3b1cb20 5ed3bc5 8f3f71c 5ed3bc5 258dba8 5ed3bc5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 | <!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Liger - Green-Drive Optimizer</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;700&family=Noto+Sans+KR:wght@300;400;500;700&display=swap"
rel="stylesheet">
<link rel="stylesheet" href="style.css">
<meta name="description" content="Liger: 친환경 주행 경로 최적화 및 충전소 추천 솔루션">
</head>
<body>
<div class="background-glob"></div>
<nav class="navbar">
<div class="logo">LIGER</div>
<div class="nav-links">
<a href="#demo">Demo</a>
<a href="#presentation">Presentation</a>
<a href="#workflow">Workflow</a>
</div>
</nav>
<header class="hero">
<div class="hero-content">
<span class="badge">Green-Drive Optimizer</span>
<h1>스마트한 전기차 라이프의 시작,<br> <span class="gradient-text">LIGER</span></h1>
<p>최적의 경로와 충전소를 찾아주는 당신만의 AI 드라이빙 파트너</p>
<div class="cta-group">
<a href="#demo" class="btn primary">데모 영상 보기</a>
<a href="#workflow" class="btn secondary">워크플로우 확인하기</a>
</div>
</div>
<div class="hero-image">
<img src="hero_image.png" alt="Liger Dashboard Preview" class="glass-card">
</div>
</header>
<main>
<section id="demo" class="section">
<div class="section-header">
<h2>Demo Video</h2>
<p>Liger가 어떻게 작동하는지 확인해보세요</p>
</div>
<div class="video-container glass-card">
<video controls poster="hero_image.png">
<source src="liger_demo.mp4" type="video/mp4">
브라우저가 비디오 태그를 지원하지 않습니다.
</video>
</div>
</section>
<section id="presentation" class="section">
<div class="section-header">
<h2>Presentation</h2>
<p>프로젝트 상세 소개 및 기술 스택</p>
</div>
<div class="ppt-container glass-card">
<div class="ppt-wrapper glass-card" style="padding: 0; overflow: hidden; height: auto;">
<div class="pdf-canvas-container">
<canvas id="pdf-render"></canvas>
</div>
<div class="slide-controls">
<button id="prev-page" class="btn secondary small">Prev</button>
<span id="page-count-container">
Page <span id="page-num" style="color: white; font-weight: bold;">--</span> of <span
id="page-count">--</span>
</span>
<button id="next-page" class="btn secondary small">Next</button>
<a href="liger_presentation.pdf" download class="btn small"
style="margin-left: 1rem; padding: 0.4rem 0.8rem; font-size: 0.8rem; background: rgba(255,255,255,0.05);">
📥 PDF
</a>
</div>
</div>
<!-- PDF.js Library -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script>
<script>
const url = 'liger_presentation.pdf';
let pdfDoc = null,
pageNum = 1,
pageRendering = false,
pageNumPending = null,
scale = 1.5,
canvas = document.getElementById('pdf-render'),
ctx = canvas.getContext('2d');
// Set worker source
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
/**
* Get page info from document, resize canvas accordingly, and render page.
* @param num Page number.
*/
function renderPage(num) {
pageRendering = true;
// Fetch page
pdfDoc.getPage(num).then(function (page) {
// Adjust scale to fit the container width if needed
const containerWidth = document.querySelector('.pdf-canvas-container').clientWidth;
const viewport = page.getViewport({ scale: 1 });
// Calculate scale to fit width (minus some padding)
let desiredScale = (containerWidth - 40) / viewport.width;
// Limit max scale to keep quality reasonable
if (desiredScale > 1.5) desiredScale = 1.5;
const scaledViewport = page.getViewport({ scale: desiredScale });
canvas.height = scaledViewport.height;
canvas.width = scaledViewport.width;
// Render PDF page into canvas context
const renderContext = {
canvasContext: ctx,
viewport: scaledViewport
};
const renderTask = page.render(renderContext);
// Wait for render to finish
renderTask.promise.then(function () {
pageRendering = false;
if (pageNumPending !== null) {
renderPage(pageNumPending);
pageNumPending = null;
}
});
});
// Update page counters
document.getElementById('page-num').textContent = num;
// Update buttons state
document.getElementById('prev-page').disabled = num <= 1;
document.getElementById('next-page').disabled = num >= pdfDoc.numPages;
}
/**
* If another page rendering in progress, waits until the rendering is
* finised. Otherwise, executes rendering immediately.
*/
function queueRenderPage(num) {
if (pageRendering) {
pageNumPending = num;
} else {
renderPage(num);
}
}
/**
* Displays previous page.
*/
function onPrevPage() {
if (pageNum <= 1) {
return;
}
pageNum--;
queueRenderPage(pageNum);
}
document.getElementById('prev-page').addEventListener('click', onPrevPage);
/**
* Displays next page.
*/
function onNextPage() {
if (pageNum >= pdfDoc.numPages) {
return;
}
pageNum++;
queueRenderPage(pageNum);
}
document.getElementById('next-page').addEventListener('click', onNextPage);
/**
* Asynchronously downloads PDF.
*/
pdfjsLib.getDocument(url).promise.then(function (pdfDoc_) {
pdfDoc = pdfDoc_;
document.getElementById('page-count').textContent = pdfDoc.numPages;
// Initial/first page rendering
renderPage(pageNum);
}).catch(function (error) {
console.error('Error loading PDF:', error);
// Fallback UI or message could go here
ctx.font = '20px Arial';
ctx.fillStyle = 'white';
ctx.fillText('Error loading PDF.', 50, 50);
});
// Handle window resize
window.addEventListener('resize', () => {
// Re-render current page to adjust scale
if (pdfDoc) {
queueRenderPage(pageNum);
}
});
</script>
</div>
</section>
<section id="workflow" class="section">
<div class="section-header">
<h2>Core Logic & Workflow</h2>
<p>Google Calendar 연동부터 AI 최적화 제안까지, One-Stop 자동화 프로세스</p>
</div>
<div class="workflow-container glass-card">
<div class="workflow-img-wrapper">
<img src="workflow_diagram.png" alt="n8n Workflow Diagram" class="full-width-img">
</div>
<div class="workflow-details">
<div class="logic-step">
<h3>1. Trigger & analysis</h3>
<p>구글 캘린더에 새로운 일정이 등록되면 자동으로 감지하여 출발지와 목적지, 그리고 이동 시간을 계산합니다.</p>
</div>
<div class="logic-step">
<h3>2. Dual-Optimization Engine</h3>
<p>이동 경로를 바탕으로 두 가지 시나리오를 병렬로 생성합니다.</p>
<ul>
<li><strong>탄소 배출 최적화:</strong> 친환경 경로 및 운전 습관 제안</li>
<li><strong>경제적 충전 시나리오:</strong> 최저가 충전소 및 배터리 효율 분석</li>
</ul>
</div>
<div class="logic-step">
<h3>3. AI Evaluation (Upstage Solar)</h3>
<p>Upstage Solar LLM이 환경성과 경제성을 종합적으로 평가하여, 사용자에게 가장 밸런스 잡힌 최적의 스케줄을 확정합니다.</p>
</div>
<div class="logic-step">
<h3>4. Action & Report</h3>
<p>최종 확정된 일정은 캘린더에 다시 등록되며, 상세 분석 리포트가 이메일로 즉시 전송됩니다.</p>
</div>
</div>
</div>
</section>
<section id="team" class="section">
<div class="section-header">
<h2>Our Team</h2>
<p>Liger 프로젝트를 만들어가는 사람들</p>
</div>
<div class="team-container glass-card">
<!-- Image removed as requested -->
<div class="team-grid">
<div class="team-member">
<h4>강윤재</h4>
<span class="role">Data Research & Scenario</span>
<p>전기차 전비/배터리 자료 조사<br>경제적 충전 시나리오 로직 설계</p>
</div>
<div class="team-member">
<h4>엄서훈</h4>
<span class="role">Workflow Architect</span>
<p>n8n 메인 워크플로우 개발<br>최종 리포트 템플릿 구현</p>
</div>
<div class="team-member">
<h4>이승현</h4>
<span class="role">Project Lead</span>
<p>프로젝트 총괄 및 일정 조율<br>서비스 기획 및 소개서 작성</p>
</div>
<div class="team-member">
<h4>이하윤</h4>
<span class="role">Presentation & Data</span>
<p>발표 자료 제작 및 최종 발표<br>탄소 배출 데이터 리서치</p>
</div>
<div class="team-member">
<h4>차성경</h4>
<span class="role">Media & Validation</span>
<p>아이디어 산출 및 검증<br>홍보 영상 제작 및 자료 조사</p>
</div>
</div>
</div>
</section>
</main>
<footer>
<p>© 2024 Liger Team. All rights reserved.</p>
<div class="socials">
<a href="https://huggingface.co/dltmdgus" target="_blank">Hugging Face</a>
</div>
</footer>
<script>
// Smooth scroll for anchor links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
document.querySelector(this.getAttribute('href')).scrollIntoView({
behavior: 'smooth'
});
});
});
// Simple intersection observer for fade-in animations
const observerOptions = {
threshold: 0.1
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
}
});
}, observerOptions);
document.querySelectorAll('.section, .hero').forEach(el => {
el.classList.add('fade-in-section');
observer.observe(el);
});
</script>
</body>
</html> |