g3.6
This commit is contained in:
1 parent
bdeaece35a
commit
16bc5ea38e
11 files changed
+169
-62
No files matched your search
+26
@@ -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
@@ -3,12 +3,11 @@ async function createTemp() {
|
|||||||
await couchDB.set("users", {
|
await couchDB.set("users", {
|
||||||
"turtle": {
|
"turtle": {
|
||||||
"password": "1234",
|
"password": "1234",
|
||||||
"level": 1,
|
"level": 0,
|
||||||
|
"xp": 0,
|
||||||
"avatar": null,
|
"avatar": null,
|
||||||
"abilities": [
|
"abilities": [],
|
||||||
],
|
"enabled_abilities": [],
|
||||||
"enabled_abilities": [
|
|
||||||
],
|
|
||||||
"role": "student",
|
"role": "student",
|
||||||
"courses": [
|
"courses": [
|
||||||
"weiche_ware",
|
"weiche_ware",
|
||||||
@@ -17,8 +16,9 @@ async function createTemp() {
|
|||||||
},
|
},
|
||||||
"dumble-door": {
|
"dumble-door": {
|
||||||
"password": "bla",
|
"password": "bla",
|
||||||
"level": 4,
|
"level": 10,
|
||||||
"avatar": "https://static.turtle-coding-gbr.de/profile-pic.png",
|
"xp": 0,
|
||||||
|
"avatar": "https://static.turtle-coding-gbr.de/gmci/profile-pic.png",
|
||||||
"abilities": [
|
"abilities": [
|
||||||
],
|
],
|
||||||
"enabled_abilities": [
|
"enabled_abilities": [
|
||||||
@@ -30,9 +30,18 @@ async function createTemp() {
|
|||||||
},
|
},
|
||||||
"narrator": {
|
"narrator": {
|
||||||
"password": "stanley",
|
"password": "stanley",
|
||||||
"level": 4,
|
"level": 10,
|
||||||
"avatar": "https://static.turtle-coding-gbr.de/st",
|
"xp": 0,
|
||||||
|
"avatar": "https://static.turtle-coding-gbr.de/gmci/st",
|
||||||
"abilities": [
|
"abilities": [
|
||||||
|
"dark_mode",
|
||||||
|
"accent_color",
|
||||||
|
"pink_mode",
|
||||||
|
"profile_pic",
|
||||||
|
"simple_border",
|
||||||
|
"gold_border",
|
||||||
|
"epic_border",
|
||||||
|
"title_of_honor"
|
||||||
],
|
],
|
||||||
"enabled_abilities": [
|
"enabled_abilities": [
|
||||||
],
|
],
|
||||||
@@ -72,17 +81,17 @@ async function createTemp() {
|
|||||||
{
|
{
|
||||||
"date": "2025-12-27",
|
"date": "2025-12-27",
|
||||||
"questions": [
|
"questions": [
|
||||||
{ "title": "1", "type": "text" },
|
{ "title": "Wie war die Vorlesung?", "type": "text" },
|
||||||
{ "title": "2", "type": "scala" }
|
{ "title": "Wie war der Professor?", "type": "scala" }
|
||||||
],
|
],
|
||||||
"result": [
|
"result": [
|
||||||
["Gut, aber ...", 5],
|
["Gut, weil ...", 5],
|
||||||
["Schlecht", 1]
|
["Schlecht, weil ...", 1]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"start_date": "2025-12-23",
|
"start_date": "2025-12-23",
|
||||||
"expire_date": "2025-12-27"
|
"expire_date": "2026-02-20"
|
||||||
});
|
});
|
||||||
await couchDB.set("course:weiche_ware", {
|
await couchDB.set("course:weiche_ware", {
|
||||||
"title": "Weiche Ware",
|
"title": "Weiche Ware",
|
||||||
@@ -99,8 +108,8 @@ async function createTemp() {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"result": [
|
"result": [
|
||||||
["Gut, aber ...", 5],
|
["Gut, weil ...", 5],
|
||||||
["Schlecht", 1]
|
["Schlecht, weil ...", 1]
|
||||||
],
|
],
|
||||||
"result_history": [
|
"result_history": [
|
||||||
{
|
{
|
||||||
@@ -110,12 +119,12 @@ async function createTemp() {
|
|||||||
{ "title": "2", "type": "scala" }
|
{ "title": "2", "type": "scala" }
|
||||||
],
|
],
|
||||||
"result": [
|
"result": [
|
||||||
["Gut, aber ...", 5],
|
["Gut, weil ...", 5],
|
||||||
["Schlecht", 1]
|
["Schlecht, weil ...", 1]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"start_date": "2025-12-23",
|
"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
@@ -374,14 +374,15 @@ var userData = null;
|
|||||||
const userDataListener = [];
|
const userDataListener = [];
|
||||||
|
|
||||||
async function setUserData(couchDB) {
|
async function setUserData(couchDB) {
|
||||||
const res = await getUserData(couchDB);
|
const user = await getUserData(couchDB);
|
||||||
if (res == null) {
|
if (user == null) {
|
||||||
location.href = "../login.html";
|
location.href = "../login.html";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
userData = res;
|
userData = user;
|
||||||
updateAllProfiles(res);
|
updateAllProfiles(user);
|
||||||
_constructProfile(res);
|
_constructProfile(user);
|
||||||
|
await checkUserCourses(couchDB, user);
|
||||||
|
|
||||||
while (userDataListener.length > 0) {
|
while (userDataListener.length > 0) {
|
||||||
const call = userDataListener[userDataListener.length - 1];
|
const call = userDataListener[userDataListener.length - 1];
|
||||||
@@ -407,18 +408,51 @@ async function updateUserData(couchDB, user = userData) {
|
|||||||
|
|
||||||
|
|
||||||
function updateAllProfiles(user) {
|
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");
|
const profiles = document.getElementsByClassName("profile");
|
||||||
for (var i of profiles) {
|
for (var i of profiles) {
|
||||||
if (hasProfilAbility) {
|
if (hasProfilAbility && user.avatar) {
|
||||||
i.style.backgroundImage = `url("${user.avatar}")`;
|
i.style.backgroundImage = `url("${user.avatar}")`;
|
||||||
} else {
|
} 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;
|
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) {
|
function _onProfileClick(event) {
|
||||||
var buttonRect = this.getBoundingClientRect();
|
var buttonRect = this.getBoundingClientRect();
|
||||||
|
|
||||||
@@ -543,3 +577,25 @@ function getUserDisplayName(user) {
|
|||||||
const title_of_honor = hasHonor ? "(Sir) " : "";
|
const title_of_honor = hasHonor ? "(Sir) " : "";
|
||||||
return `${title_of_honor}${ !user.title ? "" : user.title + " " }${ form1(user.name) }`;
|
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
@@ -1,12 +1,12 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Login</title>
|
<title>Login</title>
|
||||||
<link rel="stylesheet" href="./lib/basic.css" />
|
<link rel="stylesheet" href="./lib/basic.css" />
|
||||||
<script src="./auth.js" defer></script>
|
<script src="./auth.js"></script>
|
||||||
<script src="./lib/basic.js" defer></script>
|
<script src="./lib/basic.js"></script>
|
||||||
<style>
|
<style>
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
button {
|
button {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0.6rem;
|
padding: 0.6rem;
|
||||||
background-color: #2ea44f;
|
background-color: var(--accent_color_fg);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
button:hover {
|
button:hover {
|
||||||
background-color: #279f43;
|
background-color: var(--accent_color_fg_o);
|
||||||
}
|
}
|
||||||
|
|
||||||
.signup-text {
|
.signup-text {
|
||||||
@@ -113,9 +113,7 @@
|
|||||||
|
|
||||||
<button type="button" onclick="login()">Sign in</button>
|
<button type="button" onclick="login()">Sign in</button>
|
||||||
|
|
||||||
<div class="signup-text">
|
<div class="signup-text">Don't have an account yet? <a href="signup.html">Sign up</a></div>
|
||||||
Don't have an account yet? <a href="signup.html">Sign up</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -124,7 +122,7 @@
|
|||||||
async function getData() {
|
async function getData() {
|
||||||
try {
|
try {
|
||||||
const res = await couchDB.get("users");
|
const res = await couchDB.get("users");
|
||||||
return res || {};
|
return res ?? {};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Failed to get users:", e);
|
console.error("Failed to get users:", e);
|
||||||
return {};
|
return {};
|
||||||
@@ -133,10 +131,7 @@
|
|||||||
|
|
||||||
async function login() {
|
async function login() {
|
||||||
const data = await getData();
|
const data = await getData();
|
||||||
const username = document
|
const username = document.getElementById("username").value.trim().toLowerCase();
|
||||||
.getElementById("username")
|
|
||||||
.value.trim()
|
|
||||||
.toLowerCase();
|
|
||||||
const password = document.getElementById("password").value;
|
const password = document.getElementById("password").value;
|
||||||
|
|
||||||
const user = data[username];
|
const user = data[username];
|
||||||
@@ -147,8 +142,7 @@
|
|||||||
return alert("Incorrect password!");
|
return alert("Incorrect password!");
|
||||||
}
|
}
|
||||||
if (user.role === "student") {
|
if (user.role === "student") {
|
||||||
location.href =
|
location.href = "./student/uebersicht.html?user=" + username;
|
||||||
"./student/uebersicht.html?user=" + username;
|
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
location.href = "./prof/uebersicht.html?user=" + username;
|
location.href = "./prof/uebersicht.html?user=" + username;
|
||||||
|
|||||||
+7
-2
@@ -108,9 +108,14 @@ const _skillCb = {
|
|||||||
},
|
},
|
||||||
"unset_epic_border": () => unsetProfileBorder(),
|
"unset_epic_border": () => unsetProfileBorder(),
|
||||||
"title_of_honor": function() {},
|
"title_of_honor": function() {},
|
||||||
"profile_pic": () => updateAllProfiles(userData)
|
"profile_pic": () => updateEverything()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function updateEverything() {
|
||||||
|
updateAllProfiles(userData);
|
||||||
|
refreshOverlays();
|
||||||
|
}
|
||||||
|
|
||||||
function chooseAccentColor() {
|
function chooseAccentColor() {
|
||||||
var elm = getId("skill_chooseAccentColor");
|
var elm = getId("skill_chooseAccentColor");
|
||||||
if (!elm) {
|
if (!elm) {
|
||||||
@@ -142,7 +147,7 @@ function setAccentColor(elm) {
|
|||||||
|
|
||||||
hideOverlay("skill_chooseAccentColor");
|
hideOverlay("skill_chooseAccentColor");
|
||||||
_skillCb.accent_color();
|
_skillCb.accent_color();
|
||||||
refreshOverlays();
|
updateEverything()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -140,7 +140,7 @@ async function activateSkill(elm, data) {
|
|||||||
try { eval(data.call_unset); } catch (err) { console.error(err); }
|
try { eval(data.call_unset); } catch (err) { console.error(err); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
refreshOverlays();
|
updateEverything();
|
||||||
}
|
}
|
||||||
async function _buySkill(data) {
|
async function _buySkill(data) {
|
||||||
const elms = document.getElementsByClassName("skill_" + data.id);
|
const elms = document.getElementsByClassName("skill_" + data.id);
|
||||||
|
|||||||
+9
-13
@@ -1,12 +1,12 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Sign Up</title>
|
<title>Sign Up</title>
|
||||||
<link rel="stylesheet" href="./lib/basic.css" />
|
<link rel="stylesheet" href="./lib/basic.css" />
|
||||||
<script src="./auth.js" defer></script>
|
<script src="./auth.js"></script>
|
||||||
<script src="./lib/basic.js" defer></script>
|
<script src="./lib/basic.js"></script>
|
||||||
<style>
|
<style>
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
button {
|
button {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0.6rem;
|
padding: 0.6rem;
|
||||||
background-color: #2ea44f;
|
background-color: var(--accent_color_fg);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
button:hover {
|
button:hover {
|
||||||
background-color: #279f43;
|
background-color: var(--accent_color_fg_o);
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-text {
|
.login-text {
|
||||||
@@ -121,9 +121,7 @@
|
|||||||
|
|
||||||
<button type="button" onclick="signup()">Sign up</button>
|
<button type="button" onclick="signup()">Sign up</button>
|
||||||
|
|
||||||
<div class="login-text">
|
<div class="login-text">Already have an account? <a href="login.html">Sign in</a></div>
|
||||||
Already have an account? <a href="login.html">Sign in</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -140,10 +138,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function signup() {
|
async function signup() {
|
||||||
const username = document
|
const username = document.getElementById("username").value.trim().toLowerCase();
|
||||||
.getElementById("username")
|
|
||||||
.value.trim()
|
|
||||||
.toLowerCase();
|
|
||||||
const password = document.getElementById("password").value;
|
const password = document.getElementById("password").value;
|
||||||
const role = document.getElementById("role").value;
|
const role = document.getElementById("role").value;
|
||||||
|
|
||||||
@@ -165,6 +160,7 @@
|
|||||||
data[username] = {
|
data[username] = {
|
||||||
password: password,
|
password: password,
|
||||||
level: 1,
|
level: 1,
|
||||||
|
xp: 0,
|
||||||
avatar: null,
|
avatar: null,
|
||||||
abilities: [],
|
abilities: [],
|
||||||
enabled_abilities: [],
|
enabled_abilities: [],
|
||||||
|
|||||||
+24
-3
@@ -103,7 +103,7 @@
|
|||||||
background-color: #007bff;
|
background-color: #007bff;
|
||||||
color: white;
|
color: white;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 5px;
|
border-radius: var(--border-radius);
|
||||||
}
|
}
|
||||||
.weiter-btn:hover {
|
.weiter-btn:hover {
|
||||||
background-color: #0056b3;
|
background-color: #0056b3;
|
||||||
@@ -130,6 +130,7 @@
|
|||||||
<div class="main-container" id="container2" style="display: none;">
|
<div class="main-container" id="container2" style="display: none;">
|
||||||
<div class="end-dialog">
|
<div class="end-dialog">
|
||||||
<h2>Vielen Dank für deine Teilnahme!</h2><br>
|
<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)">
|
<button class="weiter-btn" onclick="onEndEvent(this)">
|
||||||
Zurück zur Hauptseite
|
Zurück zur Hauptseite
|
||||||
</button>
|
</button>
|
||||||
@@ -263,7 +264,7 @@ function updateContent(old_page, page) {
|
|||||||
if (page >= courseData.questions.length) {
|
if (page >= courseData.questions.length) {
|
||||||
getId("container1").style.display = "none";
|
getId("container1").style.display = "none";
|
||||||
getId("container2").style.display = "unset";
|
getId("container2").style.display = "unset";
|
||||||
updateCourseAnswer(finalResult);
|
onFinishEva();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,7 +273,15 @@ function updateContent(old_page, page) {
|
|||||||
getId("content").querySelector(".input").focus();
|
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;
|
location.href = "./uebersicht.html?user=" + userData.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,6 +292,18 @@ async function onEndEvent(elm) {
|
|||||||
return;
|
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 = [];
|
finalResult = [];
|
||||||
for (var i in courseData.questions) finalResult.push(null);
|
for (var i in courseData.questions) finalResult.push(null);
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user