add Momir Basic game type

- re-using Emblems as Vanguard cards; should probably give them their own
  CommandObject class
- setting the timing on the Momir ability to TimingRule.SORCERY causes the
  ability not to activate (?), so I've left it at INSTANT for now
- need to add a new card image source for vanguard cards
This commit is contained in:
Neil Gentleman 2015-11-11 04:22:29 -08:00
parent c25e45095e
commit 02a6780766
15 changed files with 434 additions and 8 deletions

1
.gitignore vendored
View file

@ -18,6 +18,7 @@ Mage.Server.Plugins/Mage.Deck.Limited/target
Mage.Server.Plugins/Mage.Game.CommanderDuel/target
Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/target/
Mage.Server.Plugins/Mage.Game.FreeForAll/target
Mage.Server.Plugins/Mage.Game.MomirDuel/target
Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/target
Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/target
Mage.Server.Plugins/Mage.Player.AI.DraftBot/target

View file

@ -802,7 +802,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
}
private void btnCommandZoneActionPerformed(java.awt.event.ActionEvent evt) {
DialogManager.getManager(gameId).showEmblemsDialog(CardsViewUtil.convertCommandObject(player.getCommadObjectList()), bigCard, gameId);
DialogManager.getManager(gameId).showEmblemsDialog(CardsViewUtil.convertCommandObject(player.getCommandObjectList()), bigCard, gameId);
}
private void btnExileZoneActionPerformed(java.awt.event.ActionEvent evt) {

View file

@ -28,6 +28,13 @@ public class EmblemView implements CommandObjectView, Serializable {
rules = emblem.getAbilities().getRules(sourceCard.getName());
}
public EmblemView(Emblem emblem) {
id = emblem.getId();
name = emblem.getName();
expansionSetCode = emblem.getExpansionSetCodeForImage();
rules = emblem.getAbilities().getRules(emblem.getName());
}
@Override
public String getExpansionSetCode() {
return expansionSetCode;

View file

@ -123,6 +123,7 @@ public class GameView implements Serializable {
checkPaid(stackObject.getId(), (StackAbility) stackObject);
} else if (object instanceof Emblem) {
Card sourceCard = game.getCard(((Emblem) object).getSourceId());
CardView cardView;
if (sourceCard != null) {
if (!sourceCard.getCardType().contains(CardType.PLANESWALKER)) {
if (sourceCard.getSecondCardFace() != null) {
@ -131,11 +132,12 @@ public class GameView implements Serializable {
}
((StackAbility) stackObject).setName("Emblem " + sourceCard.getName());
((StackAbility) stackObject).setExpansionSetCode(sourceCard.getExpansionSetCode());
cardView = new CardView(new EmblemView(((Emblem) object), sourceCard));
} else {
throw new IllegalArgumentException("Source card for emblem not found.");
cardView = new CardView(new EmblemView((Emblem) object));
}
stack.put(stackObject.getId(),
new StackAbilityView(game, (StackAbility) stackObject, object.getName(), new CardView(new EmblemView(((Emblem) object), sourceCard))));
new StackAbilityView(game, (StackAbility) stackObject, object.getName(), cardView));
checkPaid(stackObject.getId(), ((StackAbility) stackObject));
} else {
if (object instanceof StackAbility) {

View file

@ -132,6 +132,8 @@ public class PlayerView implements Serializable {
}
}
commandList.add(new EmblemView(emblem, sourceCard));
} else {
commandList.add(new EmblemView(emblem));
}
}
} else if (commandObject instanceof Commander) {
@ -229,7 +231,7 @@ public class PlayerView implements Serializable {
return this.userData;
}
public List<CommandObjectView> getCommadObjectList() {
public List<CommandObjectView> getCommandObjectList() {
return commandList;
}

View file

@ -0,0 +1,70 @@
/*
* Copyright 2011 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.deck;
import mage.cards.Card;
import mage.cards.decks.Deck;
import mage.cards.decks.DeckValidator;
import java.util.*;
/**
*
* @author nigelzor
*/
public class Momir extends DeckValidator {
public Momir() {
this("Momir Basic");
}
public Momir(String name) {
super(name);
}
@Override
public boolean validate(Deck deck) {
boolean valid = true;
if (deck.getCards().size() != 60) {
invalid.put("Deck", "Must contain 60 cards: has " + deck.getCards().size() + " cards");
valid = false;
}
List<String> basicLandNames = new ArrayList<>(Arrays.asList("Forest", "Island", "Mountain", "Swamp", "Plains"));
for (Card card : deck.getCards()) {
if (!basicLandNames.contains(card.getName())) {
invalid.put(card.getName(), "Only basic lands are allowed");
valid = false;
}
}
return valid;
}
}

View file

@ -0,0 +1,50 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.4</version>
</parent>
<artifactId>mage-game-momirduel</artifactId>
<packaging>jar</packaging>
<name>Mage Game Momir Basic Two Player</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mage</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
<finalName>mage-game-momirduel</finalName>
</build>
<properties/>
</project>

View file

@ -0,0 +1,174 @@
/*
* 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.game;
import mage.abilities.Ability;
import mage.abilities.common.LimitedTimesPerTurnActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.DiscardCardCost;
import mage.abilities.costs.mana.VariableManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.InfoEffect;
import mage.cards.Card;
import mage.cards.repository.CardCriteria;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import mage.constants.*;
import mage.game.command.Emblem;
import mage.game.match.MatchType;
import mage.game.permanent.token.EmptyToken;
import mage.game.turn.TurnMod;
import mage.players.Player;
import mage.util.CardUtil;
import java.util.*;
/**
*
* @author nigelzor
*/
public class MomirDuel extends GameImpl {
public MomirDuel(MultiplayerAttackOption attackOption, RangeOfInfluence range, int freeMulligans, int startLife) {
super(attackOption, range, freeMulligans, startLife);
}
public MomirDuel(final MomirDuel game) {
super(game);
}
@Override
public MatchType getGameType() {
return new MomirDuelType();
}
@Override
public int getNumPlayers() {
return 2;
}
@Override
protected void init(UUID choosingPlayerId) {
// should this be random across card names, or card printings?
Map<Integer, List<Card>> available = new HashMap<>();
CardCriteria criteria = new CardCriteria().types(CardType.CREATURE);
List<CardInfo> cards = CardRepository.instance.findCards(criteria);
for (CardInfo card : cards) {
List<Card> options = available.get(card.getConvertedManaCost());
if (options == null) {
options = new ArrayList<>();
available.put(card.getConvertedManaCost(), options);
}
options.add(card.getCard());
}
Ability ability = new SimpleStaticAbility(Zone.COMMAND, new InfoEffect("Vanguard effects"));
for (UUID playerId : state.getPlayerList(startingPlayerId)) {
Player player = getPlayer(playerId);
if (player != null) {
addEmblem(new MomirEmblem(available), ability, playerId);
}
}
getState().addAbility(ability, null);
super.init(choosingPlayerId);
state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW));
}
@Override
public Set<UUID> getOpponents(UUID playerId) {
Set<UUID> opponents = new HashSet<>();
for (UUID opponentId: this.getPlayer(playerId).getInRange()) {
if (!opponentId.equals(playerId)) {
opponents.add(opponentId);
}
}
return opponents;
}
@Override
public boolean isOpponent(Player player, UUID playerToCheck) {
return !player.getId().equals(playerToCheck);
}
@Override
public MomirDuel copy() {
return new MomirDuel(this);
}
}
// faking Vanguard as an Emblem; need to come back to this and add a new type of CommandObject
class MomirEmblem extends Emblem {
public MomirEmblem(Map<Integer, List<Card>> available) {
setName("Momir Vig, Simic Visionary");
// {X}, Discard a card: Put a token into play as a copy of a random creature card with converted mana cost X. Play this ability only any time you could play a sorcery and only once each turn.
LimitedTimesPerTurnActivatedAbility ability = new LimitedTimesPerTurnActivatedAbility(Zone.COMMAND, new MomirEffect(available), new VariableManaCost());
ability.addCost(new DiscardCardCost());
// ability.setTiming(TimingRule.SORCERY);
this.getAbilities().add(ability);
}
}
class MomirEffect extends OneShotEffect {
private static final Random rnd = new Random();
private final Map<Integer, List<Card>> available;
public MomirEffect(Map<Integer, List<Card>> available) {
super(Outcome.PutCreatureInPlay);
this.available = available;
}
public MomirEffect(MomirEffect effect) {
super(effect);
this.available = effect.available;
staticText = "Put a token into play as a copy of a random creature card with converted mana cost X";
}
@Override
public MomirEffect copy() {
return new MomirEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
int value = source.getManaCostsToPay().getX();
List<Card> options = available.get(value);
if (options != null && !options.isEmpty()) {
Card card = options.get(rnd.nextInt(options.size()));
EmptyToken token = new EmptyToken();
CardUtil.copyTo(token).from(card);
token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId(), false, false);
}
return true;
}
}

