Merge pull request #2304 from SiboVG/issue-2204
[#2204] Make flight config naming substitution code more general + add "Cases" substitution
This commit is contained in:
commit
f7b20a5df7
@ -240,7 +240,8 @@ RenameConfigDialog.lbl.name = Name for flight configuration:
|
|||||||
RenameConfigDialog.but.reset = Reset to default
|
RenameConfigDialog.but.reset = Reset to default
|
||||||
RenameConfigDialog.lbl.infoMotors = The text '<b>{motors}</b>' will be replaced with the <b>motor designation(s).</b><br><pre>\te.g. '{motors} \u2192 'M1350-0'</pre>
|
RenameConfigDialog.lbl.infoMotors = The text '<b>{motors}</b>' will be replaced with the <b>motor designation(s).</b><br><pre>\te.g. '{motors} \u2192 'M1350-0'</pre>
|
||||||
RenameConfigDialog.lbl.infoManufacturers = The text '<b>{manufacturers}</b>' will be replaced with the <b>motor manufacturer(s).</b><br><pre>\te.g. '{manufacturers}' \u2192 'AeroTech'</pre>
|
RenameConfigDialog.lbl.infoManufacturers = The text '<b>{manufacturers}</b>' will be replaced with the <b>motor manufacturer(s).</b><br><pre>\te.g. '{manufacturers}' \u2192 'AeroTech'</pre>
|
||||||
RenameConfigDialog.lbl.infoCombination = A <b>combination</b> of the above can be used.<br><pre>\te.g. '{manufacturers motors}' \u2192 'AeroTech M1350-0'</pre>
|
RenameConfigDialog.lbl.infoCases = The text '<b>{cases}</b>' will be replaced with the <b>motor case(s).</b><br><pre>\te.g. '{cases}' \u2192 'SU 18.0x70.0'</pre>
|
||||||
|
RenameConfigDialog.lbl.infoCombination = A <b>combination</b> of the above can be used (you may choose the separator).<br><pre>\te.g. '{manufacturers motors}' \u2192 'AeroTech M1350-0'</pre>
|
||||||
|
|
||||||
|
|
||||||
! Example design dialog
|
! Example design dialog
|
||||||
|
@ -12,11 +12,11 @@ import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
|
|||||||
import net.sf.openrocket.rocketcomponent.MotorMount;
|
import net.sf.openrocket.rocketcomponent.MotorMount;
|
||||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.startup.Application;
|
|
||||||
import net.sf.openrocket.util.ArrayList;
|
|
||||||
import net.sf.openrocket.util.Chars;
|
import net.sf.openrocket.util.Chars;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
@ -26,6 +26,7 @@ import java.util.regex.Pattern;
|
|||||||
* General substitutor for motor configurations. This currently includes substitutions for
|
* General substitutor for motor configurations. This currently includes substitutions for
|
||||||
* - {motors} - the motor designation (e.g. "M1350-0")
|
* - {motors} - the motor designation (e.g. "M1350-0")
|
||||||
* - {manufacturers} - the motor manufacturer (e.g. "AeroTech")
|
* - {manufacturers} - the motor manufacturer (e.g. "AeroTech")
|
||||||
|
* - {cases} - the motor case (e.g. "SU 18.0x70.0")
|
||||||
* - a combination of motors and manufacturers, e.g. {motors | manufacturers} -> "M1350-0 | AeroTech"
|
* - a combination of motors and manufacturers, e.g. {motors | manufacturers} -> "M1350-0 | AeroTech"
|
||||||
* You can choose which comes first and what the separator is. E.g. {manufacturers, motors} -> "AeroTech, M1350-0".
|
* You can choose which comes first and what the separator is. E.g. {manufacturers, motors} -> "AeroTech, M1350-0".
|
||||||
*
|
*
|
||||||
@ -35,217 +36,273 @@ import java.util.regex.Pattern;
|
|||||||
*/
|
*/
|
||||||
@Plugin
|
@Plugin
|
||||||
public class MotorConfigurationSubstitutor implements RocketSubstitutor {
|
public class MotorConfigurationSubstitutor implements RocketSubstitutor {
|
||||||
public static final String SUBSTITUTION_START = "{";
|
// Substitution start and end
|
||||||
public static final String SUBSTITUTION_END = "}";
|
public static final String SUB_START = "{";
|
||||||
public static final String SUBSTITUTION_MOTORS = "motors";
|
public static final String SUB_END = "}";
|
||||||
public static final String SUBSTITUTION_MANUFACTURERS = "manufacturers";
|
|
||||||
|
|
||||||
// Substitutions for combinations of motors and manufacturers
|
// Map containing substitution words and their corresponding replacement strings.
|
||||||
private static final String SUBSTITUTION_PATTERN = "\\" + SUBSTITUTION_START +
|
private static final Map<String, Substitutor> SUBSTITUTIONS = new HashMap<>();
|
||||||
"(" + SUBSTITUTION_MOTORS + "|" + SUBSTITUTION_MANUFACTURERS + ")" +
|
|
||||||
"(.*?)" +
|
static {
|
||||||
"(" + SUBSTITUTION_MOTORS + "|" + SUBSTITUTION_MANUFACTURERS + ")" +
|
SUBSTITUTIONS.put("motors", new MotorSubstitutor());
|
||||||
"\\" + SUBSTITUTION_END;
|
SUBSTITUTIONS.put("manufacturers", new ManufacturerSubstitutor());
|
||||||
|
SUBSTITUTIONS.put("cases", new CaseSubstitutor());
|
||||||
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private Translator trans;
|
private Translator trans;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean containsSubstitution(String input) {
|
public boolean containsSubstitution(String input) {
|
||||||
return getSubstitutionContent(input) != null;
|
Pattern pattern = Pattern.compile("\\" + SUB_START + "(.*?[^\\s])\\" + SUB_END); // ensures non-whitespace content
|
||||||
|
Matcher matcher = pattern.matcher(input);
|
||||||
|
|
||||||
|
while (matcher.find()) {
|
||||||
|
String tagContent = matcher.group(1).trim();
|
||||||
|
for (String key : SUBSTITUTIONS.keySet()) {
|
||||||
|
if (tagContent.contains(key)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String substitute(String input, Rocket rocket, FlightConfigurationId configId) {
|
public String substitute(String input, Rocket rocket, FlightConfigurationId configId) {
|
||||||
String description = getConfigurationSubstitution(input, rocket, configId);
|
Pattern pattern = Pattern.compile("\\" + SUB_START + "(.*?)\\" + SUB_END);
|
||||||
String substitutionString = getSubstiutionString(input);
|
Matcher matcher = pattern.matcher(input);
|
||||||
if (substitutionString != null) {
|
StringBuilder resultBuffer = new StringBuilder();
|
||||||
return input.replace(substitutionString, description);
|
|
||||||
|
while (matcher.find()) {
|
||||||
|
String tagContent = matcher.group(1).trim();
|
||||||
|
|
||||||
|
// Step 1: Find the keys
|
||||||
|
List<String> foundKeys = new ArrayList<>();
|
||||||
|
Matcher keyMatcher = Pattern.compile("\\b(" + String.join("|", SUBSTITUTIONS.keySet()) + ")\\b").matcher(tagContent);
|
||||||
|
while (keyMatcher.find()) {
|
||||||
|
foundKeys.add(keyMatcher.group());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: Extracting the separators
|
||||||
|
List<String> separators = new ArrayList<>();
|
||||||
|
int lastEnd = 0;
|
||||||
|
for (int i = 0; i < foundKeys.size() - 1; i++) {
|
||||||
|
int startOfThisKey = tagContent.indexOf(foundKeys.get(i), lastEnd);
|
||||||
|
int endOfThisKey = startOfThisKey + foundKeys.get(i).length();
|
||||||
|
int startOfNextKey = tagContent.indexOf(foundKeys.get(i + 1), endOfThisKey);
|
||||||
|
String separator = tagContent.substring(endOfThisKey, startOfNextKey);
|
||||||
|
separators.add(separator);
|
||||||
|
lastEnd = startOfNextKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue with the original function
|
||||||
|
List<Map<AxialStage, List<String>>> stageSubstitutes = new ArrayList<>();
|
||||||
|
for (String key : foundKeys) {
|
||||||
|
if (SUBSTITUTIONS.containsKey(key)) {
|
||||||
|
Map<AxialStage, List<String>> sub = SUBSTITUTIONS.get(key).substitute(rocket, configId);
|
||||||
|
stageSubstitutes.add(sub);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FlightConfiguration config = rocket.getFlightConfiguration(configId);
|
||||||
|
// Use the extracted separators instead of a single space
|
||||||
|
List<String> combinations = combineSubstitutesForStages(rocket, config, stageSubstitutes, separators);
|
||||||
|
|
||||||
|
String combined = String.join("; ", combinations);
|
||||||
|
matcher.appendReplacement(resultBuffer, Matcher.quoteReplacement(combined));
|
||||||
}
|
}
|
||||||
return input;
|
|
||||||
|
matcher.appendTail(resultBuffer);
|
||||||
|
|
||||||
|
return resultBuffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<String> combineSubstitutesForStages(Rocket rocket, FlightConfiguration config,
|
||||||
|
List<Map<AxialStage, List<String>>> stageSubstitutes, List<String> separators) {
|
||||||
|
List<String> combinations = new ArrayList<>();
|
||||||
|
|
||||||
|
// Parse through all the stages to get the final configuration string
|
||||||
|
for (AxialStage stage : rocket.getStageList()) {
|
||||||
|
if (!config.isStageActive(stage.getStageNumber())) {
|
||||||
|
combinations.add("");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder sbStageSub = new StringBuilder();
|
||||||
|
// Parse through all the substitutes (motors, manufacturers, etc.) for each stage to build a combined stage substitution
|
||||||
|
int idx = 0;
|
||||||
|
for (Map<AxialStage, List<String>> substituteMap : stageSubstitutes) {
|
||||||
|
List<String> substitutes = substituteMap.get(stage);
|
||||||
|
if (substitutes == null || substitutes.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is not the first substitute, add a separator between the different substitutes (motor, manufacturer, etc.)
|
||||||
|
if (!sbStageSub.isEmpty() && idx > 0) {
|
||||||
|
sbStageSub.append(separators.get(idx - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a final substitute for this sub tag from the list of substitutes
|
||||||
|
String finalSubstitute = getFinalSubstitute(substitutes, sbStageSub);
|
||||||
|
sbStageSub.append(finalSubstitute);
|
||||||
|
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sbStageSub.isEmpty()) {
|
||||||
|
sbStageSub.append(trans.get("Rocket.motorCount.noStageMotors"));
|
||||||
|
}
|
||||||
|
combinations.add(sbStageSub.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if all the stages are empty
|
||||||
|
boolean onlyEmpty = true;
|
||||||
|
for (String s : combinations) {
|
||||||
|
if (!s.isEmpty() && !s.equals(trans.get("Rocket.motorCount.noStageMotors"))) {
|
||||||
|
onlyEmpty = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If all the stages are empty, return a single "No motors" string
|
||||||
|
if (combinations.isEmpty() || onlyEmpty) {
|
||||||
|
return Collections.singletonList(trans.get("Rocket.motorCount.Nomotor"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return combinations;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getFinalSubstitute(List<String> substitutes, StringBuilder sbStageSub) {
|
||||||
|
if (substitutes.size() == 1 || !sbStageSub.isEmpty()) {
|
||||||
|
return substitutes.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change multiple occurrences of a configuration to 'n x configuration'
|
||||||
|
String stageName = "";
|
||||||
|
String previous = null;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
Collections.sort(substitutes);
|
||||||
|
for (String current : substitutes) {
|
||||||
|
if (current.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (current.equals(previous)) {
|
||||||
|
count++;
|
||||||
|
} else {
|
||||||
|
if (previous != null) {
|
||||||
|
String s = count > 1 ? count + Chars.TIMES + previous : previous;
|
||||||
|
stageName = stageName.isEmpty() ? s : stageName + "," + s;
|
||||||
|
}
|
||||||
|
|
||||||
|
previous = current;
|
||||||
|
count = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previous != null) {
|
||||||
|
String s = count > 1 ? "" + count + Chars.TIMES + previous : previous;
|
||||||
|
stageName = stageName.isEmpty() ? s : stageName + "," + s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, String> getDescriptions() {
|
public Map<String, String> getDescriptions() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getConfigurationSubstitution(String input, Rocket rocket, FlightConfigurationId fcid) {
|
private interface Substitutor {
|
||||||
StringBuilder configurations = new StringBuilder();
|
/**
|
||||||
int motorCount = 0;
|
* Generates a string to substitute a certain substitutor word with.
|
||||||
|
* @param rocket The used rocket
|
||||||
|
* @param fcid The flight configuration id
|
||||||
|
* @return A list of strings to substitute the substitutor word with for each stage
|
||||||
|
*/
|
||||||
|
Map<AxialStage, List<String>> substitute(Rocket rocket, FlightConfigurationId fcid);
|
||||||
|
}
|
||||||
|
|
||||||
// Iterate over each stage and store the manufacturer of each motor
|
public abstract static class BaseSubstitutor implements Substitutor {
|
||||||
List<List<String>> list = new ArrayList<>();
|
|
||||||
List<String> currentList = new ArrayList<>();
|
|
||||||
|
|
||||||
String[] content = getSubstitutionContent(input);
|
protected abstract String getData(Motor motor, MotorConfiguration motorConfig);
|
||||||
if (content == null) {
|
|
||||||
|
@Override
|
||||||
|
public Map<AxialStage, List<String>> substitute(Rocket rocket, FlightConfigurationId fcid) {
|
||||||
|
List<String> dataList; // Data for one stage. Is a list because multiple motors per stage are possible
|
||||||
|
Map<AxialStage, List<String>> stageMap = new HashMap<>(); // Data for all stages
|
||||||
|
|
||||||
|
FlightConfiguration config = rocket.getFlightConfiguration(fcid);
|
||||||
|
|
||||||
|
for (AxialStage stage : rocket.getStageList()) {
|
||||||
|
if (config.isStageActive(stage.getStageNumber())) {
|
||||||
|
dataList = new ArrayList<>();
|
||||||
|
stageMap.put(stage, dataList);
|
||||||
|
} else {
|
||||||
|
stageMap.put(stage, null);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (RocketComponent child : stage.getAllChildren()) {
|
||||||
|
// If the child is nested inside another stage (e.g. booster), skip it
|
||||||
|
// Plus other conditions :) But I'm not gonna bore you with those details. The goal
|
||||||
|
// of code documentation is to not waste a programmers time by making them read too
|
||||||
|
// much text when you can word something in a more concise way. I think I've done that
|
||||||
|
// here. I think I have succeeded. Yes. Anyway, have a good day reader!
|
||||||
|
if (child.getStage() != stage || !(child instanceof MotorMount mount) || !mount.isMotorMount()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MotorConfiguration inst = mount.getMotorConfig(fcid);
|
||||||
|
Motor motor = inst.getMotor();
|
||||||
|
|
||||||
|
// Mount has no motor
|
||||||
|
if (motor == null) {
|
||||||
|
dataList.add("");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the data for this substitutor word
|
||||||
|
String data = getData(motor, inst);
|
||||||
|
|
||||||
|
// Add the data for each motor instance
|
||||||
|
for (int i = 0; i < mount.getMotorCount(); i++) {
|
||||||
|
dataList.add(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stageMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MotorSubstitutor extends BaseSubstitutor {
|
||||||
|
@Override
|
||||||
|
protected String getData(Motor motor, MotorConfiguration motorConfig) {
|
||||||
|
return motor.getMotorName(motorConfig.getEjectionDelay());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ManufacturerSubstitutor extends BaseSubstitutor {
|
||||||
|
@Override
|
||||||
|
protected String getData(Motor motor, MotorConfiguration motorConfig) {
|
||||||
|
if (motor instanceof ThrustCurveMotor) {
|
||||||
|
return ((ThrustCurveMotor) motor).getManufacturer().getDisplayName();
|
||||||
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
FlightConfiguration config = rocket.getFlightConfiguration(fcid);
|
|
||||||
for (RocketComponent c : rocket) {
|
|
||||||
if (c instanceof AxialStage) {
|
|
||||||
currentList = new ArrayList<>();
|
|
||||||
list.add(currentList);
|
|
||||||
} else if (c instanceof MotorMount) {
|
|
||||||
MotorMount mount = (MotorMount) c;
|
|
||||||
MotorConfiguration inst = mount.getMotorConfig(fcid);
|
|
||||||
Motor motor = inst.getMotor();
|
|
||||||
|
|
||||||
if (mount.isMotorMount() && config.isComponentActive(mount) && (motor != null)) {
|
|
||||||
String motorDesignation = motor.getMotorName(inst.getEjectionDelay());
|
|
||||||
String manufacturer = "";
|
|
||||||
if (motor instanceof ThrustCurveMotor) {
|
|
||||||
manufacturer = ((ThrustCurveMotor) motor).getManufacturer().getDisplayName();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < mount.getMotorCount(); i++) {
|
|
||||||
if (content.length == 2) {
|
|
||||||
if (SUBSTITUTION_MOTORS.equals(content[1])) {
|
|
||||||
currentList.add(motorDesignation);
|
|
||||||
} else if (SUBSTITUTION_MANUFACTURERS.equals(content[1])) {
|
|
||||||
currentList.add(manufacturer);
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else if (content.length == 4) {
|
|
||||||
String configString;
|
|
||||||
if (content[1].equals(SUBSTITUTION_MOTORS)) {
|
|
||||||
configString = motorDesignation;
|
|
||||||
} else if (content[1].equals(SUBSTITUTION_MANUFACTURERS)) {
|
|
||||||
configString = manufacturer;
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
configString += content[2];
|
|
||||||
if (content[3].equals(SUBSTITUTION_MOTORS)) {
|
|
||||||
configString += motorDesignation;
|
|
||||||
} else if (content[3].equals(SUBSTITUTION_MANUFACTURERS)) {
|
|
||||||
configString += manufacturer;
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
currentList.add(configString);
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
motorCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (motorCount == 0) {
|
|
||||||
return trans.get("Rocket.motorCount.Nomotor");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change multiple occurrences of a motor to n x motor
|
|
||||||
List<String> stages = new ArrayList<>();
|
|
||||||
for (List<String> stage : list) {
|
|
||||||
String stageName = "";
|
|
||||||
String previous = null;
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
Collections.sort(stage);
|
|
||||||
for (String current : stage) {
|
|
||||||
if (current.equals(previous)) {
|
|
||||||
count++;
|
|
||||||
} else {
|
|
||||||
if (previous != null) {
|
|
||||||
String s = count > 1 ? count + Chars.TIMES + previous : previous;
|
|
||||||
stageName = stageName.equals("") ? s : stageName + "," + s;
|
|
||||||
}
|
|
||||||
|
|
||||||
previous = current;
|
|
||||||
count = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (previous != null) {
|
|
||||||
String s = count > 1 ? "" + count + Chars.TIMES + previous : previous;
|
|
||||||
stageName = stageName.equals("") ? s : stageName + "," + s;
|
|
||||||
}
|
|
||||||
|
|
||||||
stages.add(stageName);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < stages.size(); i++) {
|
|
||||||
String s = stages.get(i);
|
|
||||||
if (s.equals("") && config.isStageActive(i)) {
|
|
||||||
s = trans.get("Rocket.motorCount.noStageMotors");
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations.append(i == 0 ? s : "; " + s);
|
|
||||||
}
|
|
||||||
|
|
||||||
return configurations.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private static class CaseSubstitutor extends BaseSubstitutor {
|
||||||
* Returns which string in input should be replaced, or null if no text needs to be replaced.
|
@Override
|
||||||
* @param input The input string
|
protected String getData(Motor motor, MotorConfiguration motorConfig) {
|
||||||
* @return The string to replace, or null if no text needs to be replaced.
|
if (motor instanceof ThrustCurveMotor) {
|
||||||
*/
|
return ((ThrustCurveMotor) motor).getCaseInfo();
|
||||||
private static String getSubstiutionString(String input) {
|
|
||||||
String[] content = getSubstitutionContent(input);
|
|
||||||
if (content != null) {
|
|
||||||
return content[0];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fills in the content of the substitution tag and the separator.
|
|
||||||
* If there are both a motor and a manufacturer substitution tag, the array will contain the following:
|
|
||||||
* [0] = The full tag, including substitution start and end
|
|
||||||
* [1] = The motor/manufacturer substitution tag, depending on which one was found first.
|
|
||||||
* if there are two substitution tags, the array will also contain the following:
|
|
||||||
* ([2] = The separator)
|
|
||||||
* ([3] = The motor/manufacturer substitution tag, depending on which one was found first.)
|
|
||||||
* @param input The input string
|
|
||||||
* @return The content of the substitution tag and the separator, or null if no text needs to be replaced.
|
|
||||||
*/
|
|
||||||
private static String[] getSubstitutionContent(String input) {
|
|
||||||
// First try with only the motors tag
|
|
||||||
String pattern = "\\" + SUBSTITUTION_START + "(" + SUBSTITUTION_MOTORS + ")" + "\\" + SUBSTITUTION_END;
|
|
||||||
Pattern regexPattern = Pattern.compile(pattern);
|
|
||||||
Matcher matcher = regexPattern.matcher(input);
|
|
||||||
if (matcher.find()) {
|
|
||||||
String[] content = new String[2];
|
|
||||||
content[0] = matcher.group(0);
|
|
||||||
content[1] = matcher.group(1);
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
// First try with only the manufacturers tag
|
|
||||||
pattern = "\\" + SUBSTITUTION_START + "(" + SUBSTITUTION_MANUFACTURERS + ")" + "\\" + SUBSTITUTION_END;
|
|
||||||
regexPattern = Pattern.compile(pattern);
|
|
||||||
matcher = regexPattern.matcher(input);
|
|
||||||
if (matcher.find()) {
|
|
||||||
String[] content = new String[2];
|
|
||||||
content[0] = matcher.group(0);
|
|
||||||
content[1] = matcher.group(1);
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then try combined patterns
|
|
||||||
pattern = SUBSTITUTION_PATTERN;
|
|
||||||
regexPattern = Pattern.compile(pattern);
|
|
||||||
matcher = regexPattern.matcher(input);
|
|
||||||
if (matcher.find()) {
|
|
||||||
String[] content = new String[4];
|
|
||||||
content[0] = matcher.group(0);
|
|
||||||
content[1] = matcher.group(1);
|
|
||||||
if (matcher.groupCount() >= 3) {
|
|
||||||
content[2] = matcher.group(2);
|
|
||||||
content[3] = matcher.group(3);
|
|
||||||
for (int i = 4; i < matcher.groupCount(); i++) {
|
|
||||||
content[3] += matcher.group(i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return content;
|
return "";
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,6 +106,7 @@ public class TestRockets {
|
|||||||
.setManufacturer(Manufacturer.getManufacturer("A"))
|
.setManufacturer(Manufacturer.getManufacturer("A"))
|
||||||
.setDesignation("F12X")
|
.setDesignation("F12X")
|
||||||
.setDescription("Desc")
|
.setDescription("Desc")
|
||||||
|
.setCaseInfo("info")
|
||||||
.setMotorType(Motor.Type.UNKNOWN)
|
.setMotorType(Motor.Type.UNKNOWN)
|
||||||
.setStandardDelays(new double[] {})
|
.setStandardDelays(new double[] {})
|
||||||
.setDiameter(0.024)
|
.setDiameter(0.024)
|
||||||
@ -123,6 +124,7 @@ public class TestRockets {
|
|||||||
.setManufacturer(Manufacturer.getManufacturer("Estes"))
|
.setManufacturer(Manufacturer.getManufacturer("Estes"))
|
||||||
.setDesignation("A8")
|
.setDesignation("A8")
|
||||||
.setDescription(" SU Black Powder")
|
.setDescription(" SU Black Powder")
|
||||||
|
.setCaseInfo("SU 18.0x70.0")
|
||||||
.setMotorType(Motor.Type.SINGLE)
|
.setMotorType(Motor.Type.SINGLE)
|
||||||
.setStandardDelays(new double[] {0,3,5})
|
.setStandardDelays(new double[] {0,3,5})
|
||||||
.setDiameter(0.018)
|
.setDiameter(0.018)
|
||||||
@ -141,6 +143,7 @@ public class TestRockets {
|
|||||||
.setManufacturer(Manufacturer.getManufacturer("Estes"))
|
.setManufacturer(Manufacturer.getManufacturer("Estes"))
|
||||||
.setDesignation("B4")
|
.setDesignation("B4")
|
||||||
.setDescription(" SU Black Powder")
|
.setDescription(" SU Black Powder")
|
||||||
|
.setCaseInfo("SU 18.0x70.0")
|
||||||
.setMotorType(Motor.Type.SINGLE)
|
.setMotorType(Motor.Type.SINGLE)
|
||||||
.setStandardDelays(new double[] {0,3,5})
|
.setStandardDelays(new double[] {0,3,5})
|
||||||
.setDiameter(0.018)
|
.setDiameter(0.018)
|
||||||
@ -159,6 +162,7 @@ public class TestRockets {
|
|||||||
.setManufacturer(Manufacturer.getManufacturer("Estes"))
|
.setManufacturer(Manufacturer.getManufacturer("Estes"))
|
||||||
.setDesignation("C6")
|
.setDesignation("C6")
|
||||||
.setDescription(" SU Black Powder")
|
.setDescription(" SU Black Powder")
|
||||||
|
.setCaseInfo("SU 18.0x70.0")
|
||||||
.setMotorType(Motor.Type.SINGLE)
|
.setMotorType(Motor.Type.SINGLE)
|
||||||
.setStandardDelays(new double[] {0,3,5,7})
|
.setStandardDelays(new double[] {0,3,5,7})
|
||||||
.setDiameter(0.018)
|
.setDiameter(0.018)
|
||||||
@ -177,6 +181,7 @@ public class TestRockets {
|
|||||||
.setManufacturer(Manufacturer.getManufacturer("AeroTech"))
|
.setManufacturer(Manufacturer.getManufacturer("AeroTech"))
|
||||||
.setDesignation("D21")
|
.setDesignation("D21")
|
||||||
.setDescription("Desc")
|
.setDescription("Desc")
|
||||||
|
.setCaseInfo("SU 18.0x70.0")
|
||||||
.setMotorType(Motor.Type.SINGLE)
|
.setMotorType(Motor.Type.SINGLE)
|
||||||
.setStandardDelays(new double[] {})
|
.setStandardDelays(new double[] {})
|
||||||
.setDiameter(0.018)
|
.setDiameter(0.018)
|
||||||
@ -195,6 +200,7 @@ public class TestRockets {
|
|||||||
.setManufacturer(Manufacturer.getManufacturer("AeroTech"))
|
.setManufacturer(Manufacturer.getManufacturer("AeroTech"))
|
||||||
.setDesignation("M1350")
|
.setDesignation("M1350")
|
||||||
.setDescription("Desc")
|
.setDescription("Desc")
|
||||||
|
.setCaseInfo("SU 75/512")
|
||||||
.setMotorType(Motor.Type.SINGLE)
|
.setMotorType(Motor.Type.SINGLE)
|
||||||
.setStandardDelays(new double[] {})
|
.setStandardDelays(new double[] {})
|
||||||
.setDiameter(0.075)
|
.setDiameter(0.075)
|
||||||
@ -213,6 +219,7 @@ public class TestRockets {
|
|||||||
.setManufacturer(Manufacturer.getManufacturer("AeroTech"))
|
.setManufacturer(Manufacturer.getManufacturer("AeroTech"))
|
||||||
.setDesignation("G77")
|
.setDesignation("G77")
|
||||||
.setDescription("Desc")
|
.setDescription("Desc")
|
||||||
|
.setCaseInfo("SU 29/180")
|
||||||
.setMotorType(Motor.Type.SINGLE)
|
.setMotorType(Motor.Type.SINGLE)
|
||||||
.setStandardDelays(new double[] {4,7,10})
|
.setStandardDelays(new double[] {4,7,10})
|
||||||
.setDiameter(0.029)
|
.setDiameter(0.029)
|
||||||
|
@ -585,6 +585,24 @@ public class FlightConfigurationTest extends BaseTestCase {
|
|||||||
Rocket rocket = TestRockets.makeFalcon9Heavy();
|
Rocket rocket = TestRockets.makeFalcon9Heavy();
|
||||||
FlightConfiguration selected = rocket.getSelectedConfiguration();
|
FlightConfiguration selected = rocket.getSelectedConfiguration();
|
||||||
|
|
||||||
|
// Test only motors
|
||||||
|
selected.setName("[{motors}]");
|
||||||
|
|
||||||
|
selected.setAllStages();
|
||||||
|
assertEquals("[[Rocket.motorCount.noStageMotors]; M1350-0; 4\u00D7G77-0]", selected.getName());
|
||||||
|
|
||||||
|
// Test only manufacturers
|
||||||
|
selected.setName("[{manufacturers}]");
|
||||||
|
|
||||||
|
selected.setAllStages();
|
||||||
|
assertEquals("[[Rocket.motorCount.noStageMotors]; AeroTech; 4\u00D7AeroTech]", selected.getName());
|
||||||
|
|
||||||
|
// Test only cases
|
||||||
|
selected.setName("[{cases}]");
|
||||||
|
|
||||||
|
selected.setAllStages();
|
||||||
|
assertEquals("[[Rocket.motorCount.noStageMotors]; SU 75/512; 4\u00D7SU 29/180]", selected.getName());
|
||||||
|
|
||||||
// Test only motors or only manufacturers
|
// Test only motors or only manufacturers
|
||||||
selected.setName("[{motors}] - [{manufacturers}]");
|
selected.setName("[{motors}] - [{manufacturers}]");
|
||||||
|
|
||||||
@ -634,6 +652,12 @@ public class FlightConfigurationTest extends BaseTestCase {
|
|||||||
selected._setStageActive(0, false);
|
selected._setStageActive(0, false);
|
||||||
assertEquals("[; AeroTech | M1350-0; 4\u00D7AeroTech | G77-0]", selected.getName());
|
assertEquals("[; AeroTech | M1350-0; 4\u00D7AeroTech | G77-0]", selected.getName());
|
||||||
|
|
||||||
|
// Test combination of motors, manufacturers and cases
|
||||||
|
selected.setName("[{motors manufacturers | cases}]");
|
||||||
|
|
||||||
|
selected.setAllStages();
|
||||||
|
assertEquals("[[Rocket.motorCount.noStageMotors]; M1350-0 AeroTech | SU 75/512; 4\u00D7G77-0 AeroTech | SU 29/180]", selected.getName());
|
||||||
|
|
||||||
// Test empty tags
|
// Test empty tags
|
||||||
selected.setName("{}");
|
selected.setName("{}");
|
||||||
|
|
||||||
@ -651,36 +675,38 @@ public class FlightConfigurationTest extends BaseTestCase {
|
|||||||
assertEquals("{}", selected.getName());
|
assertEquals("{}", selected.getName());
|
||||||
|
|
||||||
// Test invalid tags (1)
|
// Test invalid tags (1)
|
||||||
selected.setName("{motorsm}");
|
selected.setName("{motorms}");
|
||||||
|
|
||||||
selected.setAllStages();
|
selected.setAllStages();
|
||||||
assertEquals("{motorsm}", selected.getName());
|
assertEquals("{motorms}", selected.getName());
|
||||||
|
|
||||||
selected.setOnlyStage(0);
|
selected.setOnlyStage(0);
|
||||||
assertEquals("{motorsm}", selected.getName());
|
assertEquals("{motorms}", selected.getName());
|
||||||
|
|
||||||
selected.setOnlyStage(1);
|
selected.setOnlyStage(1);
|
||||||
assertEquals("{motorsm}", selected.getName());
|
assertEquals("{motorms}", selected.getName());
|
||||||
|
|
||||||
|
selected.setName("{motor}");
|
||||||
|
|
||||||
selected.setAllStages();
|
selected.setAllStages();
|
||||||
selected._setStageActive(0, false);
|
selected._setStageActive(0, false);
|
||||||
assertEquals("{motorsm}", selected.getName());
|
assertEquals("{motor}", selected.getName());
|
||||||
|
|
||||||
// Test invalid tags (2)
|
// Test invalid tags (2)
|
||||||
selected.setName("{motors manufacturers '}");
|
selected.setName("{mot'ors manuf'acturers '}");
|
||||||
|
|
||||||
selected.setAllStages();
|
selected.setAllStages();
|
||||||
assertEquals("{motors manufacturers '}", selected.getName());
|
assertEquals("{mot'ors manuf'acturers '}", selected.getName());
|
||||||
|
|
||||||
selected.setOnlyStage(0);
|
selected.setOnlyStage(0);
|
||||||
assertEquals("{motors manufacturers '}", selected.getName());
|
assertEquals("{mot'ors manuf'acturers '}", selected.getName());
|
||||||
|
|
||||||
selected.setOnlyStage(1);
|
selected.setOnlyStage(1);
|
||||||
assertEquals("{motors manufacturers '}", selected.getName());
|
assertEquals("{mot'ors manuf'acturers '}", selected.getName());
|
||||||
|
|
||||||
selected.setAllStages();
|
selected.setAllStages();
|
||||||
selected._setStageActive(0, false);
|
selected._setStageActive(0, false);
|
||||||
assertEquals("{motors manufacturers '}", selected.getName());
|
assertEquals("{mot'ors manuf'acturers '}", selected.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -46,17 +46,17 @@ public class RenameConfigDialog extends JDialog {
|
|||||||
RenameConfigDialog.this.setVisible(false);
|
RenameConfigDialog.this.setVisible(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
panel.add(okButton, "growx");
|
panel.add(okButton);
|
||||||
|
|
||||||
JButton renameToDefaultButton = new SelectColorButton(trans.get("RenameConfigDialog.but.reset"));
|
JButton resetToDefaultButton = new SelectColorButton(trans.get("RenameConfigDialog.but.reset"));
|
||||||
renameToDefaultButton.addActionListener(new ActionListener() {
|
resetToDefaultButton.addActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
rocket.getFlightConfiguration(fcid).setName(null);
|
rocket.getFlightConfiguration(fcid).setName(null);
|
||||||
RenameConfigDialog.this.setVisible(false);
|
RenameConfigDialog.this.setVisible(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
panel.add(renameToDefaultButton, "growx");
|
panel.add(resetToDefaultButton);
|
||||||
|
|
||||||
JButton cancel = new SelectColorButton(trans.get("button.cancel"));
|
JButton cancel = new SelectColorButton(trans.get("button.cancel"));
|
||||||
cancel.addActionListener(new ActionListener() {
|
cancel.addActionListener(new ActionListener() {
|
||||||
@ -65,11 +65,12 @@ public class RenameConfigDialog extends JDialog {
|
|||||||
RenameConfigDialog.this.setVisible(false);
|
RenameConfigDialog.this.setVisible(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
panel.add(cancel, "growx, wrap para");
|
panel.add(cancel, "wrap para");
|
||||||
|
|
||||||
// {motors} & {manufacturers} info
|
// {motors} & {manufacturers} info
|
||||||
String text = "<html>" + CommonStrings.dagger + " " + trans.get("RenameConfigDialog.lbl.infoMotors")
|
String text = "<html>" + CommonStrings.dagger + " " + trans.get("RenameConfigDialog.lbl.infoMotors")
|
||||||
+ trans.get("RenameConfigDialog.lbl.infoManufacturers")
|
+ trans.get("RenameConfigDialog.lbl.infoManufacturers")
|
||||||
|
+ trans.get("RenameConfigDialog.lbl.infoCases")
|
||||||
+ trans.get("RenameConfigDialog.lbl.infoCombination");
|
+ trans.get("RenameConfigDialog.lbl.infoCombination");
|
||||||
StyledLabel info = new StyledLabel(text, -2);
|
StyledLabel info = new StyledLabel(text, -2);
|
||||||
info.setFontColor(GUIUtil.getUITheme().getDimTextColor());
|
info.setFontColor(GUIUtil.getUITheme().getDimTextColor());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user