Skip to content

Commit

Permalink
feat: add clash power range and win rate note
Browse files Browse the repository at this point in the history
  • Loading branch information
MusicOnline committed Mar 10, 2024
1 parent c4d2929 commit 313bbe9
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 42 deletions.
19 changes: 19 additions & 0 deletions components/EnemySkillForm.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
<script setup lang="ts">
const customSkill = useCustomEnemySkill()
const sinnerClashSkill = useCustomSinnerClashSkill()
const enemyClashSkill = useCustomEnemyClashSkill()
const enemyClashPowerRange = computed<[number, number]>(() =>
enemyClashSkill.value.clashPowerRange(sinnerClashSkill.value)
)
</script>

<template>
Expand Down Expand Up @@ -78,6 +84,19 @@ const customSkill = useCustomEnemySkill()
class="w-16 ml-1 font-bold inline-block"
/>
</div>
<UDivider class="my-2" />
<div>
<span> Clash Power Range: </span>
<span class="font-bold">
{{ enemyClashPowerRange[0] }}
</span>
~
<span class="font-bold">
{{ enemyClashPowerRange[1] }}
</span>
</div>
<UDivider class="my-2" />
<div>Note: Abnormalities have 0 Sanity.</div>
</div>
</template>

Expand Down
43 changes: 27 additions & 16 deletions components/SinnerClashSummary.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ const sinner = computed<ComparisonSinner>(
if (!sinner.value)
throw new Error(`Comparison sinner ${identityOrEgoId} does not exist`)
const enemySkill = useCustomEnemySkill()
const enemyClashSkill = useCustomEnemyClashSkill()
const getSinnerIdentityName = useGetSinnerIdentityName()
const getSinnerSkillName = useGetSinnerSkillName()
const removeComparisonSinner = useRemoveComparisonSinner()
Expand All @@ -21,8 +22,8 @@ const sinnerName = computed<string>(
() => SINNER_TO_NAME[<keyof typeof SINNER_TO_NAME>sinner.value.sinnerKey]
)
function getWinRate(skill: SkillStats): number {
const sinnerClashSkill = new ClashSkill(
function getSinnerClashSkill(skill: SkillStats): ClashSkill {
return new ClashSkill(
skill.basePower,
skill.numCoins,
skill.coinPower,
Expand All @@ -31,16 +32,15 @@ function getWinRate(skill: SkillStats): number {
skill.finalClashPowerModifier,
sinner.value.paralyzeCount
)
const enemyClashSkill = new ClashSkill(
enemySkill.value.basePower,
enemySkill.value.numCoins,
enemySkill.value.coinPower,
enemySkill.value.sanity,
enemySkill.value.offenseLevel,
enemySkill.value.finalClashPowerModifier,
enemySkill.value.paralyzeCount
)
return computeClash(sinnerClashSkill, enemyClashSkill).winRate
}
function getWinRate(skill: SkillStats): number {
const sinnerClashSkill = getSinnerClashSkill(skill)
return computeClash(sinnerClashSkill, enemyClashSkill.value).winRate
}
function getSinnerClashPowerRange(skill: SkillStats): [number, number] {
const sinnerClashSkill = getSinnerClashSkill(skill)
return sinnerClashSkill.clashPowerRange(enemyClashSkill.value)
}
</script>

Expand Down Expand Up @@ -81,7 +81,7 @@ function getWinRate(skill: SkillStats): number {
<div class="font-bold underline">
{{ getSinnerSkillName(sinner.sinnerKey, skill.id) }}
</div>
<div class="flex items-center">
<div class="flex flex-wrap items-center">
<div class="text-2xl font-bold">{{ skill.basePower }}</div>
<div class="ml-0.5">+</div>
<div
Expand All @@ -96,16 +96,27 @@ function getWinRate(skill: SkillStats): number {
<div class="font-bold ml-0.5 text-yellow-500">
×{{ skill.numCoins }}
</div>
<div class="ml-1">({{ skill.offenseLevel }} Off. Lv.)</div>
<label class="flex ml-1 items-center">
<div class="ml-0.5 text-sm">({{ skill.offenseLevel }} Off. Lv.)</div>
<label class="flex ml-0.5 items-center text-sm">
+ Final Mod:
<UInput
color="blue"
type="number"
size="2xs"
v-model="sinner.skills[index].finalClashPowerModifier"
class="ml-1 w-16 inline-block"
/>
</label>
<div class="ml-1 text-sm">
=
<span class="font-bold">
{{ getSinnerClashPowerRange(skill)[0] }}
</span>
~
<span class="font-bold">
{{ getSinnerClashPowerRange(skill)[1] }}
</span>
</div>
</div>
<div>
Clash win rate:
Expand Down
25 changes: 22 additions & 3 deletions components/SinnerSkillForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ import {
} from "~/entities/SinnerSkill"
import { SinnerSkillLocaleJsonSchema } from "~/entities/locales/SinnerSkill"
const customSkill = useCustomSinnerSkill()
const customSinnerStats = useCustomSinnerStats()
const sinnerToIdentityData = useSinnerToIdentityData()
const sinnerToSkillData = useSinnerToSkillData()
const sinnerToSkillLocale = useSinnerToSkillLocaleEn()
const customSkill = useCustomSinnerSkill()
const customSinnerStats = useCustomSinnerStats()
const sinnerClashSkill = useCustomSinnerClashSkill()
const enemyClashSkill = useCustomEnemyClashSkill()
const isLoadingSinner = ref<boolean>(false)
const selectedSinnerKey = ref<keyof typeof SINNER_TO_NUMBER | null>(null)
const selectedSinnerIdentityId = ref<number | null>(null)
Expand Down Expand Up @@ -75,6 +77,10 @@ const skillsForSelect = computed<{ value: number; label: string }[]>(() => {
}))
})
const sinnerClashPowerRange = computed<[number, number]>(() =>
sinnerClashSkill.value.clashPowerRange(enemyClashSkill.value)
)
async function changeSinnerAndFetchData() {
selectedSinnerIdentityId.value = null
selectedSinnerSkillId.value = null
Expand Down Expand Up @@ -182,6 +188,7 @@ function updateCustomSinnerSkill() {
v-model="selectedSinnerKey"
@change="changeSinnerAndFetchData()"
class="ml-1 font-bold flex-grow"
:ui-menu="{ height: 'max-h-fit' }"
:options="Object.entries(SINNER_TO_NAME)"
option-attribute="1"
value-attribute="0"
Expand All @@ -199,6 +206,7 @@ function updateCustomSinnerSkill() {
"
@change="selectedSinnerSkillId = null"
class="ml-1 font-bold flex-grow"
:ui-menu="{ height: 'max-h-fit' }"
:options="identitiesForSelect"
value-attribute="value"
/>
Expand Down Expand Up @@ -310,5 +318,16 @@ function updateCustomSinnerSkill() {
class="w-16 ml-1 font-bold inline-block"
/>
</div>
<UDivider class="my-2" />
<div>
<span> Clash Power Range: </span>
<span class="font-bold">
{{ sinnerClashPowerRange[0] }}
</span>
~
<span class="font-bold">
{{ sinnerClashPowerRange[1] }}
</span>
</div>
</div>
</template>
37 changes: 37 additions & 0 deletions composables/state.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ClashSkill } from "~/utils/entities"

export const useCustomEnemySkill = () =>
useState<ComputeClashSkillStats>("customEnemySkill", () => ({
basePower: 6,
Expand Down Expand Up @@ -25,3 +27,38 @@ export const useCustomSinnerStats = () =>
sanity: 45,
paralyzeCount: 0,
}))

export const useCustomSinnerClashSkill = () => {
const customSinnerStats = useCustomSinnerStats()
const customSinnerSkill = useCustomSinnerSkill()

return computed<ClashSkill>(
() =>
new ClashSkill(
customSinnerSkill.value.basePower,
customSinnerSkill.value.numCoins,
customSinnerSkill.value.coinPower,
customSinnerStats.value.sanity,
customSinnerSkill.value.offenseLevel,
customSinnerSkill.value.finalClashPowerModifier,
customSinnerStats.value.paralyzeCount
)
)
}

export const useCustomEnemyClashSkill = () => {
const customEnemySkill = useCustomEnemySkill()

return computed<ClashSkill>(
() =>
new ClashSkill(
customEnemySkill.value.basePower,
customEnemySkill.value.numCoins,
customEnemySkill.value.coinPower,
customEnemySkill.value.sanity,
customEnemySkill.value.offenseLevel,
customEnemySkill.value.finalClashPowerModifier,
customEnemySkill.value.paralyzeCount
)
)
}
48 changes: 25 additions & 23 deletions pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,13 @@ const stateTransitionDiagram = ref<HTMLElement | null>(null)
const isMathRendered = ref<boolean>(false)
const isMathematicalProofEnabled = ref<boolean>(false)
const customSinnerStats = useCustomSinnerStats()
const customSinnerSkill = useCustomSinnerSkill()
const customEnemySkill = useCustomEnemySkill()
const comparisonSinners = useComparisonSinners()
const sinnerClashSkill = useCustomSinnerClashSkill()
const enemyClashSkill = useCustomEnemyClashSkill()
const clashResult = computed(() => {
const p1 = new ClashSkill(
customSinnerSkill.value.basePower,
customSinnerSkill.value.numCoins,
customSinnerSkill.value.coinPower,
customSinnerStats.value.sanity,
customSinnerSkill.value.offenseLevel,
customSinnerSkill.value.finalClashPowerModifier,
customSinnerStats.value.paralyzeCount
)
const p2 = new ClashSkill(
customEnemySkill.value.basePower,
customEnemySkill.value.numCoins,
customEnemySkill.value.coinPower,
customEnemySkill.value.sanity,
customEnemySkill.value.offenseLevel,
customEnemySkill.value.finalClashPowerModifier,
customEnemySkill.value.paralyzeCount
)
console.time("Computed clash")
const result = computeClash(p1, p2)
const result = computeClash(sinnerClashSkill.value, enemyClashSkill.value)
console.timeEnd("Computed clash")
return result
})
Expand Down Expand Up @@ -131,6 +111,28 @@ useHead({
:win-rate="clashResult.winRate"
/>
</div>
<UDivider class="my-2 " />
<div class="text-sm text-gray-600 dark:text-gray-400">
Note:
<ul class="list-disc">
<li class="ml-4">
The in-game win rate is deceiving as it is a naive calculation that is
entirely inaccurate when negative Coin Power skills are involved.
</li>
<li class="ml-4">
Some skills, passives and support passives may conditionally grant extra Coin Power
and Clash Power that is not accounted for by default in this
calculator. You may edit the values manually.
</li class="ml-4">
<li class="ml-4">
Some skills, passives and support passives may grant extra Coin Power
and Clash Power based on the in-game win rate and NOT the accurate win
rate calculation given here. See the passive of Ishmael's base Zayin
E.G.O "Snagharpoon". You may edit the values manually.
</li>
<li class="ml-4">A better win rate does not guarantee a clash win.</li>
</ul>
</div>
<UDivider class="my-2" />
<div>
<p>
Expand Down
9 changes: 9 additions & 0 deletions utils/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,15 @@ export class ClashSkill implements ComputeClashSkillStats {
this.finalClashPowerModifier
)
}

clashPowerRange(enemy?: ClashSkill): [number, number] {
const powerAtNoHeads = this.clashPower(0, enemy)
const powerAtMaxHeads = this.clashPower(this.numCoins, enemy)
return [
Math.min(powerAtNoHeads, powerAtMaxHeads),
Math.max(powerAtNoHeads, powerAtMaxHeads),
]
}
}

export class CoinNumberState {
Expand Down

0 comments on commit 313bbe9

Please sign in to comment.