Last active
September 18, 2018 02:26
-
-
Save mageddo/c53ed9be260d55b5c67707eed8f574bd to your computer and use it in GitHub Desktop.
This file contains 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
import com.fasterxml.jackson.databind.ObjectMapper; | |
import com.fasterxml.jackson.databind.SerializationFeature; | |
import org.junit.Test; | |
import java.util.ArrayList; | |
import java.util.Comparator; | |
import java.util.List; | |
import java.util.concurrent.atomic.AtomicReference; | |
import java.util.stream.Collectors; | |
import static org.junit.Assert.assertEquals; | |
public class WeightSort { | |
private static final ObjectMapper instance = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT); | |
@Test | |
public void case1() throws Throwable { | |
// arrange | |
final List<Item> offers = new ArrayList<>(List.of( | |
new Item(1, 5.5, 0.7, 101), | |
new Item(2, 5.0, 0.6, 100), | |
new Item(3, 5.0, 0.5, 100) | |
)); | |
// act | |
sortToBestOffer(offers); | |
// assert | |
System.out.println(instance.writeValueAsString(offers)); | |
assertEquals(List.of(2, 3, 1), toIdList(offers)); | |
} | |
@Test | |
public void sortByEscrowCausePriceAndWearAreEquivalent() throws Throwable { | |
// arrange | |
final List<Item> offers = new ArrayList<>(List.of( | |
new Item(1, 5.1, 0.05, 99), | |
new Item(2, 5.3, 0.03, 100), | |
new Item(3, 5.5, 0.1, 101) | |
)); | |
// act | |
sortToBestOffer(offers); | |
// assert | |
System.out.println(instance.writeValueAsString(offers)); | |
assertEquals(List.of(1, 2, 3), toIdList(offers)); | |
} | |
@Test | |
public void wontSortAllPropsAreEquivalent() throws Throwable { | |
// arrange | |
final List<Item> offers = new ArrayList<>(List.of( | |
new Item(1, 5.5, 0.05, 100), | |
new Item(2, 5.9, 0.06, 100), | |
new Item(3, 5.1, 0.07, 100) | |
)); | |
// act | |
sortToBestOffer(offers); | |
// assert | |
System.out.println(instance.writeValueAsString(offers)); | |
assertEquals(List.of(1, 2, 3), toIdList(offers)); | |
} | |
@Test | |
public void sortIgnoringOthersPropsCausePriceHasNoAmbiguousValues() throws Throwable { | |
// arrange | |
final List<Item> offers = new ArrayList<>(List.of( | |
new Item(1, 6, 0.5, 100), | |
new Item(2, 7, 0.3, 200), | |
new Item(3, 5, 0.1, 150) | |
)); | |
// act | |
sortToBestOffer(offers); | |
// assert | |
System.out.println(instance.writeValueAsString(offers)); | |
assertEquals(List.of(3, 1, 2), toIdList(offers)); | |
} | |
@Test | |
public void findFirstItemCauseOthersHaveVeryDifferentPrice() throws Throwable { | |
// arrange | |
final List<Item> offers = new ArrayList<>(List.of( | |
new Item(1, 6, 0.5, 100), | |
new Item(2, 7, 0.3, 200), | |
new Item(3, 5, 0.1, 150) | |
)); | |
// act | |
final Item bestOffer = findBestOffer(offers); | |
// assert | |
System.out.println(instance.writeValueAsString(offers)); | |
assertEquals(3, bestOffer.getId()); | |
} | |
@Test | |
public void mustFindItemWithLowestWear() throws Throwable { | |
// arrange | |
final List<Item> offers = new ArrayList<>(List.of( | |
new Item(1, 5.5, 0.05, 100), | |
new Item(2, 5.9, 0.056, 100), | |
new Item(3, 5.1, 0.057, 100) | |
)); | |
// act | |
final Item bestOffer = findBestOffer(offers); | |
// assert | |
System.out.println(instance.writeValueAsString(offers)); | |
assertEquals(1, bestOffer.getId()); | |
} | |
public List<Integer> toIdList(List<Item> items){ | |
return items.stream().map(Item::getId).collect(Collectors.toList()); | |
} | |
/** | |
* Vai pegar os items de melhor preco, wear e escrow. | |
* Para no primeiro item que nao tiver outros items semelhantes | |
*/ | |
public void sortToBestOffer(List<Item> items){ | |
items.sort(completeComparator()); | |
} | |
/** | |
* Vai pegar o item de melhor preco, wear e escrow. Exclui os items que mais divergem e vai sorteando os mais parecidos | |
* | |
*/ | |
public Item findBestOffer(List<Item> items){ | |
items.sort(Comparator.comparing(Item::getPrice)); | |
final AtomicReference<Item> first = new AtomicReference<>(items.get(0)); | |
items = items.stream().filter(v -> v.price - first.get().price <= 1.0).collect(Collectors.toList()); | |
if(items.isEmpty()){ | |
return first.get(); | |
} | |
if(items.size() == 1){ | |
return items.get(0); | |
} | |
items.sort(Comparator.comparing(Item::getWear)); | |
first.set(items.get(0)); | |
items = items.stream().filter(v -> v.wear - first.get().wear <= 0.1).collect(Collectors.toList()); | |
if(items.isEmpty()){ | |
return first.get(); | |
} | |
if(items.size() == 1){ | |
return items.get(0); | |
} | |
items.sort(Comparator.comparing(Item::getEscrow)); | |
first.set(items.get(0)); | |
return items.stream().filter(v -> v.escrow - first.get().escrow <= 1).findFirst().orElse(first.get()); | |
} | |
/** | |
* Return items sorted by the cheapest, best quality then escrow | |
*/ | |
public static Comparator<Item> completeComparator(){ | |
return (a, b) -> { | |
int cmp = itemPriceComparator().compare(a, b); | |
if(cmp == 0){ | |
cmp = wearComparator().compare(a, b); | |
if(cmp == 0){ | |
return escrowComparator().compare(a, b); | |
} | |
} | |
return cmp; | |
}; | |
} | |
public static Comparator<Item> itemPriceComparator(){ | |
return (a, b) -> { | |
final double diff = Math.max(a.price, b.price) - Math.min(a.price, b.price); | |
return diff >= 1.0 ? Double.compare(a.price, b.price) : 0; | |
}; | |
} | |
public static Comparator<Item> wearComparator(){ | |
return (a, b) -> { | |
final double diff = Math.max(a.wear, b.wear) - Math.min(a.wear, b.wear); | |
return diff >= 0.1 ? Double.compare(a.wear, b.wear) : 0; | |
}; | |
} | |
public static Comparator<Item> escrowComparator(){ | |
return (a, b) -> { | |
final double diff = Math.max(a.escrow, b.escrow) - Math.min(a.escrow, b.escrow); | |
return diff >= 1.0 ? Double.compare(a.escrow, b.escrow) : 0; | |
}; | |
} | |
public static class Item { | |
private final int id; | |
private final double price; | |
/** | |
* Desgaste do item | |
*/ | |
private final double wear; | |
/** | |
* Second epoch when item will be instantly withdrawable | |
*/ | |
private final long escrow; | |
public Item(int id, double price, double wear, long escrow) { | |
this.id = id; | |
this.price = price; | |
this.wear = wear; | |
this.escrow = escrow; | |
} | |
public double getPrice() { | |
return price; | |
} | |
public double getWear() { | |
return wear; | |
} | |
public long getEscrow() { | |
return escrow; | |
} | |
public int getId() { | |
return id; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment