Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
local.properties
*.apk
.env
*.keystore
.idea/
build/
app/build/
.gradle/
149 changes: 149 additions & 0 deletions PRD.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# 📄 Product Requirement Document (PRD): AuraTry AR (Android Native - Jetpack Compose)

> **Project Name:** AuraTry AR
> **Platform:** Android Native (Kotlin + Jetpack Compose)
> **Target Device:** Android (Optimized for iQOO / MediaTek / Snapdragon devices)
> **Target Build Time:** < 45 Minutes

---

## 1. Executive Summary

**AuraTry AR** is a native Android application that provides a live digital try-on experience on stage. The app uses **CameraX** to render a full-screen live viewfinder, overlays transparent 2D clothing assets directly over the user's torso, triggers native Android haptics, and calls **MiniMax M3** via **OpenRouter** to synthesize an instant, spoken AI stylist commentary using Android's native `TextToSpeech` engine.

---

## 2. Technical Stack & Dependencies

* **UI Framework:** Jetpack Compose + Material3
* **Camera Library:** AndroidX CameraX (`androidx.camera.camera2`, `androidx.camera.view.PreviewView`)
* **Networking:** Ktor Client or OkHttp3 + `kotlinx.serialization` (JSON parsing)
* **Audio & Haptics:** `android.speech.tts.TextToSpeech` & `android.os.VibratorManager` / `Vibrator`
* **Image Loading:** Coil for Compose (`io.coil-kt:coil-compose`)

---

## 3. Core Functional Requirements

### 3.1 Live Camera Viewfinder (`Feature_01`)

* Implement a full-screen CameraX `Preview` pipeline rendered inside Jetpack Compose using `AndroidView(factory = { PreviewView(it) })`.
* Force selector to use the rear camera (`CameraSelector.DEFAULT_BACK_CAMERA`).

### 3.2 Dynamic AR Outfit Canvas (`Feature_02`)

* Render a transparent PNG asset centered over the torso viewport area using a Compose `Box` layout.
* Implement a bottom horizontal `LazyRow` (Outfit Carousel) displaying available clothing items (`R.drawable.outfit_jacket`, `R.drawable.outfit_hoodie`).
* Highlight the active outfit card with a neon border (`Color(0xFFFF0055)`).

### 3.3 OpenRouter MiniMax M3 Integration (`Feature_03`)

When the user taps an outfit card in the `LazyRow`:

1. Trigger an asynchronous HTTP `POST` request to `[https://openrouter.ai/api/v1/chat/completions](https://openrouter.ai/api/v1/chat/completions)`.
2. Model target: `minimax/minimax-m3`.
3. Pass `extra_body` with `reasoning: { "effort": "low" }` to guarantee sub-800ms generation speeds.

#### Request JSON Payload:

```json
{
"model": "minimax/minimax-m3",
"extra_body": {
"reasoning": { "effort": "low" }
},
"messages": [
{
"role": "system",
"content": "You are an energetic, funny AI fashion stylist at a live tech hackathon. Return ONLY valid JSON with key 'pitch' containing a 1-sentence hilarious pitch under 12 words."
},
{
"role": "user",
"content": "The user just selected: [OUTFIT_NAME]. Hype it up for the stage!"
}
],
"response_format": { "type": "json_object" },
"max_tokens": 60,
"temperature": 0.8
}

```

### 3.4 Audio & Haptics Feedback (`Feature_04`)

* **Haptics:** Trigger `VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE)` on item click.
* **Text-To-Speech:** Pass the parsed `pitch` string to `TextToSpeech.speak(pitch, TextToSpeech.QUEUE_FLUSH, null, "UtteranceId")`.

---

## 4. UI Architecture & Jetpack Compose Layout

```
Box(modifier = Modifier.fillMaxSize()) {
// 1. CameraX PreviewView (Full Screen Background)
AndroidView(factory = { previewView }, modifier = Modifier.fillMaxSize())

// 2. Translucent AR HUD Header
Surface(
modifier = Modifier.align(Alignment.TopCenter).padding(top = 48.dp),
color = Color(0xCC0A0A0F),
shape = RoundedCornerShape(16.dp)
) {
Column { Text(text = "⚡ AuraTry AR Stylist"); Text(text = aiPitchText) }
}

// 3. AR Clothing Overlay Layer
Image(
painter = painterResource(id = selectedOutfit.drawableRes),
contentDescription = null,
modifier = Modifier.align(Alignment.Center).size(300.dp)
)

// 4. Outfit Carousel Selector
LazyRow(
modifier = Modifier.align(Alignment.BottomCenter).padding(bottom = 32.dp)
) {
items(outfitList) { outfit -> OutfitCard(outfit) }
}
}

```

---

## 5. Master Implementation Prompt for Coding Agent

Copy and paste the box below into Cursor, Claude Code, or Android Studio AI Assistant:

