helldivers-2 / api

A community driven API for Helldivers 2
https://helldivers-2.github.io/api/
MIT License
210 stars 19 forks source link

[FEATURE]: Adding Liberation Change for Planets #48

Open xSentry opened 4 months ago

xSentry commented 4 months ago

What problem does it solve

Currently, there is no option to get the current change rate for a planets liberation. You would need to save a snapshot yourself and calculate the liberation rate on your own. Having such a feature in this api would be highly usefull for displaying informations such as: Winning, Loosing, Stalemate

What is the solution

We need to add the functionality of saving a snapshot of the current liberation and compare it. Everytime we want to update the liberation change we have to calculate the difference between the saved liberation and the current one to get an estimated rate of change. After calculating the rate of change we should update the snapshot.

Existing alternatives

An example for a possible output can be found here

Added value

A lot of people want to display such information. Providing this would make it easier for developers who dont want or cant implement an own database structure.

Additional notes

Here are some example Files I use, to implement such functionality with PHP in Symfony: (My implementation does not include proper defense campaign handling)

Entity to save the PlanetProgress:

class PlanetProgress
{
    #[ORM\Id]
    #[ORM\Column(type: 'uuid', unique: true)]
    public readonly Uuid $id;

    #[ORM\Column(type: 'integer')]
    #[Serializer\Groups(['default'])]
    public int $currentHealth = 0;

    #[ORM\Column(type: 'integer')]
    #[Serializer\Groups(['default'])]
    public int $maxHealth = 0;

    #[ORM\Column(type: 'float')]
    #[Serializer\Groups(['default'])]
    public float $liberation = 0;

    #[ORM\Column(type: 'float')]
    #[Serializer\Groups(['default'])]
    public float $previousLiberation = 0;

    #[ORM\Column(type: 'float')]
    #[Serializer\Groups(['default'])]
    public float $liberationChange = 0;

    #[ORM\Column(type: 'datetime')]
    public \DateTime $modifiedAt;

    #[ORM\Column(type: 'datetime_immutable')]
    private \DateTimeImmutable $createdAt;

    public function __construct(
        #[ORM\Id]
        #[ORM\Column(type: 'integer', unique: true)]
        #[Serializer\Groups(['default'])]
        public readonly int $planetIndex,

        #[ORM\Column(type: 'string')]
        #[Serializer\Groups(['default'])]
        public string $name,

        #[ORM\ManyToOne(targetEntity: WarSeason::class, inversedBy: 'planetsProgress')]
        public WarSeason $warSeason,
    ) {
        $this->id = Uuid::v4();
        $this->modifiedAt = new \DateTime();
        $this->createdAt = new \DateTimeImmutable();
    }
}

Logic to calculate the change rate:

private function updatePlanetsLiberation(WarSeason $warSeason): void
    {
        $this->logger->warning('Loading Planets Liberation...');

        $planets = $warSeason->planets;
        $planetsProgress = $warSeason->planetsProgress->toArray();

        foreach ($planets as $planetStatus) {
            $planetIndex = $planetStatus->planet->index;

            if ($planetIndex !== 0 && !$planetIndex) {
                continue;
            }

            $planetProgress = array_filter($planetsProgress, function ($planetProgress) use ($planetIndex) {
                return $planetProgress->planetIndex === $planetIndex;
            });

            if (!empty($planetProgress)) {
                $planetProgress = reset($planetProgress);
            } else {
                $planetProgress = new PlanetProgress(planetIndex: $planetIndex, name: $planetStatus->planet->name, warSeason: $warSeason);
            }

            $planetProgress->currentHealth = $planetStatus->health;
            $planetProgress->maxHealth = $planetStatus->planet->max_health;
            $planetProgress->previousLiberation = $planetProgress->liberation;
            $planetProgress->liberation = $planetStatus->liberation;

            try {
                //Calculates difference between last and current Liberation % and multiplies by 12 to get the hour estimate (Gets called every 5 Minutes)
                $planetProgress->liberationChange = ($planetProgress->liberation - $planetProgress->previousLiberation) * 12; 
            } catch (Exception $e) {
                $planetProgress->liberationChange = 0;
            }

            $planetProgress->modifiedAt = new \DateTime();

            $this->entityManager->persist($planetProgress);
        }
    }
Stonemercy commented 3 months ago

Any update on this? I'd love this feature!

dealloc commented 3 months ago

I think the main problem for us is that we synchronize every 10s. So calculating from the previous delta would result in very rapidly changing not to mention inaccurate calculations.

Aside from that, we don't store anything in a database, so if the app restarts we don't have delta's available for at least 20 seconds, and I don't know what we would/could show in that timeframe.