summaryrefslogtreecommitdiff
path: root/src/main/java/simulator/engine/HeadlessSimulationEngine.java
blob: 36a64a7eeb9caf23fb78bf1fc5af49be533ed393 (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
108
109
110
111
112
113
114
115
116
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
        }
        
        // Calculate network delay
        long networkDelay = prefs.getLong("sim.network.delay");
        long variability = prefs.getLong("sim.network.variability");
        
        // Add random variability
        if (variability > 0) {
            long variance = (long)(Math.random() * variability * 2) - variability;
            networkDelay += variance;
        }
        
        // Ensure minimum delay
        if (networkDelay < 0) {
            networkDelay = 0;
        }
        
        // Calculate delivery time based on source process time
        return source.getTime() + networkDelay;
    }
    
    @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");
        
        // 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);
            taskManager.addTask(task);
            
            if (loging != null) {
                loging.log("Message scheduled for delivery to process " + 
                          receiverProcess.getProcessNum() + "; ID: " + 
                          message.getMessageID() + "; Time: " + deliveryTime);
            }
        }
    }
    
    /**
     * 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
    }
}