Skip to content

Commit b7b2514

Browse files
authored
Layout Improvements (#69)
- Optional Saving Roll instant PS/Ammo - Fix BW Cards Chrome print - Add Ava in BW Cards - Add Booty Card - Add Meta Chemistry Card
1 parent 4e59b14 commit b7b2514

21 files changed

Lines changed: 1061 additions & 90 deletions

File tree

app/src/main/java/de/twonirwana/infinity/ExportArmyCode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ public static void main(String[] args) {
2727
.flatMap(k -> al.getCombatGroups().get(k).stream())
2828
.toList();
2929

30-
new HtmlPrinter().printCardForArmyCode(armyListOptions, List.of(), db.getAllMartialArtLevels(), al.getSectorial(), fileName, armyCode, useInch, Set.of(Weapon.Type.WEAPON, Weapon.Type.EQUIPMENT, Weapon.Type.SKILL, Weapon.Type.TURRET), true, false, HtmlPrinter.Template.a7_image);
30+
new HtmlPrinter().printCardForArmyCode(armyListOptions, List.of(), db.getAllMartialArtLevels(), db.getAllBootyRolls(), db.getAllMetaChemistryRolls(), al.getSectorial(), fileName, armyCode, useInch, false, Set.of(Weapon.Type.WEAPON, Weapon.Type.EQUIPMENT, Weapon.Type.SKILL, Weapon.Type.TURRET), true, false, HtmlPrinter.Template.a7_image);
3131
}
3232
}

app/src/main/java/de/twonirwana/infinity/HtmlPrinter.java

