Compare commits

..

11 Commits

Author SHA1 Message Date
cc9b2ad8c0 Mantap UTS 2025-11-07 22:53:49 +07:00
099c35f19a Update README.md 2025-11-06 12:04:44 +07:00
0ee43c2e9a First update calculation 2025-11-06 11:34:31 +07:00
7053fa6573 First update labels 2025-11-06 11:10:35 +07:00
51c9a8e5ff First commit 2025-11-06 09:58:07 +07:00
renovate[bot]
b029b3dd10
Update all dependencies 8.7.3 to v8.8.0 (#271)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-10 05:25:39 +00:00
renovate[bot]
90545a4a4d
Update dependency gradle 8.11.1 to v8.12 (#263)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-21 03:18:17 +00:00
renovate[bot]
e075e6ded8
Update dependency androidx.compose:compose-bom 2024.11.00 to v2024.12.01 (#260)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-12 03:31:35 +00:00
Tomáš Mlynarič
7db6c366a3 Update to kotlin 2.1.0 2024-12-09 17:16:15 +01:00
Jose Alcérreca
076428c67e
Merge pull request #257 from google-developer-training/mlykotom-renovate-fix
Add branches to renovate
2024-12-09 13:44:24 +00:00
Tomáš Mlynarič
59c134aec9
Add branches to renovate 2024-12-09 14:35:04 +01:00
15 changed files with 307 additions and 180 deletions

View File

@ -2,5 +2,10 @@
"$schema": "https://docs.renovatebot.com/renovate-schema.json", "$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [ "extends": [
"local>android/.github:renovate-config" "local>android/.github:renovate-config"
],
"baseBranches": [
"main",
"starter",
"state"
] ]
} }

View File

