Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ build/
!**/src/main/**/build/
!**/src/test/**/build/
settings.json
BattleResults/

### IntelliJ IDEA ###
.idea/modules.xml
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package dk.sdu.mmmi.modulemon.HeadlessBattleView;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class CSVWriter {
private char separator = ',';
private boolean writeExcelHeader = false;
private String[] columnTitles;

private List<Object[]> rows;

public CSVWriter(){
rows = new ArrayList<>();
}

public boolean save(String fileToWriteTo) throws IOException {
try (var writer = new BufferedWriter(new FileWriter(fileToWriteTo))) {
if(writeExcelHeader){
writer.append("sep=").append(separator);
writer.newLine();
}

if(columnTitles != null){
writer.append(String.join(String.valueOf(separator), columnTitles));
writer.newLine();
}

for(var row : rows){
boolean first = true; // Used to make sure we don't have trailing separators
for(var field : row){
if(!first){
writer.append(separator);
}
first = false;

writer.append(field.toString());
}
writer.newLine();
}

writer.flush();
}

return true;
}

public void addRow(Object... row){
rows.add(row);
}

public char getSeparator() {
return separator;
}

public void setSeparator(char separator) {
this.separator = separator;
}

public String[] getColumnTitles() {
return columnTitles;
}

public void setColumnTitles(String... columnTitles) {
this.columnTitles = columnTitles;
}

public boolean isWriteExcelHeader() {
return writeExcelHeader;
}

public void setWriteExcelHeader(boolean writeExcelHeader) {
this.writeExcelHeader = writeExcelHeader;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package dk.sdu.mmmi.modulemon.HeadlessBattleView;

//Basically a fast out handler that captures all logging and does nothing. Speeding up due to excessive logging.
public class EmptyOutHandler {
private static final java.io.PrintStream defaultStream = System.out;
public static void setEmptyHandler(){
System.out.println("Disabling System.out.println()");
System.setOut(getHandler());
}

public static void setDefaultHandler(){
System.setOut(defaultStream);
System.out.println("Enabled System.out.println()");
}

public static java.io.PrintStream getHandler(){
// Stolen from https://stackoverflow.com/a/34839209
return new java.io.PrintStream(new java.io.OutputStream() {
@Override public void write(int b) {}
}) {
@Override public void flush() {}
@Override public void close() {}
@Override public void write(int b) {}
@Override public void write(byte[] b) {}
@Override public void write(byte[] buf, int off, int len) {}
@Override public void print(boolean b) {}
@Override public void print(char c) {}
@Override public void print(int i) {}
@Override public void print(long l) {}
@Override public void print(float f) {}
@Override public void print(double d) {}
@Override public void print(char[] s) {}
@Override public void print(String s) {}
@Override public void print(Object obj) {}
@Override public void println() {}
@Override public void println(boolean x) {}
@Override public void println(char x) {}
@Override public void println(int x) {}
@Override public void println(long x) {}
@Override public void println(float x) {}
@Override public void println(double x) {}
@Override public void println(char[] x) {}
@Override public void println(String x) {}
@Override public void println(Object x) {}
@Override public java.io.PrintStream printf(String format, Object... args) { return this; }
@Override public java.io.PrintStream printf(java.util.Locale l, String format, Object... args) { return this; }
@Override public java.io.PrintStream format(String format, Object... args) { return this; }
@Override public java.io.PrintStream format(java.util.Locale l, String format, Object... args) { return this; }
@Override public java.io.PrintStream append(CharSequence csq) { return this; }
@Override public java.io.PrintStream append(CharSequence csq, int start, int end) { return this; }
@Override public java.io.PrintStream append(char c) { return this; }
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import dk.sdu.mmmi.modulemon.Battle.BattleParticipant;
import dk.sdu.mmmi.modulemon.BattleScene.BattleResult;
import dk.sdu.mmmi.modulemon.BattleSimulation.BattleSimulation;
import dk.sdu.mmmi.modulemon.CommonBattle.IBattleParticipant;
import dk.sdu.mmmi.modulemon.CommonBattleClient.IBattleResult;
import dk.sdu.mmmi.modulemon.CommonBattleSimulation.BattleEvents.AICrashedEvent;
import dk.sdu.mmmi.modulemon.CommonBattleSimulation.BattleEvents.ChangeMonsterBattleEvent;
Expand All @@ -24,6 +25,11 @@
import dk.sdu.mmmi.modulemon.common.services.IGameViewService;
import dk.sdu.mmmi.modulemon.CommonBattleSimulation.BattleEvents.MoveBattleEvent;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.sql.Array;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
Expand Down Expand Up @@ -62,19 +68,39 @@ public class HeadlessBattleView implements IGameViewService {
private int[] battleAmounts = {1, 10, 100, 250, 500, 750, 1000};
private int battleAmountIndex = 1;

private CSVWriter csvWriter;

@Override
public void init(IGameViewManager gameViewManager) {
selectSound = AssetLoader.getInstance().getSoundAsset("/sounds/select.ogg", this.getClass());
chooseSound = AssetLoader.getInstance().getSoundAsset("/sounds/choose.ogg", this.getClass());
yaySound = AssetLoader.getInstance().getSoundAsset("/sounds/YAY.ogg", this.getClass());
battleWaitMusic = AssetLoader.getInstance().getMusicAsset("/music/headless.ogg", this.getClass());
battleWaitMusic.setLooping(true);
battleWaitMusic.setVolume(getSoundVolume());
battleWaitMusic.setVolume(getMusicVolume());
menuMusic = AssetLoader.getInstance().getMusicAsset("/music/headlessMenu.ogg", this.getClass());
menuMusic.setLooping(true);
menuMusic.setVolume(getSoundVolume());
menuMusic.setVolume(getMusicVolume());
menuMusic.play();

csvWriter = new CSVWriter();
csvWriter.setWriteExcelHeader(true); // Makes it so the file is easy to open in Excel.

var coloumnTitles = new ArrayList<String>() {{
add("Battle");
add("WinnerTeam");
add("TurnsToWin");
}};
int monstersPerTeam = 3;
for(String team : new String[]{"WinnerTeam", "LoserTeam"}) {
for (int i = 0; i < monstersPerTeam; i++) {
coloumnTitles.add(String.format("%s_Monster%d_Name", team, i+1));
coloumnTitles.add(String.format("%s_Monster%d_HP", team, i+1));
}
}

csvWriter.setColumnTitles(coloumnTitles.toArray(new String[0]));

scene = new HeadlessBattleScene(settings);
battlingScene = new HeadlessBattlingScene();
}
Expand All @@ -96,13 +122,15 @@ public void update(GameData gameData, IGameViewManager gameViewManager) {
if (battleResultFuture.isDone()) {
try {
var battleResult = battleResultFuture.get();
boolean teamAWon = true;
if (battleResult.getWinner() == battleResult.getPlayer()) {
teamAWins++;
if(battleResult.getStarter() == battleResult.getWinner()){
teamAStartWins++;
}
winTurnsA += battleResult.getTurns();
} else {
teamAWon = false;
teamBWins++;
if(battleResult.getStarter() == battleResult.getWinner()){
teamBStartWins++;
Expand All @@ -112,9 +140,24 @@ public void update(GameData gameData, IGameViewManager gameViewManager) {
completedBattles++;
currentBattles--;
battleResultsToRemove.add(battleResultFuture);

var row = new ArrayList<Object>();
row.add(completedBattles);
row.add(teamAWon ? "A" : "B");
row.add(battleResult.getTurns());

var participantWinner = battleResult.getWinner();
var participantLoser = battleResult.getWinner().equals(battleResult.getPlayer()) ? battleResult.getEnemy() : battleResult.getPlayer();
for(var team : new IBattleParticipant[]{participantWinner, participantLoser}) {
for (var monster : team.getMonsterTeam()) {
row.add(monster.getName());
row.add(monster.getHitPoints());
}
}

csvWriter.addRow(row.toArray());
} catch (InterruptedException | ExecutionException e) {
System.out.println("Battle was cancelled!");
;
}
}
}
Expand All @@ -129,10 +172,26 @@ public void update(GameData gameData, IGameViewManager gameViewManager) {
if (completedBattles >= battleAmount) {
yaySound.play(getSoundVolume());
battling = false;
EmptyOutHandler.setDefaultHandler();
doneBattling = true;
currentBattles = 0;
// Stop any remaining battles
stopAllBattles();

// Save CSV file
try {
final String outputDir = "BattleResults";
var dir = new File(outputDir);
if(!dir.exists()) {
dir.mkdirs();
}
var filename = Path.of(outputDir, String.format("battle_simulation_results_%d.csv", System.currentTimeMillis() / 1000L));
csvWriter.save(filename.toAbsolutePath().toString());
} catch (IOException e) {
System.out.println("Tried to save CSV file, but failed! Oh no! Anyway..");
e.printStackTrace();
}

} else if (currentBattles < concurrentBattles && currentBattles + completedBattles < battleAmount) {
var amountBattlesToStart = concurrentBattles - currentBattles;
for (int i = 0; i < amountBattlesToStart; i++) {
Expand Down Expand Up @@ -290,6 +349,7 @@ public void handleInput(GameData gameData, IGameViewManager gameViewManager) {
battleWaitMusic.setVolume(getSoundVolume());
battleWaitMusic.play();
battling = true;
EmptyOutHandler.setEmptyHandler();
} else if (gameData.getKeys().isPressed(GameKeys.ACTION)) {
chooseSound.play(getSoundVolume());
editingMode = true;
Expand Down Expand Up @@ -373,6 +433,10 @@ private float getSoundVolume() {
return ((int) settings.getSetting(settingsRegistry.getSoundVolumeSetting()) / 100f);
}

private float getMusicVolume() {
return ((int) settings.getSetting(settingsRegistry.getMusicVolumeSetting()) / 100f);
}

public void setSettings(IGameSettings settings) {
this.settings = settings;
}
Expand Down
Binary file modified src/main/resources/music/headless.ogg
Binary file not shown.