50 lines
1.9 KiB
C#
50 lines
1.9 KiB
C#
using System;
|
||
|
||
namespace AfterHours.Economy
|
||
{
|
||
/// <summary>
|
||
/// Reine Preis-/Nachfragelogik. Engine-frei und damit testbar.
|
||
/// Keine UnityEngine-Referenzen in dieser Datei.
|
||
/// </summary>
|
||
public static class PricingService
|
||
{
|
||
/// <summary>Ab diesem Aufschlag über Empfehlung kauft niemand mehr.</summary>
|
||
public const float RejectionThreshold = 1.75f;
|
||
|
||
/// <summary>
|
||
/// Kaufwahrscheinlichkeit relativ zum empfohlenen Preis.
|
||
/// 1.0 bei Empfehlungspreis oder darunter, 0.0 ab RejectionThreshold.
|
||
/// Dazwischen quadratisch abfallend – kleine Aufschläge tun kaum weh,
|
||
/// große brechen die Nachfrage schnell ein.
|
||
/// </summary>
|
||
public static float PurchaseProbability(float askingPrice, float recommendedPrice)
|
||
{
|
||
if (recommendedPrice <= 0f) throw new ArgumentOutOfRangeException(nameof(recommendedPrice));
|
||
if (askingPrice <= 0f) return 1f;
|
||
|
||
float ratio = askingPrice / recommendedPrice;
|
||
if (ratio <= 1f) return 1f;
|
||
if (ratio >= RejectionThreshold) return 0f;
|
||
|
||
float t = (ratio - 1f) / (RejectionThreshold - 1f); // 0..1
|
||
return 1f - (t * t);
|
||
}
|
||
|
||
/// <summary>Marge in Prozent des Verkaufspreises.</summary>
|
||
public static float MarginRatio(float askingPrice, float wholesalePrice)
|
||
{
|
||
if (askingPrice <= 0f) return 0f;
|
||
return (askingPrice - wholesalePrice) / askingPrice;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Erwarteter Deckungsbeitrag pro angebotenem Stück.
|
||
/// Nützlich für den späteren "Preis-Optimum"-Hinweis im Preis-UI.
|
||
/// </summary>
|
||
public static float ExpectedProfitPerUnit(float askingPrice, float recommendedPrice, float wholesalePrice)
|
||
{
|
||
return PurchaseProbability(askingPrice, recommendedPrice) * (askingPrice - wholesalePrice);
|
||
}
|
||
}
|
||
}
|