@ -1,24 +1,38 @@
Tip Time - Solution Code # Kalkulator BMI
=================================
Solution code for the [Android Basics with Compose](https://developer.android.com/courses/android-basics-compose/course): Tip Time app. Aplikasi Android sederhana untuk menghitung Indeks Massa Tubuh (IMT) atau _Body Mass Index_ (BMI), dibuat dengan Kotlin dan Jetpack Compose.
## Deskripsi
Introduction Aplikasi ini memungkinkan pengguna untuk menghitung BMI mereka dengan memasukkan tinggi dan berat badan. Aplikasi mendukung dua sistem pengukuran:
------------
The Tip Time app contains various UI elements for calculating a tip,
teaching about user input, and State in Compose.
1. **Sistem Internasional (SI)**: Menggunakan kilogram (kg) untuk berat dan sentimeter (cm) untuk tinggi.
2. **US Customary (USC)**: Menggunakan pon (lbs) untuk berat dan inci (in) untuk tinggi.
Pre-requisites Setelah menghitung, aplikasi akan menampilkan hasil BMI dan mengklasifikasikannya ke dalam salah satu dari empat kategori:
-------------- * **Kekurangan Berat Badan**
* Experience with Kotlin syntax. * **Normal**
* How to create and run a project in Android Studio. * **Kelebihan Berat Badan**
* **Obesitas**
## Fitur Utama
Getting Started * **Perhitungan BMI Akurat**: Mengimplementasikan formula standar BMI untuk kedua sistem unit.
--------------- * **Antarmuka Modern**: Dibuat dengan Jetpack Compose, menampilkan input field yang bersih dan kartu hasil yang dinamis.
1. Install Android Studio, if you don't already have it. * **Umpan Balik Visual**: Kartu hasil berubah warna sesuai dengan kategori BMI untuk memberikan indikasi visual yang cepat dan jelas.
2. Download the sample. * **Pilihan Unit Fleksibel**: Pengguna dapat dengan mudah beralih antara sistem SI dan USC.
3. Import the sample into Android Studio. * **Validasi Sederhana**: Menangani input kosong untuk mencegah error saat perhitungan.
4. Build and run the sample. * **Kode Modular**: Kode dipecah menjadi beberapa komponen Composable yang dapat digunakan kembali (`BmiCalculatorScreen`, `EditNumberField`, `BmiResultCard`).
* **Unit Testing**: Dilengkapi dengan unit test untuk memverifikasi logika perhitungan BMI dan penentuan kategori.
## Teknologi yang Digunakan
* **Bahasa Pemrograman**: Kotlin
* **UI Toolkit**: Jetpack Compose
* **Arsitektur**: Mengikuti prinsip-prinsip dasar _state management_ di Compose dengan _unidirectional data flow_.
* **Asisten AI**: Proyek ini dikembangkan dengan bantuan **Gemini**, sebuah model bahasa besar dari Google, untuk pembuatan kode, refactoring, dokumentasi, dan debugging.
## Dibuat Oleh
* **Nama**: Yosep Gamaliel Mulia
* **NPM**: 202310715105

View File

@ -17,6 +17,7 @@
plugins { plugins {
id("com.android.application") id("com.android.application")
id("org.jetbrains.kotlin.android") id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.plugin.compose")
} }
android { android {
@ -45,18 +46,15 @@ android {
} }
} }
compileOptions { compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_17
} }
kotlinOptions { kotlinOptions {
jvmTarget = "1.8" jvmTarget = JavaVersion.VERSION_17.toString()
} }
buildFeatures { buildFeatures {
compose = true compose = true
} }
composeOptions {
kotlinCompilerExtensionVersion = rootProject.extra["compose_compiler_version"].toString()
}
packaging { packaging {
resources { resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}" excludes += "/META-INF/{AL2.0,LGPL2.1}"
@ -67,7 +65,7 @@ android {
dependencies { dependencies {
implementation(platform("androidx.compose:compose-bom:2024.11.00")) implementation(platform("androidx.compose:compose-bom:2024.12.01"))
implementation("androidx.activity:activity-compose:1.9.3") implementation("androidx.activity:activity-compose:1.9.3")
implementation("androidx.compose.material3:material3") implementation("androidx.compose.material3:material3")
implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui")
@ -78,7 +76,7 @@ dependencies {
testImplementation("junit:junit:4.13.2") testImplementation("junit:junit:4.13.2")
androidTestImplementation(platform("androidx.compose:compose-bom:2024.11.00")) androidTestImplementation(platform("androidx.compose:compose-bom:2024.12.01"))
androidTestImplementation("androidx.compose.ui:ui-test-junit4") androidTestImplementation("androidx.compose.ui:ui-test-junit4")
androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1") androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
androidTestImplementation("androidx.test.ext:junit:1.2.1") androidTestImplementation("androidx.test.ext:junit:1.2.1")

View File

@ -20,9 +20,9 @@
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@drawable/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@drawable/ic_launcher"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.TipTime" android:theme="@style/Theme.TipTime"
tools:targetApi="33"> tools:targetApi="33">

View File

@ -1,3 +1,4 @@
/* /*
* Copyright (C) 2023 The Android Open Source Project * Copyright (C) 2023 The Android Open Source Project
* *
@ -13,6 +14,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
// NPM: 202310715105
// Nama: Yosep Gamaliel Mulia
package com.example.tiptime package com.example.tiptime
import android.os.Bundle import android.os.Bundle
@ -21,52 +24,38 @@ import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawingPadding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Icon import androidx.compose.material3.*
import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.*
import androidx.compose.material3.Surface
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.example.tiptime.ui.theme.TipTimeTheme import androidx.compose.ui.unit.sp
import java.text.NumberFormat import com.example.tiptime.ui.theme.BmiCalculatorTheme
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge() enableEdgeToEdge()
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContent { setContent {
TipTimeTheme { BmiCalculatorTheme {
Surface( Surface(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
) { ) {
TipTimeLayout() BmiCalculatorScreen()
} }
} }
} }
@ -74,62 +63,90 @@ class MainActivity : ComponentActivity() {
} }
@Composable @Composable
fun TipTimeLayout() { fun BmiCalculatorScreen() {
var amountInput by remember { mutableStateOf("") } var heightInput by remember { mutableStateOf("") }
var tipInput by remember { mutableStateOf("") } var weightInput by remember { mutableStateOf("") }
var roundUp by remember { mutableStateOf(false) } var useUscUnits by remember { mutableStateOf(false) }
var bmiResult by remember { mutableStateOf<Pair<Double, String>?>(null) }
val amount = amountInput.toDoubleOrNull() ?: 0.0 val height = heightInput.toDoubleOrNull()
val tipPercent = tipInput.toDoubleOrNull() ?: 0.0 val weight = weightInput.toDoubleOrNull()
val tip = calculateTip(amount, tipPercent, roundUp)
val heightLabel = if (useUscUnits) R.string.height_in else R.string.height_cm
val weightLabel = if (useUscUnits) R.string.weight_lbs else R.string.weight_kg
Column( Column(
modifier = Modifier modifier = Modifier
.statusBarsPadding() .statusBarsPadding()
.padding(horizontal = 40.dp) .fillMaxWidth()
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())
.safeDrawingPadding(), .safeDrawingPadding()
.padding(32.dp),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center verticalArrangement = Arrangement.spacedBy(16.dp)
) { ) {
Text( Text(
text = stringResource(R.string.calculate_tip), text = stringResource(R.string.bmi_calculator_title),
style = MaterialTheme.typography.displaySmall,
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(16.dp))
// Input Fields
Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
EditNumberField(
label = heightLabel,
leadingIcon = R.drawable.height,
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Next
),
value = heightInput,
onValueChanged = { heightInput = it; bmiResult = null },
modifier = Modifier.fillMaxWidth(),
)
EditNumberField(
label = weightLabel,
leadingIcon = R.drawable.weight,
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Done
),
value = weightInput,
onValueChanged = { weightInput = it; bmiResult = null },
modifier = Modifier.fillMaxWidth(),
)
UnitSelectionRow(
useUsc = useUscUnits,
onUscChanged = { useUscUnits = it; bmiResult = null },
)
}
Button(
onClick = {
if (height != null && weight != null) {
val bmi = calculateBmi(height, weight, useUscUnits)
val category = getBmiCategory(bmi)
bmiResult = Pair(bmi, category)
}
},
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF50AADD)),
modifier = Modifier modifier = Modifier
.padding(bottom = 16.dp, top = 40.dp) .fillMaxWidth()
.align(alignment = Alignment.Start) .height(50.dp)
) ) {
EditNumberField( Text(
label = R.string.bill_amount, stringResource(R.string.calculate_bmi_button),
leadingIcon = R.drawable.money, fontSize = 18.sp
keyboardOptions = KeyboardOptions.Default.copy( )
keyboardType = KeyboardType.Number, }
imeAction = ImeAction.Next
), // Result Display
value = amountInput, bmiResult?.let { (bmi, category) ->
onValueChanged = { amountInput = it }, BmiResultCard(bmi = bmi, category = category)
modifier = Modifier.padding(bottom = 32.dp).fillMaxWidth(), }
)
EditNumberField(
label = R.string.how_was_the_service,
leadingIcon = R.drawable.percent,
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Done
),
value = tipInput,
onValueChanged = { tipInput = it },
modifier = Modifier.padding(bottom = 32.dp).fillMaxWidth(),
)
RoundTheTipRow(
roundUp = roundUp,
onRoundUpChanged = { roundUp = it },
modifier = Modifier.padding(bottom = 32.dp)
)
Text(
text = stringResource(R.string.tip_amount, tip),
style = MaterialTheme.typography.displaySmall
)
Spacer(modifier = Modifier.height(150.dp))
} }
} }
@ -145,52 +162,114 @@ fun EditNumberField(
TextField( TextField(
value = value, value = value,
singleLine = true, singleLine = true,
leadingIcon = { Icon(painter = painterResource(id = leadingIcon), null) }, leadingIcon = {
Icon(
painter = painterResource(id = leadingIcon),
contentDescription = null,
tint = MaterialTheme.colorScheme.primary
)
},
modifier = modifier, modifier = modifier,
onValueChange = onValueChanged, onValueChange = onValueChanged,
label = { Text(stringResource(label)) }, label = { Text(stringResource(label)) },
keyboardOptions = keyboardOptions keyboardOptions = keyboardOptions,
shape = MaterialTheme.shapes.medium,
colors = TextFieldDefaults.colors(
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent
)
) )
} }
@Composable @Composable
fun RoundTheTipRow( fun UnitSelectionRow(
roundUp: Boolean, useUsc: Boolean,
onRoundUpChanged: (Boolean) -> Unit, onUscChanged: (Boolean) -> Unit,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
Row( Row(
modifier = modifier.fillMaxWidth(), modifier = modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) { ) {
Text(text = stringResource(R.string.round_up_tip)) Text(text = stringResource(R.string.use_usc_units), style = MaterialTheme.typography.bodyLarge)
Switch( Switch(
modifier = Modifier checked = useUsc,
.fillMaxWidth() onCheckedChange = onUscChanged
.wrapContentWidth(Alignment.End),
checked = roundUp,
onCheckedChange = onRoundUpChanged
) )
} }
} }
/** @Composable
* Calculates the tip based on the user input and format the tip amount fun BmiResultCard(bmi: Double, category: String, modifier: Modifier = Modifier) {
* according to the local currency. val categoryColor = getCategoryColor(category)
* Example would be "$10.00". Column(
*/ modifier = modifier
private fun calculateTip(amount: Double, tipPercent: Double = 15.0, roundUp: Boolean): String { .fillMaxWidth()
var tip = tipPercent / 100 * amount .clip(RoundedCornerShape(16.dp))
if (roundUp) { .background(categoryColor)
tip = kotlin.math.ceil(tip) .padding(24.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = stringResource(R.string.your_bmi),
style = MaterialTheme.typography.titleMedium,
color = Color.White
)
Text(
text = bmi.format(1),
style = MaterialTheme.typography.displayLarge,
color = Color.White,
modifier = Modifier.padding(vertical = 8.dp)
)
Text(
text = category,
style = MaterialTheme.typography.headlineSmall,
color = Color.White
)
} }
return NumberFormat.getCurrencyInstance().format(tip)
} }
private fun getCategoryColor(category: String): Color {
return when (category) {
"Kekurangan Berat Badan" -> Color(0xFF3D5AFE) // Blue
"Normal" -> Color(0xFF00C853) // Green
"Kelebihan Berat Badan" -> Color(0xFFFFAB00) // Amber
"Obesitas" -> Color(0xFFD50000) // Red
else -> Color.Gray
}
}
internal fun calculateBmi(height: Double, weight: Double, useUscUnits: Boolean): Double {
return if (height > 0 && weight > 0) {
if (useUscUnits) {
703 * weight / (height * height)
} else {
val heightInMeters = height / 100
weight / (heightInMeters * heightInMeters)
}
} else {
0.0
}
}
internal fun getBmiCategory(bmi: Double): String {
return when {
bmi < 18.5 -> "Kekurangan Berat Badan"
bmi < 25 -> "Normal"
bmi < 30 -> "Kelebihan Berat Badan"
else -> "Obesitas"
}
}
private fun Double.format(digits: Int) = "%.${digits}f".format(this)
@Preview(showBackground = true) @Preview(showBackground = true)
@Composable @Composable
fun TipTimeLayoutPreview() { fun BmiCalculatorScreenPreview() {
TipTimeTheme { BmiCalculatorTheme {
TipTimeLayout() BmiCalculatorScreen()
} }
} }

View File

@ -0,0 +1,13 @@
package com.example.tiptime.ui.theme
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
@Composable
fun BmiCalculatorTheme(
content: @Composable () -> Unit
) {
MaterialTheme(
content = content
)
}

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#8A8A8A"
android:pathData="M16,7c0,2.21 -1.79,4 -4,4S8,9.21 8,7s1.79,-4 4,-4S16,4.79 16,7zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
</vector>

View File

@ -0,0 +1,36 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="1024dp"
android:height="1024dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M0,0C337.9,0 675.8,0 1024,0C1024,337.9 1024,675.8 1024,1024C686.1,1024 348.2,1024 0,1024C0,686.1 0,348.2 0,0Z"
android:fillColor="#FEFEFE"/>
<path
android:pathData="M305.1,287.9C306.2,287.9 307.3,287.8 308.4,287.8C312,287.8 315.7,287.8 319.3,287.8C321.8,287.8 324.3,287.8 326.9,287.8C332.2,287.8 337.5,287.8 342.8,287.8C348.9,287.8 355,287.8 361.1,287.8C367,287.8 372.9,287.8 378.8,287.8C381.2,287.8 383.7,287.8 386.2,287.8C414.4,287.7 441.3,289.4 462.4,310.3C463.2,311.2 464.1,312.1 465,313C465.7,313.7 466.5,314.4 467.2,315.2C471.3,319.4 474.5,324.1 477.6,329.1C478,329.7 478.3,330.2 478.7,330.8C485.3,342 489.1,354.8 492.4,367.3C492.6,367.9 492.8,368.6 493,369.4C506.6,419.8 512.9,472.8 513.3,525C513.3,526.2 513.4,527.4 513.4,528.7C513.5,538 512.2,545.7 505.8,552.9C499.3,558.7 492.7,560.8 484,560.4C476.6,559.4 470.7,555.8 466.2,549.9C461.7,542.7 461,534.7 460.6,526.4C460.5,525.1 460.5,523.8 460.4,522.5C460.4,521.8 460.3,521.1 460.3,520.4C458.3,482.4 453.4,444.2 446.3,406.8C446,405.3 446,405.3 445.7,403.7C444.7,398.5 443.3,393.8 441,389C439.3,389 437.7,389 436,389C434.8,390 434.8,390 434.9,391.9C435,392.8 435,393.6 435,394.5C435.1,395.5 435.1,396.5 435.1,397.5C435.2,398.6 435.2,399.7 435.3,400.8C435.4,402.5 435.4,402.5 435.4,404.3C436.2,421 437.4,437.7 438.6,454.3C439.4,465.4 440.1,476.5 440.8,487.6C440.9,489.2 441,490.8 441.2,492.3C443.4,527.2 443.4,562.1 443.3,597C443.3,601 443.3,605.1 443.3,609.1C443.3,653.6 442.9,698 441.6,742.4C441.5,743.6 441.5,744.7 441.5,745.9C440.9,764 440.4,782 439.5,800.1C439.1,807.1 438.9,814.1 438.8,821.1C438.8,823 438.7,824.8 438.7,826.6C438.7,829.4 438.6,832.2 438.6,835C438.3,861.6 438.3,861.6 429,871C421.2,877 413.8,879 404,878C397.4,876.1 391.3,872.6 387.6,866.7C382.8,857.6 381.6,848.8 381,838.6C380.9,836.6 380.7,834.7 380.6,832.8C380.4,830.7 380.3,828.6 380.2,826.5C379.7,818.8 379.1,811.1 378.6,803.4C378.5,802.6 378.4,801.7 378.4,800.9C376.8,778.9 375,757 373.2,735.1C372.9,731.9 372.7,728.7 372.4,725.4C372.1,721.2 371.7,717 371.4,712.8C371.3,711.7 371.2,710.7 371.1,709.7C370.9,706.6 370.6,703.6 370.4,700.5C368.7,680.9 367.2,661.2 365.7,641.5C365.1,634.1 364.5,626.6 363.9,619.2C363.7,616.8 363.5,614.5 363.4,612.1C363.1,608.7 362.8,605.4 362.6,602C362.4,599.9 362.2,597.9 362.1,595.8C361.9,593.8 361.8,591.9 361.6,590C361.3,585.8 361,581.6 360.8,577.4C360.8,576.7 360.8,576 360.8,575.3C360.7,573.5 360.7,571.7 360.6,570C359.8,566 358.1,564.5 355,562C351.4,561.7 351.4,561.7 348,563C344.6,566.3 344.4,569.9 344.1,574.4C344,575.2 344,575.9 343.9,576.7C343.7,579.2 343.5,581.6 343.4,584.1C343.2,585.9 343.1,587.7 342.9,589.4C342.6,594.2 342.2,599 341.8,603.7C341.5,608.7 341.1,613.7 340.7,618.7C340,627.7 339.3,636.7 338.6,645.7C338,654.2 337.3,662.7 336.7,671.2C336.1,678.8 335.5,686.5 334.9,694.1C333.7,709.7 332.5,725.3 331.2,740.9C331.1,742.3 331.1,742.3 331,743.8C330.2,753.2 329.5,762.6 328.7,772C328.4,775.5 328.1,779 327.9,782.6C327.7,784.3 327.6,786 327.4,787.7C326.6,797.6 325.9,807.6 325.2,817.5C325.1,819.4 325,821.3 324.8,823.2C324.6,826.8 324.4,830.4 324.2,834C322.4,861.5 322.4,861.5 314,870C313.3,870.7 313.3,870.7 312.6,871.5C307.5,876.2 301.9,878.1 295.1,878.4C286.9,878.1 280.8,875.7 274.8,870.1C269.4,863.8 267,856.5 266.7,848.2C266.7,847.3 266.7,846.4 266.6,845.4C266.6,844.4 266.6,843.4 266.6,842.3C266.5,840.7 266.5,840.7 266.4,839.1C266.3,835.5 266.2,831.9 266.1,828.3C266,825.7 265.9,823.2 265.8,820.6C265.6,813.8 265.4,807 265.2,800.2C265.1,795.9 264.9,791.7 264.8,787.4C264.3,772 263.8,756.6 263.3,741.2C263.1,733.5 262.9,725.7 262.6,718C261.1,671 260.6,624 261,577C261,575.4 261,575.4 261,573.8C261.3,531.4 264.3,489 267.2,446.7C267.2,446 267.2,445.3 267.3,444.6C267.8,437.6 268.3,430.6 268.8,423.6C269.6,412.1 270.3,400.6 270,389C268.4,388.7 266.7,388.3 265,388C261.3,391.8 260.7,396.4 259.6,401.4C259.4,402.3 259.2,403.3 259,404.3C256.3,416.8 254.2,429.3 252.3,441.9C252,444 251.7,446.1 251.4,448.1C247.7,472 245.8,495.8 244.4,519.9C244.3,521.7 244.3,521.7 244.2,523.5C244.1,525.8 243.9,528 243.8,530.3C243.2,540.1 241.3,547.7 234.4,555C229.4,559.1 223.7,560.6 217.4,561.5C210,560.4 203.2,557.5 198,552C175.1,514.3 197.7,428.7 207.4,387.8C211.9,369.7 216.8,351.8 225,335C225.5,334 226,333 226.5,331.9C229.9,325.3 234.1,319.6 239,314C239.6,313.3 240.2,312.6 240.8,311.9C253,298.7 269.6,292 287,289C288.5,288.7 288.5,288.7 290,288.5C295,287.8 300,287.9 305.1,287.9Z"
android:fillColor="#4EA8E3"/>
<path
android:pathData="M512.5,605.5C514.2,605.5 514.2,605.5 515.9,605.5C517.1,605.5 518.3,605.5 519.6,605.5C520.8,605.5 522,605.5 523.3,605.5C526,605.5 528.6,605.5 531.3,605.5C535.3,605.6 539.3,605.6 543.3,605.5C581.7,605.6 581.7,605.6 597,619C605.7,628.1 608.4,638.2 608.2,650.6C607.7,659.5 605.4,667.5 599,674C595.8,676.9 592.4,679.4 589,682C589.6,682.3 590.3,682.7 590.9,683C600.3,688.3 606.2,694.3 610.1,704.4C613.3,717.6 611.7,731 604.9,742.7C598.4,752.3 588.9,758.1 577.5,760.5C569.6,762 561.9,762.3 553.9,762.4C552.6,762.4 551.3,762.4 549.9,762.4C547.2,762.4 544.5,762.4 541.7,762.4C538.2,762.4 534.8,762.5 531.3,762.5C527.9,762.6 524.5,762.6 521.2,762.6C519.9,762.6 518.7,762.6 517.4,762.6C515.7,762.6 515.7,762.6 513.9,762.6C512.9,762.6 511.8,762.6 510.8,762.6C506.6,761.7 505.4,760.7 503,757C502.3,752.3 502.3,747.7 502.4,743C502.4,741.6 502.4,740.1 502.3,738.7C502.3,734.8 502.3,730.9 502.4,726.9C502.4,722.8 502.4,718.8 502.4,714.7C502.4,707.8 502.4,700.9 502.4,694C502.4,686.1 502.4,678.1 502.4,670.2C502.4,662.5 502.4,654.9 502.4,647.3C502.4,644 502.4,640.7 502.4,637.5C502.4,633.7 502.4,629.8 502.5,626C502.5,624.6 502.5,623.2 502.5,621.8C502.4,619.9 502.5,617.9 502.5,616C502.5,615 502.5,613.9 502.5,612.8C503.5,607 507.1,605.5 512.5,605.5Z"
android:fillColor="#4CA7E3"/>
<path
android:pathData="M646.2,605.4C648,605.4 648,605.4 649.8,605.4C651,605.4 652.2,605.4 653.5,605.4C654.7,605.4 655.9,605.4 657.2,605.4C667.4,605.5 667.4,605.5 672,610C673.5,612.6 674.5,615.3 675.6,618.1C675.9,618.9 676.2,619.7 676.6,620.5C677.6,623.2 678.7,625.9 679.7,628.5C680.4,630.4 681.2,632.3 681.9,634.1C683.8,639 685.7,643.9 687.6,648.8C689.6,653.7 691.6,658.7 693.5,663.7C697.4,673.5 701.2,683.2 705,693C707.1,690.9 707.7,689.5 708.8,686.7C709.1,685.8 709.5,684.9 709.8,683.9C710.4,682.5 710.4,682.5 710.9,681C711.3,679.9 711.7,678.9 712.1,677.9C712.9,675.7 713.8,673.4 714.6,671.2C715.9,667.8 717.2,664.4 718.5,661C722,651.7 725.5,642.5 728.9,633.2C730,630.3 731.1,627.5 732.1,624.6C732.6,623.3 733.1,622 733.6,620.7C734.2,618.9 734.9,617.2 735.6,615.4C735.9,614.5 736.3,613.5 736.6,612.5C738.3,609.4 740,607.9 743,606C746.1,605.5 746.1,605.5 749.5,605.5C750.7,605.5 751.9,605.5 753.2,605.5C754.5,605.5 755.7,605.5 757.1,605.5C758.3,605.5 759.6,605.5 760.9,605.5C762.2,605.5 763.4,605.5 764.7,605.5C766.3,605.5 766.3,605.5 768.1,605.5C771.6,606.1 772.8,607.2 775,610C776.4,612.8 776.2,615.1 776.3,618.2C776.3,618.9 776.3,619.5 776.3,620.2C776.4,622.3 776.4,624.5 776.5,626.7C776.5,628.2 776.6,629.7 776.6,631.2C776.7,635.3 776.8,639.4 776.9,643.5C777,646.9 777.1,650.3 777.2,653.7C777.7,673.7 778.2,693.7 778.6,713.8C778.6,714.7 778.7,715.6 778.7,716.6C778.8,721 778.9,725.4 778.9,729.8C779,733.5 779.1,737.3 779.2,741C779.2,743 779.3,745 779.3,747C779.4,747.9 779.4,748.9 779.5,749.8C779.5,754.3 779.5,756.3 776.8,760.1C773.9,762 772.7,762.6 769.3,762.7C768.4,762.7 767.6,762.7 766.7,762.7C765.8,762.7 764.9,762.6 764,762.6C763.1,762.6 762.2,762.7 761.3,762.7C760.4,762.7 759.6,762.7 758.7,762.7C757.9,762.7 757.1,762.7 756.3,762.6C752.7,761.6 751.3,759.9 749,757C748.3,753.8 748.3,750.7 748.3,747.4C748.3,746.5 748.3,745.5 748.3,744.5C748.3,741.4 748.3,738.2 748.3,735.1C748.3,732.9 748.3,730.7 748.2,728.5C748.2,722.7 748.2,717 748.2,711.2C748.2,705.3 748.1,699.5 748.1,693.6C748,682.1 748,670.5 748,659C747.8,659.6 747.5,660.2 747.3,660.8C742.8,672.1 738.4,683.3 733.9,694.5C731.4,701 728.8,707.5 726.3,714.1C725.5,716 724.7,717.9 724,719.9C723.1,722.1 722.2,724.3 721.4,726.6C718.7,733.4 718.7,733.4 715.7,736.1C712.1,737.3 708.7,737.5 705,737.4C704.3,737.5 703.6,737.5 702.9,737.5C697.8,737.5 695.6,736.4 692,733C690.5,730.2 690.5,730.2 689.2,727C688.7,725.8 688.2,724.6 687.8,723.4C687.2,722.1 686.7,720.8 686.2,719.5C685.7,718.1 685.1,716.8 684.6,715.4C683.2,711.8 681.8,708.3 680.4,704.7C678.9,701.1 677.5,697.5 676.1,693.9C674.5,689.8 672.9,685.8 671.2,681.7C668.3,674.1 665.2,666.5 662,659C662,660.2 662,661.4 662,662.7C662,674.1 661.9,685.6 661.9,697.1C661.8,703 661.8,708.9 661.8,714.8C661.8,720.4 661.8,726.1 661.7,731.8C661.7,734 661.7,736.2 661.7,738.3C661.7,741.4 661.7,744.4 661.7,747.4C661.7,748.3 661.7,749.2 661.7,750.2C661.6,754.6 661.4,756.4 658.6,760.1C655.9,762.1 654.8,762.6 651.5,762.7C650.7,762.7 649.9,762.7 649.1,762.7C648.2,762.7 647.4,762.6 646.5,762.6C645.7,762.6 644.8,762.7 643.9,762.7C639.8,762.7 637.5,762.3 633.9,760.1C631.1,755.5 631.4,751.6 631.6,746.3C631.6,745.1 631.7,743.9 631.7,742.7C631.7,740 631.8,737.3 631.9,734.6C632,729.6 632.1,724.7 632.2,719.8C632.3,710.6 632.5,701.4 632.7,692.2C632.9,684.7 633.1,677.2 633.2,669.6C633.3,663.2 633.5,656.8 633.6,650.4C633.7,646.4 633.8,642.5 633.8,638.5C633.9,634.7 634,631 634.1,627.2C634.1,625.8 634.1,624.4 634.1,623C634.3,612.2 634.3,612.2 637.2,607.7C640.5,605.7 642.4,605.4 646.2,605.4Z"
android:fillColor="#4DA7E3"/>
<path
android:pathData="M374,149C374.9,149.4 374.9,149.4 375.8,149.8C394.3,157.6 405.8,169.9 413.7,188.4C419.9,205.9 418,223.6 410.3,240.3C402,255.8 388.9,267.1 372.1,272.4C355.6,277.1 338.8,276.4 323.5,268.3C306.7,259 295.1,244.4 289.5,226.1C285.1,208.4 288.7,190.3 297.8,174.9C306.8,160.8 321.1,150.9 337.2,146.9C348.7,144.5 363.1,144.4 374,149Z"
android:fillColor="#4EA7E3"/>
<path
android:pathData="M818.9,605.4C819.9,605.4 820.8,605.4 821.7,605.4C822.7,605.4 823.6,605.4 824.6,605.4C826,605.4 826,605.4 827.4,605.4C834.3,605.5 834.3,605.5 837.6,607.9C840,611.4 840.1,613.5 840.2,617.7C840.2,618.9 840.2,620.1 840.2,621.4C840.2,622.7 840.2,624.1 840.2,625.5C840.2,626.9 840.2,628.3 840.2,629.7C840.2,634.4 840.3,639.1 840.3,643.7C840.3,645.3 840.3,647 840.3,648.6C840.3,655.2 840.3,661.9 840.3,668.6C840.4,678.2 840.4,687.8 840.4,697.4C840.5,704.1 840.5,710.9 840.5,717.6C840.5,721.6 840.5,725.7 840.6,729.7C840.6,733.5 840.6,737.3 840.6,741C840.6,742.4 840.6,743.8 840.6,745.2C840.8,757 840.8,757 837.6,760.3C834.9,762.1 833.5,762.6 830.3,762.6C829,762.5 829,762.5 827.6,762.5C826.8,762.5 825.9,762.5 824.9,762.4C824,762.4 823.1,762.4 822.2,762.4C814.4,762.3 814.4,762.3 811,760C808.9,756.7 808.7,753.9 808.7,750C808.7,748.8 808.7,747.6 808.7,746.4C808.7,745 808.7,743.7 808.7,742.3C808.7,740.9 808.7,739.5 808.7,738.1C808.6,734.2 808.6,730.3 808.6,726.5C808.6,724.1 808.6,721.7 808.6,719.2C808.6,710.8 808.6,702.4 808.6,694C808.6,686.2 808.5,678.3 808.5,670.5C808.5,663.8 808.4,657 808.4,650.3C808.4,646.3 808.4,642.3 808.4,638.3C808.4,634.5 808.4,630.7 808.4,626.9C808.4,625.5 808.4,624.1 808.4,622.8C808.2,611 808.2,611 811.4,607.7C814.2,605.9 815.6,605.4 818.9,605.4Z"
android:fillColor="#4BA6E2"/>
<path
android:pathData="M533,695C537.9,694.9 542.9,694.9 547.9,694.8C549.5,694.8 551,694.8 552.6,694.7C569.1,694.6 569.1,694.6 574.9,699.6C579.3,704.3 580.7,709.1 581.3,715.4C580.8,721.1 579.3,725.3 575.8,729.8C567.5,736.3 558.5,735.4 548.5,735.2C543.4,735.1 538.3,735.1 533,735C533,721.8 533,708.6 533,695Z"
android:fillColor="#FDFEFE"/>
<path
android:pathData="M546.9,631.8C548.1,631.7 549.3,631.7 550.6,631.7C566.9,631.6 566.9,631.6 572.6,636.3C577.1,641.4 578.4,646.1 578.2,652.7C577.7,657.9 576.2,662.3 572.2,665.9C566.9,669.4 562.4,670.3 556.1,670.2C554.8,670.2 553.5,670.2 552.2,670.2C551.6,670.2 550.9,670.2 550.2,670.2C548.2,670.2 546.1,670.2 544.1,670.2C534.1,670.1 534.1,670.1 533,669C532.9,666.3 532.9,663.7 532.9,661.1C532.9,660.3 532.9,659.5 532.9,658.7C532.9,657 532.9,655.3 532.9,653.6C532.9,651 532.9,648.4 532.9,645.8C532.9,644.2 532.9,642.6 532.9,640.9C532.9,640.2 532.9,639.4 532.9,638.6C532.9,629.1 538.8,631.8 546.9,631.8Z"
android:fillColor="#FDFEFE"/>
<path
android:pathData="M245,308C245.7,308.3 246.3,308.7 247,309C239.7,317.4 239.7,317.4 236,321C235.3,320.7 234.7,320.3 234,320C235.5,318.4 236.9,316.7 238.4,315.1C239.2,314.2 240,313.3 240.8,312.4C242.2,310.9 243.6,309.4 245,308Z"
android:fillColor="#3C9FE1"/>
<path
android:pathData="M297,177C297.8,178.6 297.8,178.6 298,181C296.1,184.3 296.1,184.3 294,187C293,184 293,184 293.8,182.2C294.9,180.5 295.9,178.7 297,177Z"
android:fillColor="#369DE0"/>
</vector>

View File

@ -1,23 +0,0 @@
<!--
~ Copyright (C) 2023 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M7.5,11C9.43,11 11,9.43 11,7.5S9.43,4 7.5,4S4,5.57 4,7.5S5.57,11 7.5,11zM7.5,6C8.33,6 9,6.67 9,7.5S8.33,9 7.5,9S6,8.33 6,7.5S6.67,6 7.5,6z"/>
<path android:fillColor="@android:color/white" android:pathData="M4.0025,18.5831l14.5875,-14.5875l1.4142,1.4142l-14.5875,14.5875z"/>
<path android:fillColor="@android:color/white" android:pathData="M16.5,13c-1.93,0 -3.5,1.57 -3.5,3.5s1.57,3.5 3.5,3.5s3.5,-1.57 3.5,-3.5S18.43,13 16.5,13zM16.5,18c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5s1.5,0.67 1.5,1.5S17.33,18 16.5,18z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#8A8A8A"
android:pathData="M9,4v1h6V4c0,-1.1 -0.9,-2 -2,-2h-2c-1.1,0 -2,0.9 -2,2zM12,10c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM19,12c-1.68,0 -3.11,0.99 -3.71,2.44L12,17.42l-3.29,-2.98C8.11,12.99 6.68,12 5,12c-2.76,0 -5,2.24 -5,5v2h24v-2c0,-2.76 -2.24,-5 -5,-5z"/>
</vector>

View File

@ -1,24 +1,16 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2023 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<resources> <resources>
<string name="app_name">Tip Time</string> <string name="app_name">Kalkulator BMI</string>
<string name="calculate_tip">Calculate Tip</string> <string name="bmi_calculator_title">Kalkulator BMI</string>
<string name="bill_amount">Bill Amount</string> <string name="height_in">Tinggi (inci)</string>
<string name="how_was_the_service">Tip Percentage</string> <string name="height_cm">Tinggi (cm)</string>
<string name="round_up_tip">Round up tip?</string> <string name="weight_lbs">Berat (pon)</string>
<string name="tip_amount">Tip Amount: %s</string> <string name="weight_kg">Berat (kg)</string>
</resources> <string name="use_usc_units">Gunakan unit USC</string>
<string name="bmi_result">BMI Anda: %s</string>
<string name="bmi_category_result">Kategori: %s</string>
<string name="height">Tinggi</string>
<string name="weight">Berat</string>
<string name="calculate_bmi_button">Hitung BMI</string>
<string name="your_bmi">BMI Anda</string>
</resources>

View File

@ -14,14 +14,10 @@
* limitations under the License. * limitations under the License.
*/ */
buildscript {
extra.apply {
set("compose_compiler_version", "1.5.3")
}
}
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins { plugins {
id("com.android.application") version "8.7.3" apply false id("com.android.application") version "8.13.0" apply false
id("com.android.library") version "8.7.3" apply false id("com.android.library") version "8.13.0" apply false
id("org.jetbrains.kotlin.android") version "1.9.10" apply false id("org.jetbrains.kotlin.android") version "2.1.0" apply false
id("org.jetbrains.kotlin.plugin.compose") version "2.1.0" apply false
} }

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

3
gradlew vendored
View File

@ -86,8 +86,7 @@ done
# shellcheck disable=SC2034 # shellcheck disable=SC2034
APP_BASE_NAME=${0##*/} APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum MAX_FD=maximum