Last active
February 28, 2021 06:30
-
-
Save ZerothAngel/57ac270056562da1e90029717ed81f2c to your computer and use it in GitHub Desktop.
A simple utility for Phantasy Star Online 2 (PSO2) to calculate the overall success rate of upslotting a weapon/unit to N slots from N-1.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
""" | |
A simple utility for Phantasy Star Online 2 to calculate the overall success | |
rate of upslotting a weapon/unit to N slots from N-1. | |
Can also take number of (filled) S-Grade Augment slots (aka SSA slots) which, | |
when present, always improve the overall chance (because they are 100% even | |
on upslot). | |
Specifying additional boosts (e.g. boost week) and/or manually specifying the | |
augmentation aid to use is also possible. | |
For example, to calculate the chance of upslotting a 7s trailblazer (aka | |
lightstream) weapon with 3 filled SGA slots during 10% boost week while | |
using a 45% augmentation aid: | |
# ./upslot.py -b .1 -a .45 8 3 | |
Base success rate per slot: 40.0% | |
Using 45.00% aid | |
Success rate per slot: 85.00% | |
Success probabilities: | |
8 : 44.371% | |
7 : 39.150% | |
6 : 13.818% | |
5 : 2.4384% | |
4 : 0.21516% | |
3 : 0.0075938% | |
That is, a 44% chance to end up with an 8 slots (i.e. total success), a 39% | |
chance to end up with 7 slots (1 failure), etc. etc. | |
""" | |
from decimal import * | |
import math | |
TARGET_SUCCESS = [ | |
Decimal("1.0"), | |
Decimal("0.9"), | |
Decimal("0.85"), | |
Decimal("0.7"), | |
Decimal("0.6"), | |
Decimal("0.55"), | |
Decimal("0.4"), | |
Decimal("0.3") | |
] | |
def clamp(rate): | |
if rate > Decimal("1.0"): | |
return Decimal("1.0") | |
return rate | |
def choose_aid(success_rate): | |
gap = Decimal("1.0") - success_rate | |
if gap == Decimal("0.0"): | |
return Decimal("0.0") | |
elif gap <= Decimal("0.1"): | |
return Decimal("0.1") | |
elif gap <= Decimal("0.3"): | |
return Decimal("0.3") | |
else: | |
return Decimal("0.4") | |
def main(target_slots, sga_slots=0, boost='0', aid=None): | |
if target_slots < 0 or target_slots > 8: | |
raise ValueError('target_slots must be in range [0,8]') | |
if sga_slots < 0 or sga_slots >= target_slots: | |
raise ValueError('sga_slots must be in range [0,target_slots)') | |
boost_week = Decimal(boost) | |
base_success = clamp(TARGET_SUCCESS[target_slots - 1] + boost_week) | |
if aid is None: | |
aid = choose_aid(base_success) | |
else: | |
aid = Decimal(aid) | |
success_rate = clamp(base_success + aid) | |
failure_rate = Decimal("1.0") - success_rate | |
print(f'Base success rate per slot: {base_success * Decimal("100")}%') | |
print(f'Using {aid * Decimal("100")}% aid') | |
print(f'Success rate per slot: {success_rate * Decimal("100")}%') | |
num_slots = target_slots - sga_slots | |
print('Success probabilities:') | |
for successes in range(num_slots, -1, -1): | |
failures = num_slots - successes | |
prob = success_rate ** successes | |
if failures > 0: | |
prob *= failure_rate ** failures | |
prob *= math.comb(num_slots, successes) | |
with localcontext() as ctxt: | |
ctxt.prec = 5 | |
print(f' {successes + sga_slots} : {prob * Decimal("100")}%') | |
if success_rate == Decimal("1"): | |
break | |
if __name__ == '__main__': | |
import argparse | |
parser = argparse.ArgumentParser(description='calculate upslot probabilities') | |
parser.add_argument('target-slots', type=int, | |
help='target slots') | |
parser.add_argument('sga-slots', type=int, nargs='?', | |
default=0, | |
help='number of SGA slots') | |
parser.add_argument('--boost', '-b', type=str, | |
default='0', | |
help='additional boosts (e.g. boost week)') | |
parser.add_argument('--aid', '-a', type=str, | |
default=None, | |
help='manual augmentation aid specification') | |
args = vars(parser.parse_args()) | |
main(args['target-slots'], sga_slots=args['sga-slots'], boost=args['boost'], | |
aid=args['aid']) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment