Skip to content

Commit

Permalink
Merge pull request #39 from neurosky-internship/feature/issue-038
Browse files Browse the repository at this point in the history
Multiplcation Table Game
  • Loading branch information
yjyoon-dev authored Dec 21, 2022
2 parents 792bbbc + 0854415 commit 7a0ec5b
Show file tree
Hide file tree
Showing 2 changed files with 197 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package com.neurosky.zonetrainer.ui.component

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ElevatedButton
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.neurosky.zonetrainer.ui.theme.NeuroTheme
import kotlin.random.Random

@Composable
fun MultiplicationTable(modifier: Modifier = Modifier) {
val random = Random(System.currentTimeMillis())

var x: Int by mutableStateOf(getRandomNumber(random))
var y: Int by mutableStateOf(getRandomNumber(random))
var table by mutableStateOf(getRandomTable(random, x, y))

Column(
modifier = modifier,
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
QuestionPanel(x, y)
Spacer(modifier = Modifier.height(24.dp))
NumberTable(
numbers = table,
answer = x * y,
onCorrect = {
x = getRandomNumber(random)
y = getRandomNumber(random)
table = getRandomTable(random, x, y)
}
)
}
}

@Composable
fun QuestionPanel(
x: Int,
y: Int
) {
Surface(
shape = RoundedCornerShape(12.dp),
color = Color.White
) {
Text(
"$x × $y = ?",
style = TextStyle(fontWeight = FontWeight.Bold),
modifier = Modifier.padding(vertical = 12.dp, horizontal = 48.dp)
)
}
}

@Composable
fun NumberTable(
numbers: List<Int>,
answer: Int,
onCorrect: () -> Unit
) {
Surface(
shape = RoundedCornerShape(12.dp),
color = Color.Transparent
) {
LazyVerticalGrid(columns = GridCells.Fixed(TABLE_SIZE)) {
items(numbers) { number ->
ElevatedButton(
onClick = { if (number == answer) onCorrect() },
modifier = Modifier.aspectRatio(1F),
contentPadding = PaddingValues(4.dp)
) {
Text(number.toString(), maxLines = 1, overflow = TextOverflow.Visible)
}
}
}
}
}

fun getRandomNumber(random: Random): Int = random.nextInt(2, 10)

fun getRandomTable(random: Random, x: Int, y: Int): MutableList<Int> {
val table =
MutableList(TABLE_SIZE * TABLE_SIZE) { getRandomNumber(random) * getRandomNumber(random) }
if (!table.contains(x * y)) {
table[random.nextInt(TABLE_SIZE * TABLE_SIZE)] = x * y
}
return table
}

private const val TABLE_SIZE = 6

