diff --git a/Exercise 1/css/style.css b/Exercise 1/css/style.css
new file mode 100644
index 00000000..e69de29b
diff --git a/Exercise 1/index.html b/Exercise 1/index.html
new file mode 100644
index 00000000..8cd9fffe
--- /dev/null
+++ b/Exercise 1/index.html
@@ -0,0 +1,143 @@
+
+
+
+
+
+ Exercise 1 By Mohamad Dabbabo
+
+
+
+
+ Exercise 1 by Mohamad Dabbabo
+ Date Submitted: 28/04/2025
+
+
+
+
+
+
+ Some facts about me:
+
+
+
+ First Name
+ Last Name
+ Favorite Movie
+ Favorite Song
+ Favorite Video
+
+
+
+
+ Mohamad
+ Dabbabo
+
+
+ Ghost in the Shell (1995) Cyberpunk, AI, Philosophy, Identity
+
+
+
+
+
+ Click “Play” to hear this concert performance held in memory of the 2011 victims.
+
+
+ Your browser doesn’t support audio.
+
+
+
+
+
+ Your browser doesn’t support video.
+
+
+
+
+
+
+
+
+
+ Enter your details below:
+
+
+
+
+
diff --git a/Exercise 1/js/script.js b/Exercise 1/js/script.js
new file mode 100644
index 00000000..e69de29b
diff --git a/Exercise 1/media/Kenji_Kawai_Making_of_a_Cyborg.mp3 b/Exercise 1/media/Kenji_Kawai_Making_of_a_Cyborg.mp3
new file mode 100644
index 00000000..f38739f7
Binary files /dev/null and b/Exercise 1/media/Kenji_Kawai_Making_of_a_Cyborg.mp3 differ
diff --git a/Exercise 2/css/style.css b/Exercise 2/css/style.css
new file mode 100644
index 00000000..cf7bfd8e
--- /dev/null
+++ b/Exercise 2/css/style.css
@@ -0,0 +1,127 @@
+/* palette variables (for later) */
+:root{
+ --primary:#0077b6; /* deep blue */
+ --accent:#00b4d8; /* cyan */
+ --light:#f0f8ff; /* very light blue */
+ --bg:#e8f4ff; /* page background */
+ --border:#185b8c; /* darker blue */
+ --table-head:#e63946;/* red */
+ }
+
+ /* base */
+ body{
+ margin:0;
+ font-family:Arial, Helvetica, sans-serif; /* Fonts I picked that resonate with me */
+ background:var(--bg);
+ color:#222;
+ padding:0 12px 40px;
+ }
+
+ /* reusable soft-card */
+ .soft{
+ background:#fff;
+ border:2px solid var(--border);
+ padding:20px;
+ margin:24px auto;
+ max-width:940px;
+ box-shadow:0 0 12px #0077b620; /* subtle bloom */
+ }
+
+ /* headings */
+ h1{
+ color:#fff;
+ background:var(--primary);
+ text-align:center;
+ margin:0 -12px 24px;
+ padding:28px 12px;
+ text-shadow:0 0 6px #ffffffaa; /* glowing effect */
+ }
+ h2{
+ color:var(--primary);
+ border-bottom:4px solid var(--accent);
+ padding-bottom:4px;
+ margin:28px auto 12px;
+ max-width:940px;
+ text-shadow:0 0 4px #00b4d880;
+ }
+ h3{
+ margin:6px 0 24px;
+ color:var(--accent);
+ text-align:center;
+ text-shadow:0 0 4px #00b4d880;
+ }
+
+ /* description paragraph */
+ p:first-of-type{
+ max-width:760px;
+ margin:0 auto 24px;
+ }
+
+ /* table */
+ table {
+ border-collapse: collapse;
+ width: 50%;
+ margin-left: auto;
+ margin-right: auto;
+ text-align: center;
+ }
+
+ th,td{
+ border:1px solid var(--accent);
+ padding:10px 6px;
+ text-align:center;
+ }
+ th{
+ background:var(--table-head);
+ color:#fff;
+ }
+
+ /* media thumbs */
+ img{
+ border:4px solid var(--accent);
+ padding:4px;
+ background:#fff;
+ box-shadow:0 0 8px #00b4d820;
+ }
+
+ /* form */
+ form{
+ background:#fff;
+ border:2px solid var(--border);
+ padding:20px;
+ max-width:540px;
+ margin:24px auto;
+ box-shadow:0 0 10px #0077b620;
+ }
+ label{display:block;margin:10px 0;}
+ input,select,textarea{
+ width:100%;max-width:100%;
+ padding:6px;border:1px solid #ccc;margin-top:4px;
+ }
+ fieldset{
+ border:1px solid var(--accent);
+ padding:10px;margin:14px 0;
+ }
+
+ /* Button CSS, background uses primary variable, no border, changes cursor to pointer */
+ button{
+ background:var(--primary);
+ color:#fff;
+ border:none;
+ padding:8px 18px;
+ margin-top:12px;
+ cursor:pointer;
+ }
+ /* This makes the reset button have a unique */
+ button[type="reset"]{background:var(--accent);}
+
+ /* This uses :hover to change colors */
+ button:hover{
+ background:var(--light);
+ color:#000000;
+ box-shadow:0 0 6px #00b4d8aa;
+ }
+
+ /* figures */
+ figure{margin:24px auto;max-width:320px;text-align:center;}
+ figcaption{margin-bottom:6px;font-weight:bold;}
\ No newline at end of file
diff --git a/Exercise 2/index.html b/Exercise 2/index.html
new file mode 100644
index 00000000..5d2943ab
--- /dev/null
+++ b/Exercise 2/index.html
@@ -0,0 +1,114 @@
+
+
+
+
+
+ Robotics & AI Expo 2025 – Information Page
+
+
+
+
+
+
+
+
+ Robotics & AI Expo 2025
+ Saturday · 24 May 2025 · Gesamtschule Konradsdorf · 10:00–17:00
+
+
+
+ Ever wanted to unleash your AI skills? Join us for a day of hands-on workshops (practical), thrilling competitions (hackathons), and thought-provoking debates (About future AI)!
+ You will learn about the latest in robotics and AI, and have the chance to showcase your own projects. Even bring your arguments to the table!
+ So what are you waiting for? Come join the event!
+
+
+
+ Event Schedule
+
+
+
+ Time
+ Activity
+ Location
+
+
+
+ 10 : 00 Opening Keynote Aula
+ 11 : 00 Autonomous-Bot Race Sporthalle
+ 13 : 00 ML Workshop: "Teach a CNN to lower grade students" Lab 1B
+ 15 : 30 Debate – "Will AI surpass us?" Auditorium
+ 16 : 45 Awards & Closing Aula
+
+
+
+
+ Sneak-peek
+
+
+
+
+
+
+
+
+
+
+ 10-seconds highlight reel:
+
+
+ Your browser doesn’t support the video tag.
+
+
+
+
+
+ Register / Contact Us
+
+ Full Name:
+
+
+
+ Email:
+
+
+
+
+ Year Group:
+
+ Grade 10
+ Grade 11
+ Grade 12
+ Teacher / Guest
+
+
+
+
+
+
+ Interested in:
+ Workshops
+ Competitions
+ Debate
+
+
+ Comments:
+
+
+
+ Send
+ Reset
+
+
+
+
+
+
diff --git a/Exercise 2/media/matplotlib_animation.ipynb b/Exercise 2/media/matplotlib_animation.ipynb
new file mode 100644
index 00000000..fa6f9f50
--- /dev/null
+++ b/Exercise 2/media/matplotlib_animation.ipynb
@@ -0,0 +1,208 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "0930f850",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAABOwAAAEcCAYAAAB07ys7AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAABTS0lEQVR4nO3dd3gU1eLG8Xc32Wx6AVIpCYQO0qULSBGUqmABlWJHVBDsWOCKqBfxYgOx4k9BVATEBoKAFOlKL6FDgCQkIb1n5/fHyoa9CRAUzVz9fp5nH8jMmZkzs7uzu++cc8ZiGIYhAAAAAAAAAKZgregKAAAAAAAAAChBYAcAAAAAAACYCIEdAAAAAAAAYCIEdgAAAAAAAICJENgBAAAAAAAAJkJgBwAAAAAAAJgIgR0AAAAAAABgIgR2AAAAAAAAgIkQ2AEAAAAAAAAmQmAHAMDfyIQJE2SxWJScnPynb2vlypWyWCxauXLln74twKyOHDkii8WiV1555U/f1qxZs2SxWHTkyJFLXpb3KwAA/1sI7AAAqCBnf3yffXh6eqpq1aoaPny4Tpw4UdHVc5k+fbpmzZpV0dVw+eijj9S4cWP5+vqqevXqGjp0qE6ePPm71jV9+nRZLBa1adPmvGUsFoseeOCBi64rJibG7fk899GrV6/fVb8/m8Ph0KxZs9SvXz9Vr15dfn5+aty4sSZNmqS8vLwyl3n//ffVoEEDeXt7q06dOnrjjTdKlZk/f75uvvlm1apVS76+vqpXr57GjRuntLS0UmXPd9zuu+++y727br7++mt17txZYWFh8vX1Va1atXTTTTdp8eLFf+p2AQAAysOzoisAAMA/3b/+9S/VrFlTeXl5Wr9+vWbNmqU1a9Zo586d8vb2rujqafr06apSpYqGDx/uNr1Tp07Kzc2Vl5fXX1aXBQsWaPjw4ercubMeeOABJSUlad68eYqLi1NUVNQlr2/27NmKiYnRxo0bdeDAAdWuXfsP1a9Zs2YaN25cqem/p25/hZycHI0YMUJt27bVfffdp7CwMK1bt07PPfecfvzxRy1fvlwWi8VVfubMmbrvvvs0cOBAjR07VqtXr9ZDDz2knJwcPf74465y99xzj6KionTbbbepRo0a2rFjh95880199913+uWXX+Tj4+NWj7KOW926df+0/X7llVf06KOPqnPnznryySfl6+urAwcOaNmyZZo7d65pA1YAAPDPQWAHAEAFu/baa9WqVStJ0l133aUqVaro5Zdf1qJFi3TTTTdVcO3Oz2q1/uWB4ty5c1WpUiUtXrzYte1nn31WBQUFl7yuw4cP6+eff9b8+fN17733avbs2Xruuef+UP2qVq2q22677Q+t46/k5eWltWvXqn379q5pd999t2JiYlyhXffu3SVJubm5Gj9+vHr37q158+a5yjocDj3//PO65557FBISIkmaN2+eunTp4ratli1batiwYZo9e7buuusut3l/5XErKirS888/rx49euiHH34oNT8pKekvqQcAAMCF0CUWAACTueqqqyRJBw8edJu+fPlyXXXVVfLz81NwcLD69++vPXv2lLmO5ORk3XTTTQoMDFTlypU1evToUl0czwYXsbGxstvtiomJ0VNPPaX8/HxXmZiYGO3atUs//fSTq6vi2SDmfGNibdiwQdddd51CQkLk5+enJk2a6LXXXnPNT0hI0IgRI1StWjXZ7XZFRkaqf//+5RqXy2q1qqioSB4eHm7Tf08rv9mzZyskJES9e/fWoEGDNHv27Etex6VKSkpSaGiounTpIsMwXNMPHDggPz8/3Xzzza5pXbp0UePGjbVlyxa1b99ePj4+qlmzpt5+++0y13vnnXcqPDxc3t7eatq0qT766KOL1sfLy8strDvr+uuvlyS319eKFSuUkpKi+++/363sqFGjlJ2drW+//dat7uVZ57kKCgqUnZ190Tr/UcnJycrIyFCHDh3KnB8WFub2d15eniZMmKC6devK29tbkZGRuuGGG0q9PyXpnXfecb2frrzySm3atKlUmb1792rQoEGqVKmSvL291apVKy1atKhUuV27dqlr167y8fFRtWrVNGnSJDkcjlLlLBaLJkyYUGp6TExMqVaxZdmwYYN69eqloKAg+fr6qnPnzlq7du1FlwMAAH8uAjsAAEzmbHB1trWSJC1btkw9e/ZUUlKSJkyYoLFjx+rnn39Whw4dygy6brrpJuXl5enFF1/Uddddp9dff1333HOPW5m77rpLzz77rFq0aKH//Oc/6ty5s1588UXdcsstrjLTpk1TtWrVVL9+fX388cf6+OOPNX78+PPWfenSperUqZN2796t0aNHa+rUqbr66qv1zTffuMoMHDhQCxYs0IgRIzR9+nQ99NBDyszM1LFjxy56bEaMGKGMjAw9++yzFy17MbNnz9YNN9wgLy8vDR48WPv37y8zYLkUhYWFSk5OLvXIzc2V5AyDZsyYoZ9++sk19pvD4dDw4cMVEBCg6dOnu63vzJkzuu6669SyZUv9+9//VrVq1TRy5Eh98MEHrjK5ubnq0qWLPv74Y916662aMmWKgoKCNHz4cLeg9FIkJCRIkqpUqeKa9uuvv0qSqzXoWS1btpTVanXNv5R1nrV8+XL5+vrK399fMTExv7ve5REWFiYfHx99/fXXSk1NvWDZ4uJi9enTRxMnTlTLli01depUjR49Wunp6dq5c6db2Tlz5mjKlCm69957NWnSJB05ckQ33HCDCgsLXWV27dqltm3bas+ePXriiSc0depU+fn5acCAAVqwYIGrXEJCgq6++mpt3bpVTzzxhMaMGaP/+7//u+zHZfny5erUqZMyMjL03HPPafLkyUpLS1PXrl21cePGy7otAABwiQwAAFAhPvzwQ0OSsWzZMuP06dPG8ePHjXnz5hmhoaGG3W43jh8/7irbrFkzIywszEhJSXFN27Ztm2G1Wo2hQ4e6pj333HOGJKNfv35u27r//vsNSca2bdsMwzCMrVu3GpKMu+66y63cI488Ykgyli9f7prWqFEjo3PnzqXqv2LFCkOSsWLFCsMwDKOoqMioWbOmER0dbZw5c8atrMPhMAzDMM6cOWNIMqZMmVL+A3WO6dOnG3a73ZBkvPbaa79rHYZhGJs3bzYkGUuXLnXVr1q1asbo0aNLlZVkjBo16qLrjI6ONiSV+XjxxRfdyg4ePNjw9fU14uLijClTphiSjIULF7qV6dy5syHJmDp1qmtafn6+67VQUFBgGIZhTJs2zZBkfPLJJ65yBQUFRrt27Qx/f38jIyOj3MflrO7duxuBgYFuz+OoUaMMDw+PMsuHhoYat9xyywXXeeeddxoeHh5GXFyc2/S+ffsaL7/8srFw4ULj/fffN6666ipDkvHYY49dcr3L69lnnzUkGX5+fsa1115rvPDCC8aWLVtKlfvggw8MScarr75aat7Z1/Thw4cNSUblypWN1NRU1/yvvvrKkGR8/fXXrmndunUzrrjiCiMvL89tPe3btzfq1KnjmjZmzBhDkrFhwwbXtKSkJCMoKMiQZBw+fNg1XZLx3HPPlapfdHS0MWzYMNff//1+dTgcRp06dYyePXu69sUwDCMnJ8eoWbOm0aNHjzKOHAAA+KvQwg4AgArWvXt3hYaGqnr16ho0aJD8/Py0aNEiVatWTZJ06tQpbd26VcOHD1elSpVcyzVp0kQ9evTQd999V2qdo0aNcvv7wQcflCRX2bP/jh071q3c2YH/z+3eWF6//vqrDh8+rDFjxig4ONht3tkbF/j4+MjLy0srV67UmTNnLmn9X331lUaNGqV58+Zp/PjxGjNmjD788EO3MvXq1dPtt99+0XXNnj1b4eHhuvrqq131u/nmmzV37lwVFxdfUr3O1aZNGy1durTUY/DgwW7l3nzzTQUFBWnQoEF65plndPvtt6t///6l1ufp6al7773X9beXl5fuvfdeJSUlacuWLZKcz2VERITbNmw2mx566CFlZWXpp59+uqR9mDx5spYtW6aXXnrJ7Xm80A1GvL29Xa0IyzJnzhy9//77GjdunOrUqeM2b9GiRXrsscfUv39/3XHHHfrpp5/Us2dPvfrqq4qPj7+kupfXxIkTNWfOHDVv3lxLlizR+PHj1bJlS7Vo0cKty+6XX36pKlWquN4/5zr3ZhySdPPNN7u1ij3btf3QoUOSpNTUVC1fvlw33XSTMjMzXa0vU1JS1LNnT+3fv991d+jvvvtObdu2VevWrV3rCw0N1a233nrZjsHWrVu1f/9+DRkyRCkpKa76ZGdnq1u3blq1alWZXXABAMBfg5tOAABQwd566y3VrVtX6enp+uCDD7Rq1SrZ7XbX/KNHj0pyhlH/rUGDBlqyZImys7Pl5+fnmv7foUhsbKysVqur++zRo0dltVpL3RU1IiJCwcHBrm1eirNjejVu3Pi8Zex2u15++WWNGzdO4eHhatu2rfr06aOhQ4cqIiLigut//PHHde2116pPnz7q06ePEhMTdffddysgIECDBg1STk6ODh8+XGa4cq7i4mLNnTtXV199tQ4fPuya3qZNG02dOlU//vijrrnmmkvY8xJVqlRx3aThQipVqqTXX39dN954o8LDw/X666+XWS4qKsrteZVK7p565MgRtW3bVkePHlWdOnVktbpfh23QoIEkXdJz+dlnn+npp5/WnXfeqZEjR7rN8/HxOe/NPfLy8krd+fWs1atX684771TPnj31wgsvXLQOFotFDz/8sJYsWaKVK1ee92YUxcXFOn36dJnzfHx8FBQUdMHtDB48WIMHD1ZGRoY2bNigWbNmac6cOerbt6/rDs0HDx5UvXr15Ol58a/MNWrUcPv7bHh3Npg+cOCADMPQM888o2eeeabMdSQlJalq1ao6evSo2rRpU2p+WeeA32v//v2SpGHDhp23THp6ulsICQAA/joEdgAAVLDWrVu7xgUbMGCAOnbsqCFDhmjfvn3y9/e/LNv479ZAF5v+ZxozZoz69u2rhQsXasmSJXrmmWf04osvavny5WrevHmZy6Smpmrfvn1uLYzefvttnT59WkOGDJGfn58OHTokq9WqQYMGXXD7y5cv16lTpzR37lzNnTu31PzZs2f/7sDuUixZskSSM9CJj48v1Srxr7Z06VINHTpUvXv3LvPGFpGRkSouLlZSUpLbjRkKCgqUkpKiqKioUsts27ZN/fr1U+PGjTVv3rxyBV+SVL16dUm64Bhzx48fV82aNcucN2zYMM2aNatc2woMDFSPHj3Uo0cP2Ww2ffTRR9qwYYM6d+5cruXP+u8boZxl/HZzkbOt1R555BH17NmzzLL/HaD/ERdrKXq2PlOmTFGzZs3KLHO5zj8AAODSEdgBAGAiHh4eevHFF3X11VfrzTff1BNPPKHo6GhJ0r59+0qV37t3r6pUqVKqFdb+/fvdwowDBw7I4XAoJiZGkhQdHS2Hw6H9+/e7WmJJUmJiotLS0lzblMof6sXGxkqSdu7cedFWZrGxsRo3bpzGjRun/fv3q1mzZpo6dao++eSTMsufrcPx48dd0zw8PDR37lxdc801GjhwoAIDAzVy5MiLttSbPXu2wsLC9NZbb5WaN3/+fC1YsEBvv/32eVuMXQ6LFy/We++9p8cee0yzZ8/WsGHDtGHDhlKB1smTJ0u1noyLi5Mkt+dy+/btcjgcbq3s9u7d65p/MRs2bND111+vVq1a6fPPPy8zWDsb6mzevFnXXXeda/rmzZvlcDhKhT4HDx5Ur169FBYWpu++++6Swp+z3UhDQ0PPWyYiIkJLly4tc15Z4WF5tGrVSh999JFOnTolyfk63bBhgwoLC2Wz2X7XOs+qVauWJGd35Yu9P6Kjo10t4M5V1jkgJCREaWlpbtMKCgpc+3A+Z9+vgYGB5WoVCgAA/lqMYQcAgMl06dJFrVu31rRp05SXl6fIyEg1a9ZMH330kdsP8507d+qHH35wC0/O+u8w6uwdSa+99lpJci0zbdo0t3KvvvqqJKl3796uaX5+fqUCgbK0aNFCNWvW1LRp00qVP9vKKCcnR3l5eW7zYmNjFRAQoPz8/POuOyQkRC1atNCcOXNcQZTkHDvt448/lsPhUGJiogYMGHDBOubm5mr+/Pnq06ePBg0aVOrxwAMPKDMzU4sWLbro/v5eaWlpuuuuu9S6dWtNnjxZ7733nn755RdNnjy5VNmioiLNnDnT9XdBQYFmzpyp0NBQtWzZUpLzuUxISNBnn33mttwbb7whf3//i7YU27Nnj3r37q2YmBh988035w0qu3btqkqVKmnGjBlu02fMmCFfX1+310xCQoKuueYaWa1WLVmy5LzBW2pqaqmWYIWFhXrppZfk5eXlGmOwLN7e3urevXuZj4YNG553uZycHK1bt67Med9//72kkq6nAwcOVHJyst58881SZc++pssrLCxMXbp00cyZM8sM087t3nvddddp/fr1bndqPX36tGbPnl1qudjYWK1atcpt2jvvvHPRFnYtW7ZUbGysXnnlFWVlZV2wPgAA4K9HCzsAAEzo0Ucf1Y033qhZs2bpvvvu05QpU3TttdeqXbt2uvPOO5Wbm6s33nhDQUFBmjBhQqnlDx8+rH79+qlXr15at26dPvnkEw0ZMkRNmzaVJDVt2lTDhg3TO++8o7S0NHXu3FkbN27URx99pAEDBrgFJS1bttSMGTM0adIk1a5dW2FhYeratWupbVqtVs2YMUN9+/ZVs2bNNGLECEVGRmrv3r3atWuXlixZori4OHXr1k033XSTGjZsKE9PTy1YsECJiYm65ZZbLnhM3njjDXXv3l2tW7fWvffeq/r16+vIkSP64IMPFB4eLqvVqiFDhmjDhg2uG3b8t0WLFikzM1P9+vUrc37btm0VGhqq2bNn6+abb75gfcpy4sSJMlsJ+vv7u8LE0aNHKyUlRcuWLZOHh4d69eqlu+66S5MmTVL//v1dz5HkbCn28ssv68iRI6pbt64+++wzbd26Ve+8846rxdc999yjmTNnavjw4dqyZYtiYmI0b948rV27VtOmTVNAQMB565uZmamePXvqzJkzevTRR0vdbCQ2Nlbt2rWT5BwX7vnnn9eoUaN04403qmfPnlq9erU++eQTvfDCC243ROnVq5cOHTqkxx57TGvWrNGaNWtc88LDw9WjRw9Jzudj0qRJGjRokGrWrKnU1FTN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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# This code was designed for the animation, since I didn't want to spend too much time doing it in Blender, I decided a quick Matplotlib would do it.\n",
+ "\n",
+ "import matplotlib.pyplot as plt\n",
+ "import matplotlib.animation as anim\n",
+ "from matplotlib.patches import Rectangle\n",
+ "from IPython.display import HTML\n",
+ "import numpy as np\n",
+ "from matplotlib.animation import FFMpegWriter\n",
+ "import matplotlib as mpl\n",
+ "import os\n",
+ "import imageio_ffmpeg\n",
+ "\n",
+ "# --- DATA ---\n",
+ "events = [\n",
+ " (\"Opening Keynote\", 10.00, 11.00),\n",
+ " (\"Autonomous-Bot Race\", 11.00, 13.00),\n",
+ " (\"ML Workshop – “Teach a CNN”\", 13.00, 15.50),\n",
+ " (\"Debate – “Will AI surpass us?”\",15.50, 16.75),\n",
+ " (\"Awards & Closing\", 16.75, 17.00),\n",
+ "]\n",
+ "\n",
+ "# make sure the folder exists\n",
+ "out_dir = r'C:\\Users\\iHunter\\OneDrive\\Desktop\\Building-U\\bu-learning\\Exercise 2\\media'\n",
+ "os.makedirs(out_dir, exist_ok=True)\n",
+ "out_path = os.path.join(out_dir, 'robotics_schedule.mp4')\n",
+ "\n",
+ "# --- FIGURE SETUP ---\n",
+ "fig, ax = plt.subplots(figsize=(16, 2.8))\n",
+ "mpl.rcParams['animation.ffmpeg_path'] = imageio_ffmpeg.get_ffmpeg_exe()\n",
+ "\n",
+ "# hide everything (axes, ticks, spines)\n",
+ "ax.axis('off')\n",
+ "\n",
+ "\n",
+ "# Let's assume 1 hour between each event\n",
+ "margin = 1.0\n",
+ "ax.set_xlim(9.8, events[-1][2] + margin)\n",
+ "ax.set_ylim(-0.05, 0.75)\n",
+ "\n",
+ "# horizontal baseline\n",
+ "ax.hlines(0.05, events[0][1], events[-1][2] + margin, lw=1.5, color=\"k\")\n",
+ "\n",
+ "ax.set_title(\"Robotics & AI Expo 2025 – Schedule\", pad=25)\n",
+ "\n",
+ "# color palette + contrast helper\n",
+ "palette = plt.get_cmap(\"tab10\").colors\n",
+ "\n",
+ "\n",
+ "def best_text_colour(rgb):\n",
+ " r, g, b = rgb\n",
+ " return \"black\" if 0.2126*r + 0.7152*g + 0.0722*b > 0.55 else \"white\"\n",
+ "\n",
+ "# Set minimum bar width (for display purposes)\n",
+ "MIN_BAR_WIDTH = 0.9\n",
+ "\n",
+ "bars, labels, grads = [], [], [None]*len(events)\n",
+ "\n",
+ "# initial patch + text creation (width=0 to animate in)\n",
+ "for i, (lab, start, end) in enumerate(events):\n",
+ " real_w = end - start\n",
+ " disp_w = max(real_w, MIN_BAR_WIDTH) # enforce minimum for display\n",
+ " color = palette[i % len(palette)]\n",
+ " y0, h = 0.20, 0.40\n",
+ "\n",
+ " # bar (starts at zero, grows to disp_w)\n",
+ " rect = Rectangle((start, y0), 0, h, color=color, ec=\"none\", zorder=1)\n",
+ " ax.add_patch(rect)\n",
+ " bars.append((rect, real_w, disp_w))\n",
+ "\n",
+ " # label (alpha=0 at start)\n",
+ " txt = ax.text(start, y0 + h/2, lab,\n",
+ " ha=\"left\", va=\"center\",\n",
+ " fontsize=9, alpha=0.0,\n",
+ " color=best_text_colour(color),\n",
+ " zorder=2)\n",
+ " labels.append(txt)\n",
+ "\n",
+ "# gradient helper function\n",
+ "def make_gradient(ax, x0, w, col, y0=0.20, h=0.40, n=120):\n",
+ " try:\n",
+ " grad = np.linspace(0,1,n)[:,None] * np.array(col)\n",
+ " im = ax.imshow(grad[None,:,:],\n",
+ " extent=[x0, x0+w, y0, y0+h],\n",
+ " aspect=\"auto\", zorder=0.5)\n",
+ " im.set_clip_path(Rectangle((x0, y0), w, h, transform=ax.transData))\n",
+ " return im\n",
+ " except:\n",
+ " return None\n",
+ "\n",
+ "# --- ANIMATION LOGIC ---\n",
+ "fps = 25\n",
+ "frames_per_event = 40\n",
+ "pause_frames = 10\n",
+ "total_frames = len(events) * (frames_per_event + pause_frames)\n",
+ "\n",
+ "def animate(frame):\n",
+ " idx, local = divmod(frame, frames_per_event + pause_frames)\n",
+ " artists = []\n",
+ "\n",
+ " for i, ((rect, real_w, disp_w), txt) in enumerate(zip(bars, labels)):\n",
+ " s = events[i][1]\n",
+ " # Past events → full width\n",
+ " if i < idx:\n",
+ " rect.set_x(s)\n",
+ " rect.set_width(disp_w)\n",
+ " rect.set_edgecolor(\"k\")\n",
+ " txt.set_alpha(1.0)\n",
+ "\n",
+ " # Current event sliding in\n",
+ " elif i == idx and local < frames_per_event:\n",
+ " p = local / frames_per_event\n",
+ " rect.set_x(s)\n",
+ " rect.set_width(disp_w * p)\n",
+ " # if the _real_ bar is tall enough, fade in text; otherwise show full alpha\n",
+ " if real_w >= MIN_BAR_WIDTH:\n",
+ " txt.set_alpha(p)\n",
+ " else:\n",
+ " txt.set_alpha(1.0)\n",
+ "\n",
+ " # Landed/current-pause (blink outline)\n",
+ " elif i == idx:\n",
+ " rect.set_x(s)\n",
+ " rect.set_width(disp_w)\n",
+ " rect.set_edgecolor(\"k\" if (local - frames_per_event) % 2 else \"none\")\n",
+ " txt.set_alpha(1.0)\n",
+ "\n",
+ " # Future events → hidden\n",
+ " else:\n",
+ " rect.set_width(0)\n",
+ " txt.set_alpha(0.0)\n",
+ "\n",
+ " # label placement (center if wide, outside if skinny)\n",
+ " if disp_w >= MIN_BAR_WIDTH:\n",
+ " txt.set_x(s + disp_w/2)\n",
+ " txt.set_ha(\"center\")\n",
+ " else:\n",
+ " txt.set_x(s + disp_w + 0.05)\n",
+ " txt.set_ha(\"left\")\n",
+ "\n",
+ " artists += [rect, txt]\n",
+ "\n",
+ " return artists\n",
+ "\n",
+ "ani = anim.FuncAnimation(fig, animate,\n",
+ " frames=total_frames,\n",
+ " interval=1000/fps,\n",
+ " blit=True)\n",
+ "\n",
+ "# Display in Jupyter/VS Code interactive window\n",
+ "HTML(ani.to_jshtml())\n",
+ "# save to media/ folder (make sure it exists!)\n",
+ "\n",
+ "# --- ANIMATION SAVE ---\n",
+ "# set up the writer\n",
+ "writer = FFMpegWriter(\n",
+ " fps=fps,\n",
+ " codec='libx264',\n",
+ " bitrate=1800,\n",
+ " extra_args=['-pix_fmt', 'yuv420p']\n",
+ ")\n",
+ "\n",
+ "# save the file\n",
+ "ani.save(out_path, writer=writer)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.4"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/Exercise 2/media/poster.png b/Exercise 2/media/poster.png
new file mode 100644
index 00000000..d47417bd
Binary files /dev/null and b/Exercise 2/media/poster.png differ
diff --git a/Exercise 2/media/robotics_schedule.mp4 b/Exercise 2/media/robotics_schedule.mp4
new file mode 100644
index 00000000..57dd3454
Binary files /dev/null and b/Exercise 2/media/robotics_schedule.mp4 differ