diff --git a/01-color-flipper/final/hex.html b/01-color-flipper/final/hex.html
index fbcbfc65a..b90484a41 100644
--- a/01-color-flipper/final/hex.html
+++ b/01-color-flipper/final/hex.html
@@ -12,17 +12,18 @@
-
background color : #f1f5f8
-
+
Background color: #f1f5f8
+
Click the button to see magic colors!
+
diff --git a/01-color-flipper/final/hex.js b/01-color-flipper/final/hex.js
index e61e616cb..2a75b7fe4 100644
--- a/01-color-flipper/final/hex.js
+++ b/01-color-flipper/final/hex.js
@@ -1,18 +1,40 @@
const hex = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "A", "B", "C", "D", "E", "F"];
const btn = document.getElementById("btn");
const color = document.querySelector(".color");
+const resetBtn = document.getElementById("reset"); // NEW Reset button
btn.addEventListener("click", function () {
let hexColor = "#";
for (let i = 0; i < 6; i++) {
hexColor += hex[getRandomNumber()];
}
- // console.log(hexColor);
-
- color.textContent = hexColor;
+ color.textContent = hexColor.toUpperCase();
document.body.style.backgroundColor = hexColor;
+ btn.textContent = "Change Again!";
+});
+
+// Copy color to clipboard on click
+color.addEventListener("click", function () {
+ navigator.clipboard.writeText(color.textContent);
+ showCopiedMessage(); // Custom message instead of alert
});
+// Reset background color
+resetBtn.addEventListener("click", function () {
+ document.body.style.backgroundColor = "#ffffff";
+ color.textContent = "#FFFFFF";
+ btn.textContent = "Change Color";
+});
+
+// Function to show copied message
+function showCopiedMessage() {
+ const message = document.createElement("div");
+ message.textContent = "Color Copied!";
+ message.className = "toast";
+ document.body.appendChild(message);
+ setTimeout(() => message.remove(), 1000);
+}
+
function getRandomNumber() {
return Math.floor(Math.random() * hex.length);
}
diff --git a/02-counter/final/app.js b/02-counter/final/app.js
index f34827948..e9599eb4c 100644
--- a/02-counter/final/app.js
+++ b/02-counter/final/app.js
@@ -1,29 +1,34 @@
-// set inital value to zero
-let count = 0;
-// select value and buttons
-const value = document.querySelector("#value");
-const btns = document.querySelectorAll(".btn");
+// Counter App - Modified Version for Contribution
-btns.forEach(function (btn) {
- btn.addEventListener("click", function (e) {
- const styles = e.currentTarget.classList;
- if (styles.contains("decrease")) {
- count--;
- } else if (styles.contains("increase")) {
- count++;
- } else {
- count = 0;
- }
+let counterValue = 0; // Start with 0
- if (count > 0) {
- value.style.color = "green";
- }
- if (count < 0) {
- value.style.color = "red";
- }
- if (count === 0) {
- value.style.color = "#222";
- }
- value.textContent = count;
+// Select value display and all buttons
+const valueDisplay = document.querySelector("#value");
+const buttons = document.querySelectorAll(".btn");
+
+// Function to update color based on value
+const updateColor = () => {
+ valueDisplay.style.color = counterValue > 0 ? "green" :
+ counterValue < 0 ? "red" : "#222";
+};
+
+// Function to update the display with animation
+const updateDisplay = () => {
+ valueDisplay.textContent = counterValue;
+ valueDisplay.style.opacity = "0.5";
+ setTimeout(() => (valueDisplay.style.opacity = "1"), 150);
+};
+
+// Event listener for buttons
+buttons.forEach((button) => {
+ button.addEventListener("click", (e) => {
+ const classes = e.currentTarget.classList;
+
+ if (classes.contains("decrease")) counterValue--;
+ else if (classes.contains("increase")) counterValue++;
+ else counterValue = 0;
+
+ updateColor();
+ updateDisplay();
});
});
diff --git a/02-counter/final/update app.js b/02-counter/final/update app.js
new file mode 100644
index 000000000..e9599eb4c
--- /dev/null
+++ b/02-counter/final/update app.js
@@ -0,0 +1,34 @@
+// Counter App - Modified Version for Contribution
+
+let counterValue = 0; // Start with 0
+
+// Select value display and all buttons
+const valueDisplay = document.querySelector("#value");
+const buttons = document.querySelectorAll(".btn");
+
+// Function to update color based on value
+const updateColor = () => {
+ valueDisplay.style.color = counterValue > 0 ? "green" :
+ counterValue < 0 ? "red" : "#222";
+};
+
+// Function to update the display with animation
+const updateDisplay = () => {
+ valueDisplay.textContent = counterValue;
+ valueDisplay.style.opacity = "0.5";
+ setTimeout(() => (valueDisplay.style.opacity = "1"), 150);
+};
+
+// Event listener for buttons
+buttons.forEach((button) => {
+ button.addEventListener("click", (e) => {
+ const classes = e.currentTarget.classList;
+
+ if (classes.contains("decrease")) counterValue--;
+ else if (classes.contains("increase")) counterValue++;
+ else counterValue = 0;
+
+ updateColor();
+ updateDisplay();
+ });
+});
diff --git a/groundwater_quality_2023.ipynb b/groundwater_quality_2023.ipynb
new file mode 100644
index 000000000..48353b4dc
--- /dev/null
+++ b/groundwater_quality_2023.ipynb
@@ -0,0 +1,542 @@
+{
+ "nbformat": 4,
+ "nbformat_minor": 0,
+ "metadata": {
+ "colab": {
+ "provenance": [],
+ "authorship_tag": "ABX9TyPljS5pE4t6h/4wuK6/lNky",
+ "include_colab_link": true
+ },
+ "kernelspec": {
+ "name": "python3",
+ "display_name": "Python 3"
+ },
+ "language_info": {
+ "name": "python"
+ }
+ },
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "view-in-github",
+ "colab_type": "text"
+ },
+ "source": [
+ "
"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "\n",
+ "import pandas as pd\n",
+ "from google.colab import files\n",
+ "\n",
+ "uploaded = files.upload()\n",
+ "file_name = list(uploaded.keys())[0]\n",
+ "\n",
+ "raw = pd.read_excel(file_name, header=None)\n",
+ "\n",
+ "header_row = raw[raw.apply(lambda r: r.astype(str).str.contains(\"pH\", case=False).any(), axis=1)].index[0]\n",
+ "\n",
+ "df = pd.read_excel(file_name, header=header_row)\n",
+ "\n",
+ "df.columns = df.columns.astype(str).str.strip().str.lower()\n",
+ "\n",
+ "df = df.loc[:, ~df.columns.str.contains(\"unnamed\", na=False)]\n",
+ "\n",
+ "numeric_cols = df.columns.difference([\n",
+ " \"state\",\"district\",\"location\",\"latitude\",\"longitude\",\"water source\",\"water type\"\n",
+ "])\n",
+ "\n",
+ "\n",
+ "df[numeric_cols] = df[numeric_cols].apply(pd.to_numeric, errors=\"coerce\")\n",
+ "\n",
+ "df = df.dropna(subset=numeric_cols, how=\"all\")\n",
+ "\n",
+ "df.to_csv(\"ground_water_quality_report2023_new.csv\", index=False)\n"
+ ],
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 127
+ },
+ "id": "IKR4qeuVfzMv",
+ "outputId": "1a9d2a59-1067-4b60-f5e1-3be155496eda"
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/html": [
+ "\n",
+ " \n",
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {}
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "Saving ground water quality report 2023.xlsx to ground water quality report 2023.xlsx\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "source": [],
+ "metadata": {
+ "id": "NEwCU2F48hEq"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "from google.colab import drive\n",
+ "import pandas as pd\n",
+ "drive.mount('/content/drive')\n",
+ "import os\n",
+ "\n",
+ "folder_path = '/content/drive/MyDrive/Demo water'\n",
+ "files = os.listdir(folder_path)\n",
+ "print(\"Found files:\", files)\n",
+ "\n",
+ "for file in files:\n",
+ " full_path = os.path.join(folder_path, file)\n",
+ "\n",
+ " if file.endswith('.xlsx') or file.endswith('.xls'):\n",
+ " print(f\"\\nReading file: {file}\")\n",
+ " try:\n",
+ " df = pd.read_excel(full_path)\n",
+ " print(df.head())\n",
+ " except Exception as e:\n",
+ " print(f\"Error reading {file}: {e}\")\n",
+ " elif file.endswith('.csv'):\n",
+ " print(f\"\\nReading CSV file: {file}\")\n",
+ " try:\n",
+ " df = pd.read_csv(full_path, encoding='utf-8')\n",
+ " except UnicodeDecodeError:\n",
+ " df = pd.read_csv(full_path, encoding='latin1')\n",
+ " print(df.head())\n",
+ "\n",
+ "\n",
+ "\n"
+ ],
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "Rq_FhEjI7Rt1",
+ "outputId": "afd05ed8-243c-49e9-eda4-589d66094af9"
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount(\"/content/drive\", force_remount=True).\n",
+ "Found files: ['ground water quality report 2019', 'ground water quality report 2020', 'ground water quality 2021', 'ground water quality report 2022', 'ground water quality 2023']\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "source": [],
+ "metadata": {
+ "id": "aLVpKL1a87vi"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [],
+ "metadata": {
+ "id": "jODmyzCvGfpj"
+ },
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "import pandas as pd\n",
+ "import os\n",
+ "\n",
+ "# Mount Google Drive (if using Colab)\n",
+ "from google.colab import drive\n",
+ "drive.mount('/content/drive')\n",
+ "\n",
+ "# Folder path\n",
+ "folder_path = '/content/drive/MyDrive/Demo water'\n",
+ "files = os.listdir(folder_path)\n",
+ "print(\"Found files:\", files)\n",
+ "\n",
+ "# Standard column mapping\n",
+ "column_mapping = {\n",
+ " 'ph': ['ph', 'pH'],\n",
+ " 'ec_µs/cm_at': ['ec', 'EC', 'ec_(µs/cm_at', 'ec_(μs/cm', 'ec_in_μs/cm'],\n",
+ " 'co3_mg/l': ['co3', 'CO3', 'co3_mg/l', 'co3_(mg/l)'],\n",
+ " 'hco3': ['hco3', 'HCO3', 'bicarbonate'],\n",
+ " 'cl_mg/l': ['cl', 'Cl', 'cl_mg/l', 'cl_(mg/l)'],\n",
+ " 'so4': ['so4', 'SO4', 'sulphate'],\n",
+ " 'no3': ['no3', 'NO3', 'nitrate'],\n",
+ " 'po4': ['po4', 'PO4', 'phosphate'],\n",
+ " 'total_hardness': ['total_hardness', 'total hardness', 'th'],\n",
+ " 'ca_mg/l': ['ca', 'Ca', 'ca_mg/l', 'ca_(mg/l)'],\n",
+ " 'mg_mg/l': ['mg', 'Mg', 'mg_mg/l', 'mg_(mg/l)'],\n",
+ " 'na_mg/l': ['na', 'Na', 'na_mg/l', 'na_(mg/l)'],\n",
+ " 'k_mg/l': ['k', 'K', 'k_mg/l', 'k_(mg/l)'],\n",
+ " 'f_mg/l': ['f', 'F', 'f_mg/l', 'f_(mg/l)'],\n",
+ " 'fe_ppm': ['fe', 'Fe', 'fe_ppm'],\n",
+ " 'as_ppb': ['as', 'As', 'as_ppb'],\n",
+ " 'u_ppb': ['u_ppb_', 'u_ppb', 'U_ppb', 'U_(ppb)', 'U(ppb)', 'u_(ppb)']\n",
+ "}\n",
+ "\n",
+ "all_dfs = []\n",
+ "\n",
+ "for f in files:\n",
+ " full_path = os.path.join(folder_path, f)\n",
+ "\n",
+ " try:\n",
+ " df = pd.read_excel(full_path, engine='openpyxl')\n",
+ "\n",
+ " # Clean column names\n",
+ " df.columns = (\n",
+ " df.columns.astype(str)\n",
+ " .str.strip()\n",
+ " .str.lower()\n",
+ " .str.replace(\" \", \"_\")\n",
+ " .str.replace(\"(\", \"\", regex=False)\n",
+ " .str.replace(\")\", \"\", regex=False)\n",
+ " )\n",
+ "\n",
+ " # Rename columns using mapping\n",
+ " for standard_name, variations in column_mapping.items():\n",
+ " for col in df.columns:\n",
+ " if col.lower() in [v.lower() for v in variations]:\n",
+ " df.rename(columns={col: standard_name}, inplace=True)\n",
+ "\n",
+ " # Keep only needed columns\n",
+ " required_cols = ['state', 'year'] + list(column_mapping.keys())\n",
+ " df = df[[c for c in required_cols if c in df.columns]]\n",
+ "\n",
+ " # Convert numeric columns\n",
+ " numeric_cols = df.columns.difference(['state', 'year'])\n",
+ " for col in numeric_cols:\n",
+ " df[col] = pd.to_numeric(df[col], errors='coerce')\n",
+ "\n",
+ " # Forward fill state\n",
+ " if 'state' in df.columns:\n",
+ " df['state'] = df['state'].ffill()\n",
+ "\n",
+ " # Drop rows where all numeric values are NaN\n",
+ " df = df.dropna(subset=numeric_cols, how='all')\n",
+ "\n",
+ " all_dfs.append(df)\n",
+ " print(f\"Read {f} successfully, shape: {df.shape}\")\n",
+ "\n",
+ " except Exception as e:\n",
+ " print(f\"Could not read {f}: {e}\")\n",
+ "\n",
+ "# Combine and Aggregate\n",
+ "if all_dfs:\n",
+ " combined_df = pd.concat(all_dfs, ignore_index=True)\n",
+ "\n",
+ " agg_df = combined_df.groupby(['state', 'year'], as_index=False).mean(numeric_only=True)\n",
+ "\n",
+ " # Column order\n",
+ " columns_order = ['state', 'year'] + list(column_mapping.keys())\n",
+ " agg_df = agg_df[[c for c in columns_order if c in agg_df.columns]]\n",
+ "\n",
+ " # Save CSV\n",
+ " output_file = \"groundwater_quality_2019-2023.csv\"\n",
+ "agg_df.to_csv(output_file, index=False)\n",
+ "\n",
+ "print(f\"\\n✅ Combined and cleaned CSV saved as '{output_file}'\")\n",
+ "\n",
+ "# Download file\n",
+ "from google.colab import files\n",
+ "files.download(output_file)"
+ ],
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 193
+ },
+ "id": "BO_lSqolXBGE",
+ "outputId": "a1c2a58c-bce9-4a86-c50e-f6e153cfb6db"
+ },
+ "execution_count": 1,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "Mounted at /content/drive\n",
+ "Found files: ['ground water quality report 2022.xlsx', 'ground water quality 2021.xlsx', 'ground water quality report 2020.xlsx', 'ground water quality report 2019.xlsx', 'ground water quality 2023.xlsx']\n",
+ "Read ground water quality report 2022.xlsx successfully, shape: (13600, 17)\n",
+ "Read ground water quality 2021.xlsx successfully, shape: (5375, 16)\n",
+ "Read ground water quality report 2020.xlsx successfully, shape: (6970, 16)\n",
+ "Read ground water quality report 2019.xlsx successfully, shape: (13549, 16)\n",
+ "Read ground water quality 2023.xlsx successfully, shape: (16776, 18)\n",
+ "\n",
+ "✅ Combined and cleaned CSV saved as 'groundwater_quality_2019-2023.csv'\n"
+ ]
+ },
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "application/javascript": [
+ "\n",
+ " async function download(id, filename, size) {\n",
+ " if (!google.colab.kernel.accessAllowed) {\n",
+ " return;\n",
+ " }\n",
+ " const div = document.createElement('div');\n",
+ " const label = document.createElement('label');\n",
+ " label.textContent = `Downloading \"${filename}\": `;\n",
+ " div.appendChild(label);\n",
+ " const progress = document.createElement('progress');\n",
+ " progress.max = size;\n",
+ " div.appendChild(progress);\n",
+ " document.body.appendChild(div);\n",
+ "\n",
+ " const buffers = [];\n",
+ " let downloaded = 0;\n",
+ "\n",
+ " const channel = await google.colab.kernel.comms.open(id);\n",
+ " // Send a message to notify the kernel that we're ready.\n",
+ " channel.send({})\n",
+ "\n",
+ " for await (const message of channel.messages) {\n",
+ " // Send a message to notify the kernel that we're ready.\n",
+ " channel.send({})\n",
+ " if (message.buffers) {\n",
+ " for (const buffer of message.buffers) {\n",
+ " buffers.push(buffer);\n",
+ " downloaded += buffer.byteLength;\n",
+ " progress.value = downloaded;\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " const blob = new Blob(buffers, {type: 'application/binary'});\n",
+ " const a = document.createElement('a');\n",
+ " a.href = window.URL.createObjectURL(blob);\n",
+ " a.download = filename;\n",
+ " div.appendChild(a);\n",
+ " a.click();\n",
+ " div.remove();\n",
+ " }\n",
+ " "
+ ]
+ },
+ "metadata": {}
+ },
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "application/javascript": [
+ "download(\"download_df38e27b-f7f4-41ff-9ef7-735d929239fb\", \"groundwater_quality_2019-2023.csv\", 25476)"
+ ]
+ },
+ "metadata": {}
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file