This commit is contained in:
Turtle committed 2025-12-31 12:13:23 +01:00
1 parent bdeaece35a
commit 16bc5ea38e
11 files changed
+169 -62

No files matched your search

+26
View File
@@ -0,0 +1,26 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="./auth.js"></script>
<script src="./lib/basic.js"></script>
<script src="./help/data_xample.js"></script>
</head>
<body>
<script>
(async () => {
try {
await createTemp();
location.href = "./login.html";
} catch(err) {
alert("Ein Fehler ist aufgetreten: " + err);
}
})();
</script>
</body>
</html>
+28 -19
View File
@@ -3,12 +3,11 @@ async function createTemp() {
await couchDB.set("users", {
"turtle": {
"password": "1234",
"level": 1,
"level": 0,
"xp": 0,
"avatar": null,
"abilities": [
],
"enabled_abilities": [
],
"abilities": [],
"enabled_abilities": [],
"role": "student",
"courses": [
"weiche_ware",
@@ -17,8 +16,9 @@ async function createTemp() {
},
"dumble-door": {
"password": "bla",
"level": 4,
"avatar": "https://static.turtle-coding-gbr.de/profile-pic.png",
"level": 10,
"xp": 0,
"avatar": "https://static.turtle-coding-gbr.de/gmci/profile-pic.png",
"abilities": [
],
"enabled_abilities": [
@@ -30,9 +30,18 @@ async function createTemp() {
},
"narrator": {
"password": "stanley",
"level": 4,
"avatar": "https://static.turtle-coding-gbr.de/st",
"level": 10,
"xp": 0,
"avatar": "https://static.turtle-coding-gbr.de/gmci/st",
"abilities": [
"dark_mode",
"accent_color",
"pink_mode",
"profile_pic",
"simple_border",
"gold_border",
"epic_border",
"title_of_honor"
],
"enabled_abilities": [
],
@@ -72,17 +81,17 @@ async function createTemp() {
{
"date": "2025-12-27",
"questions": [
{ "title": "1", "type": "text" },
{ "title": "2", "type": "scala" }
{ "title": "Wie war die Vorlesung?", "type": "text" },
{ "title": "Wie war der Professor?", "type": "scala" }
],
"result": [
["Gut, aber ...", 5],
["Schlecht", 1]
["Gut, weil ...", 5],
["Schlecht, weil ...", 1]
]
}
],
"start_date": "2025-12-23",
"expire_date": "2025-12-27"
"expire_date": "2026-02-20"
});
await couchDB.set("course:weiche_ware", {
"title": "Weiche Ware",
@@ -99,8 +108,8 @@ async function createTemp() {
}
],
"result": [
["Gut, aber ...", 5],
["Schlecht", 1]
["Gut, weil ...", 5],
["Schlecht, weil ...", 1]
],
"result_history": [
{
@@ -110,12 +119,12 @@ async function createTemp() {
{ "title": "2", "type": "scala" }
],
"result": [
["Gut, aber ...", 5],
["Schlecht", 1]
["Gut, weil ...", 5],
["Schlecht, weil ...", 1]
]
}
],
"start_date": "2025-12-23",
"expire_date": "2025-12-27"
"expire_date": "2025-02-20"
});
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

+64 -8
View File
@@ -374,14 +374,15 @@ var userData = null;
const userDataListener = [];
async function setUserData(couchDB) {
const res = await getUserData(couchDB);
if (res == null) {
const user = await getUserData(couchDB);
if (user == null) {
location.href = "../login.html";
return false;
}
userData = res;
updateAllProfiles(res);
_constructProfile(res);
userData = user;
updateAllProfiles(user);
_constructProfile(user);
await checkUserCourses(couchDB, user);
while (userDataListener.length > 0) {
const call = userDataListener[userDataListener.length - 1];
@@ -407,18 +408,51 @@ async function updateUserData(couchDB, user = userData) {
function updateAllProfiles(user) {
const hasProfilAbility = user.enabled_abilities.includes("profile_pic");
const features = user.enabled_abilities ??= [];
const hasProfilAbility = features.includes("profile_pic");
const profiles = document.getElementsByClassName("profile");
for (var i of profiles) {
if (hasProfilAbility) {
if (hasProfilAbility && user.avatar) {
i.style.backgroundImage = `url("${user.avatar}")`;
} else {
i.style.removeProperty("backgroundImage");
if (features.includes("pink_mode")) {
i.style.backgroundImage = `url("https://static.turtle-coding-gbr.de/gmci/rosa_profil.png")`;
} else {
i.style.backgroundImage = `url("https://static.turtle-coding-gbr.de/gmci/standart_profil.png")`;
}
}
i.onclick = _onProfileClick;
}
}
async function checkUserCourses(couchDB, userData) {
for (var cName of userData.courses) {
const course = await couchDB.get("course:" + cName);
if (!course || !course.expire_date) continue;
const expire_date = new Date(course.expire_date);
if (expire_date < new Date()) {
course.result_history ??= [];
course.questions ??= [];
course.result ??= [];
if (course.questions.length == 0 || course.result.length == 0) continue;
course.result_history.push({
"date": course.start_date ?? expire_date,
"questions": course.questions,
"result": course.result
});
course.questions = [];
course.result = [];
await couchDB.set("course:" + cName, course);
console.log(`Course ${cName} expired`);
}
}
}
function _onProfileClick(event) {
var buttonRect = this.getBoundingClientRect();
@@ -543,3 +577,25 @@ function getUserDisplayName(user) {
const title_of_honor = hasHonor ? "(Sir) " : "";
return `${title_of_honor}${ !user.title ? "" : user.title + " " }${ form1(user.name) }`;
}
async function levelUpXP(couchDB, user = userData, xp = 1) {
var resLevelUp = false;
userData.xp ??= 0;
userData.level ??= 0;
userData.xp += xp;
while (userData.xp >= userData.level+1) {
userData.xp -= (userData.level + 1);
userData.level++;
resLevelUp = true;
}
if (userData.xp < 0) {
console.error("UserData-XP was below zero!");
userData.xp = 0;
}
await updateUserData(couchDB, user);
return resLevelUp;
}
+10 -16
View File
@@ -1,12 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Login</title>
<link rel="stylesheet" href="./lib/basic.css" />
<script src="./auth.js" defer></script>
<script src="./lib/basic.js" defer></script>
<script src="./auth.js"></script>
<script src="./lib/basic.js"></script>
<style>
* {
box-sizing: border-box;
@@ -57,7 +57,7 @@
button {
width: 100%;
padding: 0.6rem;
background-color: #2ea44f;
background-color: var(--accent_color_fg);
color: #fff;
border: none;
border-radius: 6px;
@@ -67,7 +67,7 @@
}
button:hover {
background-color: #279f43;
background-color: var(--accent_color_fg_o);
}
.signup-text {
@@ -113,9 +113,7 @@
<button type="button" onclick="login()">Sign in</button>
<div class="signup-text">
Don't have an account yet? <a href="signup.html">Sign up</a>
</div>
<div class="signup-text">Don't have an account yet? <a href="signup.html">Sign up</a></div>
</div>
<script>
@@ -124,7 +122,7 @@
async function getData() {
try {
const res = await couchDB.get("users");
return res || {};
return res ?? {};
} catch (e) {
console.error("Failed to get users:", e);
return {};
@@ -133,10 +131,7 @@
async function login() {
const data = await getData();
const username = document
.getElementById("username")
.value.trim()
.toLowerCase();
const username = document.getElementById("username").value.trim().toLowerCase();
const password = document.getElementById("password").value;
const user = data[username];
@@ -147,8 +142,7 @@
return alert("Incorrect password!");
}
if (user.role === "student") {
location.href =
"./student/uebersicht.html?user=" + username;
location.href = "./student/uebersicht.html?user=" + username;
return;
} else {
location.href = "./prof/uebersicht.html?user=" + username;
+7 -2
View File
@@ -108,9 +108,14 @@ const _skillCb = {
},
"unset_epic_border": () => unsetProfileBorder(),
"title_of_honor": function() {},
"profile_pic": () => updateAllProfiles(userData)
"profile_pic": () => updateEverything()
};
function updateEverything() {
updateAllProfiles(userData);
refreshOverlays();
}
function chooseAccentColor() {
var elm = getId("skill_chooseAccentColor");
if (!elm) {
@@ -142,7 +147,7 @@ function setAccentColor(elm) {
hideOverlay("skill_chooseAccentColor");
_skillCb.accent_color();
refreshOverlays();
updateEverything()
}
+1 -1
View File
@@ -140,7 +140,7 @@ async function activateSkill(elm, data) {
try { eval(data.call_unset); } catch (err) { console.error(err); }
}
}
refreshOverlays();
updateEverything();
}
async function _buySkill(data) {
const elms = document.getElementsByClassName("skill_" + data.id);
+9 -13
View File
@@ -1,12 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Sign Up</title>
<link rel="stylesheet" href="./lib/basic.css" />
<script src="./auth.js" defer></script>
<script src="./lib/basic.js" defer></script>
<script src="./auth.js"></script>
<script src="./lib/basic.js"></script>
<style>
* {
box-sizing: border-box;
@@ -59,7 +59,7 @@
button {
width: 100%;
padding: 0.6rem;
background-color: #2ea44f;
background-color: var(--accent_color_fg);
color: #fff;
border: none;
border-radius: 6px;
@@ -69,7 +69,7 @@
}
button:hover {
background-color: #279f43;
background-color: var(--accent_color_fg_o);
}
.login-text {
@@ -121,9 +121,7 @@
<button type="button" onclick="signup()">Sign up</button>
<div class="login-text">
Already have an account? <a href="login.html">Sign in</a>
</div>
<div class="login-text">Already have an account? <a href="login.html">Sign in</a></div>
</div>
<script>
@@ -140,10 +138,7 @@
}
async function signup() {
const username = document
.getElementById("username")
.value.trim()
.toLowerCase();
const username = document.getElementById("username").value.trim().toLowerCase();
const password = document.getElementById("password").value;
const role = document.getElementById("role").value;
@@ -165,6 +160,7 @@
data[username] = {
password: password,
level: 1,
xp: 0,
avatar: null,
abilities: [],
enabled_abilities: [],
+24 -3
View File
@@ -103,7 +103,7 @@
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
border-radius: var(--border-radius);
}
.weiter-btn:hover {
background-color: #0056b3;
@@ -130,6 +130,7 @@
<div class="main-container" id="container2" style="display: none;">
<div class="end-dialog">
<h2>Vielen Dank für deine Teilnahme!</h2><br>
<h3 id="level_up" style="display: none;">Level up!<br><br><br></h3>
<button class="weiter-btn" onclick="onEndEvent(this)">
Zurück zur Hauptseite
</button>
@@ -263,7 +264,7 @@ function updateContent(old_page, page) {
if (page >= courseData.questions.length) {
getId("container1").style.display = "none";
getId("container2").style.display = "unset";
updateCourseAnswer(finalResult);
onFinishEva();
return;
}
@@ -272,7 +273,15 @@ function updateContent(old_page, page) {
getId("content").querySelector(".input").focus();
}
async function onEndEvent(elm) {
async function onFinishEva() {
await playLevelSound();
await updateCourseAnswer(finalResult);
if (await levelUpXP(couchDB)) {
const lvlElm = getId("level_up");
if (lvlElm) lvlElm.style.display = "unset";
}
}
async function onEndEvent() {
location.href = "./uebersicht.html?user=" + userData.name;
}
@@ -283,6 +292,18 @@ async function onEndEvent(elm) {
return;
}
if (!courseData.expire_date) {
console.error("courseData.expire_date is null");
return;
}
const expire_date = new Date(courseData.expire_date);
if (courseData.questions.length == 0 || expire_date < new Date()) {
onEndEvent();
return;
}
finalResult = [];
for (var i in courseData.questions) finalResult.push(null);