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
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ endif()
# Link our native node module against cmake-js, a few Windows-specific libraries, and libOpenCOR.

if(WIN32)
set(WINDOWS_LIBS crypt32 version wldap32 ws2_32)
set(WINDOWS_LIBS bcrypt crypt32 iphlpapi version wldap32 ws2_32)
endif()

target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
Expand Down
82 changes: 41 additions & 41 deletions bun.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"url": "git+https://github.com/opencor/webapp.git"
},
"type": "module",
"version": "0.20260529.0",
"version": "0.20260604.0",
"engines": {
"bun": ">=1.2.0"
},
Expand Down Expand Up @@ -89,10 +89,10 @@
"stylelint-config-standard": "^40.0.0",
"tailwindcss": "^4.3.0",
"tailwindcss-primeui": "^0.6.1",
"tar": "^7.5.15",
"tar": "^7.5.16",
"typescript": "^6.0.3",
"unplugin-vue-components": "^32.1.0",
"vite": "^7.3.2",
"vue-tsc": "^3.3.2"
"vue-tsc": "^3.3.3"
}
}
76 changes: 38 additions & 38 deletions src/renderer/bun.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions src/renderer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
},
"./style.css": "./dist/opencor.css"
},
"version": "0.20260529.0",
"libopencorVersion": "0.20260529.0",
"version": "0.20260604.0",
"libopencorVersion": "0.20260604.0",
"scripts": {
"build": "vite build && bun scripts/generate.version.js",
"build:lib": "vite build --config vite.lib.config.ts && bunx --bun vue-tsc --project tsconfig.lib.types.json",
Expand Down Expand Up @@ -94,6 +94,6 @@
"typescript": "^6.0.3",
"unplugin-vue-components": "^32.1.0",
"vite": "^7.3.2",
"vue-tsc": "^3.3.2"
"vue-tsc": "^3.3.3"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,25 @@
<i class="pi pi-clock text-primary"></i>
<div>
<h3 class="section-title">Simulation</h3>
<p class="section-description">Configure the starting and ending points of the simulation, as well as its point interval.</p>
<p class="section-description">Configure the initial, starting, and ending points of the simulation, as well as its point interval.</p>
</div>
</div>

<!-- Simulation settings -->

<div class="settings-form">
<div class="form-row">
<InputScientificNumber v-model="localSettings.simulation.initialPoint" class="form-field"
:label="`Initial point (${voiUnit})`"
size="small"
/>
<div class="form-field self-stretch">
<div v-if="!simulationSettingsIssues.length" class="form-field items-center text-muted-color text-sm">
<i class="pi pi-info-circle mr-2"></i>
<span>Data points between the initial and starting points will not be tracked.</span>
</div>
</div>
</div>
<div class="form-row">
<InputScientificNumber v-model="localSettings.simulation.startingPoint" class="form-field"
:label="`Starting point (${voiUnit})`"
Expand Down Expand Up @@ -905,6 +917,7 @@ import { useOpenCORToast } from '../OpenCORToast';

export interface ISimulationExperimentViewSettings {
simulation: {
initialPoint: number;
startingPoint: number;
endingPoint: number;
pointInterval: number;
Expand Down Expand Up @@ -1042,6 +1055,13 @@ const simulationSettingsIssues = vue.computed<locApi.IIssue[]>(() => {

const res: locApi.IIssue[] = [];

if (localSettings.value.simulation.initialPoint == null) {
res.push({
type: EIssueType.WARNING,
description: 'The initial point must be specified.'
});
}

if (localSettings.value.simulation.startingPoint == null) {
res.push({
type: EIssueType.WARNING,
Expand All @@ -1056,6 +1076,17 @@ const simulationSettingsIssues = vue.computed<locApi.IIssue[]>(() => {
});
}

if (
localSettings.value.simulation.initialPoint !== null &&
localSettings.value.simulation.startingPoint !== null &&
localSettings.value.simulation.startingPoint < localSettings.value.simulation.initialPoint
) {
res.push({
type: EIssueType.WARNING,
description: 'The starting point must be greater or equal to the initial point.'
});
}

if (
localSettings.value.simulation.startingPoint !== null &&
localSettings.value.simulation.endingPoint !== null &&
Expand Down Expand Up @@ -1500,6 +1531,7 @@ const onOk = () => {

emit('ok', {
simulation: {
initialPoint: localSettings.value.simulation.initialPoint,
startingPoint: localSettings.value.simulation.startingPoint,
endingPoint: localSettings.value.simulation.endingPoint,
pointInterval: localSettings.value.simulation.pointInterval
Expand Down
32 changes: 31 additions & 1 deletion src/renderer/src/components/views/SimulationExperimentView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@
@change="updatePlot()"
/>
</Fieldset>
<Fieldset v-if="preSimulationDuration" legend="Note" class="note">
The simulation was run for <br/>
<strong>{{ preSimulationDuration }} {{ interactiveInstanceTask ? interactiveInstanceTask.voiUnit() : '' }}</strong> prior to plotting.
</Fieldset>
</ScrollPanel>
</SplitterPanel>
<SplitterPanel :size="75">
Expand Down Expand Up @@ -208,6 +212,10 @@
</div>
</div>
</Fieldset>
<Fieldset v-if="preSimulationDuration" legend="Note" class="note">
The simulation was run for <br/>
<strong>{{ preSimulationDuration }} {{ interactiveInstanceTask ? interactiveInstanceTask.voiUnit() : '' }}</strong> prior to plotting.
</Fieldset>
</ScrollPanel>
</div>
<div class="relative flex flex-col grow h-full min-h-0">
Expand Down Expand Up @@ -674,6 +682,7 @@ const interactiveSettings = vue.computed<ISimulationExperimentViewSettings>(() =

return {
simulation: {
initialPoint: interactiveUniformTimeCourse.initialTime(),
startingPoint: interactiveUniformTimeCourse.outputStartTime(),
endingPoint: interactiveUniformTimeCourse.outputEndTime(),
pointInterval:
Expand All @@ -691,6 +700,12 @@ const interactiveSettings = vue.computed<ISimulationExperimentViewSettings>(() =
}
};
});
const preSimulationDuration = vue.computed<number>(() => {
const settings = interactiveSettings.value;

return settings.simulation.startingPoint - settings.simulation.initialPoint;
});

const interactiveOldSettings = vue.ref<string>(JSON.stringify(vue.toRaw(interactiveSettings.value)));

// A helper function to generate a unique external data ID based on a candidate name and a set of already used IDs, by
Expand Down Expand Up @@ -1845,7 +1860,7 @@ const onInteractiveSettingsOk = (settings: ISimulationExperimentViewSettings): v

const oldCvodeMaximumStep = interactiveCvode.maximumStep();

interactiveUniformTimeCourse.setInitialTime(settings.simulation.startingPoint);
interactiveUniformTimeCourse.setInitialTime(settings.simulation.initialPoint);
interactiveUniformTimeCourse.setOutputStartTime(settings.simulation.startingPoint);
interactiveUniformTimeCourse.setOutputEndTime(settings.simulation.endingPoint);
interactiveUniformTimeCourse.setNumberOfSteps(
Expand Down Expand Up @@ -1983,6 +1998,21 @@ if (common.isDesktop()) {
font-size: 1.25rem;
}

.note {
color: var(--p-text-muted-color);
margin-top: 0.5rem;
border: 1px dashed var(--p-content-border-color);
padding: 0 0.5rem 0.5rem 0.5rem !important;
text-align: center;
font-size: 0.75rem;
}

.note :deep(.p-fieldset-legend) {
font-size: 0.875rem;
padding-top: 0;
padding-bottom: 0;
}

:deep(.p-button-icon) {
font-size: 1.5rem;
}
Expand Down
17 changes: 10 additions & 7 deletions src/renderer/src/components/widgets/InputScientificNumber.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
:aria-valuenow="currentNumericValue ?? undefined"
:aria-valuemin="props.min ?? undefined"
:aria-valuemax="props.max ?? undefined"
v-keyfilter="{ pattern: /^[+-]?(\d*(\.\d*)?|\.\d*)([eE][+-]?\d*)?$/, validateOnly: true }"
v-keyfilter="{ pattern: /^[+-]?(\d*(\.\d*)?|\.\d*)([eE][+-]?\d*)?$/ }"
@update:model-value="onUpdateModelValue"
@focus="onFocus"
@blur="onBlur"
Expand Down Expand Up @@ -149,7 +149,7 @@ const currentNumericValue = vue.computed<number | undefined>(() => {
const inferredNumericValue = vue.computed<number>(() => {
const source = internalValue.value === '' ? (props.modelValue ?? props.min ?? 0) : parseFloat(internalValue.value);

return Number.isFinite(source) ? source : (props.modelValue ?? props.min ?? 0);
return Number.isFinite(source) ? source : (props.modelValue ?? 0);
});
const activeButton = vue.ref<'increment' | 'decrement' | null>(null);
const minBoundary = vue.computed<boolean>(() => {
Expand Down Expand Up @@ -213,12 +213,17 @@ const onPaste = (event: ClipboardEvent) => {

event.preventDefault();

const pastedValue = clipboardData.getData('text') || '';
const rawPastedValue = clipboardData.getData('text') || '';

if (pastedValue === '') {
if (rawPastedValue === '') {
return;
}

// Normalise Unicode minus signs to ASCII hyphen-minus so that negative numbers copied from text sources using
// typographic minus signs are handled correctly.

const pastedValue = rawPastedValue.replace(/[\u2212\u2213]/g, '-');

// Try to extract a valid scientific-number pattern from the pasted text. Failing that, try to sanitise the pasted
// text first by removing invalid characters, then extracting a scientific-number pattern from it.
// Note: the pattern used in the keyfilter is suitable for validating a scientific number when typing it in, but here
Expand Down Expand Up @@ -393,9 +398,7 @@ const spin = (direction: 1 | -1): boolean => {

const inferredBaseValue =
internalValue.value === '' ? (props.modelValue ?? props.min ?? 0) : parseFloat(internalValue.value);
const safeCurrentValue = Number.isFinite(inferredBaseValue)
? inferredBaseValue
: (props.modelValue ?? props.min ?? 0);
const safeCurrentValue = Number.isFinite(inferredBaseValue) ? inferredBaseValue : (props.modelValue ?? 0);
const nextValue = validateValue(addWithPrecision(safeCurrentValue, step * direction));

if (!Number.isFinite(nextValue) || nextValue === safeCurrentValue) {
Expand Down
Loading