Skip to content

Commit

Permalink
#440: changed operand type conversion to copy-on-mutate, returning op…
Browse files Browse the repository at this point in the history
…erand (original or modified) and changed calling code to accommodate; added a UT to check that parameter conversion does not change actual parameter
  • Loading branch information
dbenn committed Jul 13, 2024
1 parent f6245bb commit 714e00e
Show file tree
Hide file tree
Showing 5 changed files with 432 additions and 454 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,189 +45,171 @@
/**
* This plugin allows a VeLa function to be used for observation transformation.
*/
public class VeLaObservationTransformer extends
ObservationTransformerPluginBase {

private VeLaInterpreter vela;
private boolean shouldInvokeDialog;
private boolean firstInvocation;

@Override
public String getDisplayName() {
return "VeLa Observation Transformer";
}

@Override
public String getDescription() {
return "VeLa observation transformation tool";
}

/**
* @see org.aavso.tools.vstar.plugin.IPlugin#getDocName()
*/
@Override
public String getDocName() {
return "VeLa Observation Transformer Plug-In.pdf";
}

@Override
public IUndoableAction createAction(ISeriesInfoProvider seriesInfo,
Set<SeriesType> series) {
return new IUndoableAction() {

private Map<SeriesType, List<Double>> mags = new HashMap<SeriesType, List<Double>>();
private Map<SeriesType, List<Double>> errs = new HashMap<SeriesType, List<Double>>();

@Override
public boolean execute(UndoableActionType type) {
boolean ok = true;

if (firstInvocation) {
Mediator.getInstance().getNewStarNotifier()
.addListener(getNewStarListener());

firstInvocation = false;
}

switch (type) {
case DO:
vela = new VeLaInterpreter();

Pair<Boolean, String> pair = invokeDialog(vela);

ok = pair.first;

if (ok && pair.second.trim().length() != 0) {
vela.program(pair.second);
} else {
break;
}
// Note: there being no unconditional break here is on purpose!
case REDO:
for (SeriesType seriesType : series) {
for (ValidObservation ob : seriesInfo
.getObservations(seriesType)) {
// Store old magnitude for undo
Magnitude magnitude = ob.getMagnitude();

if (mags.get(seriesType) == null) {
mags.put(seriesType, new ArrayList<Double>());
}
mags.get(seriesType).add(magnitude.getMagValue());

if (errs.get(seriesType) == null) {
errs.put(seriesType, new ArrayList<Double>());
}
errs.get(seriesType)
.add(magnitude.getUncertainty());

// Push an environment that makes the
// observation available to VeLa code...
vela.pushEnvironment(new VeLaValidObservationEnvironment(
ob));

// ...and call the function with the current
// observation's magnitude and error values.
String funCall = String.format("do()",
magnitude.getMagValue(),
magnitude.getUncertainty());

Optional<Operand> result = vela.program(funCall);

if (result.isPresent()
&& result.get().getType() == Type.LIST) {
Operand op = result.get();

if (op.listVal().size() == 2) {
boolean bothReal = op
.listVal()
.stream()
.allMatch(
x -> x.convert(Type.REAL) == Type.REAL);

if (bothReal) {
double mag = op.listVal().get(0)
.doubleVal();
double err = op.listVal().get(1)
.doubleVal();
ob.setMagnitude(new Magnitude(mag, err));
} else {
// Need two real numbers
ok = false;
}
} else {
// Need two real numbers
ok = false;
}
} else {
// Need (two real numbers in) a list
ok = false;
}

if (!ok) {
ok = false;
MessageBox.showErrorDialog("VeLa Error",
"Expected a 2 element result list");
}

// Push current observation's environment.
vela.popEnvironment();
}
}
break;
case UNDO:
// Undo by restoring magnitude and error values.
for (SeriesType seriesType : series) {
for (int i = 0; i < seriesInfo.getObservations(
seriesType).size(); i++) {
double mag = mags.get(seriesType).get(i);
double err = errs.get(seriesType).get(i);
ValidObservation ob = seriesInfo.getObservations(
seriesType).get(i);
ob.setMagnitude(new Magnitude(mag, err));
}
}
break;
}

return ok;
}

@Override
public String getDisplayString() {
return "VeLa observation transformation";
}
};
}

/**
* Get the new star listener for this plugin.
*/
protected Listener<NewStarMessage> getNewStarListener() {
return new Listener<NewStarMessage>() {
public void update(NewStarMessage info) {
shouldInvokeDialog = true;
}

public boolean canBeRemoved() {
return false;
}
};
}

/**
* Invoke dialog to request magnitude shift value.
*
* @return A pair containing a Boolean and string: whether the dialog's OK
* button was clicked and the VeLa code string.
*/
private Pair<Boolean, String> invokeDialog(VeLaInterpreter vela) {
VeLaDialog velaDialog = new VeLaDialog(
"Define VeLa function: do():list");

boolean ok = !velaDialog.isCancelled();
String code = velaDialog.getCode();

return new Pair<Boolean, String>(ok, code);
}
public class VeLaObservationTransformer extends ObservationTransformerPluginBase {

private VeLaInterpreter vela;
private boolean shouldInvokeDialog;
private boolean firstInvocation;

@Override
public String getDisplayName() {
return "VeLa Observation Transformer";
}

@Override
public String getDescription() {
return "VeLa observation transformation tool";
}

/**
* @see org.aavso.tools.vstar.plugin.IPlugin#getDocName()
*/
@Override
public String getDocName() {
return "VeLa Observation Transformer Plug-In.pdf";
}

@Override
public IUndoableAction createAction(ISeriesInfoProvider seriesInfo, Set<SeriesType> series) {
return new IUndoableAction() {

private Map<SeriesType, List<Double>> mags = new HashMap<SeriesType, List<Double>>();
private Map<SeriesType, List<Double>> errs = new HashMap<SeriesType, List<Double>>();

@Override
public boolean execute(UndoableActionType type) {
boolean ok = true;

if (firstInvocation) {
Mediator.getInstance().getNewStarNotifier().addListener(getNewStarListener());

firstInvocation = false;
}

switch (type) {
case DO:
vela = new VeLaInterpreter();

Pair<Boolean, String> pair = invokeDialog(vela);

ok = pair.first;

if (ok && pair.second.trim().length() != 0) {
vela.program(pair.second);
} else {
break;
}
// Note: there being no unconditional break here is on purpose!
case REDO:
for (SeriesType seriesType : series) {
for (ValidObservation ob : seriesInfo.getObservations(seriesType)) {
// Store old magnitude for undo
Magnitude magnitude = ob.getMagnitude();

if (mags.get(seriesType) == null) {
mags.put(seriesType, new ArrayList<Double>());
}
mags.get(seriesType).add(magnitude.getMagValue());

if (errs.get(seriesType) == null) {
errs.put(seriesType, new ArrayList<Double>());
}
errs.get(seriesType).add(magnitude.getUncertainty());

// Push an environment that makes the
// observation available to VeLa code...
vela.pushEnvironment(new VeLaValidObservationEnvironment(ob));

// ...and call the function with the current
// observation's magnitude and error values.
String funCall = String.format("do()", magnitude.getMagValue(), magnitude.getUncertainty());

Optional<Operand> result = vela.program(funCall);

if (result.isPresent() && result.get().getType() == Type.LIST) {
Operand op = result.get();

if (op.listVal().size() == 2) {
boolean bothReal = op.listVal().stream()
.allMatch(x -> x.convert(Type.REAL).getType() == Type.REAL);

if (bothReal) {
double mag = op.listVal().get(0).doubleVal();
double err = op.listVal().get(1).doubleVal();
ob.setMagnitude(new Magnitude(mag, err));
} else {
// Need two real numbers
ok = false;
}
} else {
// Need two real numbers
ok = false;
}
} else {
// Need (two real numbers in) a list
ok = false;
}

if (!ok) {
ok = false;
MessageBox.showErrorDialog("VeLa Error", "Expected a 2 element result list");
}

// Push current observation's environment.
vela.popEnvironment();
}
}
break;
case UNDO:
// Undo by restoring magnitude and error values.
for (SeriesType seriesType : series) {
for (int i = 0; i < seriesInfo.getObservations(seriesType).size(); i++) {
double mag = mags.get(seriesType).get(i);
double err = errs.get(seriesType).get(i);
ValidObservation ob = seriesInfo.getObservations(seriesType).get(i);
ob.setMagnitude(new Magnitude(mag, err));
}
}
break;
}

return ok;
}

@Override
public String getDisplayString() {
return "VeLa observation transformation";
}
};
}

/**
* Get the new star listener for this plugin.
*/
protected Listener<NewStarMessage> getNewStarListener() {
return new Listener<NewStarMessage>() {
public void update(NewStarMessage info) {
shouldInvokeDialog = true;
}

public boolean canBeRemoved() {
return false;
}
};
}

/**
* Invoke dialog to request magnitude shift value.
*
* @return A pair containing a Boolean and string: whether the dialog's OK
* button was clicked and the VeLa code string.
*/
private Pair<Boolean, String> invokeDialog(VeLaInterpreter vela) {
VeLaDialog velaDialog = new VeLaDialog("Define VeLa function: do():list");

boolean ok = !velaDialog.isCancelled();
String code = velaDialog.getCode();

return new Pair<Boolean, String>(ok, code);
}
}
Loading

0 comments on commit 714e00e

Please sign in to comment.