001package com.fs.starfarer.api.campaign.econ;
002
003import java.util.ArrayList;
004import java.util.Arrays;
005import java.util.LinkedHashMap;
006import java.util.LinkedList;
007import java.util.List;
008
009import com.fs.starfarer.api.Global;
010import com.fs.starfarer.api.campaign.CargoAPI;
011import com.fs.starfarer.api.campaign.SectorEntityToken;
012import com.fs.starfarer.api.impl.campaign.MonthlyReportNodeTooltipCreator;
013import com.fs.starfarer.api.impl.campaign.ids.Factions;
014import com.fs.starfarer.api.ui.TooltipMakerAPI.TooltipCreator;
015
016public class MonthlyReport {
017
018        public static String CREW = "node_id_crew";
019        public static String MARINES = "node_id_marines";
020        public static String FLEET = "node_id_fleet";
021        public static String OUTPOSTS = "node_id_outposts";
022        public static String PRODUCTION = "node_id_prod";
023        public static String PRODUCTION_WEAPONS = "node_id_prod_weapons";
024        //public static String SURPLUS = "node_id_surplus";
025        public static String OVERHEAD = "node_id_overhead";
026        public static String STOCKPILING = "node_id_stockpiling";
027        public static String RESTOCKING = "node_id_restocking";
028        
029        public static String INCENTIVES = "node_id_incentives";
030        public static String INDUSTRIES = "node_id_industries";
031        public static String EXPORTS = "node_id_exports";
032        public static String STORAGE = "node_id_storage";
033        public static String ADMIN = "node_id_admin";
034        public static String STORAGE_CARGO = "node_id_storage_cargo";
035        public static String STORAGE_SHIPS = "node_id_storage_ships";
036        
037        public static String LAST_MONTH_DEBT = "node_id_last_month_debt";
038        //public static String IMPORTS = "node_id_imports";
039        
040        public static String OFFICERS = "node_id_officers";
041        
042        /**
043         * Financial data node for a monthly income/expenses report.
044         *
045         * <ul>
046         *     <li>Represent a node in the monthly report panel.</li>
047         *     <li>Example: com.fs.starfarer.api.impl.campaign.tutorial.GalatianAcademyStipend</li>
048         *     <li>Example: com.fs.starfarer.api.impl.campaign.CoreScript.reportEconomyTick(int)</li>
049         * </ul>
050         *
051         * <p>Adding custom node to monthly report under storage section</p>
052         * <pre>
053         * <code>
054         *       MonthlyReport report = SharedData.getData().getCurrentReport();
055         *         MonthlyReport.FDNode storageNode = report.getNode(MonthlyReport.STORAGE);
056         *         //Check if the storageNode has been initialized in order to not override the node.
057         *         if(storageNode.name == null) {
058         *             storageNode.name = "Storage";
059         *             storageNode.custom = MonthlyReport.STORAGE;
060         *             storageNode.tooltipCreator = report.getMonthlyReportTooltip();
061         *         }
062         *         //Add in the custom node by getting the storageNode and create a new node from it
063         *         MonthlyReport.FDNode anotherNode = report.getNode(storageNode, "A unique ID");
064         *         anotherNode.name = "Another node inside storage node";
065         * </code>
066         * </pre>
067         * @author Alex Mosolov
068         *
069         * Copyright 2017 Fractal Softworks, LLC
070         *
071         */
072        public static class FDNode {
073                protected LinkedHashMap<String, FDNode> children;
074                public FDNode parent;
075                //public String sortString;
076                public String name;
077                public String icon;
078                
079                public float income;
080                public float upkeep;
081                public float totalIncome;
082                public float totalUpkeep;
083                
084                public Object custom;
085                public Object custom2;
086                public SectorEntityToken mapEntity;
087                
088                public TooltipCreator tooltipCreator = null;
089                public Object tooltipParam;
090
091                public LinkedHashMap<String, FDNode> getChildren() {
092                        if (children == null) return new LinkedHashMap<String, FDNode>();
093                        return children;
094                }
095                
096                public int getDepth() {
097                        FDNode curr = this;
098                        int count = 0;
099                        while (curr.parent != null) {
100                                curr = curr.parent;
101                                count++;
102                        }
103                        return count;
104                }
105        }
106        
107        private FDNode root = new FDNode();
108        private long timestamp;
109        private int debt = 0;
110        private int previousDebt = 0;
111        
112        private MonthlyReportNodeTooltipCreator monthlyReportTooltip;
113        public MonthlyReportNodeTooltipCreator getMonthlyReportTooltip() {
114                if (monthlyReportTooltip == null) {
115                        monthlyReportTooltip = new MonthlyReportNodeTooltipCreator();
116                }
117                return monthlyReportTooltip;
118        }
119        
120        public void computeTotals() {
121                computeTotals(root);
122        }
123        
124        public long getTimestamp() {
125                return timestamp;
126        }
127
128        public void setTimestamp(long timestamp) {
129                this.timestamp = timestamp;
130        }
131        
132        public int getPreviousDebt() {
133                return previousDebt;
134        }
135
136        public void setPreviousDebt(int previousDebt) {
137                this.previousDebt = previousDebt;
138        }
139
140        public int getDebt() {
141                return debt;
142        }
143
144        public void setDebt(int debt) {
145                this.debt = debt;
146        }
147
148        public FDNode getRoot() {
149                return root;
150        }
151
152        protected void computeTotals(FDNode curr) {
153                curr.totalIncome = curr.income;
154                curr.totalUpkeep = curr.upkeep;
155                
156                for (FDNode child : curr.getChildren().values()) {
157                        computeTotals(child);
158                }
159                
160                if (curr.parent != null) {
161                        curr.parent.totalIncome += curr.totalIncome;
162                        curr.parent.totalUpkeep += curr.totalUpkeep;
163                }
164        }
165        
166        public List<FDNode> getAllNodes() {
167                List<FDNode> all = new ArrayList<FDNode>();
168                getAllNodes(root, all);
169                return all;
170        }
171        
172        protected void getAllNodes(FDNode curr, List<FDNode> nodes) {
173                nodes.add(curr);
174                
175                for (FDNode child : curr.getChildren().values()) {
176                        getAllNodes(child, nodes);
177                }
178        }
179        
180        public FDNode getNode(String ... path) {
181                return getNode(root, new LinkedList<String>(Arrays.asList(path)));
182        }
183        
184        public FDNode getNode(FDNode from, String ... path) {
185                return getNode(from, new LinkedList<String>(Arrays.asList(path)));
186        }
187        public FDNode getNode(FDNode from, List<String> path) {
188                if (path.isEmpty()) return from;
189                
190                String nextId = path.remove(0);
191                FDNode next = from.children == null ? null : from.children.get(nextId);
192                if (next == null) { 
193                        if (from.children == null) {
194                                from.children = new LinkedHashMap<String, FDNode>();
195                        }
196                        next = new FDNode();
197                        next.parent = from;
198                        from.children.put(nextId, next);
199                }
200                return getNode(next, path);
201        }
202
203        
204        public FDNode getColoniesNode() {
205                FDNode marketsNode = getNode(MonthlyReport.OUTPOSTS);
206                if (marketsNode.name == null) {
207                        marketsNode.name = "Colonies";
208                        marketsNode.custom = MonthlyReport.OUTPOSTS;
209                        marketsNode.tooltipCreator = getMonthlyReportTooltip();
210                }
211                return marketsNode;
212        }
213        
214        public FDNode getMarketNode(MarketAPI market) {
215                FDNode marketsNode = getColoniesNode();
216                
217                FDNode mNode = getNode(marketsNode, market.getId());
218                if (mNode.name == null) {
219                        mNode.name = market.getName() + " (" + market.getSize() + ")";
220                        mNode.custom = market;
221                }
222                return mNode;
223        }
224        
225        public FDNode getCounterShortageNode(MarketAPI market) {
226                FDNode mNode = getMarketNode(market);
227                
228                FDNode sNode = getNode(mNode, MonthlyReport.STOCKPILING);
229                if (sNode.name == null) {
230                        sNode.name = "Stockpiles used to counter shortages";
231                        sNode.custom = MonthlyReport.STOCKPILING;
232                        sNode.custom2 = Global.getFactory().createCargo(true);
233                        ((CargoAPI)sNode.custom2).initMothballedShips(Factions.PLAYER);
234                        sNode.tooltipCreator = getMonthlyReportTooltip();
235                }
236                return sNode;
237        }
238        
239        public FDNode getRestockingNode(MarketAPI market) {
240                //FDNode mNode = getMarketNode(market);
241                
242                FDNode mNode = getColoniesNode();
243                
244                FDNode sNode = getNode(mNode, MonthlyReport.RESTOCKING);
245                if (sNode.name == null) {
246                        sNode.name = "Stockpiles drawn by your fleet";
247                        sNode.custom = MonthlyReport.RESTOCKING;
248                        sNode.custom2 = Global.getFactory().createCargo(true);
249                        ((CargoAPI)sNode.custom2).initMothballedShips(Factions.PLAYER);
250                        sNode.tooltipCreator = getMonthlyReportTooltip();
251                }
252                return sNode;
253        }
254        
255        public FDNode getDebtNode() {
256                FDNode debtNode = getNode(MonthlyReport.LAST_MONTH_DEBT);
257                if (debtNode.name == null) {
258                        debtNode.name = "Last month's debt";
259                        debtNode.custom = MonthlyReport.LAST_MONTH_DEBT;
260                        debtNode.icon = Global.getSettings().getSpriteName("income_report", "generic_expense");
261                        debtNode.tooltipCreator = getMonthlyReportTooltip();
262                }
263                return debtNode;
264        }
265        
266        public static void main(String[] args) {
267                MonthlyReport data = new MonthlyReport();
268                
269                data.getNode("test", "test1", "test2").income = 10;
270                
271                System.out.println(data);
272        }
273}
274
275
276
277
278