Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/ISSUE_TEMPLATE/project-submission.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ body:
- Learning
validations:
required: true
- type: input
id: course
attributes:
label: Course (optional)
description: For coursework, give the programme, official module code and name, scheduled semester, and handbook or project source. Leave blank for personal projects.
placeholder: "AIN-B-29 · Deep Learning/Big Data · Semester 6"
- type: textarea
id: collaboration
attributes:
Expand Down
2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ The submission workflow leaves an acknowledgement and checks whether the reposit

To update or remove your own listing, open an issue or pull request. If you need to discuss something privately, [email Alexander](mailto:alex.rudaev@outlook.com).

For coursework, use the optional `academic` object in `site/projects.json`: `kind` is `coursework` or `companion`, `modules` lists `code`, `name`, and scheduled `semester`, and `source` links the official handbook. Add the project-to-course evidence to [COURSES.md](COURSES.md). Personal projects do not need a course assignment. Module codes and course names are searchable in the showroom.

## Change the website

The website is buildless HTML, CSS, and JavaScript in `site/`. It uses a local JSON catalogue, with no visitor accounts or database. Search and filters run in the browser. An external Google Fonts stylesheet provides the fonts; system sans-serif fonts are the fallback.
Expand Down
28 changes: 28 additions & 0 deletions COURSES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Projects by course

Bachelor of Science in Artificial Intelligence (AIN-B), Deggendorf Institute of Technology. Module codes identify courses; they are **not semester numbers**. Semester means the scheduled curriculum semester, not when a particular author completed a project.

