diff --git a/app/build.gradle b/app/build.gradle index 97e77b1c..1c61cd23 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -100,7 +100,7 @@ dependencies { // Android implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'androidx.core:core-ktx:1.4.0-alpha01' + implementation 'androidx.core:core-ktx:1.3.0' implementation 'com.google.android.material:material:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0' diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/HandHistoryActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/HandHistoryActivity.kt index f9aa1f21..1bcafff3 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/HandHistoryActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/HandHistoryActivity.kt @@ -72,11 +72,7 @@ class HandHistoryActivity : BaseActivity() { val attached = intent.getBooleanExtra(IntentKey.ATTACHED.keyName, false) val fragment = HandHistoryFragment.newInstance(handHistoryId, sessionId, attached) - - val fragmentTransaction = supportFragmentManager.beginTransaction() - fragmentTransaction.add(R.id.container, fragment) - fragmentTransaction.commit() - + showFragment(fragment, R.id.container) this.fragment = fragment } @@ -85,22 +81,19 @@ class HandHistoryActivity : BaseActivity() { // val attached = intent.getBooleanExtra(IntentKey.ATTACHED.keyName, false) val fragment = ReplayerFragment.newInstance(handHistoryId) - - val fragmentTransaction = supportFragmentManager.beginTransaction() - fragmentTransaction.add(R.id.container, fragment) - fragmentTransaction.commit() - + showFragment(fragment, R.id.container) this.fragment = fragment } override fun onBackPressed() { - var shouldShowDataLossWarning = false - this.fragment?.let { hhFragment -> - if ((hhFragment as? HandHistoryFragment)?.isEditing == true) { - shouldShowDataLossWarning = true - } - } + val shouldShowDataLossWarning = ((this.fragment as? HandHistoryFragment)?.isEditing == true) + +// this.fragment?.let { hhFragment -> +// if ((hhFragment as? HandHistoryFragment)?.isEditing == true) { +// shouldShowDataLossWarning = true +// } +// } if (shouldShowDataLossWarning) { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerAnimator.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerAnimator.kt index d3efe89e..89b8d214 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerAnimator.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/ReplayerAnimator.kt @@ -9,9 +9,10 @@ import net.pokeranalytics.android.model.handhistory.Street import net.pokeranalytics.android.model.realm.handhistory.HandHistory import net.pokeranalytics.android.ui.modules.handhistory.model.ActionList import net.pokeranalytics.android.ui.modules.handhistory.model.ComputedAction +import net.pokeranalytics.android.util.MathUtils import timber.log.Timber -import kotlin.math.abs import kotlin.math.max +import kotlin.math.min class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) { @@ -247,14 +248,6 @@ class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) { this.tableCornerXRadius = this.tableRect.width() / 3 this.tableCornerYRadius = this.tableRect.height() / 3 -// for (i in (0 until handHistory.numberOfPlayers)) { -// -// val angle = i * (2 * Math.PI / handHistory.numberOfPlayers) -// val x = -// val y = -// -// } - // this.tableCornerRadius = (if (portrait) width else height) / 8 @@ -290,141 +283,199 @@ class ReplayerAnimator(var handHistory: HandHistory, var export: Boolean) { this.totalPotTextPoint = TextPoint(centerX, centerY - 2f * chipTextSize, chipTextSize) val playerCount = this.handHistory.numberOfPlayers - // number of players in this order: bottom / left / top / right - val repartition = when (playerCount) { - 2 -> mutableListOf(1, 0, 1, 0) - 3 -> mutableListOf(1, 1, 0, 1) - 4 -> mutableListOf(1, 1, 1, 1) - 5 -> mutableListOf(1, 1, 2, 1) - 6 -> mutableListOf(2, 1, 2, 1) - 7 -> mutableListOf(2, 1, 3, 1) - 8 -> mutableListOf(3, 1, 3, 1) - 9 -> mutableListOf(3, 1, 4, 1) - 10 -> mutableListOf(4, 1, 4, 1) - else -> throw PAIllegalStateException("can't happen") - } - if (repartition.sum() != playerCount) { - throw PAIllegalStateException("Problem in the $playerCount players repartition: $repartition") - } - if (portrait && playerCount > 4) { repartition.reverse() } // adjustment for portrait vs landscape - val chipsVerticalOffsetFromStackCenter = this.playerItemsHeight * 0.9f - val chipsHorizontalOffsetFromStackCenter = this.tableHPadding * 1.2f + val positions = MathUtils.positionsAroundRoundedRectangle(playerCount, this.tableRect, this.tableCornerXRadius, this.tableCornerYRadius) + for (i in (0 until playerCount)) { - var pIndex = -1 - repartition.forEachIndexed { index, count -> + val point = positions[i].first + val bottomOriented = positions[i].second + val rectCenterX = point.x + val rectCenterY = point.y - val xItemSpacing = width / (count + 1) - val yItemSpacing = height / (count + 1) + val left = rectCenterX - this.playerItemsWidth / 2 + val top = rectCenterY - this.playerItemsHeight / 2 + val right = rectCenterX + this.playerItemsWidth / 2 + val bottom = rectCenterY + this.playerItemsHeight / 2 + this.playerStackRects.add(RectF(left, top, right, bottom)) - var rectCenterX: Float - var rectCenterY: Float - var chipXOffset: Float - var chipYOffset: Float - var chipTextYOffsetCoef = 0f - var circleOffset = playerItemsHeight * 1.75f - for (i in 1..count) { +// val chipCircleY = rectCenterY + chipYOffset - chipTextYOffsetCoef * chipRadius - pIndex += 1 - Timber.d("Creating dimensions for player $pIndex") + val line = MathUtils.Line(point.x, point.y, tableRect.centerX(), tableRect.centerY()) + val chipPoint = line.pointForDistance(this.playerItemsWidth * 0.8f) - // when the position is in a corner, because we have 3/4 players - // we need an additional offset direction to display the chips - val cornerDirection = when { - count > 2 && i == 1 -> { 1 } - count > 2 && i == count -> { - 1 } - else -> { 0 } - } + this.chipCircles.add(Circle(chipPoint.x, chipPoint.y, chipRadius)) - when (index) { - 0 -> { // bottom - rectCenterX = xItemSpacing * i - rectCenterY = height - this.tableVPadding - circleOffset *= -1 - chipXOffset = cornerDirection * chipsHorizontalOffsetFromStackCenter - chipYOffset = -1 * chipsVerticalOffsetFromStackCenter - chipTextYOffsetCoef = 1f - } - 1 -> { // left - rectCenterY = if (count == 4 && (i == 2 || i == 3)) { - height - yItemSpacing - this.playerItemsHeight * 1.2f - pzHeight * (i - 2) - } else { - height - yItemSpacing * i - } - rectCenterX = this.tableHPadding -// rectCenterY = height - yItemSpacing * i - chipXOffset = 1 * chipsHorizontalOffsetFromStackCenter - chipYOffset = cornerDirection * -1 * chipsVerticalOffsetFromStackCenter - chipTextYOffsetCoef = 1f * (i - 1) / count - - if (count == 4 && i == 1) { - circleOffset *= -1 - } else { - circleOffset = abs(circleOffset) - } + this.chipTextPoints.add(TextPoint(chipPoint.x, chipPoint.y + 2 * chipTextSize, chipTextSize)) - } - 2 -> { // top - rectCenterX = xItemSpacing * i - rectCenterY = this.tableVPadding - chipXOffset = cornerDirection * -1 * chipsHorizontalOffsetFromStackCenter - chipYOffset = 1 * chipsVerticalOffsetFromStackCenter - } - 3 -> { // right - rectCenterX = width - this.tableHPadding - rectCenterY = yItemSpacing * i - chipXOffset = -1 * chipsHorizontalOffsetFromStackCenter - chipYOffset = cornerDirection * chipsVerticalOffsetFromStackCenter - chipTextYOffsetCoef = 1f * (count - i + 1) / count - } - else -> throw PAIllegalStateException("can't happen") - } - - val left = rectCenterX - this.playerItemsWidth / 2 - val top = rectCenterY - this.playerItemsHeight / 2 - val right = rectCenterX + this.playerItemsWidth / 2 - val bottom = rectCenterY + this.playerItemsHeight / 2 - this.playerStackRects.add(RectF(left, top, right, bottom)) - - - val chipCircleY = rectCenterY + chipYOffset - chipTextYOffsetCoef * chipRadius - - this.chipCircles.add(Circle(rectCenterX + chipXOffset, chipCircleY, chipRadius)) - - this.chipTextPoints.add(TextPoint(rectCenterX + chipXOffset, chipCircleY + 2 * chipTextSize, chipTextSize)) - - // we give each text zone 1/3rd of the box height, leaving 1/3 for space - // the y given is the bottom of the text rect, giving 1/18th as the offset - // 1 / (3_total_space * 3_each_space * 2_center) + // we give each text zone 1/3rd of the box height, leaving 1/3 for space + // the y given is the bottom of the text rect, giving 1/18th as the offset + // 1 / (3_total_space * 3_each_space * 2_center) - val bottomOffset = this.playerItemsHeight / (3 * 3 * 2) - val fontSize = this.playerItemsHeight / 3 - this.playerNamePoints.add(TextPoint(rectCenterX, rectCenterY - bottomOffset, fontSize)) - this.playerStackPoints.add(TextPoint(rectCenterX, rectCenterY + this.playerItemsHeight / 3, fontSize)) - this.playerActionPoints.add(TextPoint(rectCenterX, rectCenterY + this.playerItemsHeight / 9, fontSize)) + val bottomOffset = this.playerItemsHeight / (3 * 3 * 2) + val fontSize = this.playerItemsHeight / 3 + this.playerNamePoints.add(TextPoint(rectCenterX, rectCenterY - bottomOffset, fontSize)) + this.playerStackPoints.add(TextPoint(rectCenterX, rectCenterY + this.playerItemsHeight / 3, fontSize)) + this.playerActionPoints.add(TextPoint(rectCenterX, rectCenterY + this.playerItemsHeight / 9, fontSize)) - this.playerCircles.add(Circle(rectCenterX, rectCenterY - circleOffset, this.playerItemsHeight / 2)) + val orientation = if (bottomOriented) -1 else 1 + val circleOffset = playerItemsHeight * 1.75f * orientation + this.playerCircles.add(Circle(rectCenterX, rectCenterY - circleOffset, this.playerItemsHeight / 2)) - val cardsUsed = this.handHistory.playerSetupForPosition(pIndex)?.cards?.size ?: maxPlayerCards - val cardsRectangles = mutableListOf() - if (cardsUsed > 0) { - val offSet = (cardsUsed / 2 - 0.5f) * cardWPaddingWidth + val cardsUsed = this.handHistory.playerSetupForPosition(i)?.cards?.size ?: maxPlayerCards + val cardsRectangles = mutableListOf() + if (cardsUsed > 0) { + val offSet = (cardsUsed / 2 - 0.5f) * cardWPaddingWidth - val cardCenterY = rectCenterY - circleOffset / 2 - for (c in 0 until cardsUsed) { + val cardCenterY = rectCenterY - circleOffset / 2 + for (c in 0 until cardsUsed) { - val cardCenterX = rectCenterX - offSet + c * cardWPaddingWidth - val cardRect = RectF(cardCenterX - cardSpecs.width / 2, cardCenterY - cardSpecs.height / 2, cardCenterX + cardSpecs.width / 2, cardCenterY + cardSpecs.height / 2) - cardsRectangles.add(cardRect) - } + val cardCenterX = rectCenterX - offSet + c * cardWPaddingWidth + val cardRect = RectF(cardCenterX - cardSpecs.width / 2, cardCenterY - cardSpecs.height / 2, cardCenterX + cardSpecs.width / 2, cardCenterY + cardSpecs.height / 2) + cardsRectangles.add(cardRect) } - this.playerCardRects.add(cardsRectangles) - } + this.playerCardRects.add(cardsRectangles) } + + + // number of players in this order: bottom / left / top / right +// val repartition = when (playerCount) { +// 2 -> mutableListOf(1, 0, 1, 0) +// 3 -> mutableListOf(1, 1, 0, 1) +// 4 -> mutableListOf(1, 1, 1, 1) +// 5 -> mutableListOf(1, 1, 2, 1) +// 6 -> mutableListOf(2, 1, 2, 1) +// 7 -> mutableListOf(2, 1, 3, 1) +// 8 -> mutableListOf(3, 1, 3, 1) +// 9 -> mutableListOf(3, 1, 4, 1) +// 10 -> mutableListOf(4, 1, 4, 1) +// else -> throw PAIllegalStateException("can't happen") +// } +// if (repartition.sum() != playerCount) { +// throw PAIllegalStateException("Problem in the $playerCount players repartition: $repartition") +// } +// if (portrait && playerCount > 4) { repartition.reverse() } // adjustment for portrait vs landscape +// +// val chipsVerticalOffsetFromStackCenter = this.playerItemsHeight * 0.9f +// val chipsHorizontalOffsetFromStackCenter = this.tableHPadding * 1.2f +// +// var pIndex = -1 +// repartition.forEachIndexed { index, count -> +// +// val xItemSpacing = width / (count + 1) +// val yItemSpacing = height / (count + 1) +// +// var rectCenterX: Float +// var rectCenterY: Float +// var chipXOffset: Float +// var chipYOffset: Float +// var chipTextYOffsetCoef = 0f +// var circleOffset = playerItemsHeight * 1.75f +// +// for (i in 1..count) { +// +// pIndex += 1 +// Timber.d("Creating dimensions for player $pIndex") +// +// // when the position is in a corner, because we have 3/4 players +// // we need an additional offset direction to display the chips +// val cornerDirection = when { +// count > 2 && i == 1 -> { 1 } +// count > 2 && i == count -> { - 1 } +// else -> { 0 } +// } +// +// when (index) { +// 0 -> { // bottom +// rectCenterX = xItemSpacing * i +// rectCenterY = height - this.tableVPadding +// circleOffset *= -1 +// chipXOffset = cornerDirection * chipsHorizontalOffsetFromStackCenter +// chipYOffset = -1 * chipsVerticalOffsetFromStackCenter +// chipTextYOffsetCoef = 1f +// } +// 1 -> { // left +// rectCenterY = if (count == 4 && (i == 2 || i == 3)) { +// height - yItemSpacing - this.playerItemsHeight * 1.2f - pzHeight * (i - 2) +// } else { +// height - yItemSpacing * i +// } +// rectCenterX = this.tableHPadding +//// rectCenterY = height - yItemSpacing * i +// chipXOffset = 1 * chipsHorizontalOffsetFromStackCenter +// chipYOffset = cornerDirection * -1 * chipsVerticalOffsetFromStackCenter +// chipTextYOffsetCoef = 1f * (i - 1) / count +// +// if (count == 4 && i == 1) { +// circleOffset *= -1 +// } else { +// circleOffset = abs(circleOffset) +// } +// +// } +// 2 -> { // top +// rectCenterX = xItemSpacing * i +// rectCenterY = this.tableVPadding +// chipXOffset = cornerDirection * -1 * chipsHorizontalOffsetFromStackCenter +// chipYOffset = 1 * chipsVerticalOffsetFromStackCenter +// } +// 3 -> { // right +// rectCenterX = width - this.tableHPadding +// rectCenterY = yItemSpacing * i +// chipXOffset = -1 * chipsHorizontalOffsetFromStackCenter +// chipYOffset = cornerDirection * chipsVerticalOffsetFromStackCenter +// chipTextYOffsetCoef = 1f * (count - i + 1) / count +// } +// else -> throw PAIllegalStateException("can't happen") +// } +// +// val left = rectCenterX - this.playerItemsWidth / 2 +// val top = rectCenterY - this.playerItemsHeight / 2 +// val right = rectCenterX + this.playerItemsWidth / 2 +// val bottom = rectCenterY + this.playerItemsHeight / 2 +// this.playerStackRects.add(RectF(left, top, right, bottom)) +// +// +// val chipCircleY = rectCenterY + chipYOffset - chipTextYOffsetCoef * chipRadius +// +// this.chipCircles.add(Circle(rectCenterX + chipXOffset, chipCircleY, chipRadius)) +// +// this.chipTextPoints.add(TextPoint(rectCenterX + chipXOffset, chipCircleY + 2 * chipTextSize, chipTextSize)) +// +// // we give each text zone 1/3rd of the box height, leaving 1/3 for space +// // the y given is the bottom of the text rect, giving 1/18th as the offset +// // 1 / (3_total_space * 3_each_space * 2_center) +// +// val bottomOffset = this.playerItemsHeight / (3 * 3 * 2) +// val fontSize = this.playerItemsHeight / 3 +// this.playerNamePoints.add(TextPoint(rectCenterX, rectCenterY - bottomOffset, fontSize)) +// this.playerStackPoints.add(TextPoint(rectCenterX, rectCenterY + this.playerItemsHeight / 3, fontSize)) +// this.playerActionPoints.add(TextPoint(rectCenterX, rectCenterY + this.playerItemsHeight / 9, fontSize)) +// +// this.playerCircles.add(Circle(rectCenterX, rectCenterY - circleOffset, this.playerItemsHeight / 2)) +// +// val cardsUsed = this.handHistory.playerSetupForPosition(pIndex)?.cards?.size ?: maxPlayerCards +// val cardsRectangles = mutableListOf() +// if (cardsUsed > 0) { +// val offSet = (cardsUsed / 2 - 0.5f) * cardWPaddingWidth +// +// val cardCenterY = rectCenterY - circleOffset / 2 +// for (c in 0 until cardsUsed) { +// +// val cardCenterX = rectCenterX - offSet + c * cardWPaddingWidth +// val cardRect = RectF(cardCenterX - cardSpecs.width / 2, cardCenterY - cardSpecs.height / 2, cardCenterX + cardSpecs.width / 2, cardCenterY + cardSpecs.height / 2) +// cardsRectangles.add(cardRect) +// } +// } +// this.playerCardRects.add(cardsRectangles) +// +// } +// +// } + } fun stackRectForPlayer(positionIndex: Int): RectF { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/TableDrawer.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/TableDrawer.kt index e84f9d64..d44158b2 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/TableDrawer.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/replayer/TableDrawer.kt @@ -48,6 +48,7 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) { private val fillPaint = Paint() private val tablePaint = Paint() + private val feltPaint = Paint() private val textPaint = Paint() private val cardTextPaint = Paint() private val cardStrokePaint = Paint() @@ -62,9 +63,14 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) { backgroundPaint.color = context.getColor(backgroundColor) tablePaint.isAntiAlias = true - tablePaint.style = Paint.Style.STROKE tablePaint.strokeWidth = animator.tableStrokeWidth tablePaint.color = context.getColor(R.color.green) + tablePaint.style = Paint.Style.STROKE + + feltPaint.isAntiAlias = true + feltPaint.color = context.getColor(R.color.green_transparent_felt) + feltPaint.style = Paint.Style.STROKE + feltPaint.strokeWidth = animator.tableStrokeWidth strokePaint.isAntiAlias = true strokePaint.style = Paint.Style.STROKE @@ -212,6 +218,27 @@ class TableDrawer(bitmap: Bitmap) : Canvas(bitmap) { canvas.drawColor(context.getColor(backgroundColor)) + // Felt rosace + val xr = animator.tableCornerXRadius + val yr = animator.tableCornerYRadius + val r = animator.tableRect + val r1 = RectF(r.left, r.top, r.left + 2 * xr, r.top + 2 * yr) + canvas.drawRoundRect(r1, animator.tableCornerXRadius, animator.tableCornerYRadius, this.feltPaint) + val r2 = RectF(r.right - 2 * xr, r.top, r.right, r.top + 2 * yr) + canvas.drawRoundRect(r2, animator.tableCornerXRadius, animator.tableCornerYRadius, this.feltPaint) + val r3 = RectF(r.right - 2 * xr, r.bottom - 2 * yr, r.right, r.bottom) + canvas.drawRoundRect(r3, animator.tableCornerXRadius, animator.tableCornerYRadius, this.feltPaint) + val r4 = RectF(r.left, r.bottom - 2 * yr, r.left + 2 * xr, r.bottom) + canvas.drawRoundRect(r4, animator.tableCornerXRadius, animator.tableCornerYRadius, this.feltPaint) +// val r5 = RectF(r.right - 2 * xr, r.centerY() - yr, r.right, r.centerY() + yr) +// canvas.drawRoundRect(r5, animator.tableCornerXRadius, animator.tableCornerYRadius, this.feltPaint) +// val r6 = RectF(r.right - 2 * xr, r.top, r.right, r.top + 2 * yr) +// canvas.drawRoundRect(r6, animator.tableCornerXRadius, animator.tableCornerYRadius, this.feltPaint) +// val r7 = RectF(r.left, r.centerY() - yr, r.left + 2 * xr, r.centerY() + yr) +// canvas.drawRoundRect(r7, animator.tableCornerXRadius, animator.tableCornerYRadius, this.feltPaint) +// val r8 = RectF(r.left, r.bottom - 2 * yr, r.left + 2 * xr, r.bottom) +// canvas.drawRoundRect(r8, animator.tableCornerXRadius, animator.tableCornerYRadius, this.feltPaint) + canvas.drawRoundRect(animator.tableRect, animator.tableCornerXRadius, animator.tableCornerYRadius, this.tablePaint) this.cardTextPaint.textSize = animator.cardSpecs.height * .38f diff --git a/app/src/main/java/net/pokeranalytics/android/util/MathUtils.kt b/app/src/main/java/net/pokeranalytics/android/util/MathUtils.kt new file mode 100644 index 00000000..b9ba53e9 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/util/MathUtils.kt @@ -0,0 +1,112 @@ +package net.pokeranalytics.android.util + +import android.graphics.PointF +import android.graphics.RectF +import kotlin.math.pow +import kotlin.math.sqrt +import kotlin.math.tan + +class MathUtils { + + private interface Path { + val length: Float + fun pointForDistance(distance: Float): PointF + } + + class Line(val x1: Float, val y1: Float, val x2: Float, val y2: Float): Path { + override val length: Float + get() { + return PointF(x2 - x1, y2 - y1).length() + } + + override fun pointForDistance(distance: Float): PointF { + val ratio = distance / this.length + return PointF(x1 + ratio * (x2 - x1), y1 + ratio * (y2 - y1)) + } + + val slope: Float + get() { return (x2 - x1) / (y2 - y1) } + } + + private class EllipseQuarter(val x1: Float, val y1: Float, val xRadius: Float, val yRadius: Float, val direction: Direction): Path { + + enum class Direction { SOUTH_EAST, SOUTH_WEST, NORTH_EAST, NORTH_WEST; + val east: Boolean + get() { return this == SOUTH_EAST || this == NORTH_EAST } + val angle: Float + get() { + return when (this) { + NORTH_EAST -> Math.PI.toFloat() * 0.5f + NORTH_WEST -> Math.PI.toFloat() + SOUTH_EAST -> 0f + SOUTH_WEST -> Math.PI.toFloat() * 1.5f + } + } + } + + override val length: Float + get() { + return ellipseCircumference(this.xRadius, this.yRadius) / 4f + } + + override fun pointForDistance(distance: Float): PointF { + val angle = Math.PI.toFloat() / 2 * distance / length + return pointForAngle(angle) + } + + private fun pointForAngle(angle: Float): PointF { + val baseAngle = direction.angle - angle + val denominator = sqrt(yRadius.pow(2) + xRadius.pow(2) * tan(baseAngle).pow(2)) + val x = xRadius * yRadius / denominator + val y = xRadius * yRadius * tan(baseAngle) / denominator + return if (this.direction.east) PointF(x1 + x, y1 - y) + else PointF(x1 - x, y1 + y) + } + + } + + companion object{ + + private fun ellipseCircumference(a: Float, b: Float): Float { + return Math.PI.toFloat() * sqrt(2f * (a.pow(2) + b.pow(2))) + } + + fun positionsAroundRoundedRectangle(numberOfPlayers: Int, rect: RectF, xRadius: Float, yRadius: Float): List> { + + val segments = listOf( + Line(rect.centerX(), rect.bottom, rect.left + xRadius, rect.bottom), + EllipseQuarter(rect.left + xRadius, rect.bottom - yRadius, xRadius, yRadius, EllipseQuarter.Direction.SOUTH_WEST), + Line(rect.left, rect.bottom - yRadius, rect.left, rect.top + yRadius), + EllipseQuarter(rect.left + xRadius, rect.top + yRadius, xRadius, yRadius, EllipseQuarter.Direction.NORTH_WEST), + Line(rect.left + xRadius, rect.top, rect.right - xRadius, rect.top), + EllipseQuarter(rect.right - xRadius, rect.top + yRadius, xRadius, yRadius, EllipseQuarter.Direction.NORTH_EAST), + Line(rect.right, rect.top + yRadius, rect.right, rect.bottom - yRadius), + EllipseQuarter(rect.right - xRadius, rect.bottom - yRadius, xRadius, yRadius, EllipseQuarter.Direction.SOUTH_EAST), + Line(rect.right - xRadius, rect.bottom, rect.centerX(), rect.bottom) + ) + + val perimeter = segments.sumByDouble { it.length.toDouble() } + val distancePerPlayer = perimeter / numberOfPlayers + + val playerPoints = mutableListOf>() + for (i in 0 until numberOfPlayers) { + var distanceFromOrigin = i * distancePerPlayer.toFloat() + var pathIndex = 0 + + while (distanceFromOrigin > segments[pathIndex].length) { + distanceFromOrigin -= segments[pathIndex].length + pathIndex++ + } + + val p = segments[pathIndex].pointForDistance(distanceFromOrigin) + // 2 first and 2 last are at the bottom + val bottom = pathIndex < 2 || pathIndex > 6 + playerPoints.add(Pair(p, bottom)) + } + + return playerPoints + } + + } + +} \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 5314f613..57fcbc68 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -21,6 +21,7 @@ #58C473 #2558C473 + #257BC18C #65FF82 #282e29 #2E8148