summaryrefslogtreecommitdiff
path: root/src/main/java/simulator/engine/HeadlessSimulationEngine.java
blob: 921cbb17c6c6b93fc5431390ba76b8bf9f6af644 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package simulator.engine;

import core.*;
import prefs.VSPrefs;
import events.internal.VSMessageReceiveEvent;
import simulator.VSLogging;

/**
 * Headless implementation of the simulation engine that runs without any GUI dependencies.
 * This engine focuses purely on simulation logic without any visualization concerns.
 */
public class HeadlessSimulationEngine extends AbstractSimulationEngine {
    
    public HeadlessSimulationEngine(VSPrefs prefs, VSLogging loging) {
        super(prefs, loging);
    }
    
    @Override
    protected long calculateDeliveryTime(VSMessage message) {
        // Get source process
        VSInternalProcess source = (VSInternalProcess) message.getSendingProcess();
        
        if (source == null) {
            return time; // Deliver immediately if process not found
        }
        
        // Use the process's getDurationTime method to get the message duration
        // This respects the message.sendingtime.min and message.sendingtime.max preferences
        long durationTime = source.getDurationTime();
        
        // Calculate delivery time based on source process's global time + duration
        return source.getGlobalTime() + durationTime;
    }
    
    @Override
    protected void scheduleMessageDelivery(VSMessage message, long deliveryTime) {
        // In DS-Sim, messages are broadcast to all processes
        VSInternalProcess sendingProcess = (VSInternalProcess) message.getSendingProcess();
        boolean recvOwn = prefs.getBoolean("sim.message.own.recv");
        
        // Debug logging removed to avoid affecting test behavior
        
        // Schedule delivery to all processes
        for (VSInternalProcess receiverProcess : processes) {
            if (receiverProcess.equals(sendingProcess)) {
                // Only deliver to self if configured
                if (!recvOwn) {
                    continue;
                }
            }
            
            // Create receive event for this process
            VSMessageReceiveEvent receiveEvent = new VSMessageReceiveEvent(message);
            VSTask task = new VSTask(deliveryTime, receiverProcess, receiveEvent, VSTask.GLOBAL);
            
            // Important: Use the task manager from the receiving process's simulator canvas
            // This ensures tasks are added to the correct task manager that's being run
            VSTaskManager actualTaskManager = receiverProcess.getSimulatorCanvas().getTaskManager();
            actualTaskManager.addTask(task);
            
            // Debug logging removed
        }
    }
    
    /**
     * Run one simulation step.
     * This method advances time and executes all tasks scheduled for the current time.
     */
    public void runStep() {
        if (isPaused || hasFinished) {
            return;
        }
        
        // Sync all process times
        for (VSInternalProcess process : processes) {
            process.syncTime(time);
        }
        
        // Run tasks for current time
        taskManager.runTasks(time, 0, time - 1);
        
        // Check if simulation has finished
        // TODO: Implement proper finish detection
        // For now, rely on external control or time limits
    }
    
    /**
     * Run the simulation for a specified duration.
     * @param duration Duration in milliseconds
     */
    public void runFor(long duration) {
        long endTime = time + duration;
        
        while (time < endTime && !hasFinished) {
            runStep();
            time++;
        }
    }
    
    /**
     * Check if any protocols are still active.
     * TODO: Implement this when protocol tracking is available
     */
    private boolean hasActiveProtocols() {
        return false; // For now, assume no active protocols
    }
}