Skip to content
Mai Trinh
Completed

Lucky Wheel

A configurable, weighted-probability prize wheel for events and giveaways — built solo, completed and released.

Role
Solo developer — product, architecture & release preparation
Platform
Android
Period
2026

Project overview

Domain
Consumer utility — event and group random-selection tools
Product
Lucky Wheel is an Android app for creating configurable prize wheels: add prizes or items with a weight, spin the wheel, and get a randomly selected result — built for events, giveaways, and trade shows, not gambling.
Audience
Anyone running an event, giveaway, or group activity who wants a visual, fair way to pick a random result.
Why it exists
A simple, visual alternative to manually picking a winner, with a probability model that can be configured per prize rather than always being equal odds.
Problem
Groups running giveaways or events needed a simple, trustworthy way to run a weighted random draw without building anything themselves.

My role & contributions

This is a personal, solo project — product idea, product design direction, Android implementation, automated testing, and release preparation are all my own work. It's built on top of a reusable Android product foundation I maintain separately, reserved for the app-specific logic: wheel/prize management, the weighted-selection engine, spin animation, and history.

Challenges & solutions

  1. Technical challenges

    The core challenge was making a weighted random draw feel fair and trustworthy: the winner has to be selected correctly according to each prize's configured weight, the spin animation has to visually land on that exact result without looking ambiguous, and a rapid double-tap or an accidental back-press during the result dialog must never be able to record two results for one spin.

    How I approached it

    The winner is selected first, using cumulative-weight random sampling — not a naive equal-chance pick — before any animation runs. The wheel's visual slices are deliberately equal in size regardless of weight, so probability and visual layout stay decoupled; a separate geometry calculation then computes the spin's landing rotation, with a safety margin that nudges the stop point away from a slice boundary so the result never looks ambiguous. Saving or skipping a result after the spin is guarded by a single-flight state check, confirmed with a dedicated concurrency test, so at most one history record can ever result from one spin.

Architecture & technologies

A native Android app in Kotlin with Jetpack Compose, Hilt for dependency injection, and Room for fully local, offline persistence — there is no backend and no network permission at all. It consumes several reusable modules (design system, local storage, dependency injection setup, an in-app review prompt, onboarding and settings screens) from a separate Android product foundation project, while all wheel/prize/spin-specific logic stays in the app itself.

Technologies

  • Kotlin
  • Jetpack Compose
  • Hilt
  • Room
  • Kotlin Coroutines
  • JUnit

This project demonstrates

A release-readiness review of the app found it substantially feature-complete but identified two concrete items to fix before publishing — a placeholder privacy-policy link and a missing way to delete a wheel once the free-tier limit is reached. That's a normal, healthy part of shipping software: feature-complete isn't the same as release-ready, and a dedicated release check is what catches the difference before real users do.

  • Android Development
  • Offline Support
  • Release Support
  • QA & Testing

Current progress

  1. Product definition

    Done
  2. Core development

    Done
  3. Testing & refinement

    Done
  4. Release preparation

    Done
  5. Release & improvement

    Done

Have a similar project in mind?

Tell me about your product or challenge, and we can discuss how I can help.

Work With Me