More Projects
59 in totalEcoSavvy AI
2023
HackOwasp entry around e-waste handling. An Express/MySQL app serves the login, register, dashboard and statistics pages and exposes auth, dashboard and data routes, while a detached python/ folder holds scikit-learn models pickled into the repo: a LinearRegression over weight, battery, screen, RAM and storage for device composition, an SVR for siting collection points, and a random forest ranking state-level volume. All three are trained on data the team generated rather than collected — one generator assigns composition as a uniform random number — and nothing in the Node app loads a pickle or shells out to Python, so no endpoint runs a model.
Project Details
2023
Hackathon · AI
E-waste recycling has two questions worth predicting: what is actually inside a device once it arrives, and where you should put the facility that receives it. EcoSavvy was a HackOwasp entry that took both, with an Express dashboard on the front and a folder of scikit-learn models behind it.
The honest framing is that neither question had a dataset behind it. Recovering composition from a device's specifications needs teardown data that nobody publishes, and siting a collection facility needs regional volume figures that in India live in Central Pollution Control Board reports rather than in a CSV. Over a weekend, with a demo to give, the team wrote generators instead. That decision is the most interesting thing in the repo, and it determines what every number on the dashboard is worth.
What the Express side is
index.js is 36 lines and mounts three routers. Pages are raw HTML served with sendFile -
there is no view engine and no templating anywhere, so the shared header is injected
client-side by a jQuery snippet that does $("#header").load("../html/header.html") on every
dashboard page. Four static mounts cover /css, /html, /js and /media.
GET /,/login,/registerand/testingoff the root.POST /auth/registerinserts intousersand maps MySQL'sER_DUP_ENTRYto a 409.POST /auth/loginselects by username and compares the password in JavaScript.- Seven pages under
/dashboard- statistics at the root, then logistics, waste status, inventory capacity, current inventory, components available and shred composition. GET /get/logisticsandGET /get/inventory, each aSELECT *returned as JSON.
That is the whole surface. Three of the route files open their own MySQL connection to the
ecosavvyai database as root with an empty password, and there is no session layer at all -
a successful login is a redirect and nothing more, so /dashboard and /get answer to anyone
who asks. Passwords go into the table as plaintext. The only schema in the repo is a
CREATE TABLE inventory plus 32 inserts sitting in a file called hello.txt; the users and
logistics tables exist only as implications of the queries that read them.
Where the models live, and what calls them
Nothing does. The python/ directory holds four subfolders and nine scripts, and not one of
them is invoked from the Node app - there is no endpoint anywhere that runs a model, loads a
pickle or shells out to Python. The two halves of the project were built to be demonstrated
next to each other rather than wired together, which is a fair weekend tradeoff but worth
saying out loud, because it means every figure the dashboard displays comes from a MySQL table
rather than from a prediction.
The data problem, stated plainly
Two of the four model folders are named "(Based on random data)", and that is accurate.
gen_data.py synthesises 5,000 candidate sites and defines capacity as a fixed linear
combination of the inputs; gendata.py generates 1,000 devices and assigns composition as a
uniform random number. The regressors therefore recover a formula the generator wrote, or
nothing at all. What the pipeline demonstrates is the shape - feature encoding, scaling,
train/test split, serialised model, served prediction - with real e-waste data as the
substitution that was never made.
It is worth seeing the two failure modes side by side, because they fail in opposite
directions. In the siting case the target is written as
0.5*latitude + 0.3*longitude + 1.5*population/1000 + 0.7*gdp/1000 + 2*distance, with no
noise term at all, and then train_data.py fits an SVR(kernel='rbf', C=100, gamma=0.1) to
recover it. Any score that reports is a measure of how well an RBF kernel approximates a
straight line, and since the population term is three orders of magnitude larger than the
others, the model is mostly learning 1.5 * population/1000. In the composition case the
target is random.uniform(0, 100) appended to each row, statistically independent of weight,
battery, screen size, RAM and storage, so LinearRegression has nothing to find and the
printed R-squared should sit at roughly zero. The state-level ranking is the same story again:
training_data.py draws E-Waste (MT) as an independent uniform over 30 rows, and new.py
then prints the top ten states by predicted tonnage, which is a ranking of memorised noise.
What it does
- Auth pages over MySQL - register with duplicate-username handling that returns a proper 409, login, and a redirect into the dashboard.
- Seven dashboard views routed off
/dashboard: logistics, waste status, inventory capacity, current inventory, components available, shred composition, and statistics. - A read API at
/get/logisticsand/get/inventoryserving the underlying tables as JSON, which the two data-backed pages fetch and render into HTML tables client-side. - Composition regression.
trainer.pyone-hot encodes device type through aColumnTransformer, scales the numeric features, fits aLinearRegressionover weight, battery capacity, screen size, RAM and storage, and reports MSE and R-squared on a held-out fifth. - An interactive checker that prompts for those six fields at the terminal and prints the predicted recoverable composition for one device.
- Site capacity prediction.
train_data.pyfits anSVR(kernel='rbf', C=100, gamma=0.1, epsilon=0.1)over latitude, longitude, population, GDP and distance to nearest city, and serialises the fitted model toe-waste-model.pkl. - State-level volume ranking with a
RandomForestRegressorover population, urban share, GDP, literacy rate and internet penetration, printing the top ten states by predicted tonnage in metric tons. - A component lookup over
appliance_dataset.csvthat returns which parts of an appliance are still worth recovering given its age. It is a pandas filter over six rows, with no model involved despite the folder name. - A rule-based disposal recommendation on the waste-status page - shred, disassemble or refurbish - decided by an if/else over the damage percentage and the age, in the browser.
- Trained artifacts checked into the repo -
ewaste_model.pkl,e-waste-model.pkl,rf_model.pklandlogistic_regression_model.joblib.
The parts that would not survive a second day
Reading it back, the interesting failures are in the seams rather than in the models. Neither
trainer saves its StandardScaler or its ColumnTransformer, only the estimator, so none of
the four pickles can be loaded and used correctly afterwards. predict_data.py demonstrates
exactly that: it fits a fresh scaler on the single row it is trying to predict, which
standardises every feature to zero, so it returns the same number whatever coordinates you
hand it. checker.py reads e-Twaste_data.csv, a filename that does not exist, and refits
the whole pipeline from scratch rather than loading the model that was just trained. Two of
the four checked-in artifacts are orphans whose recorded feature names - population density,
urbanisation rate, e-waste generation rate - match no CSV and no script in the tree, so they
came from a notebook that was never committed.
The front end has its own version of the same gap. Both data-backed pages fetch from /get,
write the response into localStorage, and then read localStorage synchronously on the next
line, before the fetch has resolved. The table you see is always the previous page load's
copy, and on a first-ever visit the parse returns null and the render throws. Two of the seven
dashboard pages are six-line stubs with a header loader and nothing else, and the statistics
page is a CSS mock chart with 2018 dollar figures still in it.
Built over a hackathon weekend with two teammates. The Express app and the model plumbing both run; the numbers they produce are the part that would need real inventory data behind them.
Project Details
2023
Hackathon · AI