View Javadoc
1   package de.aikiit.game.kaiser;
2   
3   import org.apache.commons.lang3.StringUtils;
4   
5   import java.math.BigDecimal;
6   import java.math.RoundingMode;
7   
8   import static org.apache.commons.lang3.compare.ComparableUtils.is;
9   
10  /**
11   * This class contains static helper methods to print
12   * results or calculation or status information of the currently running game.
13   */
14  public class KaiserEnginePrinter {
15  
16      // inspired by https://talyian.github.io/ansicolors/
17      /**
18       * Reset anything in console.
19       */
20      public static final String ANSI_RESET = "\u001B[0m";
21      /**
22       * Colour BLACK.
23       */
24      public static final String ANSI_BLACK = "\u001B[30m";
25      /**
26       * Colour RED.
27       */
28      public static final String ANSI_RED = "\u001B[31m";
29      /**
30       * Colour GREEN.
31       */
32      public static final String ANSI_GREEN = "\u001B[32m";
33      /**
34       * Colour YELLOW.
35       */
36      public static final String ANSI_YELLOW = "\u001B[33m";
37      /**
38       * Colour BLUE.
39       */
40      public static final String ANSI_BLUE = "\u001B[34m";
41      /**
42       * Colour PURPLE.
43       */
44      public static final String ANSI_PURPLE = "\u001B[35m";
45      /**
46       * Colour CYAN.
47       */
48      public static final String ANSI_CYAN = "\u001B[36m";
49      /**
50       * Colour WHITE.
51       */
52      public static final String ANSI_WHITE = "\u001B[37m";
53      /**
54       * Colour ORANGE.
55       */
56      public static final String ORANGE = "\u001B[38;5;202m";
57  
58      private final KaiserEngine engine;
59  
60      public KaiserEnginePrinter(KaiserEngine engine) {
61          this.engine = engine;
62      }
63  
64      /**
65       * Show status information of the underlying game engine for the given round.
66       *
67       * @param round current round/year of the game.
68       * @return colour-encoded status.
69       */
70      public String getStatus(int round) {
71          StringBuilder status = new StringBuilder();
72          status.append(ANSI_GREEN).append("### STATUS nach Runde ").append(round).append(ANSI_RESET).append(System.lineSeparator());
73          status.append(ANSI_CYAN).append("Die Einwohnerzahl beträgt jetzt   ").append(StringUtils.leftPad(String.valueOf(this.engine.getPopulation()), 10)).append(ANSI_RESET).append(System.lineSeparator());
74          status.append(ANSI_CYAN).append("Die Stadt besitzt an Land (Hektar)").append(StringUtils.leftPad(String.valueOf(this.engine.getArea()), 10)).append(ANSI_RESET).append(System.lineSeparator());
75          status.append(ANSI_CYAN).append("Die Ernte betrug (dzt/Hektar)     ").append(StringUtils.leftPad(String.valueOf(this.engine.getYield()), 10)).append(ANSI_RESET).append(System.lineSeparator());
76          status.append(ANSI_RED).append("Ratten haben gefressen (dzt)      ").append(StringUtils.leftPad(String.valueOf(this.engine.getExternalDamage()), 10)).append(ANSI_RESET).append(System.lineSeparator());
77          status.append(ANSI_RED).append("Eure Vorräte betragen (dzt)       ").append(StringUtils.leftPad(String.valueOf(this.engine.getSupplies()), 10)).append(ANSI_RESET).append(System.lineSeparator());
78          return status.toString();
79      }
80  
81      /**
82       * Show population result of the current round.
83       *
84       * @param round current round/year of the game.
85       * @return colour-encoded population statistics.
86       */
87      public String getYearResult(int round) {
88          return ANSI_GREEN + "Im Jahr " + round + ANSI_RESET + System.lineSeparator() +
89                  ANSI_CYAN + "Es starben         " + StringUtils.leftPad(String.valueOf(this.engine.getDeathToll()), 10) + " Einwohner" + ANSI_RESET + System.lineSeparator() +
90                  ANSI_CYAN + "hinzugekommen sind " + StringUtils.leftPad(String.valueOf(this.engine.getIncrease()), 10) + " Einwohner" + ANSI_RESET + System.lineSeparator();
91      }
92  
93      /**
94       * After the game ends and the maximum number of years is reached an overall statistics is printed out.
95       *
96       * @return colour-encoded overall statistics.
97       */
98      public String getResults() {
99          return "In Ihrer " + KaiserGame.MAX_ROUNDS + "-jährigen Amtszeit sind durchschnittlich " +
100                 this.engine.getPercentDeathToll() + " % im Jahr verstorben." + System.lineSeparator() +
101                 "Insgesamt sind damit " + this.engine.getDeathTollSum() + " Einwohner verstorben." + System.lineSeparator() +
102                 System.lineSeparator() +
103                 "Anfangs hatten Sie 10 Hektar pro Einwohner, jetzt haben Sie " + this.engine.getAreaPerCapita() + " Hektar/Einwohner." + System.lineSeparator();
104     }
105 
106     /**
107      * Depending on global rules the player's legacy is described/classified depending on the engine's results.
108      *
109      * @return colour-encoded legacy/regency output.
110      */
111     public String evaluateRegency() {
112         StringBuilder result = new StringBuilder();
113         result.append(ANSI_BLUE).append(">>>> Bewertung Ihrer Herrschaft <<<<").append(System.lineSeparator());
114 
115         result.append("In ihrer ").append(engine.getZYear()).append("-jährigen Amtszeit sind ");
116         result.append(engine.getPercentDeathToll()).append("% der Bevölkerung im Jahr verstorben.").append(System.lineSeparator());
117         result.append("Insgesamt sind ").append(engine.getDeathTollSum()).append(" Einwohner gestorben.").append(System.lineSeparator());
118 
119         BigDecimal legacy = engine.getArea().divide(engine.getPopulation(), RoundingMode.HALF_UP);
120         result.append("Zu Beginn hatten sie 10 Hektar pro Einwohner,").append(System.lineSeparator());
121         result.append("jetzt sind es ").append(legacy).append(" Hektar/Einwohner.").append(System.lineSeparator());
122 
123         // TODO: check and fix legacy calculation - message should match criteria
124         if (is(engine.getPercentDeathToll()).greaterThan(BigDecimal.valueOf(33)) || is(legacy).lessThan(BigDecimal.valueOf(7))) {
125             result.append("Auf Grund dieser extremen Misswirtschaft, werden Sie nicht nur aus Amt und Würden gejagt,").append(System.lineSeparator());
126             result.append("sondern auch zum Versager des Jahres erklärt.").append(System.lineSeparator());
127         } else {
128 
129             if (is(engine.getPercentDeathToll()).greaterThan(BigDecimal.TEN) || is(legacy).lessThan(BigDecimal.valueOf(9))) {
130                 result.append("Ihre hartherzige Regierungsmethode erinnert an Nero und Iwan den Schrecklichen.");
131                 result.append(System.lineSeparator());
132                 result.append("Die (verbliebenen) Einwohner würden Sie gerne zum Teufel jagen!");
133             } else if (is(engine.getPercentDeathToll()).greaterThan(BigDecimal.TEN) || is(legacy).lessThan(BigDecimal.valueOf(9))) {
134                 result.append("Sie hätten glücklicher agieren können, aber es war nicht übel.");
135                 result.append(System.lineSeparator());
136                 result.append(this.engine.getPopulation().multiply(new BigDecimal("0.8"))).append(" Einwohner möchten Sie zwar hängen sehen, aber kleine Probleme hat ja jeder.");
137             } else {
138                 result.append("Eine wunderbare Regierungszeit! Karl, Konrad und Willi (die Großen) hätten es nicht besser machen können.");
139             }
140         }
141 
142         result.append(ANSI_RESET);
143         result.append(System.lineSeparator());
144         result.append(System.lineSeparator());
145         return result.toString();
146     }
147 }