Mahdi Rizk
Software engineer at Teli.ai, Michigan CS class of 2026. Every project on this page is something you can run: type into the database, assemble a program, step the CPU, shoot a zombie, fly the rocket.

Loan data, out and back
I'm the sole engineer on an in-house loan origination system that replaces a third-party vendor on an AI mortgage platform. Part of that is a production MISMO 3.4 exporter and importer, built in TypeScript from Fannie Mae's public specifications. 9 of 9 test loans validate against the DU schema and round-trip with zero differences.
This does the same loop in miniature: edit the loan, it serializes to XML, then the XML is parsed back and compared field by field.
- Audited 162 vendor API operations; migration plan approved by the CTO and leadership
- 39-table PostgreSQL schema with row-level security, field-level audit logging, and SSN masking; all 433 Fannie Mae DU data points mapped
- Two vendor-replacement slices in production, backed by 436 pgTAP assertions
- Found a vendor bug that misstated debt-to-income by 100x on rental-property loans; fixed a path-traversal hole in the vendor API proxy
SillyQL
An in-memory relational database engine with typed columns and a small SQL-like command language. Dual indexing with hash maps and BSTs cut conditional queries from O(n) scans to O(1) and O(log n) lookups, and ranked in the top 10 for runtime among 1000+ submissions.
A JavaScript port of the command set, so the class code stays private. Click a line to run it, or type your own.
Pipelined CPU
A cycle-accurate 5-stage LC-2K pipeline with explicit pipeline registers, forwarding paths, load-use stall control, and branch-not-taken prediction, plus a configurable write-back cache with LRU replacement.
Step through seven instructions. Turn forwarding off and watch the stalls pile up behind every read-after-write.
13 cycles · 2 stalls · CPI 1.29
LC-2K assembler
A two-pass assembler that turns LC-2K assembly into 32-bit machine code, an instruction-level simulator that executes it, and a 15-bit multiplier written in LC-2K using only add and nor.
Edit the program. Pass one builds the label table; pass two encodes each line as you type. Try an undefined label or register 9 to see the errors.
8 words · 4 labels · no errors
Zoo routing
Graph algorithms over 2D cage coordinates: Prim's minimum spanning tree in O(n²), a nearest-neighbor tour refined by 2-opt swaps, and an exact tour by branch and bound.
Click the field to add cages. Build a tour, then let 2-opt untangle it one swap at a time.
Add cages, then build a tour.
Priority queues
Four interchangeable priority queue containers behind one abstract interface: unordered, sorted, binary heap, and pairing heap. The binary heap uses fixUp, fixDown, and bottom-up heapify; the pairing heap melds in O(1) and does two-pass pairwise merging on pop.
This is the binary max-heap. Push a value and watch fixUp carry it toward the root one swap at a time. Heapify rebuilds from the bottom up.
Push a value and watch fixUp.
Zombie defense
A round-based simulation where a player with a limited quiver shoots approaching zombies in priority order: ETA (distance / speed), then health, then name. Zombies live in a std::deque so pointers stay stable; a priority_queue of pointers orders them. A max-heap and min-heap pair tracks the running median of lifetimes with O(log n) inserts and O(1) reads.
Spawn a few, then shoot. Each shot is a round: survivors advance, the kill's lifetime drops into one of the two heaps, and the median updates.
Spawn zombies, then shoot the one with the lowest ETA.
Quiet. Spawn some.
Roots are highlighted. Sizes stay within one of each other, so the median is a root or the mean of both.
BST and Map
A templated binary search tree with a custom comparator and in-order iterator, wrapped into an associative Map<Key, Value>. operator[] inserts a default value on a miss; 27 unit tests under AddressSanitizer and UBSan.
Type a course number. The find path lights up as you type; Enter inserts it the way operator[] would.
Type a number. Enter inserts it.
Linked list text buffer
A templated doubly linked List<T> with the Big Three and a bidirectional iterator, used as storage for a cursor-based TextBuffer that tracks row, column, and index as the cursor moves and text is inserted or removed.
Type in the editor. Each character is a node; the cursor is an iterator sitting between two of them.
cursor at index 5 · row 0, column 5
Search engine
A search engine over 3,062 Wikipedia pages: a six-job MapReduce pipeline builds a tf-idf inverted index in three segments, Flask index servers rank by tf-idf and PageRank, and a search server merges their results with a k-way heap merge.
This box ranks the rest of this page with the same tf-idf cosine scoring.
Four interchangeable priority queue containers behind a common abstract interface: unordered, sorted, binary heap, and pairing heap.
A round-based simulation where a player with a limited quiver shoots approaching zombies in priority order, with optional verbose, running-median, and statistics output.
Static site generator
A Click CLI that reads config.json, renders each listed Jinja2 template with its context into url/index.html, and copies static assets into the output tree, with clear non-zero exits for a missing config, malformed JSON, or template errors.
A tiny template engine that handles variables, for loops, and if blocks. Edit either side; break the JSON to see the error path.
exit 0 · html/index.html written
SQL queries
Twelve queries and a view over a bookstore schema and a university schema: conditional aggregation with COUNT DISTINCT CASE, relational division written as NOT EXISTS over a MINUS, and a self-join view of student pairs. Full marks on the autograder.
Three of the patterns, evaluated live over a small bookstore. Rows that feed the answer are highlighted.
SELECT a.name FROM authors a WHERE NOT EXISTS ( SELECT b.subject FROM books b JOIN authors r ON r.id = b.author_id WHERE r.name = 'J. K. Rowling' MINUS SELECT b2.subject FROM books b2 WHERE b2.author_id = a.id );
Naive Bayes classifier
Bag-of-words classifiers trained on 10,000 IMDB reviews with add-one smoothing, scored against a vocabulary-count baseline and a null classifier on 1,000 held-out reviews, then extended to multi-class emotion labels with argmax over log posteriors.
Write a review. Each known word pulls the log-odds one way or the other; the bars are the per-word evidence. The lexicon here is 32 words, so it's a toy.
Two-sample statistics
A command-line tool that splits a CSV column into two groups, prints descriptive statistics for each, and estimates a 95% confidence interval for the difference in means from 1,000 bootstrap resamples, with an Excel-style interpolated percentile.
Edit the two groups, then resample. The histogram is the sampling distribution of the mean difference; the dashed lines are the 2.5th and 97.5th percentiles.
mean A 13.50 · mean B 17.00 · difference 3.50
Asteroids
A dodge-the-asteroids game with a landing page, settings panel, tutorial, levels through portals, shield pickups, pause, and game over. setInterval timers drive the loop; keydown and keyup flags give smooth diagonal motion; collisions are axis-aligned bounding boxes.
This is the real build. Click into it, then use the arrow keys. Portals level you up; shields absorb one hit.
This is the real build. Tap into it, then drag your finger to fly. Portals level you up; shields absorb one hit.
Artist search
A single-page app that searches the iTunes API by artist and lets you filter by genre, sort, favorite, and play 30-second previews. Genre buttons are derived from the result set; the audio player has random next, repeat, volume, and a progress bar fed by timeupdate events.
The built app, embedded. It hits the real iTunes catalog, so results are live.
EarnedIt
An iOS app for impulsive shoppers that turns purchases into rewards: save items to a wishlist from the Amazon share sheet, finish tasks in easy, medium, and difficult tiers to earn points, and unlock an item with a "You've Earned It" screen that links back to buy it. Grounded in user research and personas.
The core loop, in a phone. Check off tasks until the keyboard unlocks.
Final demo video ↗Snap-Shot
Voice-guided campus navigation on Snap Spectacles for blind and visually impaired students. Say a destination and the glasses give continuous step-by-step directions from Google Places data, while on-device computer vision watches for obstacles. I owned testing, logistics, and the presentation.
Pick two buildings and press speak. The route is schematic; the voice is your browser's.
Demo video from MHacks ↗- 1Face east. Walk 260 meters along the path.
- 2Turn right to face south. Walk 40 meters.
- 3Duderstadt Center is directly ahead. The entrance is at street level.
PySurfers
Play Subway Surfers with your whole body: a webcam tracks your movements with OpenCV and maps them to the game's controls, Kinect-style. Tuning movement sensitivity was the main technical challenge. I playtested, recorded test data for debugging, supplied the hardware, and presented.
A three-lane runner. Arrow keys work; turn on the webcam and lean left or right instead. Motion is detected by frame differencing, in the browser, and nothing leaves your machine.
Arrow keys move. The webcam is optional.
NeuroScanAI
A deep learning model that detects and classifies brain tumors in MRI scans. We started training with EfficientNet, hit hardware limits, and switched to YOLOv8 on a mentor's advice, using transfer learning on a brain MRI dataset. I found and vetted the datasets and helped design the desktop and mobile site.
The one project here without a live demo. The trained weights aren't published, and a fake detector would be worse than none.
Devpost ↗- hr 0Pick the problem: tumor detection and classification on MRI. Find and vet public brain MRI datasets.
- hr 6Start training EfficientNet. Laptops run out of memory.
- hr 12A mentor suggests YOLOv8. Switch to transfer learning from pretrained weights.
- hr 24Flask serves the model; SvelteKit front end for desktop and mobile.
- hr 36Deploying the model was new to all of us. It shipped.
This website
Started as a vanilla HTML, CSS, and JS single page, then rebuilt as a multi-page Astro site with per-page SEO. All content lives in JSON data files, and a theme switcher supports 13 color schemes through CSS custom properties, including a L33T mode for the aesthetically adventurous.
Yes, this site is listed as a project on itself. The recursion was intentional. Pick a theme; it sticks.
theme: Bench