forked from Ugric/Komodo-Hub
Merge pull request 'Updated navbar buttons, added about page, added rough hangman game' (#58) from TussockyJoker/Komodo-Hub:main into main
Reviewed-on: Ugric/Komodo-Hub#58
This commit is contained in:
commit
ed5147fafe
10 files changed
+201
-13
No files matched your search
@@ -1,5 +1,5 @@
|
||||
from datetime import datetime
|
||||
from database.db_connection import get_db, get_db
|
||||
from database.db_connection import get_db
|
||||
import hashlib
|
||||
import os
|
||||
import bcrypt
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
from flask import render_template, Blueprint
|
||||
|
||||
page = Blueprint('about', __name__, url_prefix='/about')
|
||||
|
||||
|
||||
@page.route('')
|
||||
def home():
|
||||
return render_template('about/about.jinja')
|
||||
@@ -0,0 +1,11 @@
|
||||
from flask import render_template, Blueprint
|
||||
from database.db_commands import get_all_species
|
||||
|
||||
page = Blueprint('game', __name__)
|
||||
|
||||
|
||||
@page.route('/game')
|
||||
def game():
|
||||
species = get_all_species()
|
||||
species_list = [s['species_english'] for s in species]
|
||||
return render_template('game/game.jinja', species_list=species_list)
|
||||
@@ -0,0 +1,78 @@
|
||||
const bodyParts = ['p-head','p-body','p-larm','p-rarm','p-lleg','p-rleg'];
|
||||
let word, guessed, lives, over;
|
||||
|
||||
function initGame() {
|
||||
word = SPECIES_LIST[Math.floor(Math.random() * SPECIES_LIST.length)].toUpperCase().replace(/\s+/g, ' ').trim();
|
||||
guessed = [];
|
||||
lives = 6;
|
||||
over = false;
|
||||
bodyParts.forEach(id => document.getElementById(id).setAttribute('display', 'none'));
|
||||
document.getElementById('hm-msg').textContent = '';
|
||||
document.getElementById('hm-msg').className = 'hm-msg';
|
||||
document.getElementById('hm-restart-wrap').style.display = 'none';
|
||||
renderWord();
|
||||
renderKeyboard();
|
||||
renderLives();
|
||||
renderGuessed();
|
||||
}
|
||||
|
||||
function renderWord() {
|
||||
const el = document.getElementById('hm-word');
|
||||
el.innerHTML = word.split('').map(l => {
|
||||
const show = l === ' ' || guessed.includes(l) || over;
|
||||
return `<div class="hm-letter"><span>${show ? l : ''}</span>${l !== ' ' ? '<hr>' : ''}</div>`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function renderLives() {
|
||||
document.getElementById('hm-lives').textContent = `Lives: ${lives}`;
|
||||
}
|
||||
|
||||
function renderGuessed() {
|
||||
const wrong = guessed.filter(l => !word.includes(l));
|
||||
document.getElementById('hm-guessed').textContent = wrong.length ? `Wrong: ${wrong.join(', ')}` : '';
|
||||
}
|
||||
|
||||
function renderKeyboard() {
|
||||
const kb = document.getElementById('hm-keyboard');
|
||||
kb.innerHTML = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('').map(l => {
|
||||
const used = guessed.includes(l);
|
||||
const isRight = used && word.includes(l);
|
||||
const isWrong = used && !word.includes(l);
|
||||
return `<button class="hm-key${isRight ? ' right' : isWrong ? ' wrong' : ''}" ${used || over ? 'disabled' : ''} data-letter="${l}">${l}</button>`;
|
||||
}).join('');
|
||||
kb.querySelectorAll('.hm-key:not(:disabled)').forEach(btn => {
|
||||
btn.addEventListener('click', () => guess(btn.dataset.letter));
|
||||
});
|
||||
}
|
||||
|
||||
function guess(letter) {
|
||||
if (over || guessed.includes(letter)) return;
|
||||
guessed.push(letter);
|
||||
if (!word.includes(letter)) {
|
||||
lives--;
|
||||
document.getElementById(bodyParts[6 - lives - 1]).setAttribute('display', 'inline');
|
||||
}
|
||||
const won = word.split('').filter(l => l !== ' ').every(l => guessed.includes(l));
|
||||
const lost = lives === 0;
|
||||
if (won || lost) {
|
||||
over = true;
|
||||
const msg = document.getElementById('hm-msg');
|
||||
msg.textContent = won ? `You won! The species was: ${word}` : `Game over! The species was: ${word}`;
|
||||
msg.className = 'hm-msg ' + (won ? 'win' : 'lose');
|
||||
document.getElementById('hm-restart-wrap').style.display = 'block';
|
||||
}
|
||||
renderWord();
|
||||
renderKeyboard();
|
||||
renderLives();
|
||||
renderGuessed();
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', e => {
|
||||
const l = e.key.toUpperCase();
|
||||
if (/^[A-Z]$/.test(l) && !over) guess(l);
|
||||
});
|
||||
|
||||
document.getElementById('hm-restart').addEventListener('click', initGame);
|
||||
|
||||
initGame();
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 41 KiB |
@@ -7,7 +7,7 @@
|
||||
viewBox="0 0 200 200"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
inkscape:export-filename="endangered.png"
|
||||
inkscape:export-filename="leastconcern.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:version="1.4.3 (0d15f75, 2025-12-25)"
|
||||
@@ -27,12 +27,12 @@
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="0.59"
|
||||
inkscape:cx="305.9322"
|
||||
inkscape:cx="305.08475"
|
||||
inkscape:cy="369.49153"
|
||||
inkscape:window-width="1637"
|
||||
inkscape:window-width="1512"
|
||||
inkscape:window-height="685"
|
||||
inkscape:window-x="1715"
|
||||
inkscape:window-y="111"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="83"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
@@ -68,7 +68,7 @@
|
||||
r="100"
|
||||
inkscape:label="border" />
|
||||
<circle
|
||||
style="fill:#ff6600;fill-opacity:1;stroke-width:0.251354"
|
||||
style="fill:#008000;fill-opacity:1;stroke-width:0.251354"
|
||||
id="path1-6"
|
||||
cy="100"
|
||||
cx="100"
|
||||
@@ -76,14 +76,14 @@
|
||||
inkscape:label="bg" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0.33940673,0,0,0.42414264,-29.953106,38.567598)"
|
||||
transform="matrix(0.33940673,0,0,0.42414264,-29.612494,38.567598)"
|
||||
id="text3"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:263.496px;font-family:'Arial Unicode MS';-inkscape-font-specification:'Arial Unicode MS, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect4);display:inline;fill:#1a1a1a"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:263.496px;font-family:'Arial Unicode MS';-inkscape-font-specification:'Arial Unicode MS, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;writing-mode:lr-tb;direction:ltr;white-space:pre;shape-inside:url(#rect4);display:inline;fill:#ffffff"
|
||||
x="375.42374"
|
||||
y="0"
|
||||
inkscape:label="text"><tspan
|
||||
x="194.10007"
|
||||
x="208.70299"
|
||||
y="239.14691"
|
||||
id="tspan2">EN</tspan></text>
|
||||
id="tspan1">LC</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
+1
-1
@@ -822,7 +822,7 @@ input:focus {
|
||||
flex:1;
|
||||
}
|
||||
|
||||
/* flash message css please review */
|
||||
/* flash message css */
|
||||
.flash-container {
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
{% extends "base.jinja" %}
|
||||
{% block title %}About{% endblock %}
|
||||
{% block head %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
{% from 'button.jinja' import button %}
|
||||
<section style="padding: 100px 20px;">
|
||||
<h1>About Komodo Hub</h1>
|
||||
<p>
|
||||
Komodo Hub is a website deisgned to assist and educate people worldwide about conservation, with a focus on Indonesia. We aim to inform people on how to better
|
||||
protect wildlife and their habitats.
|
||||
</p>
|
||||
<p>
|
||||
Badan Pusat Statistik, the Indonesian Bureau of Statistics, has recently published data on the country’s endangered endemic species. Despite spending millions
|
||||
of dollars on conservation efforts, the government might have not seen any significant breakthroughs in the population of some species. The success of Komodo
|
||||
has been largely exclusive, and the world is now left with merely less than 100 Sumatran Tigers, Javan Rhinoceros, Bali Mynas, Javan Eagles, Tarsius, and
|
||||
Celebes Crested Macaques, respectively. Habitat loss remains the primary cause of the problems. Other causes include habitat changes, commercial
|
||||
over-exploitation, the introduction of harmful non-native species, pollution, and the spread of diseases.
|
||||
</p>
|
||||
<p>
|
||||
In 2022 the Komodo Foundation, a not-for-profit organization, was given a substantial amount of funds to initiate the development of a revolutionary digital
|
||||
platform for animal conservation in Indonesia. Komodo Hub.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,64 @@
|
||||
{% extends "base.jinja" %}
|
||||
{% block title %}Hangman{% endblock %}
|
||||
{% block head %}
|
||||
<style>
|
||||
#hangman-app { padding: 1.5rem 0; max-width: 520px; margin: 0 auto; }
|
||||
.hm-title { font-size: 22px; font-weight: 500; margin: 0 0 0.25rem; }
|
||||
.hm-subtitle { font-size: 14px; color: #6b7280; margin: 0 0 1.5rem; }
|
||||
.hm-canvas-wrap { background: #f9fafb; border-radius: 12px; padding: 1rem; margin-bottom: 1.25rem; display: flex; justify-content: center; }
|
||||
.hm-word { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin-bottom: 1.25rem; }
|
||||
.hm-letter { width: 32px; text-align: center; }
|
||||
.hm-letter span { display: block; font-size: 22px; font-weight: 500; min-height: 28px; }
|
||||
.hm-letter hr { border: none; border-top: 2px solid #111827; margin: 4px 0 0; }
|
||||
.hm-guessed { font-size: 13px; color: #6b7280; text-align: center; margin-bottom: 1.25rem; min-height: 18px; }
|
||||
.hm-keyboard { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; margin-bottom: 1.25rem; }
|
||||
.hm-key { width: 36px; height: 36px; border-radius: 8px; border: 1px solid #d1d5db; background: #fff; font-size: 13px; font-weight: 500; cursor: pointer; transition: background 0.1s; }
|
||||
.hm-key:hover:not(:disabled) { background: #f3f4f6; }
|
||||
.hm-key:disabled { opacity: 0.3; cursor: not-allowed; }
|
||||
.hm-key.wrong { background: #fee2e2; color: #991b1b; border-color: #fca5a5; }
|
||||
.hm-key.right { background: #dcfce7; color: #166534; border-color: #86efac; }
|
||||
.hm-msg { text-align: center; font-size: 15px; font-weight: 500; margin-bottom: 1rem; min-height: 22px; }
|
||||
.hm-msg.win { color: #166534; }
|
||||
.hm-msg.lose { color: #991b1b; }
|
||||
.hm-lives { text-align: center; font-size: 13px; color: #6b7280; margin-bottom: 0.75rem; }
|
||||
</style>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
{% from 'button.jinja' import button %}
|
||||
|
||||
<div id="hangman-app">
|
||||
<p class="hm-title">Hangman</p>
|
||||
<p class="hm-subtitle">Guess the species name, one letter at a time.</p>
|
||||
|
||||
<div class="hm-canvas-wrap">
|
||||
<svg id="gallows" width="160" height="160" viewBox="0 0 160 160">
|
||||
<line x1="20" y1="155" x2="140" y2="155" stroke="#9ca3af" stroke-width="2"/>
|
||||
<line x1="50" y1="155" x2="50" y2="10" stroke="#9ca3af" stroke-width="2"/>
|
||||
<line x1="50" y1="10" x2="110" y2="10" stroke="#9ca3af" stroke-width="2"/>
|
||||
<line x1="110" y1="10" x2="110" y2="30" stroke="#9ca3af" stroke-width="2"/>
|
||||
<circle id="p-head" cx="110" cy="42" r="12" stroke="#111827" stroke-width="2" fill="none" display="none"/>
|
||||
<line id="p-body" x1="110" y1="54" x2="110" y2="100" stroke="#111827" stroke-width="2" display="none"/>
|
||||
<line id="p-larm" x1="110" y1="65" x2="88" y2="85" stroke="#111827" stroke-width="2" display="none"/>
|
||||
<line id="p-rarm" x1="110" y1="65" x2="132" y2="85" stroke="#111827" stroke-width="2" display="none"/>
|
||||
<line id="p-lleg" x1="110" y1="100" x2="88" y2="125" stroke="#111827" stroke-width="2" display="none"/>
|
||||
<line id="p-rleg" x1="110" y1="100" x2="132" y2="125" stroke="#111827" stroke-width="2" display="none"/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div id="hm-word" class="hm-word"></div>
|
||||
<div id="hm-lives" class="hm-lives">Lives: 6</div>
|
||||
<div id="hm-guessed" class="hm-guessed"></div>
|
||||
<div id="hm-msg" class="hm-msg"></div>
|
||||
<div id="hm-keyboard" class="hm-keyboard"></div>
|
||||
|
||||
<div id="hm-restart-wrap" style="display:none; text-align:center;">
|
||||
{{ button(url='/game', button_text='Play Again!', extra_classes='homepage-btn', id='hm-restart') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const SPECIES_LIST = {{ species_list | tojson }};
|
||||
</script>
|
||||
<script src="{{ url_for('static', filename='game.js') }}"></script>
|
||||
|
||||
{% endblock %}
|
||||
@@ -29,7 +29,8 @@
|
||||
<a href="/settings">Settings</a>
|
||||
<a href="/logout">Logout</a>
|
||||
{% else %}
|
||||
{{ button(url='/login', button_text='Login/Register', extra_classes='') }}
|
||||
{{ button(url='/login', button_text='Login', extra_classes='') }}
|
||||
{{ button(url='/register', button_text='Register', extra_classes='') }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
Reference in new issue
Block a user