Lines changed: 81 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -97,33 +97,51 @@ public HtmlPrinter() {
9797

9898
/*todo:
9999
* T2, AP, Shock, Continous Damage from Skill to weapon table
100-
* dina7 format: points and sws
101100
* Mark profiles cards that belong to the same trooper, like transformations
102101
* Mark trooper cards that belong to the same unit, like peripherals
103102
* Max Image width
104103
* Second page for units with more then 6 weapons?
105-
* weapon add saving modifier, savingNum to table? -> in notes?
106104
*/
107105

108106
public void printCardForArmyCode(List<UnitOption> unitOptions,
109107
List<HackingProgram> allHackingPrograms,
110108
List<MartialArtLevel> allMartialArtLevels,
109+
List<BootyRoll> allBootyRolls,
110+
List<MetaChemistryRoll> allMetaChemistryRolls,
111111
Sectorial sectorial,
112112
String fileName,
113113
String armyCode,
114114
boolean useInch,
115+
boolean showSavingRollInstantOfAmmo,
115116
Set<Weapon.Type> showWeaponOfType,
116117
boolean showImage,
117118
boolean showHackingPrograms,
118119
Template template) {
119-
writeCards(unitOptions, allHackingPrograms, allMartialArtLevels, fileName, armyCode, sectorial, UNIT_IMAGE_FOLDER, CUSTOM_UNIT_IMAGE_FOLDER, UNIT_LOGOS_FOLDER, CARD_FOLDER, useInch, showWeaponOfType, showImage, showHackingPrograms, template);
120+
writeCards(unitOptions,
121+
allHackingPrograms,
122+
allMartialArtLevels,
123+
allBootyRolls,
124+
allMetaChemistryRolls,
125+
fileName,
126+
armyCode,
127+
sectorial,
128+
UNIT_IMAGE_FOLDER,
129+
CUSTOM_UNIT_IMAGE_FOLDER,
130+
UNIT_LOGOS_FOLDER,
131+
CARD_FOLDER,
132+
useInch,
133+
showSavingRollInstantOfAmmo,
134+
showWeaponOfType,
135+
showImage,
136+
showHackingPrograms,
137+
template);
120138
}
121139

122140
public void printAll(Database db, boolean useInch, Template template) {
123141
db.getAllSectorials().stream()
124142
.filter(s -> !s.isDiscontinued())
125143
.flatMap(s -> db.getAllUnitsForSectorialWithoutMercs(s).stream())
126-
.forEach(u -> writeToFile(u, db.getAllMartialArtLevels(), UNIT_IMAGE_FOLDER, CUSTOM_UNIT_IMAGE_FOLDER, UNIT_LOGOS_FOLDER, "all/" + u.getSectorial().getSlug(), useInch, template));
144+
.forEach(u -> writeToFile(u, db.getAllMartialArtLevels(), UNIT_IMAGE_FOLDER, CUSTOM_UNIT_IMAGE_FOLDER, UNIT_LOGOS_FOLDER, "all/" + u.getSectorial().getSlug(), useInch, false, template));
127145
}
128146

129147
private void copyFile(String fileName, String sourcePath, String outPath) {
@@ -201,17 +219,19 @@ private void copyCustomUnitImages(UnitOption option, String unitImagePath, Strin
201219

202220
public void writeToFile(UnitOption unitOption,
203221
List<MartialArtLevel> allMartialArtLevels,
204-
205222
String unitImagePath,
206223
String customUnitImagePath,
207224
String logoImagePath,
208225
String outputFolder,
209226
boolean useInch,
227+
boolean showSavingRollInstantOfAmmo,
210228
Template template) {
211229
String fileName = "%s_%s".formatted(unitOption.getCombinedId(), unitOption.getSlug());
212230
writeCards(List.of(unitOption),
213231
List.of(),
214232
allMartialArtLevels,
233+
List.of(),
234+
List.of(),
215235
fileName,
216236
"-",
217237
unitOption.getSectorial(),
@@ -220,6 +240,7 @@ public void writeToFile(UnitOption unitOption,
220240
logoImagePath,
221241
outputFolder,
222242
useInch,
243+
showSavingRollInstantOfAmmo,
223244
Set.of(Weapon.Type.WEAPON, Weapon.Type.EQUIPMENT, Weapon.Type.SKILL),
224245
true,
225246
false,
@@ -229,6 +250,8 @@ public void writeToFile(UnitOption unitOption,
229250
public void writeCards(List<UnitOption> unitOptions,
230251
List<HackingProgram> allHackingPrograms,
231252
List<MartialArtLevel> allMartialArtLevels,
253+
List<BootyRoll> allBootyRolls,
254+
List<MetaChemistryRoll> allMetaChemistryRolls,
232255
String fileName,
233256
String armyCode,
234257
Sectorial sectorial,
@@ -237,6 +260,7 @@ public void writeCards(List<UnitOption> unitOptions,
237260
String logoImagePath,
238261
String outputFolder,
239262
boolean useInch,
263+
boolean showSavingRollInstantOfAmmo,
240264
Set<Weapon.Type> showWeaponOfType,
241265
boolean showImage,
242266
boolean showHackingPrograms,
@@ -273,7 +297,7 @@ public void writeCards(List<UnitOption> unitOptions,
273297
final List<PrintHackingProgram> programsCard1;
274298
final List<PrintHackingProgram> programsCard2;
275299

276-
int maxProgramsOnFirstCard = 7;
300+
int maxProgramsOnFirstCard = template.numberOfHackingProgramsPerCard;
277301
if (usedHackingPrograms.size() > maxProgramsOnFirstCard) {
278302
programsCard1 = usedHackingPrograms.subList(0, maxProgramsOnFirstCard);
279303
programsCard2 = usedHackingPrograms.subList(maxProgramsOnFirstCard, usedHackingPrograms.size());
@@ -285,6 +309,9 @@ public void writeCards(List<UnitOption> unitOptions,
285309
int cardWidthInMm = template.widthInMm;
286310
int cardHeightInMm = template.heightInMm;
287311

312+
boolean hasBooty = hasAnySkill(unitOptions, "Booty");
313+
boolean hasMetaChemistry = hasAnySkill(unitOptions, "MetaChemistry");
314+
288315
Context context = new Context();
289316
context.setVariable("unitPrintCards", unitPrintCards);
290317
context.setVariable("rangeModifierClassMap", RANGE_CLASS_MAP);
@@ -293,15 +320,17 @@ public void writeCards(List<UnitOption> unitOptions,
293320
context.setVariable("primaryColor", primaryColor);
294321
context.setVariable("secondaryColor", secondaryColor);
295322
context.setVariable("headerColor", headerColor);
296-
context.setVariable("showImage", true);
323+
context.setVariable("showSavingRollInstantOfAmmo", showSavingRollInstantOfAmmo);
297324
context.setVariable("printUtils", new PrintUtils());
298325
context.setVariable("programs", programsCard1);
299326
context.setVariable("programs2", programsCard2);
327+
context.setVariable("metaChemistry", hasMetaChemistry ? mapToPrintMetaChemistry(allMetaChemistryRolls) : List.of());
328+
context.setVariable("bootyRolls", hasBooty ? mapToPrintBootyRoll(allBootyRolls) : List.of());
329+
context.setVariable("bootyWeapons", hasBooty ? mapBootyWeapons(allBootyRolls) : List.of());
300330
context.setVariable("pageSize", "%dmm %dmm".formatted(cardWidthInMm, cardHeightInMm));
301331
context.setVariable("cardWidthInMm", "%dmm".formatted(cardWidthInMm));
302332
context.setVariable("cardHeightInMm", "%dmm".formatted(cardHeightInMm));
303-
context.setVariable("primaryFontSize", template.primaryFontSize);
304-
context.setVariable("secondaryFontSize", template.secondaryFontSize);
333+
context.setVariable("useInch", useInch);
305334

306335
String savePath = "%s/%s.html".formatted(outputPath, fileName);
307336
try (FileWriter writer = new FileWriter(savePath)) {
@@ -311,6 +340,44 @@ public void writeCards(List<UnitOption> unitOptions,
311340
}
312341
}
313342

343+
private boolean hasAnySkill(List<UnitOption> unitOptions, String skillName) {
344+
return unitOptions.stream()
345+
.flatMap(u -> u.getAllTrooper().stream())
346+
.flatMap(t -> t.getProfiles().stream())
347+
.flatMap(s -> s.getSkills().stream())
348+
.anyMatch(s -> skillName.equals(s.getName()));
349+
}
350+
351+
private List<PrintDoubleTable> mapToPrintMetaChemistry(List<MetaChemistryRoll> metaChemistryRolls) {
352+
int halfCount = (metaChemistryRolls.size() / 2) - 1;
353+
List<PrintDoubleTable> printMetaChemistries = new ArrayList<>();
354+
for (int i = 0; i <= halfCount; i++) {
355+
MetaChemistryRoll r1 = metaChemistryRolls.get(i);
356+
MetaChemistryRoll r2 = metaChemistryRolls.get(halfCount + i + 1);
357+
printMetaChemistries.add(new PrintDoubleTable(r1.getRoll(), r1.getBonus(), r2.getRoll(), r2.getBonus()));
358+
}
359+
return printMetaChemistries;
360+
}
361+
362+
private List<PrintDoubleTable> mapToPrintBootyRoll(List<BootyRoll> bootyRolls) {
363+
int halfCount = (bootyRolls.size() / 2) - 1;
364+
List<PrintDoubleTable> doubleTables = new ArrayList<>();
365+
for (int i = 0; i <= halfCount; i++) {
366+
BootyRoll r1 = bootyRolls.get(i);
367+
BootyRoll r2 = bootyRolls.get(halfCount + i + 1);
368+
doubleTables.add(new PrintDoubleTable(r1.getRoll(), r1.getBonus(), r2.getRoll(), r2.getBonus()));
369+
}
370+
return doubleTables;
371+
}
372+
373+
private List<Weapon> mapBootyWeapons(List<BootyRoll> bootyRolls) {
374+
return bootyRolls.stream()
375+
.flatMap(b -> b.getWeapons().stream())
376+
.filter(Objects::nonNull)
377+
.distinct()
378+
.toList();
379+
}
380+
314381
private List<PrintHackingProgram> getUsedHackingPrograms(List<UnitOption> unitOptions, List<HackingProgram> allHackingPrograms) {
315382
Set<Integer> hackingDeviceIds = allHackingPrograms.stream()
316383
.flatMap(h -> Optional.ofNullable(h.getDeviceIds()).orElse(List.of()).stream())
@@ -353,14 +420,13 @@ private List<PrintHackingProgram> getUsedHackingPrograms(List<UnitOption> unitOp
353420

354421
@AllArgsConstructor
355422
public enum Template {
356-
a7_image("ColorAndOptionalImageCard", 99, 70, "6pt", "4pt"),
357-
a4_image("ColorAndOptionalImageCard", 297, 210, "18pt", "12pt"),
358-
letter_image("ColorAndOptionalImageCard", 279, 216, "18pt", "12pt"),
359-
card_bw("CardBW", 0, 0, "0", "0");
423+
a7_image("ColorAndOptionalImageCardSmall", 99, 70, 7),
424+
a4_image("ColorAndOptionalImageCard", 297, 210, 10),
425+
letter_image("ColorAndOptionalImageCard", 279, 216, 10),
426+
card_bw("CardBW", 0, 0, 0);
360427
final String fileName;
361428
final int widthInMm;
362429
final int heightInMm;
363-
final String primaryFontSize;
364-
final String secondaryFontSize;
430+
final int numberOfHackingProgramsPerCard;
365431
}
366432
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package de.twonirwana.infinity;
2+
3+
import lombok.Value;
4+
5+
@Value
6+
public class PrintDoubleTable {
7+
String roll1;
8+
String bonus1;
9+
String roll2;
10+
String bonus2;
11+
}

app/src/main/java/de/twonirwana/infinity/PrintUtils.java

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ public static String prettyWeaponName(Weapon weapon, boolean useInch) {
3838
}
3939
String out;
4040
if (weapon.getMode() != null) {
41-
out = "%s [%s]".formatted(weapon.getName(), weapon.getMode().replace(" Mode", ""));
41+
out = "%s [%s]".formatted(weapon.getName(), weapon.getMode()
42+
.replace("Anti-Material", "DA")
43+
.replace("Anti-materiel", "DA")
44+
.replace("Anti-Materiel", "DA")
45+
.replace(" Mode", ""));
4246
} else {
4347
out = weapon.getName();
4448
}
@@ -114,15 +118,17 @@ public static String getWeaponBurstWithExtra(UnitPrintCard unitPrintCard, Weapon
114118
if (weapon.getSkill() == Weapon.Skill.CC
115119
&& unitPrintCard.getMartialArtLevels() != null
116120
&& !"0".equals(unitPrintCard.getMartialArtLevels().getBurst())) {
117-
maBurstBonus = unitPrintCard.getMartialArtLevels().getBurst();
121+
maBurstBonus = unitPrintCard.getMartialArtLevels().getBurst()
122+
.replace("B, ", "")
123+
.replace("B", "");
118124
}
119125

120126
return weapon.getBurst() + Joiner.on("").join(burstExtra) + Joiner.on("").join(sdExtra) + maBurstBonus;
121127
}
122128

123129
public static String getWeaponPsWithExtra(TrooperProfile trooperProfile, Weapon weapon) {
124-
if (weapon.getDamage() == null || weapon.getDamage().equals("-") || weapon.getDamage().equals("*")) {
125-
return weapon.getDamage();
130+
if (weapon.getProbabilityOfSurvival() == null || weapon.getProbabilityOfSurvival().equals("*") || weapon.getProbabilityOfSurvival().equals("-")) {
131+
return weapon.getProbabilityOfSurvival();
126132
}
127133
String weaponSkill = getWeaponSkill(weapon);
128134
Optional<Integer> srExtra;
@@ -146,17 +152,39 @@ public static String getWeaponPsWithExtra(TrooperProfile trooperProfile, Weapon
146152
.map(Integer::parseInt)
147153
.findFirst();
148154

149-
int damage = psExtra.orElse(Integer.parseInt(weapon.getDamage()));
155+
int ps = psExtra.orElse(Integer.parseInt(weapon.getProbabilityOfSurvival()));
150156
if (srExtra.isPresent()) {
151-
damage = damage - srExtra.get();
157+
ps = ps - srExtra.get();
152158
}
153159

154160
if (psExtra.isPresent() || srExtra.isPresent()) {
155-
return damage + "*";
161+
return ps + "*";
162+
}
163+
return ps + "";
164+
}
165+
166+
public static String getWeaponSavingRollWithExtra(TrooperProfile trooperProfile, Weapon weapon) {
167+
String modifiedPs = getWeaponPsWithExtra(trooperProfile, weapon);
168+
if (weapon.getProbabilityOfSurvival() == null || weapon.getProbabilityOfSurvival().equals("*")) {
169+
return weapon.getProbabilityOfSurvival();
170+
} else if (weapon.getProbabilityOfSurvival().equals("-")) {
171+
if (weapon.getSaving().equals("-") || weapon.getSaving().isEmpty()) {
172+
return weapon.getProbabilityOfSurvival();
173+
}
174+
return getSavingRoll(weapon, null); //PARA weapons
156175
}
157176

158-
return damage + "";
177+
return getSavingRoll(weapon, modifiedPs);
178+
}
159179

180+
public static String getSavingRoll(Weapon weapon, String ps) {
181+
final String psOp;
182+
if (ps == null || "-".equals(ps)) {
183+
psOp = "";
184+
} else {
185+
psOp = ps + "+";
186+
}
187+
return "%sd ≤ %s%s".formatted(weapon.getSavingNum(), psOp, weapon.getSaving());
160188
}
161189

162190
public static String getRangeModifier(Weapon.RangeModifier rangeModifier, boolean useInch) {
@@ -253,14 +281,21 @@ static Optional<String> toSpecialDieExtra(ExtraValue extraValue) {
253281
return Optional.empty();
254282
}
255283

256-
public static String getRangeClass(TrooperProfile profile, String range, Map<String, String> rangeClassMap) {
284+
public static String getRangeClassWithOptionalXVisor(TrooperProfile profile, String range, Map<String, String> rangeClassMap) {
257285
if (range == null) {
258286
return null;
259287
}
260288
String updatedRange = applyXVisorToRangeModi(profile, range);
261289
return rangeClassMap.getOrDefault(updatedRange, "");
262290
}
263291

292+
public static String getRangeClass(String range, Map<String, String> rangeClassMap) {
293+
if (range == null) {
294+
return null;
295+
}
296+
return rangeClassMap.getOrDefault(range, "");
297+
}
298+
264299
public static String get20cmRangeName(boolean useInch) {
265300
return useInch ? "≤8" : "≤20";
266301
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package de.twonirwana.infinity;
2+
3+
import de.twonirwana.infinity.unit.api.Trooper;
4+
import de.twonirwana.infinity.unit.api.TrooperProfile;
5+
import de.twonirwana.infinity.unit.api.UnitOption;
6+
7+
import java.io.File;
8+
import java.io.IOException;
9+
import java.nio.file.Files;
10+
import java.nio.file.StandardOpenOption;
11+
import java.util.List;
12+
13+
public class UnitOwnershipCheckList {
14+
public static void main(String[] args) throws IOException {
15+
exportIntoCSV(new DatabaseImp());
16+
}
17+
18+
public static void exportIntoCSV(Database db) throws IOException {
19+
Sectorial sectorial = db.getAllSectorials().stream()
20+
.filter(s -> s.getId() == 603)
21+
.findFirst().orElseThrow();
22+
File csvOut = new File("out/Infinity_Unit_" + sectorial.getSlug() + ".csv");
23+
24+
if (csvOut.exists()) {
25+
csvOut.delete();
26+
}
27+
csvOut.createNewFile();
28+
Files.writeString(csvOut.toPath(), "ID\\Name\\AVA\n");
29+
db.getAllUnitsForSectorial(sectorial).stream()
30+
.filter(s -> !s.isReinforcementUnit())
31+
.filter(s -> !s.isMerc())
32+
.flatMap(u -> u.getAllTrooper()
33+
.stream().map(t -> unitData(u, t)))
34+
.distinct()
35+
.sorted()
36+
.forEach(s -> {
37+
try {
38+
Files.writeString(csvOut.toPath(), s, StandardOpenOption.APPEND);
39+
} catch (IOException e) {
40+
throw new RuntimeException(e);
41+
}
42+
});
43+
44+
}
45+
46+
private static String unitData(UnitOption unit, Trooper trooper) {
47+
List<Integer> ava = trooper.getProfiles().stream()
48+
.map(TrooperProfile::getAvailability)
49+
.distinct()
50+
.toList();
51+
if (ava.stream().filter(i -> i != -1) //no availability given
52+
.count() > 1) {
53+
throw new RuntimeException(unit.toString());
54+
}
55+
String name = unit.getUnitName();
56+
if (!unit.getPrimaryUnit().equals(trooper)) {
57+
name = trooper.getOptionName();
58+
}
59+
60+
return "%s\\%s\\%d\n".formatted(unit.getUnitId(), name, ava.getFirst());
61+
}
62+
}

0 commit comments

Comments
 (0)