@Preview
@Composable
private fun MultiplicationTablePreview() {
NeuroTheme {
MultiplicationTable(modifier = Modifier.padding(16.dp))
}
}
129 changes: 78 additions & 51 deletions app/src/main/java/com/neurosky/zonetrainer/ui/neuro/NeuroContent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package com.neurosky.zonetrainer.ui.neuro
import androidx.camera.core.CameraSelector
import androidx.camera.core.Preview
import androidx.camera.view.PreviewView
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
Expand All @@ -13,7 +15,9 @@ import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Cameraswitch
import androidx.compose.material.icons.rounded.ChevronLeft
import androidx.compose.material.icons.rounded.DonutLarge
import androidx.compose.material.icons.rounded.FiberManualRecord
import androidx.compose.material.icons.rounded.Games
import androidx.compose.material.icons.rounded.Stop
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.Icon
Expand All @@ -34,6 +38,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.neurosky.zonetrainer.R
import com.neurosky.zonetrainer.ui.component.MultiplicationTable
import com.neurosky.zonetrainer.ui.component.NeuroDonut
import com.neurosky.zonetrainer.ui.theme.Black
import com.neurosky.zonetrainer.ui.theme.NeuroGreen
Expand All @@ -52,6 +57,7 @@ fun NeuroContent(
stopRecording: () -> Unit
) {
var lensFacing by remember { mutableStateOf(CameraSelector.LENS_FACING_BACK) }
var isPlaying by remember { mutableStateOf(false) }

val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current
Expand All @@ -62,6 +68,8 @@ fun NeuroContent(
.requireLensFacing(lensFacing)
.build()

val systemUiController = rememberSystemUiController()

LaunchedEffect(lensFacing) {
val cameraProvider = context.getCameraProvider()
cameraProvider.unbindAll()
Expand All @@ -74,8 +82,6 @@ fun NeuroContent(
preview.setSurfaceProvider(previewView.surfaceProvider)
}

val systemUiController = rememberSystemUiController()

LaunchedEffect(isRecording) {
systemUiController.setStatusBarColor(
color = if (isRecording) NeuroGreen else White,
Expand All @@ -84,67 +90,88 @@ fun NeuroContent(
}

Box(
modifier = Modifier
.fillMaxSize()
modifier = Modifier.fillMaxSize()
) {
AndroidView({ previewView }, modifier = Modifier.fillMaxSize())

Box(
Column(
modifier = Modifier
.fillMaxSize()
.padding(12.dp)
.padding(12.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceBetween
) {
FilledIconButton(
onClick = onBack,
colors = IconButtonDefaults.iconButtonColors(
contentColor = Black,
containerColor = White
),
modifier = Modifier.align(Alignment.TopStart)
) {
Icon(imageVector = Icons.Rounded.ChevronLeft, contentDescription = null)
}
FilledIconButton(
onClick = {
lensFacing = if (lensFacing == CameraSelector.LENS_FACING_BACK) {
CameraSelector.LENS_FACING_FRONT
} else {
CameraSelector.LENS_FACING_BACK
}
},
colors = IconButtonDefaults.iconButtonColors(
contentColor = Black,
containerColor = White
),
modifier = Modifier.align(Alignment.TopCenter)
) {
Icon(imageVector = Icons.Rounded.Cameraswitch, contentDescription = null)
}
FilledIconButton(
onClick = if (isRecording) stopRecording else startRecording,
colors = IconButtonDefaults.iconButtonColors(
contentColor = Black,
containerColor = White
),
modifier = Modifier.align(Alignment.TopEnd)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.Top
) {
if (isRecording) {
Icon(
imageVector = Icons.Rounded.Stop,
contentDescription = null
FilledIconButton(
onClick = onBack,
colors = IconButtonDefaults.iconButtonColors(
contentColor = Black,
containerColor = White
)
} else {
Icon(
imageVector = Icons.Rounded.FiberManualRecord,
contentDescription = null,
tint = Color.Red
) {
Icon(imageVector = Icons.Rounded.ChevronLeft, contentDescription = null)
}
FilledIconButton(
onClick = {
lensFacing = if (lensFacing == CameraSelector.LENS_FACING_BACK) {
CameraSelector.LENS_FACING_FRONT
} else {
CameraSelector.LENS_FACING_BACK
}
},
colors = IconButtonDefaults.iconButtonColors(
contentColor = Black,
containerColor = White
)
) {
Icon(imageVector = Icons.Rounded.Cameraswitch, contentDescription = null)
}
Column {
FilledIconButton(
onClick = if (isRecording) stopRecording else startRecording,
colors = IconButtonDefaults.iconButtonColors(
contentColor = Black,
containerColor = White
)
) {
if (isRecording) {
Icon(
imageVector = Icons.Rounded.Stop,
contentDescription = null
)
} else {
Icon(
imageVector = Icons.Rounded.FiberManualRecord,
contentDescription = null,
tint = Color.Red
)
}
}
FilledIconButton(
onClick = { isPlaying = isPlaying.not() },
colors = IconButtonDefaults.iconButtonColors(
contentColor = Black,
containerColor = White
)
) {
Icon(
imageVector = if (isPlaying) Icons.Rounded.DonutLarge else Icons.Rounded.Games,
contentDescription = null
)
}
}
}

if (isPlaying) {
MultiplicationTable(modifier = Modifier.padding(4.dp))
}

Row(
modifier = Modifier
.align(Alignment.BottomCenter)
.fillMaxWidth()
modifier = Modifier.fillMaxWidth()
) {
NeuroDonut(
title = stringResource(id = R.string.attention),
Expand Down

0 comments on commit 7a0ec5b

Please sign in to comment.