Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Viewport and SimulatedRegion position to be the center instead of a corner #675

Open
wants to merge 10 commits into
base: dev
Choose a base branch
from

Conversation

Dassderdie
Copy link
Collaborator

@Dassderdie Dassderdie commented Feb 16, 2023

  • Refactor Viewport and SimulatedRegion position to be the center instead of a corner
  • Simplified GeometryHelper API by removing Positions<>
  • The ResizeRectangleInteraction now has a minimum size and prevents flipping of the rectangle

…ad of a corner

* Simplified GeometryHelper API by removing `Positions`
* The ResizeRectangleInteraction now has a minimumSize and preventsflipping of the rectangle
@Dassderdie Dassderdie self-assigned this Feb 16, 2023
@Dassderdie Dassderdie marked this pull request as ready for review February 16, 2023 22:50
@Dassderdie Dassderdie enabled auto-merge (squash) February 16, 2023 22:55
Copy link
Contributor

@benn02 benn02 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but it still has unresolved conflicts, please resolve them for approval

Comment on lines 106 to 107
const oldXLength = draggedCorner - originCorner;
const newXLength = mouseCoordinate - originCorner;
Copy link
Contributor

@Greenscreen23 Greenscreen23 Feb 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the X from those variable names, as it is also used for Y coordinates.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Comment on lines 15 to 36
case '[Viewport] Add viewport':
if (action.viewport.position.type === 'coordinates') {
oldViewportSizes[action.viewport.id] = cloneDeep(
action.viewport.size
);
}
migrateRectangularElement(action.viewport);
break;
case '[Viewport] Move viewport': {
const oldViewportSize = oldViewportSizes[action.viewportId];
if (oldViewportSize) {
migratePosition(action.targetPosition, oldViewportSize);
}
break;
}
case '[Viewport] Resize viewport': {
const oldViewportSize = cloneDeep(action.newSize);
oldViewportSizes[action.viewportId] = oldViewportSize;
migratePosition(action.targetPosition, oldViewportSize);
migrateSize(action.newSize);
break;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about actions related to simulated regions?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added them.

Copy link
Contributor

@lukasrad02 lukasrad02 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Besides the aspects mentioned by Benildur and Lukas, I'm fine with this.

Comment on lines +80 to +90
/**
* Migrates the position of a rectangular element to the center of the element.
*
* This migration is not accurate for previously "flipped" viewports (height and/or width was negative).
* To catch this case, access to the size of the viewport before this migration would be required.
*
* @param migratedSize the size of the element after it had been migrated to the center
*/
function migratePositionWithMigratedSize(coordinates: any, migratedSize: any) {
migratePosition(coordinates, migratedSize);
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The move-actions only include the targetPosition. However, the "real" position of the element was defined by its position and size (because of negative height/width). This information gets lost during this migration. Therefore, the current migration system doesn't allow for an accurate migration in these cases.

I believe this to be acceptable, as this is an edge case that would only result in some regions in imported exercise histories being at slightly different positions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depending on the position and size, the location can differ a lot, even with values that are realistic to occur in an exercise. Since resizing of viewports and simulated regions is an operation of exercise creation, this is a breaking change according to our definition (see https://github.com/hpi-sam/digital-fuesim-manv#versions).

We though about a solution for this problem in our team. Our idea was to keep a log which "optical" corner of the rectangle the current location refers to. This log could be updated from the newSize of each resize action before migrating it (so one can deduct the corner from the sign of the width and height). With the information about the corner, one could restore the exact desired position and extent on the map after a move action.

What do you think about this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depending on the position and size, the location can differ a lot, even with values that are realistic to occur in an exercise. Since resizing of viewports and simulated regions is an operation of exercise creation, this is a breaking change according to our definition (see https://github.com/hpi-sam/digital-fuesim-manv#versions).

This should only be a breaking change for exercises with history. With my current implementation, states should be losslessly converted to the new definition. Only certain Move-Actions in the history should pose problems.

We though about a solution for this problem in our team. Our idea was to keep a log which "optical" corner of the rectangle the current location refers to. This log could be updated from the newSize of each resize action before migrating it (so one can deduct the corner from the sign of the width and height). With the information about the corner, one could restore the exact desired position and extent on the map after a move action.

What do you think about this?

If I understand it correctly, this would be similar to my previous approach (look at the migration in this PR from a few weeks ago), in which I kept a log of all old viewport sizes. (Though, I believe I forgot to populate the log with the previous sizes of viewports which didn't have a resize or create action.) To still do this, one would have to adjust the migration system again, to realise this log.

Alternatively one could create two migrations for this change and use the first migration to write this log in the intermediate exerciseState and perform the lossless migration. The second one would only remove this log from the state again.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depending on the position and size, the location can differ a lot, even with values that are realistic to occur in an exercise. Since resizing of viewports and simulated regions is an operation of exercise creation, this is a breaking change according to our definition (see https://github.com/hpi-sam/digital-fuesim-manv#versions).

This should only be a breaking change for exercises with history. With my current implementation, states should be losslessly converted to the new definition. Only certain Move-Actions in the history should pose problems.

At the moment, our definition only differentiates between prepared and played exercises. But prepared exercises can also be exported with history which I think is a legitimate choice.

We though about a solution for this problem in our team. Our idea was to keep a log which "optical" corner of the rectangle the current location refers to. This log could be updated from the newSize of each resize action before migrating it (so one can deduct the corner from the sign of the width and height). With the information about the corner, one could restore the exact desired position and extent on the map after a move action.
What do you think about this?

If I understand it correctly, this would be similar to my previous approach (look at the migration in this PR from a few weeks ago), in which I kept a log of all old viewport sizes. [...]

Yes, this is what we though of

To still do this, one would have to adjust the migration system again, to realise this log.

Alternatively one could create two migrations for this change and use the first migration to write this log in the intermediate exerciseState and perform the lossless migration. The second one would only remove this log from the state again.

Probably not the cleanest solution, but the log could also be saved in a local variable in your typescript file, requiring no changes to the migration system

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the moment, our definition only differentiates between prepared and played exercises. But prepared exercises can also be exported with history, which I think is a legitimate choice.

What is the purpose of not yet played exports with a history? Do you want to keep the option to undo and redo changes in the prepared exercise?

Probably not the cleanest solution, but the log could also be saved in a local variable in your typescript file, requiring no changes to the migration system

This would introduce strange side effects to this particular migration function.
You would have to manually empty the log if the exerciseId of the intermediaryState changes. In addition, you would have to rely on the call of the state-migration function to be directly followed by all the action migration calls of the same exercise (first migrating the initial states of all exercises, and then all their actions would result in incorrect migrations). Otherwise, you would have to save all logs for all exercises, which would be a memory leak.
I would rather opt for my approach as this state introduction could set a bad precedent for future programmers.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of not yet played exports with a history? Do you want to keep the option to undo and redo changes in the prepared exercise?

Yes, this is what I've though of. Trainers might have complex scenarios and then just omit the last couple of actions to create an easier version of them. (Although I think there is no option to do this from the user interface yet).

Another reason for me is that I would expect some people to be in doubt of the meaning of the export options "Kompletter Verlauf" (full history) and "Aktueller Zustand" (current state) and export their prepared exercises as full history just to be safe.

I would rather opt for my approach as this state introduction could set a bad precedent for future programmers.

Are you talking about the two migrations or about the changes to the migration system?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is what I've thought of. Trainers might have complex scenarios and then just omit the last couple of actions to create an easier version of them. (Although I think there is no option to do this from the user interface yet).

No, there is no interface for this yet. This could also get a bit tricky with the UX, as you would often not see any changes if you undo something globally (e.g., changing a vehicle name that isn't visible).

Another reason for me is that I would expect some people to be in doubt of the meaning of the export options "Kompletter Verlauf" (full history) and "Aktueller Zustand" (current state) and export their prepared exercises as full history just to be safe.

One could also disallow exporting the history if the exercise hasn't been started yet.

But I'm ok with keeping the current definition and postponing any decisions about this indefinitely for now due to low ROI ^^

Are you talking about the two migrations or about the changes to the migration system?

The two migrations.

A new migration system would need more discussion and would probably also only make sense after we have more experience with the needs of migrations. The last refactoring removed some capabilities (adding actions, combining actions, reordering actions, in general, more context-aware operations on actions). Though I believe all except adding actions can be worked around via two consecutive migrations.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The two migrations.

Okay, sounds good.

A new migration system would need more discussion and would probably also only make sense after we have more experience with the needs of migrations. The last refactoring removed some capabilities (adding actions, combining actions, reordering actions, in general, more context-aware operations on actions). Though I believe all except adding actions can be worked around via two consecutive migrations.

@Nils1729 might be the right person if you'd like to go into the discussion on the migration system (not for this PR but in general)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Refactor Viewport and SimulatedRegion position to be the center instead of a corner
4 participants