View file

@ -0,0 +1,55 @@
/*
* 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.game;
import mage.game.match.MatchImpl;
import mage.game.match.MatchOptions;
/**
*
* @author nigelzor
*/
public class MomirDuelMatch extends MatchImpl {
public MomirDuelMatch(MatchOptions options) {
super(options);
}
@Override
public void startGame() throws GameException {
// Momir Vig, Simic Visionary gives +4 starting life
int startLife = 24;
MomirDuel game = new MomirDuel(options.getAttackOption(), options.getRange(), options.getFreeMulligans(), startLife);
game.setStartMessage(this.createGameStartMessage());
this.initGame(game);
games.add(game);
}
}

View file

@ -0,0 +1,57 @@
/*
* 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.game;
import mage.game.match.MatchType;
/**
*
* @author nigelzor
*/
public class MomirDuelType extends MatchType {
public MomirDuelType() {
this.name = "Momir Basic Two Player Duel";
this.maxPlayers = 2;
this.minPlayers = 2;
this.numTeams = 0;
this.useAttackOption = false;
this.useRange = false;
this.sideboardingAllowed = true;
}
protected MomirDuelType(final MomirDuelType matchType){
super(matchType);
}
@Override
public MomirDuelType copy() {
return new MomirDuelType(this);
}
}

