package geniusweb.actions; import java.util.Collections; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import geniusweb.issuevalue.Bid; /** * Indicates that a party conditionally agrees with any of the * {@link VoteWithValue}s provided. */ public class VotesWithValue extends AbstractAction { private final Set votes; /** * * @param id party id * @param votes the {@link Vote}s that the party can agree on, if the * condition of the Vote holds. Every {@link Vote#getActor()} * should equal the id. The sum of the values must =100. */ @JsonCreator public VotesWithValue(@JsonProperty("actor") PartyId id, @JsonProperty("votes") Set votes) { super(id); this.votes = votes; if (votes == null) throw new NullPointerException("votes must be not null"); for (VoteWithValue vote : votes) { if (!vote.getActor().equals(id)) { throw new IllegalArgumentException("All votes must come from " + id + " but found " + vote); } } if (votes.stream().map(v -> v.getValue()).reduce(0, Integer::sum) != 100) throw new IllegalArgumentException( "Sum of the placed votes must be 100"); // check for duplicate Vote's, possibly with different powers Map counts = votes.stream().map(vote -> vote.getBid()) .collect(Collectors.groupingBy(bid -> bid, Collectors.counting())); Optional> nonunique = counts.entrySet().stream() .filter(entry -> entry.getValue() > 1).findAny(); if (nonunique.isPresent()) throw new IllegalArgumentException( "Votes contains multiple Vote's for " + nonunique.get().getKey()); } /** * Test if Votes extends other votes. Extending means that for each vote on * bid B with power P in othervotes, this contains also a vote for bid B * with power at most P. * * @param otherVotes the {@link VotesWithValue}, usually from a previous * round, that this should extend. * @return true iff this extends the otherVotes. */ public boolean isExtending(VotesWithValue otherVotes) { if (!otherVotes.getActor().equals(getActor())) return false; for (VoteWithValue vote : otherVotes.getVotes()) { VoteWithValue myvote = getVote(vote.getBid()); if (myvote == null || myvote.getMinPower() > vote.getMinPower() || myvote.getMaxPower() < vote.getMaxPower()) return false; } return true; } /** * * @param bid the bid that we may have a vote for * @return myvote for bid, or null if no vote for that bid; */ public VoteWithValue getVote(Bid bid) { for (VoteWithValue vote : votes) { if (vote.getBid().equals(bid)) return vote; } return null; } public Set getVotes() { return Collections.unmodifiableSet(votes); } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((votes == null) ? 0 : votes.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; VotesWithValue other = (VotesWithValue) obj; if (votes == null) { if (other.votes != null) return false; } else if (!votes.equals(other.votes)) return false; return true; } @Override public String toString() { return "VotesWithValue[" + getActor() + "," + votes + "]"; } }