mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2025-12-16 14:30:31 +00:00
Improve fairness logic (#2807)
* Improve fairness logic * Add unit test against abuse * Further simplify the code That first pass is not needed anymore, first loop covers it
This commit is contained in:
committed by
GitHub
parent
00f7d2bfb9
commit
df4f8d1e62
@@ -4,7 +4,7 @@
|
||||
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
// |
|
||||
// Copyright 2015-2022 Łukasz "JustArchi" Domeradzki
|
||||
// Copyright 2015-2023 Łukasz "JustArchi" Domeradzki
|
||||
// Contact: JustArchi@JustArchi.net
|
||||
// |
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -28,6 +28,28 @@ namespace ArchiSteamFarm.Tests;
|
||||
|
||||
[TestClass]
|
||||
public sealed class Trading {
|
||||
[TestMethod]
|
||||
public void ExploitingNewSetsIsFairButNotNeutral() {
|
||||
HashSet<Asset> inventory = new() {
|
||||
CreateItem(1, 40),
|
||||
CreateItem(2, 10),
|
||||
CreateItem(3, 10)
|
||||
};
|
||||
|
||||
HashSet<Asset> itemsToGive = new() {
|
||||
CreateItem(2, 5),
|
||||
CreateItem(3, 5)
|
||||
};
|
||||
|
||||
HashSet<Asset> itemsToReceive = new() {
|
||||
CreateItem(1, 9),
|
||||
CreateItem(4)
|
||||
};
|
||||
|
||||
Assert.IsTrue(IsFairExchange(itemsToGive, itemsToReceive));
|
||||
Assert.IsFalse(IsTradeNeutralOrBetter(inventory, itemsToGive, itemsToReceive));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MismatchRarityIsNotFair() {
|
||||
HashSet<Asset> itemsToGive = new() { CreateItem(1, rarity: Asset.ERarity.Rare) };
|
||||
|
||||
@@ -171,33 +171,17 @@ public sealed class Trading : IDisposable {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If amount of unique items in the set increases, this is always a good trade (e.g. 0 2 -> 1 1)
|
||||
if (afterAmounts.Count > beforeAmounts.Count) {
|
||||
continue;
|
||||
// Otherwise, fill the missing holes in our data if needed, since we actually had zeros there
|
||||
for (byte i = 0; i < afterAmounts.Count - beforeAmounts.Count; i++) {
|
||||
beforeAmounts.Insert(0, 0);
|
||||
}
|
||||
|
||||
// At this point we're sure that amount of unique items stays the same, so we can evaluate actual sets
|
||||
// We make use of the fact that our amounts are already sorted in ascending order, so we can just take the first value instead of calculating ourselves
|
||||
uint beforeSets = beforeAmounts[0];
|
||||
uint afterSets = afterAmounts[0];
|
||||
|
||||
// If amount of our sets for this game decreases, this is always a bad trade (e.g. 2 2 2 -> 3 2 1)
|
||||
if (afterSets < beforeSets) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If amount of our sets for this game increases, this is always a good trade (e.g. 3 2 1 -> 2 2 2)
|
||||
if (afterSets > beforeSets) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// At this point we're sure that both number of unique items in the set stays the same, as well as number of our actual sets
|
||||
// We need to ensure set progress here and keep in mind overpaying, so we'll calculate neutrality as a difference in amounts at appropriate indexes
|
||||
// Now we need to ensure set progress and keep in mind overpaying, so we'll calculate neutrality as a difference in amounts at appropriate indexes
|
||||
// We start from the amounts we have the least of, our data is already sorted in ascending order, so we can just subtract and compare until we cover every amount
|
||||
// Neutrality can't reach value below 0 at any single point of calculation, as that would imply a loss of progress even if we'd end up with a positive value by the end
|
||||
int neutrality = 0;
|
||||
|
||||
// Skip initial 0 index, as we already checked it above and it doesn't change neutrality from 0
|
||||
for (byte i = 1; i < afterAmounts.Count; i++) {
|
||||
for (byte i = 0; i < afterAmounts.Count; i++) {
|
||||
// We assume that the difference between amounts will be within int range, therefore we accept underflow here (for subtraction), and since we cast that result to int afterwards, we also accept overflow for the cast itself
|
||||
neutrality += unchecked((int) (afterAmounts[i] - beforeAmounts[i]));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user