From 651dc754b8fa32758e56defb3af4b0203a30dce9 Mon Sep 17 00:00:00 2001 From: Leandro Afonso Date: Tue, 14 Oct 2025 02:20:24 +0100 Subject: [PATCH 1/4] personal branch --- TODO.md | 175 ++++++++++++++++++ main/src/main/java/sd/CruzamentoServer.java | 34 ---- main/src/main/java/sd/Entry.java | 7 + main/src/main/java/sd/Main.java | 7 - main/src/main/java/sd/Semaforo.java | 47 ----- main/src/main/java/sd/Veiculo.java | 35 ---- main/target/classes/sd/CruzamentoServer.class | Bin 792 -> 0 bytes main/target/classes/sd/Entry.class | Bin 0 -> 526 bytes main/target/classes/sd/Main.class | Bin 522 -> 0 bytes main/target/classes/sd/Semaforo.class | Bin 1591 -> 0 bytes main/target/classes/sd/Veiculo.class | Bin 1648 -> 0 bytes 11 files changed, 182 insertions(+), 123 deletions(-) create mode 100644 TODO.md delete mode 100644 main/src/main/java/sd/CruzamentoServer.java create mode 100644 main/src/main/java/sd/Entry.java delete mode 100644 main/src/main/java/sd/Main.java delete mode 100644 main/src/main/java/sd/Semaforo.java delete mode 100644 main/src/main/java/sd/Veiculo.java delete mode 100644 main/target/classes/sd/CruzamentoServer.class create mode 100644 main/target/classes/sd/Entry.class delete mode 100644 main/target/classes/sd/Main.class delete mode 100644 main/target/classes/sd/Semaforo.class delete mode 100644 main/target/classes/sd/Veiculo.class diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..001c208 --- /dev/null +++ b/TODO.md @@ -0,0 +1,175 @@ +### Compreender os Conceitos Fundamentais + +Primeiro, as tecnologias e paradigmas chave necessários para este projeto devem ser totalmente compreendidos. + +- **Processos vs. Threads:** O projeto especifica o uso de ambos. + + - **Processos (para Cruzamentos)** são programas independentes, cada um com o seu próprio espaço de memória. Em Java, cada cruzamento será provavelmente executado como uma aplicação Java separada (uma instância distinta da JVM). + + - **Threads (para Semáforos)** existem _dentro_ de um processo e partilham memória. Isto é adequado para os semáforos, pois eles precisam de ser coordenados e partilhar dados (como filas de veículos) dentro do mesmo cruzamento. + +- **Comunicação Entre Processos (IPC - Inter-Process Communication):** Como os cruzamentos são processos separados, é necessário um método para que eles comuniquem. **Sockets** são o método especificado. Quando um veículo sai de um cruzamento (ex: `Cr1`) e vai para outro (ex: `Cr2`), o processo `Cr1` precisa de enviar uma mensagem contendo os dados do veículo para o processo `Cr2` através de uma conexão por socket. + +- **Simulação de Eventos Discretos (DES - Discrete-Event Simulation):** Este é o paradigma de simulação que deve ser utilizado. Em vez de o tempo fluir continuamente, o relógio da simulação salta de um evento para o seguinte. + + - Um **evento** é um objeto que representa algo que acontece num ponto específico no tempo (ex: "Veículo A chega ao Cr2 no tempo 15.7s"). + + - Uma **lista de eventos** central, frequentemente uma fila de prioridades, será necessária para armazenar eventos futuros, ordenados pelo seu timestamp. O ciclo principal da simulação retira o próximo evento da lista, processa-o e adiciona quaisquer novos eventos que resultem dele. + +- **Processo de Poisson:** Para o modelo "mais realista" de chegadas de veículos, é especificado um processo de Poisson. A principal conclusão é que o tempo _entre_ chegadas consecutivas de veículos segue uma **distribuição exponencial**. Em Java, este intervalo pode ser gerado usando `Math.log(1 - Math.random()) / -lambda`, onde `lambda` (λi​) é a taxa de chegada especificada. + + +--- + +### Uma Sugestão de Arquitetura de Alto Nível + +Abaixo, é apresentada uma possível estrutura para a aplicação distribuída. Pode ser vista como um conjunto de programas independentes que comunicam através de uma rede. + +1. **Processo Coordenador/Gerador (1 Processo):** + + - **Propósito:** Iniciar a simulação, gerar veículos e gerir o relógio global da simulação ou os critérios de paragem. + + - **Responsabilidades:** + + - Lê a configuração da simulação (ex: carga de tráfego λi​, tempos dos semáforos). + + - Gera veículos de acordo com o modelo selecionado (intervalo fixo ou processo de Poisson). + + - Atribui a cada novo veículo um percurso com base na distribuição uniforme especificada. + + - Injeta o veículo no sistema enviando uma mensagem para o primeiro processo de cruzamento no seu percurso (ex: de um ponto de entrada E1 para Cr1). + +2. **Processos de Cruzamento (5 Processos):** + + - **Propósito:** Simular cada cruzamento (`Cr1` a `Cr5`) como um processo distinto. + + - **Responsabilidades:** + + - Escuta por veículos a chegar de outros processos. + + - Gere as filas de veículos para os seus semáforos. + + - Executa múltiplas **threads de Semáforo** internamente. + + - Coordena estas threads para garantir que apenas uma direção de tráfego está aberta a cada momento. + + - Quando um veículo atravessa, é encaminhado para o processo seguinte no seu percurso. + + - Envia periodicamente as suas estatísticas (ex: comprimentos atuais das filas) para o Servidor do Dashboard. + +3. **Processo de Nó de Saída (1 Processo):** + + - **Propósito:** Representar o ponto de saída `S` e atuar como um coletor de dados para estatísticas globais. + + - **Responsabilidades:** + + - Recebe veículos que completaram o seu percurso. + + - Calcula métricas globais como o tempo total de viagem (tempo de permanência) para cada veículo. + + - Agrega e calcula as estatísticas finais (ex: tempo de viagem mínimo, máximo e médio por tipo de veículo). + + - Envia estas estatísticas globais para o Servidor do Dashboard. + +4. **Processo do Servidor do Dashboard (1 Processo):** + + - **Propósito:** Agregar e exibir todos os dados da simulação em tempo real. + + - **Responsabilidades:** + + - Abre um socket de servidor e escuta por dados a chegar de todos os processos de Cruzamento e de Saída. + + - Armazena e atualiza as estatísticas à medida que chegam. + + - Apresenta os dados numa interface de utilizador, que deve exibir métricas e ser atualizada durante a simulação. + + +--- + +### Plano + +Nem tudo deve ser construído de uma só vez. Os seguintes passos incrementais são recomendados. + +#### **Passo 1: Modelação e Classes Principais (Não-distribuído)** + +Antes de escrever qualquer lógica complexa, as estruturas de dados devem ser definidas. Devem ser criados Plain Old Java Objects (POJOs) para: + +- `Veiculo`: Com atributos como um identificador único, tipo, tempo de entrada e o percurso realizado. Deve ser tornado `Serializable` para que possa ser enviado através de sockets. + +- `Evento`: Com atributos como um timestamp e o tipo de evento (ex: `VEHICLE_ARRIVAL`), bem como dados associados. + +- `Semaforo`: Para conter o seu estado (`VERDE`/`VERMELHO`) e a fila de veículos. + +- `Cruzamento`: Para conter os seus semáforos e a lógica operacional. + + +#### **Passo 2: Construir um Protótipo de Processo Único** + +Este é um passo crucial. Sockets e processos devem ser deixados de lado por agora para construir toda a simulação numa única aplicação Java. + +- Deve ser criado um ciclo de simulação central baseado numa fila de prioridades para objetos `Evento`. + +- Todos os objetos `Cruzamento` e `Semaforo` devem ser instanciados. + +- A lógica principal deve ser tornada funcional: veículos a moverem-se entre filas, semáforos a mudar de estado e estatísticas básicas a serem recolhidas. + +- **Objetivo:** Uma simulação totalmente funcional e não-distribuída. Isto torna a depuração significativamente mais fácil. + + +#### **Passo 3: Distribuir os Cruzamentos** + +O protótipo pode agora ser convertido num sistema distribuído. + +- A classe `Cruzamento` deve ser tornada executável como uma aplicação Java autónoma (com um método `main`). Serão lançadas cinco instâncias, uma para cada cruzamento. + +- Devem ser configurados sockets TCP para comunicação. Cada processo de cruzamento precisa de saber o endereço/porta dos vizinhos para os quais pode enviar veículos. + +- Um **protocolo de comunicação** claro deve ser definido. Por exemplo, quando `Cr1` envia um veículo para `Cr2`, o objeto `Veiculo` é serializado e escrito no socket conectado a `Cr2`. O processo `Cr2` terá uma thread dedicada para escutar estas conexões de entrada. + + +#### **Passo 4: Implementar as Threads dos Semáforos** + +Dentro de cada processo `Cruzamento`, os semáforos devem ser implementados como threads. + +- O principal desafio aqui é a **sincronização**. As threads dos semáforos num único cruzamento partilham as filas de veículos. + +- As ferramentas de concorrência do Java (como `synchronized`, `ReentrantLock`, `Semaphore`) devem ser usadas para garantir que apenas um semáforo pode estar verde para um percurso conflituante e que o acesso às filas partilhadas é seguro (thread-safe). + + +#### **Passo 5: Implementar o Dashboard** + +- O processo `DashboardServer` deve ser criado. Ele irá escutar numa porta específica por estatísticas a chegar. + +- Nos processos `Cruzamento` e `Saida`, deve ser adicionado um mecanismo para enviar periodicamente um resumo das suas estatísticas atuais para o Servidor do Dashboard. + +- A UI deve ser construída para exibir estes dados em tempo real. + + +#### **Passo 6: Testes e Análise** + +Assim que o sistema completo estiver a funcionar, as experiências exigidas pela descrição do projeto podem ser realizadas. + +- A simulação deve ser executada com diferentes taxas de chegada de veículos para simular cargas baixas, médias e altas. + +- Diferentes políticas de temporização dos semáforos devem ser testadas para medir o seu impacto no congestionamento. + +- Diferentes algoritmos de seleção de percurso e o seu impacto no desempenho do sistema devem ser avaliados. + +- Para cada cenário, a simulação deve ser executada várias vezes para recolher estatísticas fiáveis (médias, desvios padrão, intervalos de confiança), conforme solicitado. + + +#### **Passo 7: Escrever o Relatório** + +À medida que cada passo é concluído, deve ser documentado. Isto tornará a escrita do relatório final muito mais fácil. Todos os pontos mencionados nas secções "Entrega" e "Critérios de Avaliação" devem ser abordados. + +--- + +### OBS: + +- **Começar de Forma Simples:** O protótipo de processo único (Passo 2) evitará grandes dificuldades mais tarde. + +- **Protocolo de Comunicação:** O protocolo de mensagens deve ser definido o mais cedo possível. A informação exata que um processo envia para outro deve ser clara//simples//consistente. + +- **Debugging:** Debugging de sistemas distribuídos podem ser difíceis. Uma framework de logging (como Log4j 2 ou SLF4J) pode ser usada para registar eventos//alterações de estado nos diferentes processos. + +- **Configuração:** Valores como endereços IP, números de porta ou parâmetros da simulação não devem ser "hardcoded". Um ficheiro de configuração (ex: um ficheiro `.properties` ou `.json`) torna a aplicação mais fácil de executar e testar. \ No newline at end of file diff --git a/main/src/main/java/sd/CruzamentoServer.java b/main/src/main/java/sd/CruzamentoServer.java deleted file mode 100644 index 1d84a00..0000000 --- a/main/src/main/java/sd/CruzamentoServer.java +++ /dev/null @@ -1,34 +0,0 @@ -package sd; - -import java.io.IOException; -import java.net.ServerSocket; -import java.net.Socket; - -public class CruzamentoServer { - public static void main(String[] args) { - // ... Inicializa Semáforos (Threads) ... - // ... Inicializa as Estruturas de Dados ... - - try (ServerSocket serverSocket = new ServerSocket(portaDoCruzamento)) { - while (true) { - Socket clienteSocket = serverSocket.accept(); - // Cria uma Thread de atendimento para lidar com o Veículo/Cliente - new Thread(new AtendenteVeiculo(clienteSocket)).start(); - } - } catch (IOException e) { /* ... */ } - } - - // Método chamado pelo AtendenteVeiculo para gerenciar o tráfego - public synchronized boolean tentarPassar(Veiculo veiculo, String direcao) { - // 1. Veículo entra na fila da direção - // 2. Verifica o estado do semáforo da direção: - Semaforo semaforo = getSemaforo(direcao); - semaforo.esperarPeloVerde(); // O Veículo fica bloqueado se for vermelho - - // 3. Após o verde: - // - Remove da fila - // - Permite a passagem (envia resposta de volta ao Veículo cliente) - // 4. Envia estatística de passagem ao Simulador Principal (Cliente TCP) - return true; - } -} diff --git a/main/src/main/java/sd/Entry.java b/main/src/main/java/sd/Entry.java new file mode 100644 index 0000000..b1d76a6 --- /dev/null +++ b/main/src/main/java/sd/Entry.java @@ -0,0 +1,7 @@ +package sd; + +public class Entry { + public static void main(String[] args) { + System.out.println("Hello, World!"); + } +} diff --git a/main/src/main/java/sd/Main.java b/main/src/main/java/sd/Main.java deleted file mode 100644 index 137fc4e..0000000 --- a/main/src/main/java/sd/Main.java +++ /dev/null @@ -1,7 +0,0 @@ -package sd; - -public class Main { - public static void main(String[] args) { - System.out.println("Hello world!"); - } -} \ No newline at end of file diff --git a/main/src/main/java/sd/Semaforo.java b/main/src/main/java/sd/Semaforo.java deleted file mode 100644 index 8f1d8ad..0000000 --- a/main/src/main/java/sd/Semaforo.java +++ /dev/null @@ -1,47 +0,0 @@ -package sd; - -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; - -public class Semaforo extends Thread { - // ... atributos ... - private final Lock semaforoLock; // Para sincronizar acesso ao estado - private final Condition verdeCondition; // Para Veículos esperarem pelo verde - - public Semaforo(...) { - this.semaforoLock = new ReentrantLock(); - this.verdeCondition = semaforoLock.newCondition(); - } - - @Override - public void run() { - while (true) { - // Ciclo de tempo (ajustável para controle) - estado = Estado.VERMELHO; - // Notificar o Cruzamento sobre o estado - try { - Thread.sleep(tempoVermelho); - estado = Estado.VERDE; - // Ao ficar VERDE, notifica as threads Veículo que estão esperando - semaforoLock.lock(); - try { - verdeCondition.signalAll(); - } finally { - semaforoLock.unlock(); - } - Thread.sleep(tempoVerde); - } catch (InterruptedException e) { /* ... */ } - } - } - // Método para a thread Veículo esperar - public void esperarPeloVerde() throws InterruptedException { - semaforoLock.lock(); - try { - if (estado == Estado.VERMELHO) { - verdeCondition.await(); - } - } finally { - semaforoLock.unlock(); - } - } -} \ No newline at end of file diff --git a/main/src/main/java/sd/Veiculo.java b/main/src/main/java/sd/Veiculo.java deleted file mode 100644 index 2a55ec9..0000000 --- a/main/src/main/java/sd/Veiculo.java +++ /dev/null @@ -1,35 +0,0 @@ -package sd; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.net.Socket; - -public class Veiculo implements Runnable { - // ... - private String proximoCruzamentoIP; - private int proximoCruzamentoPorta; - - public void run() { - // Simular o movimento na rua (Thread.sleep(t)) - - // 1. Tenta se conectar ao próximo Cruzamento - try (Socket socket = new Socket(proximoCruzamentoIP, proximoCruzamentoPorta); - ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()); - ObjectInputStream in = new ObjectInputStream(socket.getInputStream())) { - - // Envia o objeto Veículo com a solicitação de passagem - out.writeObject(this); - - // 2. BLOQUEIA a Thread, esperando a resposta do Servidor/Cruzamento - String permissao = (String) in.readObject(); - - if ("OK_PASSAR".equals(permissao)) { - // Simular tempo de travessia do cruzamento (pequeno Thread.sleep()) - // Atualiza a rota (próximo nó) - } - - } catch (IOException | ClassNotFoundException e) { /* ... */ } - // ... continua o loop da rota até a Saída (S) ... - } -} diff --git a/main/target/classes/sd/CruzamentoServer.class b/main/target/classes/sd/CruzamentoServer.class deleted file mode 100644 index f1925fd16c31698188474663711a02028dc17e6d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 792 zcmaJNMXfB)xAfW=M2#``D0Vij7nz-7vBd<3S-1$MA zDuD!deiUMyM5IE2%Z%soee>}A{Pp!afG2oRLq*`ANc*R*{G@U+-j2vE$kk94XkDm< z>SxMK`>!V#lz4%?$J%KBRA49WjRmTwHl+wVXf&~lJ%Rn9HuS2@C*;o5BqM?L&?YJy zE2o3Kc2@mN7XqE(meK>J&6PF+hw+EuriGDr+Dr$%aSb=Q&?fN0IqT{;5cvGoI4W$m zpj0L{pX*F{ZH=5e%eC|3k&GI1>%4kyHv`K=8DqViko*JoRw}tz_Z&5zc`_+4hsLCn zGPD1L_>XgnBDBy6`#9tY<82cNG?~#W_eK?kasu5rY+}tm*aCT9$6bN!|MP|M&SoTY z@-v&tDftoQ>fAaTua?)7x{xK0a?Zb$N{&d+`JrpMS;*=FB7taROPA0~9saTNcfv{d z0d&E)z{doZBHRGW8e4tVg7xn4CF)=JQ9;Bqguw~dSTO66!>S>WE1{r+!C)Wp>Q diff --git a/main/target/classes/sd/Entry.class b/main/target/classes/sd/Entry.class new file mode 100644 index 0000000000000000000000000000000000000000..72c0d912807819313e2300f0e339ffae72b597a8 GIT binary patch literal 526 zcmZutJ5K^Z5dN0eJv;pm+ak{fqNN5dTJoUP#p0W?kXM(-P_(s^dpAcsSIRv z&X8`lx(u0%a3E}?VL8Ym$58NOAZ{jpPw0EzQ-Y!7g?+BNT+6urYi6P+IcBiEf4w$w z`CJAJ)#jr&*X=}F2E%r%Yhev#1EmF5o#{9dzJqmC$Wb^UgOwRrhVC69Bf<;rw@qv? z>X2aAxO%_~KGMOIqVcnIp@|DWz>hMX z0tq2ub8qjxJ;OV{f8Rd<&T(WQC18yD&W+T8fs8rAwIHteK6s$w%p2(PZCH+<&n*#Q= z^1QJ28b)5fZebg{26hC>6SYNvjXmr$jOT>IqpM0|nJJo<(SYwLFYzp3wZn1LQ&&2P z!Aw#;NwiQ0-7<3^#V^LjYH)Jc1$*}R3;FlS*Yx15FIBWAKRoUq2-&_2@(oYmA!DHz=0}AND)FxiNw*}9U9YJdu4m0a^QC% zfdqGc6k@y$X^~QtLlNTQwLR}Wk7wWb`;X6G0pKb0YEWXZX5(;-sd%T2u0e&t#(Oan zVItH~crZ06Vg^k+2aI%d%%D3eAi0xC7-<#d#-MUxLO~mP$R30B8JZaPwTh*aS}}O= zC(;5(%<2=VqP}$cp)}Y0peU{kJ7;Wm%W~KTYWzgzmhB1$Hn#n}?^LS?T zVS=fB%!9`GgL2}8qbG5SIemornn_l+unLB41pBXoAm#k%ICM8pBnAB%SFAniP}i zD#Cv+gBVx1*QFmHKohPup#dERTm4hB6($}#Bh}HK_fmT#6~4;TLo^4zybL;ISCLHS z<(_X=ycrm@M(0|Cj9E6hs>3bD?yumvOTS;^|N6o7j-buZ2=f{f@5`8~9Slz*%zS^^ z8r);Beb&)0m81U5Gl%g4REHe~?q3v}QXT8uMEF8_m$ZI8kOQAEbb-u3PiP4`a0RL~ z>p%_a^et1Q0RfF`w0cym0fH~keA`+71RLK9)-@WdgaJZr(%3BK0c^o_S~0kBfx^ut g3Y$w6Zj(X@?vPrA^zJUnW_yWNf2kHHl@fG+0tHReApigX diff --git a/main/target/classes/sd/Veiculo.class b/main/target/classes/sd/Veiculo.class deleted file mode 100644 index 3414695d80379293bc7ce3bfe3bcb6d565323d1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1648 zcmZux-%}e^6#gzG*(6o;%}&8JQ8EaK=&ppgvf?yGh8>lFjbjd(U^zch0%r*}wk#?RNlo@U?f3St7O-s-k*S^8ex5EyPc_EWQAuR8t@dc&|h zySPQD*29)P$F%mB1x8v0k{c0k`Y(>EvL5Ov5v<|)ie z=DZB=EV?ixTan?tqvBn>CvfSBV|qqg90KWZnc9oX5Harcg>t#Dox~#Us93>WD#rNE*Xum&3)vq^_JWE}q;8SYG){B;s#)s(2FM`snNOSJwB5UqMd&cbNv5qn`o5Z(ha2&yp_=#f# zEnf2XH?RAhaf8K{Rl5-sdWh&0cMj9bC>D@mON`Oq1pXmHR&;^YWYszq9l_5iVT(Q{ zaeyzdO_q7wBL5C?EA;s#?-(lFQ^e2<8e$5Bg0 Date: Mon, 20 Oct 2025 12:09:05 +0100 Subject: [PATCH 2/4] added config based traffic --- .../main/java/sd/config/SimulationConfig.java | 101 +++++++++++++++++ main/src/main/java/sd/model/Event.java | 61 +++++++++++ main/src/main/java/sd/model/EventType.java | 13 +++ .../main/java/sd/model/TrafficLightState.java | 9 ++ main/src/main/java/sd/model/VehicleType.java | 10 ++ main/src/main/resources/simulation.properties | 103 ++++++++++++++++++ 6 files changed, 297 insertions(+) create mode 100644 main/src/main/java/sd/config/SimulationConfig.java create mode 100644 main/src/main/java/sd/model/Event.java create mode 100644 main/src/main/java/sd/model/EventType.java create mode 100644 main/src/main/java/sd/model/TrafficLightState.java create mode 100644 main/src/main/java/sd/model/VehicleType.java create mode 100644 main/src/main/resources/simulation.properties diff --git a/main/src/main/java/sd/config/SimulationConfig.java b/main/src/main/java/sd/config/SimulationConfig.java new file mode 100644 index 0000000..b2100b1 --- /dev/null +++ b/main/src/main/java/sd/config/SimulationConfig.java @@ -0,0 +1,101 @@ +package sd.config; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +/** + * Class to load and manage simulation configurations. + * Configurations are read from a .properties file. + */ +public class SimulationConfig { + private final Properties properties; + + public SimulationConfig(String filePath) throws IOException { + properties = new Properties(); + try (InputStream input = new FileInputStream(filePath)) { + properties.load(input); + } + } + + // Network configurations + public String getIntersectionHost(String intersectionId) { + return properties.getProperty("intersection." + intersectionId + ".host", "localhost"); + } + + public int getIntersectionPort(String intersectionId) { + return Integer.parseInt(properties.getProperty("intersection." + intersectionId + ".port", "0")); + } + + public String getDashboardHost() { + return properties.getProperty("dashboard.host", "localhost"); + } + + public int getDashboardPort() { + return Integer.parseInt(properties.getProperty("dashboard.port", "9000")); + } + + public String getExitHost() { + return properties.getProperty("exit.host", "localhost"); + } + + public int getExitPort() { + return Integer.parseInt(properties.getProperty("exit.port", "9001")); + } + + // Simulation configurations + public double getSimulationDuration() { + return Double.parseDouble(properties.getProperty("simulation.duration", "3600.0")); + } + + public String getArrivalModel() { + return properties.getProperty("simulation.arrival.model", "POISSON"); + } + + public double getArrivalRate() { + return Double.parseDouble(properties.getProperty("simulation.arrival.rate", "0.5")); + } + + public double getFixedArrivalInterval() { + return Double.parseDouble(properties.getProperty("simulation.arrival.fixed.interval", "2.0")); + } + + // Traffic light configurations + public double getTrafficLightGreenTime(String intersectionId, String direction) { + String key = "trafficlight." + intersectionId + "." + direction + ".green"; + return Double.parseDouble(properties.getProperty(key, "30.0")); + } + + public double getTrafficLightRedTime(String intersectionId, String direction) { + String key = "trafficlight." + intersectionId + "." + direction + ".red"; + return Double.parseDouble(properties.getProperty(key, "30.0")); + } + + // Vehicle configurations + public double getLightVehicleProbability() { + return Double.parseDouble(properties.getProperty("vehicle.probability.light", "0.7")); + } + + public double getLightVehicleCrossingTime() { + return Double.parseDouble(properties.getProperty("vehicle.crossing.time.light", "2.0")); + } + + public double getHeavyVehicleCrossingTime() { + return Double.parseDouble(properties.getProperty("vehicle.crossing.time.heavy", "4.0")); + } + + // Statistics + public double getStatisticsUpdateInterval() { + return Double.parseDouble(properties.getProperty("statistics.update.interval", "10.0")); + } + + // Generic method to get any property + public String getProperty(String key, String defaultValue) { + return properties.getProperty(key, defaultValue); + } + + public String getProperty(String key) { + return properties.getProperty(key); + } +} diff --git a/main/src/main/java/sd/model/Event.java b/main/src/main/java/sd/model/Event.java new file mode 100644 index 0000000..355112a --- /dev/null +++ b/main/src/main/java/sd/model/Event.java @@ -0,0 +1,61 @@ +package sd.model; + +import java.io.Serializable; + +/** + * Represents an event in the discrete event simulation. + * Events are ordered by timestamp for sequential processing. + */ +public class Event implements Comparable, Serializable { + private static final long serialVersionUID = 1L; + + private final double timestamp; // Time when the event occurs + private final EventType type; + private final Object data; // Data associated with the event (e.g., Vehicle, traffic light id, etc.) + private final String location; // Intersection or location where the event occurs + + public Event(double timestamp, EventType type, Object data, String location) { + this.timestamp = timestamp; + this.type = type; + this.data = data; + this.location = location; + } + + public Event(double timestamp, EventType type, Object data) { + this(timestamp, type, data, null); + } + + @Override + public int compareTo(Event other) { + // Sort by timestamp (earlier events have priority) + int cmp = Double.compare(this.timestamp, other.timestamp); + if (cmp == 0) { + // If timestamps are equal, sort by event type + return this.type.compareTo(other.type); + } + return cmp; + } + + // Getters + public double getTimestamp() { + return timestamp; + } + + public EventType getType() { + return type; + } + + public Object getData() { + return data; + } + + public String getLocation() { + return location; + } + + @Override + public String toString() { + return String.format("Event{t=%.2f, type=%s, loc=%s}", + timestamp, type, location); + } +} diff --git a/main/src/main/java/sd/model/EventType.java b/main/src/main/java/sd/model/EventType.java new file mode 100644 index 0000000..577a8df --- /dev/null +++ b/main/src/main/java/sd/model/EventType.java @@ -0,0 +1,13 @@ +package sd.model; + +/** + * Enumeration representing event types in the simulation. + */ +public enum EventType { + VEHICLE_ARRIVAL, // Vehicle arrives at an intersection + TRAFFIC_LIGHT_CHANGE, // Traffic light changes state (green/red) + CROSSING_START, // Vehicle starts crossing the intersection + CROSSING_END, // Vehicle finishes crossing + VEHICLE_GENERATION, // New vehicle is generated in the system + STATISTICS_UPDATE // Time to send statistics to dashboard +} diff --git a/main/src/main/java/sd/model/TrafficLightState.java b/main/src/main/java/sd/model/TrafficLightState.java new file mode 100644 index 0000000..95d81f2 --- /dev/null +++ b/main/src/main/java/sd/model/TrafficLightState.java @@ -0,0 +1,9 @@ +package sd.model; + +/** + * Enumeration representing the state of a traffic light. + */ +public enum TrafficLightState { + GREEN, // Allows passage + RED // Blocks passage +} diff --git a/main/src/main/java/sd/model/VehicleType.java b/main/src/main/java/sd/model/VehicleType.java new file mode 100644 index 0000000..b6d455c --- /dev/null +++ b/main/src/main/java/sd/model/VehicleType.java @@ -0,0 +1,10 @@ +package sd.model; + +/** + * Enumeration representing vehicle types in the simulation. + */ +public enum VehicleType { + BIKE, // Motorcycle + LIGHT, // Light vehicle (car) + HEAVY // Heavy vehicle (truck, bus) +} diff --git a/main/src/main/resources/simulation.properties b/main/src/main/resources/simulation.properties new file mode 100644 index 0000000..06ec791 --- /dev/null +++ b/main/src/main/resources/simulation.properties @@ -0,0 +1,103 @@ +# Traffic simulation configuration +# This file contains all the necessary configurations to run the simulation + +# === NETWORK CONFIGURATIONS === +# Intersections +intersection.Cr1.host=localhost +intersection.Cr1.port=8001 +intersection.Cr2.host=localhost +intersection.Cr2.port=8002 +intersection.Cr3.host=localhost +intersection.Cr3.port=8003 +intersection.Cr4.host=localhost +intersection.Cr4.port=8004 +intersection.Cr5.host=localhost +intersection.Cr5.port=8005 + +# Exit Node +exit.host=localhost +exit.port=9001 + +# Dashboard +dashboard.host=localhost +dashboard.port=9000 + +# === SIMULATION CONFIGURATIONS === +# Simulation duration in seconds (3600 = 1 hour) +simulation.duration=3600.0 + +# Vehicle arrival model: FIXED or POISSON +simulation.arrival.model=POISSON + +# Arrival rate (λ) for Poisson model (vehicles per second) +simulation.arrival.rate=0.5 + +# Fixed interval between arrivals (used if model = FIXED) +simulation.arrival.fixed.interval=2.0 + +# === TRAFFIC LIGHT CONFIGURATIONS === +# Times in seconds for each traffic light (green and red) +# Format: trafficlight... + +# Intersection 1 +trafficlight.Cr1.North.green=30.0 +trafficlight.Cr1.North.red=30.0 +trafficlight.Cr1.South.green=30.0 +trafficlight.Cr1.South.red=30.0 +trafficlight.Cr1.East.green=30.0 +trafficlight.Cr1.East.red=30.0 +trafficlight.Cr1.West.green=30.0 +trafficlight.Cr1.West.red=30.0 + +# Intersection 2 +trafficlight.Cr2.North.green=25.0 +trafficlight.Cr2.North.red=35.0 +trafficlight.Cr2.South.green=25.0 +trafficlight.Cr2.South.red=35.0 +trafficlight.Cr2.East.green=35.0 +trafficlight.Cr2.East.red=25.0 +trafficlight.Cr2.West.green=35.0 +trafficlight.Cr2.West.red=25.0 + +# Intersection 3 +trafficlight.Cr3.North.green=30.0 +trafficlight.Cr3.North.red=30.0 +trafficlight.Cr3.South.green=30.0 +trafficlight.Cr3.South.red=30.0 +trafficlight.Cr3.East.green=30.0 +trafficlight.Cr3.East.red=30.0 +trafficlight.Cr3.West.green=30.0 +trafficlight.Cr3.West.red=30.0 + +# Intersection 4 +trafficlight.Cr4.North.green=30.0 +trafficlight.Cr4.North.red=30.0 +trafficlight.Cr4.South.green=30.0 +trafficlight.Cr4.South.red=30.0 +trafficlight.Cr4.East.green=30.0 +trafficlight.Cr4.East.red=30.0 +trafficlight.Cr4.West.green=30.0 +trafficlight.Cr4.West.red=30.0 + +# Intersection 5 +trafficlight.Cr5.North.green=30.0 +trafficlight.Cr5.North.red=30.0 +trafficlight.Cr5.South.green=30.0 +trafficlight.Cr5.South.red=30.0 +trafficlight.Cr5.East.green=30.0 +trafficlight.Cr5.East.red=30.0 +trafficlight.Cr5.West.green=30.0 +trafficlight.Cr5.West.red=30.0 + +# === VEHICLE CONFIGURATIONS === +# Probability of generating a light vehicle (0.0 to 1.0) +# The rest will be heavy vehicles +vehicle.probability.light=0.7 + +# Crossing time in seconds +vehicle.crossing.time.light=2.0 +vehicle.crossing.time.heavy=4.0 + +# === STATISTICS CONFIGURATIONS === +# Interval to send updates to the dashboard (in seconds) +statistics.update.interval=10.0 From ce226f261aedb1b81335408adc130c49eb2161df Mon Sep 17 00:00:00 2001 From: Leandro Afonso Date: Tue, 21 Oct 2025 11:11:56 +0100 Subject: [PATCH 3/4] added intersect, vehicle and light logic + random poisson dist --- .gitignore | 50 +++++ main/src/main/java/sd/model/Intersection.java | 132 +++++++++++++ main/src/main/java/sd/model/TrafficLight.java | 180 ++++++++++++++++++ main/src/main/java/sd/model/Vehicle.java | 117 ++++++++++++ .../main/java/sd/util/RandomGenerator.java | 68 +++++++ main/src/main/resources/simulation.properties | 50 +++-- main/target/classes/sd/Entry.class | Bin 526 -> 0 bytes 7 files changed, 577 insertions(+), 20 deletions(-) create mode 100644 .gitignore create mode 100644 main/src/main/java/sd/model/Intersection.java create mode 100644 main/src/main/java/sd/model/TrafficLight.java create mode 100644 main/src/main/java/sd/model/Vehicle.java create mode 100644 main/src/main/java/sd/util/RandomGenerator.java delete mode 100644 main/target/classes/sd/Entry.class diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6fa7db9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,50 @@ +# Compiled class files +*.class + +# Log files +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# VS Code settings +.vscode/ + +# Eclipse files +*.pydevproject +.project +.classpath +.cproject +.settings/ +bin/ +tmp/ + +# IntelliJ IDEA files +*.iml +.idea/ +out/ + +# Mac system files +.DS_Store + +# Windows system files +Thumbs.db + +# Maven +target/ + +# Gradle +.gradle/ +build/ + +# Other +*.swp +*.pdf diff --git a/main/src/main/java/sd/model/Intersection.java b/main/src/main/java/sd/model/Intersection.java new file mode 100644 index 0000000..3e0df5e --- /dev/null +++ b/main/src/main/java/sd/model/Intersection.java @@ -0,0 +1,132 @@ +package sd.model; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Represents an intersection in the traffic simulation. + * + * Each intersection coordinates multiple traffic lights - one for each direction - + * and handles routing vehicles based on their next destination. + */ +public class Intersection { + + // Identity and configuration + private final String id; // ex. "Cr1", "Cr2" + private final Map trafficLights; // direction -> light + private final Map routing; // destination -> direction + + // Stats + private int totalVehiclesReceived; + private int totalVehiclesSent; + private double averageWaitingTime; + + public Intersection(String id) { + this.id = id; + this.trafficLights = new HashMap<>(); + this.routing = new HashMap<>(); + this.totalVehiclesReceived = 0; + this.totalVehiclesSent = 0; + this.averageWaitingTime = 0.0; + } + + /** + * Registers a traffic light under this intersection. + * The light is identified by its direction (ex., "North", "East"). + */ + public void addTrafficLight(TrafficLight trafficLight) { + trafficLights.put(trafficLight.getDirection(), trafficLight); + } + + /** + * Defines how vehicles should be routed through this intersection. + * + * @param nextDestination The next intersection or exit on the vehicle's route + * @param direction The direction (traffic light) vehicles should take + */ + public void configureRoute(String nextDestination, String direction) { + routing.put(nextDestination, direction); + } + + /** + * Accepts an incoming vehicle and places it in the correct queue. + * If the route or traffic light can't be found, logs an error. + */ + public void receiveVehicle(Vehicle vehicle) { + totalVehiclesReceived++; + + String nextDestination = vehicle.getCurrentDestination(); + String direction = routing.get(nextDestination); + + if (direction != null && trafficLights.containsKey(direction)) { + trafficLights.get(direction).addVehicle(vehicle); + } else { + System.err.printf( + "Routing error: could not place vehicle %s (destination: %s)%n", + vehicle.getId(), nextDestination + ); + } + } + + /** Returns the traffic light controlling the given direction, if any. */ + public TrafficLight getTrafficLight(String direction) { + return trafficLights.get(direction); + } + + /** Returns all traffic lights belonging to this intersection. */ + public List getTrafficLights() { + return new ArrayList<>(trafficLights.values()); + } + + /** Returns the total number of vehicles currently queued across all directions. */ + public int getTotalQueueSize() { + return trafficLights.values().stream() + .mapToInt(TrafficLight::getQueueSize) + .sum(); + } + + // --- Stats and getters --- + + public String getId() { + return id; + } + + public int getTotalVehiclesReceived() { + return totalVehiclesReceived; + } + + public int getTotalVehiclesSent() { + return totalVehiclesSent; + } + + public void incrementVehiclesSent() { + totalVehiclesSent++; + } + + public double getAverageWaitingTime() { + return averageWaitingTime; + } + + /** + * Updates the running average waiting time with a new sample. + */ + public void updateAverageWaitingTime(double newTime) { + // Weighted incremental average (avoids recalculating from scratch) + averageWaitingTime = (averageWaitingTime * (totalVehiclesSent - 1) + newTime) + / totalVehiclesSent; + } + + @Override + public String toString() { + return String.format( + "Intersection{id='%s', lights=%d, queues=%d, received=%d, sent=%d}", + id, + trafficLights.size(), + getTotalQueueSize(), + totalVehiclesReceived, + totalVehiclesSent + ); + } +} diff --git a/main/src/main/java/sd/model/TrafficLight.java b/main/src/main/java/sd/model/TrafficLight.java new file mode 100644 index 0000000..b7f8516 --- /dev/null +++ b/main/src/main/java/sd/model/TrafficLight.java @@ -0,0 +1,180 @@ +package sd.model; + +import java.util.LinkedList; +import java.util.Queue; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * Represents a single traffic light controlling one direction at an intersection. + * + * Each light maintains its own queue of vehicles and alternates between + * green and red states. It's designed to be thread-safe (maybe...), so multiple + * threads (like vehicles or controllers) can safely interact with it. + */ +public class TrafficLight { + + // Identity and configuration + private final String id; // ex. "Cr1-N" + private final String direction; // ex. "North", "South", etc. + private TrafficLightState state; + + // Vehicle management + private final Queue queue; + + // Synchronization primitives + private final Lock lock; + private final Condition vehicleAdded; + private final Condition lightGreen; + + // Timing configuration (seconds) + private double greenTime; + private double redTime; + + // Basic stats + private int totalVehiclesProcessed; + + public TrafficLight(String id, String direction, double greenTime, double redTime) { + this.id = id; + this.direction = direction; + this.state = TrafficLightState.RED; + this.queue = new LinkedList<>(); + + this.lock = new ReentrantLock(); + this.vehicleAdded = lock.newCondition(); + this.lightGreen = lock.newCondition(); + + this.greenTime = greenTime; + this.redTime = redTime; + this.totalVehiclesProcessed = 0; + } + + /** + * Adds a vehicle to the waiting queue. + * Signals any waiting threads that a new vehicle has arrived. + */ + public void addVehicle(Vehicle vehicle) { + lock.lock(); + try { + queue.offer(vehicle); + vehicleAdded.signalAll(); + } finally { + lock.unlock(); + } + } + + /** + * Attempts to let one vehicle pass through. + * Only works if the light is green; otherwise returns null. + */ + public Vehicle removeVehicle() { + lock.lock(); + try { + if (state == TrafficLightState.GREEN && !queue.isEmpty()) { + Vehicle vehicle = queue.poll(); + totalVehiclesProcessed++; + return vehicle; + } + return null; + } finally { + lock.unlock(); + } + } + + /** + * Changes the light’s state (ex., RED -> GREEN). + * When the light turns green, waiting threads are notified. + * ¯\_(ツ)_/¯ + */ + public void changeState(TrafficLightState newState) { + lock.lock(); + try { + this.state = newState; + if (newState == TrafficLightState.GREEN) { + lightGreen.signalAll(); + } + } finally { + lock.unlock(); + } + } + + /** Returns how many vehicles are currently queued. */ + public int getQueueSize() { + lock.lock(); + try { + return queue.size(); + } finally { + lock.unlock(); + } + } + + /** Checks whether there are no vehicles waiting. */ + public boolean isQueueEmpty() { + lock.lock(); + try { + return queue.isEmpty(); + } finally { + lock.unlock(); + } + } + + // --- Getters & Setters --- + + public String getId() { + return id; + } + + public String getDirection() { + return direction; + } + + public TrafficLightState getState() { + lock.lock(); + try { + return state; + } finally { + lock.unlock(); + } + } + + public double getGreenTime() { + return greenTime; + } + + public void setGreenTime(double greenTime) { + this.greenTime = greenTime; + } + + public double getRedTime() { + return redTime; + } + + public void setRedTime(double redTime) { + this.redTime = redTime; + } + + public int getTotalVehiclesProcessed() { + return totalVehiclesProcessed; + } + + public Lock getLock() { + return lock; + } + + public Condition getVehicleAdded() { + return vehicleAdded; + } + + public Condition getLightGreen() { + return lightGreen; + } + + @Override + public String toString() { + return String.format( + "TrafficLight{id='%s', direction='%s', state=%s, queueSize=%d}", + id, direction, state, getQueueSize() + ); + } +} diff --git a/main/src/main/java/sd/model/Vehicle.java b/main/src/main/java/sd/model/Vehicle.java new file mode 100644 index 0000000..d8d4954 --- /dev/null +++ b/main/src/main/java/sd/model/Vehicle.java @@ -0,0 +1,117 @@ +package sd.model; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a single vehicle moving through the simulation. + * + * Each vehicle has a route - a sequence of intersections it will pass through - + * and keeps track of how long it has waited and traveled overall. + * + * Serializable so it can be sent between processes or nodes over sockets. type shit + */ +public class Vehicle implements Serializable { + private static final long serialVersionUID = 1L; + + // Identity and configuration + private final String id; + private final VehicleType type; + private final double entryTime; // When it entered the system + private final List route; // ex., ["Cr1", "Cr3", "S"] + private int currentRouteIndex; // Current position in the route + + // Metrics + private double totalWaitingTime; // Total time spent waiting at red lights + private double totalCrossingTime; // Time spent actually moving between intersections + + public Vehicle(String id, VehicleType type, double entryTime, List route) { + this.id = id; + this.type = type; + this.entryTime = entryTime; + this.route = new ArrayList<>(route); + this.currentRouteIndex = 0; + this.totalWaitingTime = 0.0; + this.totalCrossingTime = 0.0; + } + + /** + * Moves the vehicle to the next stop in its route. + * + * @return true if there are still destinations ahead, false if the route is finished + */ + public boolean advanceRoute() { + currentRouteIndex++; + return currentRouteIndex < route.size(); + } + + /** + * Gets the current destination (the next intersection or exit). + * Returns null if the route is already complete. + */ + public String getCurrentDestination() { + return (currentRouteIndex < route.size()) ? route.get(currentRouteIndex) : null; + } + + /** Returns true if the vehicle has completed its entire route. */ + public boolean hasReachedEnd() { + return currentRouteIndex >= route.size(); + } + + // --- Getters and metrics management --- + + public String getId() { + return id; + } + + public VehicleType getType() { + return type; + } + + public double getEntryTime() { + return entryTime; + } + + public List getRoute() { + return new ArrayList<>(route); + } + + public int getCurrentRouteIndex() { + return currentRouteIndex; + } + + public double getTotalWaitingTime() { + return totalWaitingTime; + } + + public void addWaitingTime(double time) { + totalWaitingTime += time; + } + + public double getTotalCrossingTime() { + return totalCrossingTime; + } + + public void addCrossingTime(double time) { + totalCrossingTime += time; + } + + /** + * Calculates how long the vehicle has been in the system so far. + * + * @param currentTime the current simulation time + * @return total elapsed time since the vehicle entered + */ + public double getTotalTravelTime(double currentTime) { + return currentTime - entryTime; + } + + @Override + public String toString() { + return String.format( + "Vehicle{id='%s', type=%s, next='%s', route=%s}", + id, type, getCurrentDestination(), route + ); + } +} diff --git a/main/src/main/java/sd/util/RandomGenerator.java b/main/src/main/java/sd/util/RandomGenerator.java new file mode 100644 index 0000000..3c44b0d --- /dev/null +++ b/main/src/main/java/sd/util/RandomGenerator.java @@ -0,0 +1,68 @@ +package sd.util; + +import java.util.Random; + +/** + * Utility class for generating random values used throughout the simulation. + * + * Includes helpers for exponential distributions (for vehicle arrivals), + * uniform randoms, and probability-based decisions. + */ +public class RandomGenerator { + + private static final Random random = new Random(); + + /** + * Returns a random time interval that follows an exponential distribution. + * + * Useful for modeling inter-arrival times in a Poisson process. + * + * @param lambda the arrival rate (λ) + * @return the time interval until the next arrival + */ + public static double generateExponentialInterval(double lambda) { + return Math.log(1 - random.nextDouble()) / -lambda; + } + + /** + * Returns a random integer between {@code min} and {@code max}, inclusive. + */ + public static int generateRandomInt(int min, int max) { + return random.nextInt(max - min + 1) + min; + } + + /** + * Returns a random double between {@code min} (inclusive) and {@code max} (exclusive). + */ + public static double generateRandomDouble(double min, double max) { + return min + (max - min) * random.nextDouble(); + } + + /** + * Returns {@code true} with the given probability. + * + * @param probability a value between 0.0 and 1.0 + */ + public static boolean occursWithProbability(double probability) { + return random.nextDouble() < probability; + } + + /** + * Picks a random element from the given array. + * + * @throws IllegalArgumentException if the array is empty + */ + public static T chooseRandom(T[] array) { + if (array.length == 0) { + throw new IllegalArgumentException("Array cannot be empty."); + } + return array[random.nextInt(array.length)]; + } + + /** + * Sets the random generator’s seed, allowing reproducible results. + */ + public static void setSeed(long seed) { + random.setSeed(seed); + } +} diff --git a/main/src/main/resources/simulation.properties b/main/src/main/resources/simulation.properties index 06ec791..6deec88 100644 --- a/main/src/main/resources/simulation.properties +++ b/main/src/main/resources/simulation.properties @@ -1,8 +1,13 @@ -# Traffic simulation configuration -# This file contains all the necessary configurations to run the simulation +# ========================================================= +# Traffic Simulation Configuration +# --------------------------------------------------------- +# All parameters controlling network layout, timing, +# and simulation behavior. +# ========================================================= -# === NETWORK CONFIGURATIONS === -# Intersections +# === NETWORK CONFIGURATION === + +# Intersections (each with its host and port) intersection.Cr1.host=localhost intersection.Cr1.port=8001 intersection.Cr2.host=localhost @@ -14,30 +19,32 @@ intersection.Cr4.port=8004 intersection.Cr5.host=localhost intersection.Cr5.port=8005 -# Exit Node +# Exit node exit.host=localhost exit.port=9001 -# Dashboard +# Dashboard server dashboard.host=localhost dashboard.port=9000 -# === SIMULATION CONFIGURATIONS === -# Simulation duration in seconds (3600 = 1 hour) + +# === SIMULATION CONFIGURATION === + +# Total duration in seconds (3600 = 1 hour) simulation.duration=3600.0 # Vehicle arrival model: FIXED or POISSON simulation.arrival.model=POISSON -# Arrival rate (λ) for Poisson model (vehicles per second) +# λ (lambda): average arrival rate (vehicles per second) simulation.arrival.rate=0.5 -# Fixed interval between arrivals (used if model = FIXED) +# Fixed interval between arrivals (only used if model=FIXED) simulation.arrival.fixed.interval=2.0 -# === TRAFFIC LIGHT CONFIGURATIONS === -# Times in seconds for each traffic light (green and red) -# Format: trafficlight... + +# === TRAFFIC LIGHT TIMINGS === +# Format: trafficlight...= # Intersection 1 trafficlight.Cr1.North.green=30.0 @@ -89,15 +96,18 @@ trafficlight.Cr5.East.red=30.0 trafficlight.Cr5.West.green=30.0 trafficlight.Cr5.West.red=30.0 -# === VEHICLE CONFIGURATIONS === -# Probability of generating a light vehicle (0.0 to 1.0) -# The rest will be heavy vehicles -vehicle.probability.light=0.7 +# === VEHICLE CONFIGURATION === +# Probability distribution for vehicle types (must sum to 1.0) +vehicle.probability.bike=0.2 +vehicle.probability.light=0.6 +vehicle.probability.heavy=0.2 -# Crossing time in seconds +# Average crossing times (in seconds) +vehicle.crossing.time.bike=1.5 vehicle.crossing.time.light=2.0 vehicle.crossing.time.heavy=4.0 -# === STATISTICS CONFIGURATIONS === -# Interval to send updates to the dashboard (in seconds) +# === STATISTICS === + +# Interval between dashboard updates (seconds) statistics.update.interval=10.0 diff --git a/main/target/classes/sd/Entry.class b/main/target/classes/sd/Entry.class deleted file mode 100644 index 72c0d912807819313e2300f0e339ffae72b597a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 526 zcmZutJ5K^Z5dN0eJv;pm+ak{fqNN5dTJoUP#p0W?kXM(-P_(s^dpAcsSIRv z&X8`lx(u0%a3E}?VL8Ym$58NOAZ{jpPw0EzQ-Y!7g?+BNT+6urYi6P+IcBiEf4w$w z`CJAJ)#jr&*X=}F2E%r%Yhev#1EmF5o#{9dzJqmC$Wb^UgOwRrhVC69Bf<;rw@qv? z Date: Tue, 21 Oct 2025 11:19:40 +0100 Subject: [PATCH 4/4] added bike//heavy prob & cross time --- .../main/java/sd/config/SimulationConfig.java | 50 ++++++++++++------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/main/src/main/java/sd/config/SimulationConfig.java b/main/src/main/java/sd/config/SimulationConfig.java index b2100b1..153f9e4 100644 --- a/main/src/main/java/sd/config/SimulationConfig.java +++ b/main/src/main/java/sd/config/SimulationConfig.java @@ -11,90 +11,102 @@ import java.util.Properties; */ public class SimulationConfig { private final Properties properties; - + public SimulationConfig(String filePath) throws IOException { properties = new Properties(); try (InputStream input = new FileInputStream(filePath)) { properties.load(input); } } - + // Network configurations public String getIntersectionHost(String intersectionId) { return properties.getProperty("intersection." + intersectionId + ".host", "localhost"); } - + public int getIntersectionPort(String intersectionId) { return Integer.parseInt(properties.getProperty("intersection." + intersectionId + ".port", "0")); } - + public String getDashboardHost() { return properties.getProperty("dashboard.host", "localhost"); } - + public int getDashboardPort() { return Integer.parseInt(properties.getProperty("dashboard.port", "9000")); } - + public String getExitHost() { return properties.getProperty("exit.host", "localhost"); } - + public int getExitPort() { return Integer.parseInt(properties.getProperty("exit.port", "9001")); } - + // Simulation configurations public double getSimulationDuration() { return Double.parseDouble(properties.getProperty("simulation.duration", "3600.0")); } - + public String getArrivalModel() { return properties.getProperty("simulation.arrival.model", "POISSON"); } - + public double getArrivalRate() { return Double.parseDouble(properties.getProperty("simulation.arrival.rate", "0.5")); } - + public double getFixedArrivalInterval() { return Double.parseDouble(properties.getProperty("simulation.arrival.fixed.interval", "2.0")); } - + // Traffic light configurations public double getTrafficLightGreenTime(String intersectionId, String direction) { String key = "trafficlight." + intersectionId + "." + direction + ".green"; return Double.parseDouble(properties.getProperty(key, "30.0")); } - + public double getTrafficLightRedTime(String intersectionId, String direction) { String key = "trafficlight." + intersectionId + "." + direction + ".red"; return Double.parseDouble(properties.getProperty(key, "30.0")); } - + // Vehicle configurations public double getLightVehicleProbability() { return Double.parseDouble(properties.getProperty("vehicle.probability.light", "0.7")); } - + public double getLightVehicleCrossingTime() { return Double.parseDouble(properties.getProperty("vehicle.crossing.time.light", "2.0")); } - + + public double getBikeVehicleProbability() { + return Double.parseDouble(properties.getProperty("vehicle.probability.bike", "0.0")); + } + + public double getBikeVehicleCrossingTime() { + return Double.parseDouble(properties.getProperty("vehicle.crossing.time.bike", "1.5")); + } + + public double getHeavyVehicleProbability() { + return Double.parseDouble(properties.getProperty("vehicle.probability.heavy", "0.0")); + } + public double getHeavyVehicleCrossingTime() { return Double.parseDouble(properties.getProperty("vehicle.crossing.time.heavy", "4.0")); } - + // Statistics public double getStatisticsUpdateInterval() { return Double.parseDouble(properties.getProperty("statistics.update.interval", "10.0")); } - + // Generic method to get any property public String getProperty(String key, String defaultValue) { return properties.getProperty(key, defaultValue); } - + public String getProperty(String key) { return properties.getProperty(key); }