siciliaguerrabot2020/SiciliaGuerraBot2020.java (view raw)
1/*
2 * To change this license header, choose License Headers in Project Properties.
3 * To change this template file, choose Tools | Templates
4 * and open the template in the editor.
5 */
6package siciliaguerrabot2020;
7
8import siciliaguerrabot2020.Guerra.Comune;
9import siciliaguerrabot2020.Guerra.Territorio;
10import siciliaguerrabot2020.Guerra.Centroide;
11import java.io.BufferedReader;
12import java.io.File;
13import java.io.FileReader;
14import java.io.IOException;
15import java.util.ArrayList;
16import java.util.Collections;
17import java.util.Scanner;
18import java.util.StringTokenizer;
19import java.util.concurrent.ThreadLocalRandom;
20import picocli.CommandLine;
21import picocli.CommandLine.Option;
22import siciliaguerrabot2020.Calendario.Calendario;
23import siciliaguerrabot2020.Calendario.Data;
24
25/**
26 *
27 * @author Bi-Rabittoh
28 */
29
30public class SiciliaGuerraBot2020 {
31 @Option(names = "-v", description = "only simulate one war (default ${DEFAULT-VALUE})")
32 private boolean verbose = false;
33 @Option(names = "-s", description = "load data from a specific file (default ${DEFAULT-VALUE})")
34 private File source_file = new File("data.txt");
35 @Option(names = "-m", description = "filter cities for max population (default ${DEFAULT-VALUE})")
36 private int max_population = 12000;
37 @Option(names = "-n", description = "sets number of wars to simulate (default ${DEFAULT-VALUE})")
38 private int n_wars = 500;
39 @Option(names = { "-h", "--help" }, usageHelp = true, description = "display a help message")
40 private boolean helpRequested;
41
42
43 public static void main(String[] args) {
44 //String[] debug_args = {"-m=50000", "-h"}; SiciliaGuerraBot2020 par = CommandLine.populateCommand(new SiciliaGuerraBot2020(), debug_args);
45 SiciliaGuerraBot2020 par = CommandLine.populateCommand(new SiciliaGuerraBot2020(), args);
46
47 if(par.helpRequested){
48 CommandLine.usage(par, System.out);
49 System.exit(0);
50 }
51
52 final File file = par.source_file;
53 final int soglia_popolazione = par.max_population;
54 final boolean verbose = par.verbose;
55 final int n_guerre = par.n_wars;
56
57 //LEGGO I DATI DA FILE
58 ArrayList<Comune> comuni_unfiltered = new ArrayList<>();
59 BufferedReader reader;
60 StringTokenizer st;
61 try {
62 reader = new BufferedReader(new FileReader(file));
63 String line = reader.readLine();
64 while (line != null){
65 st = new StringTokenizer(line);
66 comuni_unfiltered.add(new Comune(st.nextToken(), Integer.parseInt(st.nextToken()), new Centroide(Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()))));
67 line = reader.readLine();
68 }
69 } catch (IOException e){
70 System.out.println("File non trovato.");
71 System.exit(1);
72 }
73
74 if(verbose){
75 //FILTRO LE CITTA' PER POPOLAZIONE
76 ArrayList<Comune> comuni = riempiLista(comuni_unfiltered, soglia_popolazione);
77 System.out.println("I comuni in guerra sono " + comuni.size() + ":");
78 for(Comune c : comuni){
79 System.out.println(c.getNome());
80 }
81 System.out.println("\nLa guerra si è conclusa. L'intera regione è adesso unificata sotto il regno di " + combatteteSchiavi(comuni, verbose).getNome() + ".");
82 } else {
83 //ANALIZZO LE PERCENTUALI DI VITTORIA
84 ArrayList<StatComune> statistiche = getStats(comuni_unfiltered, soglia_popolazione, verbose, n_guerre);
85 Collections.sort(statistiche);
86 for(StatComune sc : statistiche){
87 System.out.println(sc.getNome() + ": " + sc.getWinrate(n_guerre) + "%");
88 }
89 }
90 //FINE MAIN
91 System.exit(0);
92 }
93
94 private static Comune combatteteSchiavi(ArrayList<Comune> lista_comuni, boolean verbose){
95 Calendario calendario = new Calendario(new Data(0, 1, 2020));
96 ArrayList<Comune> lista = new ArrayList<>();
97 for(Comune c: lista_comuni){
98 lista.add(new Comune(c.getNome(), c.getPop(), new Centroide(c.getPos().x, c.getPos().y)));
99 }
100 Comune attaccante;
101 Territorio vittima;
102 int vivi = lista.size();
103 int random;
104 boolean esito;
105 Comune propVittima;
106 while(true){
107 //scelgo un comune casuale come attaccante
108 random = ThreadLocalRandom.current().nextInt(0, vivi); //dovrei avere "vivi - 1" ma non serve perchè questa funzione non include l'ultimo valore del range
109 //System.out.println("rand tra 0 e " + (vivi - 1) + ": "+ random);
110 attaccante = lista.get(random);
111 vittima = attaccante.trovaVicino(lista);
112 propVittima = vittima.getProprietario();
113 esito = attaccante.conquista(vittima);
114
115 if(verbose){
116 System.out.print("\n" + calendario.nextString() + ", " + attaccante.getNome() + " ha conquistato il territorio di " + vittima.getNome());
117 if(!propVittima.getNome().equals(vittima.getNome())){
118 System.out.print(" precedentemente occupato da " + propVittima.getNome());
119 }
120 System.out.print(".\n");
121 }
122 if(esito){
123 vivi--;
124 if(verbose)
125 System.out.print(propVittima.getNome() + " è stata completamente sconfitta. " + vivi + " comuni rimanenti.\n");
126 }
127 Collections.sort(lista);
128 if (vivi == 1)
129 break;
130 }
131 return attaccante;
132 }
133
134 public static void pause(){
135 Scanner scanner = new Scanner(System.in);
136 scanner.nextLine();
137 }
138
139 public static void currentStatus(ArrayList<Comune> comuni){
140 for(Comune c : comuni){
141 System.out.println(c.getNome() + ": Territori:");
142 for(Territorio t : c.getTerritori()){
143 System.out.println("\t" + t.getNome());
144 }
145 System.out.println();
146 }
147 System.out.println("\n");
148 }
149
150 public static ArrayList<Comune> riempiLista(ArrayList<Comune> comuni_unfiltered, int soglia_popolazione){
151 ArrayList<Comune> comuni = new ArrayList<>();
152 for(Comune c : comuni_unfiltered){
153 if(c.getPop() >= soglia_popolazione)
154 comuni.add(new Comune(c.getNome(), c.getPop(), new Centroide(c.getPos().x, c.getPos().y)));
155 }
156 return comuni;
157 }
158
159 public static ArrayList<StatComune> getStats(ArrayList<Comune> comuni_unfiltered, int soglia_popolazione, boolean verbose, int n_guerre){
160 ArrayList<Comune> comuni_src = riempiLista(comuni_unfiltered, soglia_popolazione);
161
162 ArrayList<Comune> comuni;
163
164 ArrayList<StatComune> stat = new ArrayList<>();
165 for(Comune c : comuni_src){
166 stat.add(new StatComune(c.getNome()));
167 }
168 String vinc;
169
170 for(int i = 0; i < n_guerre; i++){
171 comuni = new ArrayList<>();
172 for(Comune c : comuni_src){
173 comuni.add(c);
174 }
175 vinc = combatteteSchiavi(comuni, verbose).getNome();
176 for(StatComune sc : stat){
177 if(sc.getNome().equals(vinc)){
178 sc.winWar();
179 break;
180 }
181 }
182 }
183 return stat;
184 }
185}