```text
Build a native Android application in Kotlin using Jetpack Compose for "AuraTry AR" (AI Live Outfit Try-On).

Key Technical Requirements:
1. CAMERAX PREVIEW:
- Use CameraX to display a full-screen live rear camera feed using AndroidView and PreviewView.
- Handle camera permissions gracefully with Accompanist Permissions or ActivityResultContracts.

2. AR OVERLAY & CAROUSEL:
- Create a data class Outfit(val id: String, val name: String, val drawableRes: Int).
- Display a Box containing an Image overlay positioned at the center of the screen displaying the current selected outfit drawable.
- At the bottom, render a LazyRow showing outfit thumbnails. Apply a neon pink border (0xFFFF0055) around the selected item.

3. OPENROUTER MINIMAX M3 API INTEGRATION:
- Create a repository function `fetchStylistPitch(outfitName: String): String` using OkHttp or Ktor.
- Target URL: "https://openrouter.ai/api/v1/chat/completions"
- Headers: "Authorization: Bearer <OPENROUTER_API_KEY>", "Content-Type: application/json".
- Body JSON: Send model "minimax/minimax-m3", extra_body: { reasoning: { effort: "low" } }, response_format: { type: "json_object" }.
- Prompt system: "You are a hilarious AI stylist. Return JSON: {\"pitch\": \"1-sentence hype line under 12 words\"}".

4. NATIVE TTS & HAPTICS:
- Initialize android.speech.tts.TextToSpeech in MainActivity.
- On selecting an outfit:
a) Trigger a heavy haptic vibration using Vibrator / VibrationEffect.
b) Fetch the pitch from OpenRouter asynchronously using Coroutines.
c) Speak the pitch out loud using tts.speak().

5. UI DESIGN:
- Dark Cyberpunk glassmorphic HUD card at top (Color: 0xCC0A0A0F, Border: 0xFF00FFCC).
- Clean, production-ready, single-activity implementation.

```
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,27 @@

| | |
|---|---|
| **Team name** | _e.g. Team Nova_ |
| **Members** | _Name 1, Name 2, Name 3_ |
| **City / Venue** | _Pune / Hyderabad / Bengaluru / Chennai_ |
| **Team name** | AuraTry Team |
| **Members** | Ayush |
| **City / Venue** | Remote |

---

## 🎯 App

| | |
|---|---|
| **App name** | _Your app name_ |
| **Theme** | _Pick one:_ Simple game · Utility app · Productivity · Fun & social · Learning tool · Creative tool |
| **One-liner** | _What your app does, in one sentence._ |
| **App name** | AuraTry AR |
| **Theme** | Fun & social |
| **One-liner** | A live digital AR try-on experience with an AI stylist commentary. |

### What we built
_A short paragraph: what the app does and who it's for._
AuraTry AR is a native Android application that provides a live digital try-on experience on stage. It overlays AR clothing on the user's camera feed and calls an AI model to generate a funny stylist pitch when an outfit is selected, which is then spoken out loud using Text-To-Speech alongside haptic feedback.

### How the AI is used
- **Model:** _e.g. `openai/gpt-4o-mini` (via OpenRouter)_
- **What the AI does:** _e.g. generates quiz questions from a topic the user types._
- **AI pattern:** _Chat · Summarise · Classify · Generate · Extract · Vision_
- **Model:** `minimax/minimax-m3` (via OpenRouter)
- **What the AI does:** Acts as an energetic, funny AI fashion stylist at a live tech hackathon to generate a 1-sentence hilarious pitch under 12 words for the selected outfit.
- **AI pattern:** Generate

---

Expand Down Expand Up @@ -71,8 +71,8 @@ cd TechQuest
---

## ✅ Submission checklist
- [ ] This README is filled in (team, theme, how to run)
- [ ] The API key is **NOT** in the repo (see `.gitignore` below)
- [x] This README is filled in (team, theme, how to run)
- [x] The API key is **NOT** in the repo (see `.gitignore` below)
- [ ] Final code pushed to **your fork**
- [ ] APK and/or a screen recording added or linked
- [ ] **Pull Request opened** from your fork → `Reskilll/TechQuest` **before the deadline**
Expand Down
98 changes: 98 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
}

import java.util.Properties
import java.io.FileInputStream

val localProperties = Properties()
val localPropertiesFile = rootProject.file("local.properties")
if (localPropertiesFile.exists()) {
localProperties.load(FileInputStream(localPropertiesFile))
}
val openRouterApiKey = localProperties.getProperty("OPENROUTER_API_KEY") ?: "\"dummy_key\""

android {
namespace = "com.techquest.auratryar"
compileSdk = 34

defaultConfig {
applicationId = "com.techquest.auratryar"
minSdk = 26
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
}
val safeApiKey = if (openRouterApiKey.startsWith("\"")) openRouterApiKey else "\"$openRouterApiKey\""
buildConfigField("String", "OPENROUTER_API_KEY", safeApiKey)
}

buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
buildFeatures {
compose = true
buildConfig = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.4"
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
}

dependencies {
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
implementation("androidx.activity:activity-compose:1.8.2")
implementation(platform("androidx.compose:compose-bom:2023.10.01"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3")

// CameraX
val camerax_version = "1.3.1"
implementation("androidx.camera:camera-core:${camerax_version}")
implementation("androidx.camera:camera-camera2:${camerax_version}")
implementation("androidx.camera:camera-lifecycle:${camerax_version}")
implementation("androidx.camera:camera-view:${camerax_version}")

// Accompanist for Permissions
implementation("com.google.accompanist:accompanist-permissions:0.34.0")

// Networking - OkHttp
implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")

// Image Loading
implementation("io.coil-kt:coil-compose:2.5.0")

testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
androidTestImplementation(platform("androidx.compose:compose-bom:2023.10.01"))
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest")
}
33 changes: 33 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-feature
android:name="android.hardware.camera"
android:required="false" />

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AuraTryAR"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true"
android:theme="@style/Theme.AuraTryAR">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Loading