* Added a deck hash tag that's shown at the start of the game log to be able to identify a deck.

This commit is contained in:
LevelX2 2015-04-11 00:47:54 +02:00
parent 3bdf2a7957
commit 0fb7cf8317
7 changed files with 95 additions and 15 deletions

View file

@ -29,18 +29,25 @@
package mage.cards.decks;
import java.io.Serializable;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import mage.cards.Card;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import mage.game.GameException;
import mage.util.DeckUtil;
public class Deck implements Serializable {
private String name;
private final Set<Card> cards = new LinkedHashSet<>();
private final Set<Card> sideboard = new LinkedHashSet<>();
private long deckHashCode = 0;
public static Deck load(DeckCardLists deckCardLists) throws GameException {
return Deck.load(deckCardLists, false);
@ -53,23 +60,39 @@ public class Deck implements Serializable {
public static Deck load(DeckCardLists deckCardLists, boolean ignoreErrors, boolean mockCards) throws GameException {
Deck deck = new Deck();
deck.setName(deckCardLists.getName());
List<String> deckCardNames = new ArrayList<>();
for (DeckCardInfo deckCardInfo: deckCardLists.getCards()) {
Card card = createCard(deckCardInfo, mockCards);
if (card != null) {
deck.cards.add(card);
deckCardNames.add(card.getName());
} else if (!ignoreErrors) {
throw createCardNotFoundGameException(deckCardInfo, deckCardLists.getName());
}
}
List<String> sbCardNames = new ArrayList<>();
for (DeckCardInfo deckCardInfo: deckCardLists.getSideboard()) {
Card card = createCard(deckCardInfo, mockCards);
if (card != null) {
deck.sideboard.add(card);
sbCardNames.add(card.getName());
} else if (!ignoreErrors) {
throw createCardNotFoundGameException(deckCardInfo, deckCardLists.getName());
}
}
Collections.sort(deckCardNames);
Collections.sort(sbCardNames);
String deckString = deckCardNames.toString() + sbCardNames.toString();
deck.setDeckHashCode(DeckUtil.fixedHash(deckString));
// try{
// MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
// messageDigest.update(deckString.getBytes());
// String encryptedString = new String(messageDigest.digest());
// deck.setDeckHashCode(encryptedString.hashCode());
// }
// catch (NoSuchAlgorithmException e) {
// // nothing
// }
return deck;
}
@ -137,4 +160,13 @@ public class Deck implements Serializable {
public Set<Card> getSideboard() {
return sideboard;
}
public long getDeckHashCode() {
return deckHashCode;
}
public void setDeckHashCode(long deckHashCode) {
this.deckHashCode = deckHashCode;
}
}

View file

@ -400,6 +400,7 @@ public abstract class MatchImpl implements Match {
if (player != null) {
// make sure the deck name (needed for Tiny Leaders) won't get lost by sideboarding
deck.setName(player.getDeck().getName());
deck.setDeckHashCode(player.getDeck().getDeckHashCode());
player.submitDeck(deck);
}
synchronized (this) {
@ -425,6 +426,7 @@ public abstract class MatchImpl implements Match {
sb.append(" QUITTED");
}
sb.append("<br/>");
sb.append("DeckHash: ").append(mp.getDeck().getDeckHashCode()).append("<br/>");
}
if (getDraws() > 0) {
sb.append(" Draws: ").append(getDraws()).append("<br/>");

View file

@ -90,6 +90,7 @@ public class MatchPlayer {
if (this.deck != null) {
// preserver deck name, important for Tiny Leaders format
deck.setName(this.getDeck().getName());
deck.setDeckHashCode(this.getDeck().getDeckHashCode());
}
this.deck = deck;
}

View file

@ -2783,13 +2783,13 @@ public abstract class PlayerImpl implements Player, Serializable {
card = game.getCard(card.getId());
}
if (!game.isSimulation()) {
StringBuilder sb = new StringBuilder(this.getName()).append(" puts ").append(withName ? card.getLogName() : "a face down card ");
StringBuilder sb = new StringBuilder(this.getName()).append(" puts ").append(withName ? card.getLogName() : "a face down card");
switch(fromZone) {
case EXILED:
sb.append("from exile zone ");
sb.append(" from exile zone ");
break;
default:
sb.append(fromZone != null ? new StringBuilder("from ").append(fromZone.toString().toLowerCase(Locale.ENGLISH)).append(" ") : "");
sb.append(fromZone != null ? new StringBuilder(" from ").append(fromZone.toString().toLowerCase(Locale.ENGLISH)).append(" ") : "");
break;
}
sb.append(card.getOwnerId().equals(this.getId()) ? "into his or her hand" : "into its owner's hand");
@ -2927,7 +2927,7 @@ public abstract class PlayerImpl implements Player, Serializable {
card = game.getCard(card.getId());
}
game.informPlayers(new StringBuilder(this.getName())
.append(" moves ").append(withName ? card.getLogName() : "a card face down ")
.append(" moves ").append(withName ? card.getLogName() : "a card face down").append(" ")
.append(fromZone != null ? new StringBuilder("from ").append(fromZone.toString().toLowerCase(Locale.ENGLISH)).append(" ") : "")
.append("to the exile zone").toString());
}

View file

@ -0,0 +1,45 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.util;
/**
*
* @author LevelX2
*/
public class DeckUtil {
public static long fixedHash(String string) {
long h = 1125899906842597L; // prime
int len = string.length();
for (int i = 0; i < len; i++) {
h = 31 * h + string.charAt(i);
}
return h;
}
}