Skip to content

Commit d52df03

Browse files
committed
- add animal age caluclator
1 parent 999ec4d commit d52df03

File tree

1 file changed

+363
-0
lines changed

1 file changed

+363
-0
lines changed

tools/animal_age_calculator.html

Lines changed: 363 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,363 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width,initial-scale=1.0">
6+
<title>Animal Age Calculator</title>
7+
<style>
8+
* {
9+
margin: 0;
10+
padding: 0;
11+
box-sizing: border-box
12+
}
13+
14+
body {
15+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
16+
background: #fafafa;
17+
color: #1a1a1a;
18+
padding: 20px;
19+
min-height: 100vh
20+
}
21+
22+
.container {
23+
max-width: 1100px;
24+
margin: 0 auto
25+
}
26+
27+
header {
28+
text-align: center;
29+
margin-bottom: 50px;
30+
padding-top: 30px
31+
}
32+
33+
h1 {
34+
font-size: 2.2em;
35+
font-weight: 600;
36+
margin-bottom: 8px;
37+
color: #1a1a1a
38+
}
39+
40+
.subtitle {
41+
color: #666;
42+
font-size: 1em
43+
}
44+
45+
.calculator {
46+
background: #fff;
47+
border-radius: 12px;
48+
padding: 32px;
49+
margin-bottom: 40px;
50+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06)
51+
}
52+
53+
.input-wrapper {
54+
display: flex;
55+
flex-direction: column;
56+
align-items: center;
57+
gap: 20px
58+
}
59+
60+
.mode-toggle {
61+
display: flex;
62+
gap: 8px;
63+
background: #f5f5f5;
64+
padding: 4px;
65+
border-radius: 8px
66+
}
67+
68+
.mode-toggle button {
69+
border: none;
70+
padding: 10px 20px;
71+
border-radius: 6px;
72+
font-size: 0.95em;
73+
cursor: pointer;
74+
background: transparent;
75+
color: #666;
76+
font-weight: 500;
77+
transition: all 0.2s
78+
}
79+
80+
.mode-toggle button.active {
81+
background: #fff;
82+
color: #1a1a1a;
83+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1)
84+
}
85+
86+
.age-input-group {
87+
display: flex;
88+
align-items: center;
89+
gap: 12px
90+
}
91+
92+
.age-input-group input {
93+
font-size: 2.5em;
94+
font-weight: 600;
95+
width: 120px;
96+
text-align: center;
97+
border: none;
98+
border-bottom: 3px solid #e0e0e0;
99+
padding: 8px;
100+
color: #1a1a1a;
101+
transition: border-color 0.2s
102+
}
103+
104+
.age-input-group input:focus {
105+
outline: none;
106+
border-color: #2196f3
107+
}
108+
109+
.age-input-group span {
110+
font-size: 1.5em;
111+
color: #666
112+
}
113+
114+
.animal-select {
115+
padding: 12px 20px;
116+
font-size: 1em;
117+
border: 2px solid #e0e0e0;
118+
border-radius: 8px;
119+
background: #fff;
120+
cursor: pointer;
121+
font-family: inherit;
122+
color: #1a1a1a
123+
}
124+
125+
.animal-select:focus {
126+
outline: none;
127+
border-color: #2196f3
128+
}
129+
130+
.human-result {
131+
background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%);
132+
border-radius: 12px;
133+
padding: 32px;
134+
text-align: center;
135+
margin-bottom: 30px;
136+
border: 2px solid #2196f3
137+
}
138+
139+
.human-result-label {
140+
font-size: 1em;
141+
color: #1565c0;
142+
margin-bottom: 8px;
143+
font-weight: 500
144+
}
145+
146+
.human-result-age {
147+
font-size: 3.5em;
148+
font-weight: 700;
149+
color: #0d47a1;
150+
margin-bottom: 4px
151+
}
152+
153+
.human-result-text {
154+
font-size: 1.1em;
155+
color: #1565c0
156+
}
157+
158+
.results {
159+
display: grid;
160+
grid-template-columns:repeat(auto-fill, minmax(240px, 1fr));
161+
gap: 20px
162+
}
163+
164+
.card {
165+
background: #fff;
166+
border-radius: 10px;
167+
padding: 24px;
168+
text-align: center;
169+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
170+
transition: transform 0.2s, box-shadow 0.2s
171+
}
172+
173+
.card:hover {
174+
transform: translateY(-2px);
175+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1)
176+
}
177+
178+
.card-icon {
179+
font-size: 3em;
180+
margin-bottom: 12px;
181+
display: block
182+
}
183+
184+
.card-name {
185+
font-size: 1.1em;
186+
font-weight: 600;
187+
color: #1a1a1a;
188+
margin-bottom: 12px
189+
}
190+
191+
.card-age {
192+
font-size: 2.2em;
193+
font-weight: 700;
194+
color: #2196f3;
195+
margin-bottom: 4px
196+
}
197+
198+
.card-label {
199+
font-size: 0.85em;
200+
color: #999;
201+
text-transform: uppercase;
202+
letter-spacing: 0.5px
203+
}
204+
205+
.card.highlight {
206+
background: linear-gradient(135deg, #fff3e0 0%, #ffe0b2 100%);
207+
border: 2px solid #ff9800
208+
}
209+
210+
.card.highlight .card-age {
211+
color: #e65100
212+
}
213+
214+
footer {
215+
text-align: center;
216+
margin-top: 50px;
217+
color: #999;
218+
font-size: 0.9em
219+
}
220+
221+
@media (max-width: 768px) {
222+
h1 {
223+
font-size: 1.8em
224+
}
225+
226+
.age-input-group input {
227+
font-size: 2em;
228+
width: 100px
229+
}
230+
231+
.age-input-group span {
232+
font-size: 1.2em
233+
}
234+
235+
.human-result-age {
236+
font-size: 2.5em
237+
}
238+
239+
.results {
240+
grid-template-columns:repeat(auto-fill, minmax(160px, 1fr));
241+
gap: 16px
242+
}
243+
244+
.card {
245+
padding: 20px
246+
}
247+
248+
.card-icon {
249+
font-size: 2.5em
250+
}
251+
252+
.card-age {
253+
font-size: 1.8em
254+
}
255+
}
256+
</style>
257+
</head>
258+
<body>
259+
<div class="container">
260+
<header>
261+
<h1>Animal Age Calculator</h1>
262+
<p class="subtitle">See how your age compares across different species</p>
263+
</header>
264+
<div class="calculator">
265+
<div class="input-wrapper">
266+
<div class="mode-toggle">
267+
<button class="active" data-mode="human" onclick="switchMode('human')">I am <strong>Human</strong>
268+
</button>
269+
<button data-mode="animal" onclick="switchMode('animal')">I am <strong>Animal</strong></button>
270+
</div>
271+
<div class="age-input-group">
272+
<input type="number" id="ageInput" value="25" min="0" max="150" oninput="calculate()">
273+
<span>years old</span>
274+
</div>
275+
<select id="animalSelect" class="animal-select" style="display:none" onchange="calculate()">
276+
<option value="dog">🐕 Dog</option>
277+
<option value="cat">🐱 Cat</option>
278+
<option value="horse">🐴 Horse</option>
279+
<option value="rabbit">🐰 Rabbit</option>
280+
<option value="hamster">🐹 Hamster</option>
281+
<option value="parrot">🦜 Parrot</option>
282+
<option value="turtle">🐢 Turtle</option>
283+
<option value="goldfish">🐠 Goldfish</option>
284+
</select>
285+
</div>
286+
</div>
287+
<div id="humanResult" style="display:none"></div>
288+
<div class="results" id="results"></div>
289+
<footer>Age calculations based on average lifespans and scientific estimates</footer>
290+
</div>
291+
<script>
292+
let currentMode = 'human';
293+
const animals = {
294+
dog: {
295+
icon: '🐕', name: 'Dog', toAnimal: h => {
296+
if (h <= 2) return h * 10.5;
297+
return 21 + (h - 2) * 4
298+
}, toHuman: a => {
299+
if (a <= 21) return a / 10.5;
300+
return 2 + (a - 21) / 4
301+
}
302+
},
303+
cat: {
304+
icon: '🐱', name: 'Cat', toAnimal: h => {
305+
if (h <= 1) return 15;
306+
if (h <= 2) return 24;
307+
return 24 + (h - 2) * 4
308+
}, toHuman: a => {
309+
if (a <= 15) return 1;
310+
if (a <= 24) return 1 + (a - 15) / 9;
311+
return 2 + (a - 24) / 4
312+
}
313+
},
314+
horse: {icon: '🐴', name: 'Horse', toAnimal: h => h * 3, toHuman: a => a / 3},
315+
rabbit: {icon: '🐰', name: 'Rabbit', toAnimal: h => h * 8, toHuman: a => a / 8},
316+
hamster: {icon: '🐹', name: 'Hamster', toAnimal: h => h * 25, toHuman: a => a / 25},
317+
parrot: {icon: '🦜', name: 'Parrot', toAnimal: h => h * 0.8, toHuman: a => a / 0.8},
318+
turtle: {icon: '🐢', name: 'Turtle', toAnimal: h => h * 0.6, toHuman: a => a / 0.6},
319+
goldfish: {icon: '🐠', name: 'Goldfish', toAnimal: h => h * 5, toHuman: a => a / 5}
320+
};
321+
322+
function switchMode(mode) {
323+
if (currentMode === mode) return;
324+
currentMode = mode;
325+
document.querySelectorAll('.mode-toggle button').forEach(b => b.classList.remove('active'));
326+
document.querySelector(`[data-mode="${mode}"]`).classList.add('active');
327+
document.getElementById('animalSelect').style.display = mode === 'animal' ? 'block' : 'none';
328+
calculate();
329+
}
330+
331+
function calculate() {
332+
const age = parseFloat(document.getElementById('ageInput').value) || 0;
333+
const resultsDiv = document.getElementById('results');
334+
const humanResultDiv = document.getElementById('humanResult');
335+
let html = '';
336+
if (currentMode === 'human') {
337+
humanResultDiv.style.display = 'none';
338+
Object.keys(animals).forEach(key => {
339+
const animal = animals[key];
340+
const animalAge = animal.toAnimal(age);
341+
html += `<div class="card"><span class="card-icon">${animal.icon}</span><div class="card-name">${animal.name}</div><div class="card-age">${animalAge.toFixed(1)}</div><div class="card-label">years</div></div>`;
342+
});
343+
} else {
344+
const selectedKey = document.getElementById('animalSelect').value;
345+
const animalAge = age;
346+
const humanAge = animals[selectedKey].toHuman(animalAge);
347+
humanResultDiv.style.display = 'block';
348+
humanResultDiv.innerHTML = `<div class="human-result"><div class="human-result-label">Your human age equivalent</div><div class="human-result-age">${humanAge.toFixed(1)}</div><div class="human-result-text">years old</div></div>`;
349+
Object.keys(animals).forEach(key => {
350+
const animal = animals[key];
351+
const displayAge = key === selectedKey ? animalAge : animal.toAnimal(humanAge);
352+
const isSelected = key === selectedKey;
353+
html += `<div class="card${isSelected ? ' highlight' : ''}"><span class="card-icon">${animal.icon}</span><div class="card-name">${animal.name}</div><div class="card-age">${displayAge.toFixed(1)}</div><div class="card-label">${isSelected ? '(you)' : 'equivalent'}</div></div>`;
354+
});
355+
}
356+
resultsDiv.innerHTML = html;
357+
}
358+
359+
calculate();
360+
</script>
361+
<script src="../logo.js"></script>
362+
</body>
363+
</html>

0 commit comments

Comments
 (0)