| Semester | Module code | Course | Project |
| --- | --- | --- | --- |
| 2 | AIN-B-10 | Internet Technologies | [Devablos V2](https://github.com/THD-AI/Devablos-Project-V2), [original prototype](https://github.com/THD-AI/Devablos-Project) |
| 3 | AIN-B-16 | Assistance Systems | [Project Apero](https://github.com/THD-AI/Project-Arepo) – decision support and a Rasa chatbot |
| 4 | AIN-B-21 | Machine Learning | [Painfully Trivial](https://github.com/THD-AI/Painfully-Trivial) – train-delay prediction and waste-sorting experiments |
| 4 | AIN-B-22 | Computer Vision | [Painfully Trivial](https://github.com/THD-AI/Painfully-Trivial) – waste-sorting vision project |
| 6 | AIN-B-29 | Deep Learning/Big Data | [CheXVision](https://github.com/THD-AI/chexvision), [CheXVision Mini](https://github.com/THD-AI/chexvision-mini) (companion implementation) |

## Independent work and related projects

- [THD Room Finder](https://github.com/THD-AI/THD-Room-Finder) is an independent campus tool. No course code or semester is assigned.
- [Studybooks](https://github.com/THD-AI/studybooks) spans multiple modules. Use each book's own course information.
- [iTravel](https://github.com/arudaev/iTravel) identifies itself as a Media Technology project. It is outside the AIN-B course list; its exact module and semester are not documented in its README.
- [Smart Bin Recognition](https://github.com/arudaev/smart-bin-recognition) and [bahn-predict](https://github.com/arudaev/bahn-predict) continue ideas from Painfully Trivial. They are successor projects, not additional course submissions. [The delay-prediction paper](https://github.com/arudaev/ml-db-delay-paper) documents the earlier ML work.

## Sources and corrections

Course codes, names, and scheduled semesters were checked on 18 October 2026 against the [official AIN-B module handbook](https://www.th-deg.de/Studierende/Antraege-und-Organisatorisches/Modulhandbuecher/modulhandbuch-ain-b-ws25-26.pdf) (document dated 7 September 2026; Internet Technologies p. 33, Assistance Systems p. 51, Machine Learning p. 67, Computer Vision p. 70, Deep Learning/Big Data p. 93). The [2023 handbook](https://cs-mariakirchen.th-deg.de/Studierende/Antraege-und-Organisatorisches/Modulhandbuecher/Module%20Handbooks/modulhandbuch-ain-b-en.pdf) also identifies these modules in the original cohort curriculum.

Project associations use the creators' confirmation and repository evidence: [CheXVision README](https://github.com/arudaev/chexvision#readme), [Mini README](https://github.com/arudaev/chexvision-mini#readme), [Painfully Trivial README](https://github.com/arudaev/Painfully-Trivial#readme), and [Devablos prototype README](https://github.com/THD-AI/Devablos-Project#readme). Alexander confirmed the Assistance Systems association for Apero and both course associations for Painfully Trivial. Its README explicitly records Machine Learning; the Computer Vision association is creator-confirmed rather than a claim of a separate graded submission.

The official course name is **Internet Technologies**, not Ethernet Technologies, and **Assistance Systems**. Rasa is a framework used by Apero, not a separate module. Project names, creator credits, original artwork, licences, and repository URLs are preserved. GitHub has no separate repository display-name field, so course-first names appear in descriptions, documentation, and the showroom.

Curricula can change. When adding coursework, provide the programme, exact module code, course name, scheduled semester, handbook edition, and evidence linking the project to the course. For personal work, leave course fields empty. Never infer an academic assignment from its technical subject alone.
3 changes: 2 additions & 1 deletion asset-sources.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
"project-painfully-trivial.png": "https://raw.githubusercontent.com/arudaev/Painfully-Trivial/main/.github/banner.png",
"project-devablos.png": "https://raw.githubusercontent.com/THD-AI/Devablos-Project-V2/main/.github/banner.png",
"project-room.webp": "https://raw.githubusercontent.com/arudaev/THD-Room-Finder/main/website/assets/hero-day.webp",
"history-avatar-first-redesign.png": "https://github.com/THD-AI/.github/tree/main/archive/2026-10-17-first-redesign"
"history-avatar-first-redesign.png": "https://github.com/THD-AI/.github/tree/main/archive/2026-10-17-first-redesign",
"project-apero.png": "https://raw.githubusercontent.com/arudaev/Project-Arepo/main/.github/banner.png"
}
17 changes: 17 additions & 0 deletions scripts/check.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,23 @@ for (const project of collection.projects) {
https(creator.url, 'creator');
}
assert(Array.isArray(project.tags) && project.tags.every(t => typeof t === 'string'), 'Project tags must be strings');
if (project.academic) {
const academic = project.academic;
assert(['coursework', 'companion', 'independent', 'collection'].includes(academic.kind), 'Known academic context required');
if (['coursework', 'companion'].includes(academic.kind)) {
assert(academic.modules?.length, 'Coursework must identify its modules');
https(academic.source, 'course source');
const moduleCodes = new Set();
for (const module of academic.modules) {
assert(/^AIN-B-\d+$/.test(module.code) && !moduleCodes.has(module.code), 'Unique official AIN-B module code required');
moduleCodes.add(module.code);
assert(module.name?.trim(), 'Course name required');
assert(Number.isInteger(module.semester) && module.semester >= 1 && module.semester <= 7, 'Curriculum semester must be 1–7');
}
} else {
assert(academic.label?.trim() && !academic.modules, 'Independent work and collections must not imply a single course assignment');
}
}
if (project.image) {
assert(project.image.startsWith('assets/') && !project.image.includes('..'), 'Project image must be a local asset');
await access(path.join(site, project.image));
Expand Down
2 changes: 1 addition & 1 deletion site/404.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="theme-color" content="#eeedf8"><title>Page not found – THD AI</title><link rel="stylesheet" href="/style.css?v=3"><link rel="icon" type="image/png" href="/assets/symbol.png"></head><body>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="theme-color" content="#eeedf8"><title>Page not found – THD AI</title><link rel="stylesheet" href="/style.css?v=4"><link rel="icon" type="image/png" href="/assets/symbol.png"></head><body>
<a class="skip-link" href="#content">Skip to content</a>
<header class="site-header wrap"><a class="identity" href="/" aria-label="THD AI home"><img src="/assets/symbol.png" width="48" height="48" alt=""><span>THD <b>AI</b></span></a><nav aria-label="Main navigation"><a href="/#projects">The showroom</a><a href="/#about">The idea</a><a href="/history/">Earlier chapters</a></nav><a class="header-action" href="/#share">Share your project ↗</a></header>
<main id="content" class="history-main wrap"><p class="eyebrow">404 / A small detour</p><h1>This shelf<br>is empty.</h1><p class="lede">That page may have moved. The showroom and project collection are still here.</p><a class="button primary" href="https://thd-ai.github.io/">Back to the showroom ↗</a></main>
Expand Down
16 changes: 13 additions & 3 deletions site/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,23 @@ function card(project) {
bottom.append(safeLink('Explore the project ↗', project.repository));
if (project.demo) bottom.append(safeLink(project.demoLabel || 'Try it ↗', project.demo));
else if (project.community) bottom.append(safeLink('Build with others ↗', project.community));
article.append(projectArt(project), meta, element('h3', '', project.title), element('p', 'project-description', project.description), creators, bottom, element('p', 'collaboration', project.collaboration));
article.append(projectArt(project), meta, element('h3', '', project.title));
if (project.academic) {
const context = element('p', 'project-course');
if (project.academic.modules) {
context.append(safeLink(project.academic.modules.map(module => `${module.code} · Semester ${module.semester}`).join(' / '), project.academic.source));
if (project.academic.kind === 'companion') context.append(document.createTextNode(' · Companion project'));
} else context.textContent = project.academic.label;
article.append(context);
}
article.append(element('p', 'project-description', project.description), creators, bottom, element('p', 'collaboration', project.collaboration));
return article;
}
function render() {
const query = search.value.trim().toLocaleLowerCase();
const visible = projects.filter(project => {
const haystack = [project.title, project.description, project.categoryLabel, ...project.tags, ...project.creators.map(c => c.name)].join(' ').toLocaleLowerCase();
const courseTerms = project.academic?.modules?.flatMap(module => [module.code, module.name, `Semester ${module.semester}`]) || [project.academic?.label || ''];
const haystack = [project.title, project.description, project.categoryLabel, ...courseTerms, ...project.tags, ...project.creators.map(c => c.name)].join(' ').toLocaleLowerCase();
return (activeFilter === 'all' || project.categories.includes(activeFilter)) && haystack.includes(query);
});
grid.replaceChildren(...visible.map(card));
Expand All @@ -83,7 +93,7 @@ async function loadProjects() {
document.querySelector('#load-error').hidden = true;
document.querySelector('#project-count').textContent = 'Opening the showroom…';
try {
const response = await fetch(new URL('projects.json', import.meta.url));
const response = await fetch(new URL('projects.json', import.meta.url), { cache: 'no-cache' });
if (!response.ok) throw new Error(`Project data: ${response.status}`);
const data = await response.json();
if (!Array.isArray(data.projects)) throw new Error('Invalid project collection');
Expand Down
Binary file added site/assets/project-apero.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions site/credits/index.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="theme-color" content="#eeedf8"><title>Credits & licences – THD AI</title><link rel="stylesheet" href="../style.css?v=3"><link rel="icon" type="image/png" href="../assets/symbol.png"></head><body>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="theme-color" content="#eeedf8"><title>Credits & licences – THD AI</title><link rel="stylesheet" href="../style.css?v=4"><link rel="icon" type="image/png" href="../assets/symbol.png"></head><body>
<a class="skip-link" href="#content">Skip to content</a>
<header class="site-header wrap"><a class="identity" href="../" aria-label="THD AI home"><img src="../assets/symbol.png" width="48" height="48" alt=""><span>THD <b>AI</b></span></a><nav aria-label="Main navigation"><a href="../#projects">The showroom</a><a href="../#about">The idea</a><a href="../history/">Earlier chapters</a></nav><a class="header-action" href="../#share">Share your project ↗</a></header>
<main id="content" class="history-main wrap"><div class="credits-copy"><p class="eyebrow">The people and sources behind the work</p><h1>Give good work<br>its credit.</h1><p class="lede">The showroom connects projects. It does not take ownership of them. Every project keeps its original creators, repository, and licence.</p>
<h2>Campus artwork</h2><p>The public campus banner adapts the campus illustration from <a href="https://github.com/arudaev/THD-Room-Finder/blob/main/design/roadmap/README.md">THD Room Finder</a>. Its source photograph is <a href="https://commons.wikimedia.org/wiki/File:Hauptcampus_der_Technischen_Hochschule_Deggendorf_2018.jpg">Hauptcampus der Technischen Hochschule Deggendorf 2018</a> by <strong>Danube-Waidler</strong>, licensed <a href="https://creativecommons.org/licenses/by-sa/4.0/">CC BY-SA 4.0</a>. The repainted illustration and public banner are shared under that same licence. The banner widens the composition, changes the light and palette, simplifies people into grey silhouettes, and adds THD AI lettering.</p><p>The member-workspace and showcase illustrations follow the same visual family, using the Room Finder art as visual references. These new illustrations are also shared under CC BY-SA 4.0. The original public banner remains unchanged. Detailed source notes and production briefs live in <a href="https://github.com/THD-AI/.github/blob/main/BRAND.md">the brand record</a>.</p>
<h2>The open-portal symbol</h2><p>The THD AI symbol is an open architectural portal with a warm sun at its centre: room for a person, an idea, and what comes next. It replaces the earlier boxed initials. The new symbol and earlier typographic badge are community identity artwork shared under <a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a>. No official university marks are used.</p>
<h2>Project images and creators</h2><ul><li><strong>THD Room Finder:</strong> Alexander Rudaev. The study-space illustration is taken from its original public repository; the project is GPL-3.0. Consult the project's artwork notes for asset-specific terms.</li><li><strong>CheXVision:</strong> Alexander Rudaev. Original project banner from <a href="https://github.com/arudaev/chexvision">the source repository</a>; its licence is retained.</li><li><strong>Painfully Trivial:</strong> Alexander Rudaev, FaresM7, and TheSameerCode, as credited contributors. Original project banner from <a href="https://github.com/arudaev/Painfully-Trivial">the source repository</a>; its licence is retained.</li><li><strong>Devablos V2:</strong> Alexander Rudaev and Denisa Iulia. Original banner from <a href="https://github.com/THD-AI/Devablos-Project-V2">the archived project</a>; GPL-3.0.</li><li><strong>Course Studybooks and CheXVision Mini:</strong> Alexander Rudaev. The simple book and network motifs on this website are presentation graphics, rather than screenshots of either project.</li></ul><p>Image source URLs are recorded in <a href="https://github.com/THD-AI/thd-ai.github.io/blob/main/asset-sources.json">asset-sources.json</a>. Historical visuals retain their original rights and are not relicensed by appearing in the archive.</p>
<h2>Project images and creators</h2><ul><li><strong>THD Room Finder:</strong> Alexander Rudaev. The study-space illustration is taken from its original public repository; the project is GPL-3.0. Consult the project's artwork notes for asset-specific terms.</li><li><strong>CheXVision:</strong> Alexander Rudaev. Original project banner from <a href="https://github.com/arudaev/chexvision">the source repository</a>; its licence is retained.</li><li><strong>Painfully Trivial:</strong> Alexander Rudaev, FaresM7, and TheSameerCode, as credited contributors. Original project banner from <a href="https://github.com/arudaev/Painfully-Trivial">the source repository</a>; its licence is retained.</li><li><strong>Devablos V2:</strong> Alexander Rudaev and Denisa Iulia. Original banner from <a href="https://github.com/THD-AI/Devablos-Project-V2">the archived project</a>; GPL-3.0.</li><li><strong>Project Apero:</strong> Alexander Rudaev and shafwanur. Original banner from <a href="https://github.com/arudaev/Project-Arepo">the source repository</a>; GPL-3.0.</li><li><strong>Course Studybooks and CheXVision Mini:</strong> Alexander Rudaev. The simple book and network motifs on this website are presentation graphics, rather than screenshots of either project.</li></ul><p>Image source URLs are recorded in <a href="https://github.com/THD-AI/thd-ai.github.io/blob/main/asset-sources.json">asset-sources.json</a>. Historical visuals retain their original rights and are not relicensed by appearing in the archive.</p>
<h2>Website</h2><p>The original website code and documentation are <a href="https://github.com/THD-AI/thd-ai.github.io/blob/main/LICENSE">MIT-licensed</a>. This does not relicense the images or linked projects. The typefaces are Manrope and DM Sans, served by <a href="https://fonts.google.com/">Google Fonts</a>, with system sans-serif fallbacks. The site has no analytics, visitor accounts, or advertising.</p><p>For a credit correction, listing update, or removal request, <a href="https://github.com/THD-AI/thd-ai.github.io/issues">open an issue</a> or <a href="mailto:alex.rudaev@outlook.com">email Alexander</a>.</p></div></main>
<footer class="site-footer wrap"><div><a class="identity" href="../"><img src="../assets/symbol.png" width="38" height="38" alt=""><span>THD <b>AI</b></span></a><p>An independent project showroom.<br>Made with care, around THD.</p></div><div class="footer-links"><a href="../#projects">The showroom</a><a href="../history/">Visual history</a><a href="../credits/">Credits & licences</a><a href="https://github.com/THD-AI">GitHub ↗</a></div><p class="footer-note">Started in 2023. Room for what comes next.<br>Independent of THD; no university endorsement.</p></footer></body></html>
Loading
Loading