View file

@ -17,9 +17,10 @@
<modules>
<module>Mage.Deck.Constructed</module>
<module>Mage.Deck.Limited</module>
<module>Mage.Game.CommanderDuel</module>
<module>Mage.Game.CommanderDuel</module>
<module>Mage.Game.CommanderFreeForAll</module>
<module>Mage.Game.FreeForAll</module>
<module>Mage.Game.MomirDuel</module>
<module>Mage.Game.TinyLeadersDuel</module>
<module>Mage.Game.TwoPlayerDuel</module>
<module>Mage.Player.AI</module>

View file

@ -49,6 +49,7 @@
<gameType name="Commander Two Player Duel" jar="mage-game-commanderduel.jar" className="mage.game.CommanderDuelMatch" typeName="mage.game.CommanderDuelType"/>
<gameType name="Commander Free For All" jar="mage-game-commanderfreeforall.jar" className="mage.game.CommanderFreeForAllMatch" typeName="mage.game.CommanderFreeForAllType"/>
<gameType name="Tiny Leaders Two Player Duel" jar="mage-game-tinyleadersduel.jar" className="mage.game.TinyLeadersDuelMatch" typeName="mage.game.TinyLeadersDuelType"/>
<gameType name="Momir Basic Two Player Duel" jar="mage-game-momirduel.jar" className="mage.game.MomirDuelMatch" typeName="mage.game.MomirDuelType"/>
</gameTypes>
<tournamentTypes>
<tournamentType name="Constructed Elimination" jar="mage-tournament-constructed.jar" className="mage.tournament.ConstructedEliminationTournament" typeName="mage.tournament.ConstructedEliminationTournamentType"/>
@ -94,6 +95,7 @@
<deckType name="Variant Magic - Commander" jar="mage-deck-constructed.jar" className="mage.deck.Commander"/>
<deckType name="Variant Magic - Duel Commander" jar="mage-deck-constructed.jar" className="mage.deck.DuelCommander"/>
<deckType name="Variant Magic - Tiny Leaders" jar="mage-deck-constructed.jar" className="mage.deck.TinyLeaders"/>
<deckType name="Variant Magic - Momir Basic" jar="mage-deck-constructed.jar" className="mage.deck.Momir"/>
<deckType name="Block Constructed - Battle for Zendikar" jar="mage-deck-constructed.jar" className="mage.deck.BattleForZendikarBlock"/>
<deckType name="Block Constructed - Innistrad" jar="mage-deck-constructed.jar" className="mage.deck.InnistradBlock"/>
<deckType name="Block Constructed - Kamigawa" jar="mage-deck-constructed.jar" className="mage.deck.KamigawaBlock"/>

View file

@ -142,6 +142,12 @@
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mage-game-momirduel</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>

View file

@ -28,6 +28,7 @@
<gameType name="Commander Two Player Duel" jar="mage-game-commanderduel-${project.version}.jar" className="mage.game.CommanderDuelMatch" typeName="mage.game.CommanderDuelType"/>
<gameType name="Commander Free For All" jar="mage-game-commanderfreeforall-${project.version}.jar" className="mage.game.CommanderFreeForAllMatch" typeName="mage.game.CommanderFreeForAllType"/>
<gameType name="Tiny Leaders Two Player Duel" jar="mage-game-tinyleadersduel-${project.version}.jar" className="mage.game.TinyLeadersDuelMatch" typeName="mage.game.TinyLeadersDuelType"/>
<gameType name="Momir Basic Two Player Duel" jar="mage-game-momirduel-${project.version}.jar" className="mage.game.MomirDuelMatch" typeName="mage.game.MomirDuelType"/>
</gameTypes>
<tournamentTypes>
<tournamentType name="Constructed Elimination" jar="mage-tournament-constructed-${project.version}.jar" className="mage.tournament.ConstructedEliminationTournament" typeName="mage.tournament.ConstructedEliminationTournamentType"/>
@ -73,6 +74,7 @@
<deckType name="Variant Magic - Commander" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.Commander"/>
<deckType name="Variant Magic - Duel Commander" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.DuelCommander"/>
<deckType name="Variant Magic - Tiny Leaders" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.TinyLeaders"/>
<deckType name="Variant Magic - Momir Basic" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.Momir"/>
<deckType name="Block Constructed - Battle for Zendikar" jar="mage-deck-constructed.jar" className="mage.deck.BattleForZendikarBlock"/>
<deckType name="Block Constructed - Innistrad" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.InnistradBlock"/>
<deckType name="Block Constructed - Kamigawa" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.KamigawaBlock"/>

View file

@ -166,12 +166,9 @@ public class Main {
else {
logger.fatal("Unable to start MAGE server - another server is already started");
}
} catch (IOException ex) {
logger.fatal("Failed to start server - " + connection.toString(), ex);
} catch (Exception ex) {
logger.fatal("Failed to start server - " + connection.toString(), ex);
}
}
static void initStatistics() {