27 Commits

Author SHA1 Message Date
David Alves
8fe4e564d3 Update Diagrama de arquitetura - SD.jpg 2025-12-04 22:27:01 +00:00
David Alves
e389c0711e Updated architecture diagram image 2025-12-04 22:25:55 +00:00
David Alves
24fe1c1d67 Update Diagrama de arquitetura - SD.drawio 2025-11-27 19:54:14 +00:00
David Alves
766eabbbe4 Update .gitignore 2025-11-27 15:49:03 +00:00
David Alves
d7b1de1fe3 Update Diagrama de arquitetura - SD.drawio 2025-11-27 15:47:30 +00:00
David Alves
96b3a66b96 Diagram update
@0x1eo @Gaa56 o que acham do diagrama? Mudariam/acrescentariam algo? As legendas, parecem-vos bem?
2025-11-27 15:46:02 +00:00
David Alves
29848b04a6 Update architecture diagram 2025-11-23 23:16:08 +00:00
043ba7d185 Add workflow_dispatch trigger to Maven CI 2025-11-23 22:12:35 +00:00
25f2876c34 Refactor GitHub Actions workflow for Maven build 2025-11-23 22:10:40 +00:00
7cbecc4fab Update Maven workflow for JDK setup and packaging 2025-11-23 22:00:49 +00:00
72db59415f Add Windows build job to Maven workflow 2025-11-23 21:53:33 +00:00
60b4f0c2b6 Add 'cleanup' branch to Maven CI workflow 2025-11-22 22:53:54 +00:00
81f842e2bb Change CI branch from 'main' to 'dev' 2025-11-19 20:54:47 +00:00
David Alves
108d2e544c Enunciado uploaded 2025-10-27 18:02:24 +00:00
23f7a74798 Add dependency build to CI job 2025-10-24 20:20:15 +01:00
d7dec0d73e Merge pull request #21 from davidalves04/9-design-message-protocol-specification
Mmessage protocol specification
2025-10-24 20:12:18 +01:00
8e95bc4c01 Testing job 2025-10-23 00:46:52 +01:00
33ed84b0c2 Enhance Maven workflow with release publishing
Added a publish-release job to create a GitHub release with the built JAR file when a tag is pushed.
2025-10-23 00:36:13 +01:00
9093b13c5d Rollback
Oops
2025-10-23 00:27:37 +01:00
12b7aabe87 Enhance CI workflow with security and dependency checks
Added security scan and dependency review jobs to the workflow.
2025-10-23 00:21:36 +01:00
c30aa25de0 Update Maven workflow to use JDK 17 and improve steps 2025-10-23 00:14:34 +01:00
3689f7a207 Set working directory for dependency graph update
Specify working directory for dependency graph update
2025-10-23 00:08:16 +01:00
bb18c1119e Update Maven build file path to main/pom.xml 2025-10-23 00:02:55 +01:00
f0dbdb551d Add GitHub Actions workflow for Java CI with Maven
This workflow builds a Java project using Maven, caches dependencies, and updates the dependency graph for improved Dependabot alerts.
2025-10-23 00:01:55 +01:00
f519c9aba7 Merge pull request #20 from davidalves04/8-single-process-prototype
Step 2: Single-Process Prototype
2025-10-22 23:51:19 +01:00
1216089e80 Step 2 - Finishing touches 2025-10-22 23:37:27 +01:00
211ea25ca5 Step 2 - Finishing touches 2025-10-22 23:36:41 +01:00
12 changed files with 563 additions and 50 deletions

View File

@@ -0,0 +1,110 @@
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/29.0.3 Chrome/140.0.7339.249 Electron/38.7.0 Safari/537.36" version="29.0.3">
<diagram name="Arquitetura SD" id="QKeTeUWuUs8JeLsq44d-">
<mxGraphModel dx="1426" dy="841" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1654" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="0K4eb2koB2xQ8duQ1-_a-1" value="&lt;b&gt;CoordinatorProcess&lt;/b&gt;&lt;br&gt;(Cliente Socket)&lt;hr&gt;• VehicleGenerator&lt;br&gt;• Modelo Poisson (λ=0.5)&lt;br&gt;• Liga a Cr1-Cr5" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;verticalAlign=top;spacing=10;fontColor=#000000;" parent="1" vertex="1">
<mxGeometry x="560" y="40" width="240" height="100" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-2" value="&lt;b&gt;Cr1&lt;/b&gt; (IntersectionProcess)&lt;br&gt;Porta: 8001&lt;br&gt;Servidor + Cliente&lt;hr&gt;• ServerSocket (8001)&lt;br&gt;• Thread Semáforo Sul&lt;br&gt;• Thread Semáforo Este&lt;br&gt;• Thread Semáforo Oeste&lt;br&gt;• Fila Eventos (DES)&lt;br&gt;• ReentrantLock" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;align=left;verticalAlign=top;spacing=10;fontColor=#000000;" parent="1" vertex="1">
<mxGeometry x="280" y="200" width="180" height="160" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-3" value="&lt;b&gt;Cr2&lt;/b&gt; (IntersectionProcess)&lt;br&gt;Porta: 8002&lt;br&gt;Servidor + Cliente&lt;hr&gt;• ServerSocket (8002)&lt;br&gt;• Thread Semáforo Sul&lt;br&gt;• Thread Semáforo Este&lt;br&gt;• Thread Semáforo Oeste&lt;br&gt;• Fila Eventos (DES)&lt;br&gt;• ReentrantLock" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;align=left;verticalAlign=top;spacing=10;fontColor=#000000;" parent="1" vertex="1">
<mxGeometry x="590" y="190" width="180" height="160" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-5" value="&lt;b&gt;Cr4&lt;/b&gt; (IntersectionProcess)&lt;br&gt;Porta: 8004&lt;br&gt;Servidor + Cliente&lt;hr&gt;• ServerSocket (8004)&lt;br&gt;• Thread Semáforo Sul&lt;br&gt;• Thread Semáforo Este&lt;br&gt;• Thread Semáforo Oeste&lt;br&gt;• Fila Eventos (DES)&lt;br&gt;• ReentrantLock" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;align=left;verticalAlign=top;spacing=10;fontColor=#000000;" parent="1" vertex="1">
<mxGeometry x="440" y="530" width="180" height="160" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-6" value="&lt;b&gt;Cr5&lt;/b&gt; (IntersectionProcess)&lt;br&gt;Porta: 8005&lt;br&gt;Servidor + Cliente&lt;hr&gt;• ServerSocket (8005)&lt;br&gt;• Thread Semáforo Sul&lt;br&gt;• Thread Semáforo Este&lt;br&gt;• Thread Semáforo Oeste&lt;br&gt;• Fila Eventos (DES)&lt;br&gt;• ReentrantLock" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;align=left;verticalAlign=top;spacing=10;fontColor=#000000;" parent="1" vertex="1">
<mxGeometry x="910" y="430" width="180" height="160" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-7" value="&lt;b&gt;ExitNode (S)&lt;/b&gt;&lt;br&gt;Porta: 9001&lt;br&gt;Servidor Socket&lt;hr&gt;• Recebe veículos finais&lt;br&gt;• Calcula estatísticas:&lt;br&gt; - Tempo no sistema&lt;br&gt; - Tempo de espera&lt;br&gt; - Métricas por tipo&lt;br&gt;• Envia para Dashboard" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;align=left;verticalAlign=top;spacing=10;fontColor=#000000;" parent="1" vertex="1">
<mxGeometry x="727" y="810" width="200" height="170" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-8" value="&lt;b&gt;DashboardServer&lt;/b&gt;&lt;br&gt;Porta: 9000&lt;br&gt;Servidor Socket&lt;hr&gt;• Thread Pool (10 threads)&lt;br&gt;• ConcurrentHashMap&lt;br&gt;• Agrega estatísticas&lt;br&gt;• Display a cada 5s:&lt;br&gt; - Throughput&lt;br&gt; - Tempos médios&lt;br&gt; - Tamanhos de filas" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;align=left;verticalAlign=top;spacing=10;fontColor=#000000;" parent="1" vertex="1">
<mxGeometry x="1210" y="585" width="200" height="160" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-9" value="VEHICLE_SPAWN&lt;br&gt;(Vehicle)" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#0000FF;strokeWidth=2;" parent="1" source="0K4eb2koB2xQ8duQ1-_a-1" target="0K4eb2koB2xQ8duQ1-_a-2" edge="1">
<mxGeometry x="-0.2105" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-10" value="VEHICLE_SPAWN&lt;br&gt;(Vehicle)" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#0000FF;strokeWidth=2;" parent="1" source="0K4eb2koB2xQ8duQ1-_a-1" target="0K4eb2koB2xQ8duQ1-_a-3" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-11" value="VEHICLE_SPAWN&lt;br&gt;(Vehicle)" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#0000FF;strokeWidth=2;" parent="1" source="0K4eb2koB2xQ8duQ1-_a-1" target="0K4eb2koB2xQ8duQ1-_a-4" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-12" value="VEHICLE_TRANSFER" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#00AA00;strokeWidth=2;endArrow=classic;startArrow=classic;" parent="1" source="0K4eb2koB2xQ8duQ1-_a-2" target="0K4eb2koB2xQ8duQ1-_a-3" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-13" value="VEHICLE_TRANSFER" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#00AA00;strokeWidth=2;endArrow=classic;startArrow=classic;" parent="1" source="0K4eb2koB2xQ8duQ1-_a-3" target="0K4eb2koB2xQ8duQ1-_a-4" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-14" value="VEHICLE_TRANSFER" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#00AA00;strokeWidth=2;endArrow=classic;startArrow=classic;" parent="1" source="0K4eb2koB2xQ8duQ1-_a-2" target="0K4eb2koB2xQ8duQ1-_a-5" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-15" value="VEHICLE_TRANSFER" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#00AA00;strokeWidth=2;endArrow=classic;startArrow=classic;" parent="1" source="0K4eb2koB2xQ8duQ1-_a-3" target="0K4eb2koB2xQ8duQ1-_a-5" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-16" value="VEHICLE_TRANSFER" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#00AA00;strokeWidth=2;endArrow=classic;startArrow=classic;" parent="1" source="0K4eb2koB2xQ8duQ1-_a-5" target="0K4eb2koB2xQ8duQ1-_a-6" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-17" value="VEHICLE_TRANSFER" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#00AA00;strokeWidth=2;endArrow=classic;startArrow=none;startFill=0;" parent="1" source="0K4eb2koB2xQ8duQ1-_a-4" target="0K4eb2koB2xQ8duQ1-_a-6" edge="1">
<mxGeometry x="0.3659" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-18" value="VEHICLE_TRANSFER" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#FF6600;strokeWidth=2;" parent="1" source="0K4eb2koB2xQ8duQ1-_a-5" target="0K4eb2koB2xQ8duQ1-_a-7" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-19" value="VEHICLE_TRANSFER" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#FF6600;strokeWidth=2;" parent="1" source="0K4eb2koB2xQ8duQ1-_a-6" target="0K4eb2koB2xQ8duQ1-_a-7" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-20" value="STATS_UPDATE&lt;br&gt;(periódico 5s)" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#9933FF;strokeWidth=2;dashed=1;" parent="1" source="0K4eb2koB2xQ8duQ1-_a-2" target="0K4eb2koB2xQ8duQ1-_a-8" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-21" value="STATS_UPDATE&lt;br&gt;(periódico 5s)" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#9933FF;strokeWidth=2;dashed=1;" parent="1" source="0K4eb2koB2xQ8duQ1-_a-4" target="0K4eb2koB2xQ8duQ1-_a-8" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-22" value="STATS_UPDATE&lt;br&gt;(periódico 5s)" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#9933FF;strokeWidth=2;dashed=1;" parent="1" source="0K4eb2koB2xQ8duQ1-_a-4" target="0K4eb2koB2xQ8duQ1-_a-8" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-23" value="STATS_UPDATE&lt;br&gt;(periódico 5s)" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#9933FF;strokeWidth=2;dashed=1;" parent="1" source="0K4eb2koB2xQ8duQ1-_a-5" target="0K4eb2koB2xQ8duQ1-_a-8" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-24" value="STATS_UPDATE&lt;br&gt;(periódico 5s)" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#9933FF;strokeWidth=2;dashed=1;" parent="1" source="0K4eb2koB2xQ8duQ1-_a-6" target="0K4eb2koB2xQ8duQ1-_a-8" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-25" value="STATS_UPDATE&lt;br&gt;(periódico 5s)" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#9933FF;strokeWidth=2;dashed=1;" parent="1" source="0K4eb2koB2xQ8duQ1-_a-26" target="0K4eb2koB2xQ8duQ1-_a-8" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-27" value="&lt;b&gt;MessageProtocol&lt;/b&gt;&lt;hr&gt;interface:&lt;br&gt;• getType()&lt;br&gt;• getPayload()&lt;br&gt;• getSourceNode()&lt;br&gt;• getDestinationNode()" style="rounded=0;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fillColor=#fff2cc;strokeColor=#d6b656;spacing=10;fontColor=#000000;" parent="1" vertex="1">
<mxGeometry x="30" y="30" width="180" height="120" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-28" value="&lt;b&gt;Tipos de Mensagens&lt;/b&gt;&lt;hr&gt;• VEHICLE_TRANSFER&lt;br&gt;• VEHICLE_SPAWN&lt;br&gt;• STATS_UPDATE&lt;br&gt;• TRAFFIC_LIGHT_SYNC&lt;br&gt;• HEARTBEAT" style="rounded=0;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fillColor=#fff2cc;strokeColor=#d6b656;spacing=10;fontColor=#000000;" parent="1" vertex="1">
<mxGeometry x="20" y="170" width="200" height="120" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-29" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#9933FF;strokeWidth=2;dashed=1;" parent="1" source="0K4eb2koB2xQ8duQ1-_a-3" target="0K4eb2koB2xQ8duQ1-_a-4" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="480" y="280" as="sourcePoint" />
<mxPoint x="990" y="440" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-4" value="&lt;b&gt;Cr3&lt;/b&gt; (IntersectionProcess)&lt;br&gt;Porta: 8003&lt;br&gt;Servidor + Cliente&lt;hr&gt;• ServerSocket (8003)&lt;br&gt;• Thread Semáforo Sul&lt;br&gt;• Thread Semáforo Este&lt;br&gt;• Thread Semáforo Oeste&lt;br&gt;• Fila Eventos (DES)&lt;br&gt;• ReentrantLock" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;align=left;verticalAlign=top;spacing=10;fontColor=#000000;" parent="1" vertex="1">
<mxGeometry x="910" y="200" width="180" height="160" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-30" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#9933FF;strokeWidth=2;dashed=1;" parent="1" source="0K4eb2koB2xQ8duQ1-_a-7" target="0K4eb2koB2xQ8duQ1-_a-26" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="500" y="710" as="sourcePoint" />
<mxPoint x="1090" y="520" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-26" value="&lt;b&gt;LEGENDA&lt;/b&gt;&lt;hr&gt;━━━► Comunicação síncrona&lt;br&gt;╌╌╌► Comunicação periódica&lt;br&gt;&lt;br&gt;&lt;b&gt;Cores:&lt;/b&gt;&lt;br&gt;🔵 Azul = Geração&lt;br&gt;🟢 Verde = Transferência&lt;br&gt;🟠 Laranja = Finalização&lt;br&gt;🟣 Roxo = Monitorização&lt;br&gt;&lt;br&gt;&lt;b&gt;Serialização:&lt;/b&gt; JSON (Gson)&lt;br&gt;&lt;b&gt;Protocolo:&lt;/b&gt; TCP/IP" style="rounded=0;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#333333;spacing=10;" parent="1" vertex="1">
<mxGeometry x="1210" y="825" width="200" height="220" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

99
.github/workflows/maven.yml vendored Normal file
View File

@@ -0,0 +1,99 @@
name: Java CI with Maven
on:
workflow_dispatch:
push:
branches: [ "dev", "cleanup" ]
tags:
- 'v*.*.*'
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
cache: maven
- name: Build with Maven
run: mvn -B package
working-directory: main
- name: Upload built JAR
uses: actions/upload-artifact@v4
with:
name: package
path: main/target/*.jar
- name: Generate dependency graph
run: mvn -B -f main/pom.xml com.github.ferstl:depgraph-maven-plugin:4.0.1:graph
- name: Upload dependency graph artifact
uses: actions/upload-artifact@v4
with:
name: dependency-graph
path: main/target/**
build-windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
cache: maven
- name: Build with Maven (Skip Tests)
run: mvn -B package -DskipTests
working-directory: main
- name: Create JPackage App Image
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path "dist"
jpackage --name "DTSS" `
--input main/target `
--main-jar main-1.0-SNAPSHOT.jar `
--dest dist `
--type app-image `
--win-console
- name: Inject java.exe
shell: pwsh
run: |
$javaPath = (Get-Command java).Source
Copy-Item -Path $javaPath -Destination "dist/DTSS/runtime/bin/"
- name: Zip Windows Release
shell: pwsh
run: |
Compress-Archive -Path "dist/DTSS" -DestinationPath "dist/DTSS-Windows.zip"
- name: Upload Windows Artifact
uses: actions/upload-artifact@v4
with:
name: windows-package
path: dist/DTSS-Windows.zip
publish-release:
runs-on: ubuntu-latest
needs: [build, build-windows]
if: startsWith(github.ref, 'refs/tags/')
permissions:
contents: write
steps:
- name: Download Linux JAR
uses: actions/download-artifact@v4
with:
name: package
path: main/target/
- name: Download Windows Zip
uses: actions/download-artifact@v4
with:
name: windows-package
path: windows-dist/
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
files: |
main/target/*.jar
windows-dist/*.zip

2
.gitignore vendored
View File

@@ -47,4 +47,4 @@ build/
# Other
*.swp
*.pdf
.$Diagrama de arquitetura - SD.drawio.bkp

View File

@@ -1,24 +1,168 @@
<mxfile host="app.diagrams.net" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0" version="28.2.7">
<diagram name="Página-1" id="B1_hHcevBzWlEwI7FSV6">
<mxGraphModel dx="778" dy="476" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/29.0.3 Chrome/140.0.7339.249 Electron/38.7.0 Safari/537.36" version="29.0.3">
<diagram name="Arquitetura SD" id="QKeTeUWuUs8JeLsq44d-">
<mxGraphModel dx="1426" dy="841" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="vcp7vux32DhQR4tKQhnF-8" value="Dashboard" style="sketch=0;pointerEvents=1;shadow=0;dashed=0;html=1;strokeColor=#C73500;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;align=center;fillColor=#fa6800;shape=mxgraph.mscae.oms.dashboard;fontColor=#000000;" vertex="1" parent="1">
<mxGeometry x="389" y="230" width="50" height="41" as="geometry" />
<mxCell id="0K4eb2koB2xQ8duQ1-_a-27" value="&lt;b&gt;MessageProtocol&lt;/b&gt;&lt;hr&gt;interface:&lt;br&gt;• getType()&lt;br&gt;• getPayload()&lt;br&gt;• getSourceNode()&lt;br&gt;• getDestinationNode()" style="rounded=0;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fillColor=#fff2cc;strokeColor=#d6b656;spacing=10;fontColor=#000000;" parent="1" vertex="1">
<mxGeometry x="30" y="30" width="180" height="120" as="geometry" />
</mxCell>
<mxCell id="vcp7vux32DhQR4tKQhnF-12" value="Semaforo.java" style="shape=image;html=1;verticalAlign=top;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;imageAspect=0;aspect=fixed;image=https://icons.diagrams.net/icon-cache1/Strabo-2829/traffic_light-1068.png" vertex="1" parent="1">
<mxGeometry x="230" y="350" width="53" height="53" as="geometry" />
<mxCell id="0K4eb2koB2xQ8duQ1-_a-28" value="&lt;b&gt;Tipos de Mensagens&lt;/b&gt;&lt;hr&gt;• VEHICLE_TRANSFER&lt;br&gt;• VEHICLE_SPAWN&lt;br&gt;• STATS_UPDATE&lt;br&gt;• TRAFFIC_LIGHT_SYNC&lt;br&gt;• HEARTBEAT" style="rounded=0;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fillColor=#fff2cc;strokeColor=#d6b656;spacing=10;fontColor=#000000;" parent="1" vertex="1">
<mxGeometry x="20" y="170" width="200" height="120" as="geometry" />
</mxCell>
<mxCell id="vcp7vux32DhQR4tKQhnF-13" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="310" y="330" as="sourcePoint" />
<mxPoint x="360" y="280" as="targetPoint" />
<mxCell id="0K4eb2koB2xQ8duQ1-_a-26" value="&lt;b&gt;LEGENDA&lt;/b&gt;&lt;hr&gt;━━━► Comunicação síncrona&lt;br&gt;╌╌╌► Comunicação periódica&lt;br&gt;&lt;br&gt;&lt;b&gt;Cores:&lt;/b&gt;&lt;br&gt;🔵 Azul =&amp;nbsp;&lt;span style=&quot;background-color: transparent;&quot;&gt;Criação do veículo&lt;/span&gt;&lt;div&gt;🟢 Verde = Transferência do veículo&lt;br&gt;🟠 Laranja = Chegada ao destino&lt;br&gt;🟣 Roxo =&amp;nbsp;&lt;span style=&quot;background-color: transparent;&quot;&gt;Envio das estatísticas&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;b&gt;Serialização:&lt;/b&gt; JSON (Gson)&lt;br&gt;&lt;b&gt;Protocolo:&lt;/b&gt; TCP/IP&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;align=left;verticalAlign=top;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#333333;spacing=10;" parent="1" vertex="1">
<mxGeometry x="10" y="320" width="220" height="220" as="geometry" />
</mxCell>
<mxCell id="L62mICw2ZrYi1D68OOFe-13" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="280" y="40" width="850" height="730" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-20" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#9933FF;strokeWidth=2;dashed=1;exitX=0.616;exitY=-0.011;exitDx=0;exitDy=0;entryX=0.661;entryY=-0.002;entryDx=0;entryDy=0;entryPerimeter=0;exitPerimeter=0;" parent="L62mICw2ZrYi1D68OOFe-13" source="0K4eb2koB2xQ8duQ1-_a-2" target="0K4eb2koB2xQ8duQ1-_a-8" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="794" y="530" as="targetPoint" />
<Array as="points">
<mxPoint x="99" y="122" />
<mxPoint x="793" y="122" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="vcp7vux32DhQR4tKQhnF-14" value="CruzamentoServer.java" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=1;points=[];movable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" vertex="1" connectable="0" parent="vcp7vux32DhQR4tKQhnF-13">
<mxGeometry x="-0.3933" relative="1" as="geometry">
<mxPoint x="25" y="25" as="offset" />
<mxCell id="0K4eb2koB2xQ8duQ1-_a-1" value="&lt;b&gt;CoordinatorProcess&lt;/b&gt;&lt;br&gt;(Cliente Socket)&lt;hr&gt;• VehicleGenerator&lt;br&gt;• Modelo Poisson&lt;br&gt;• Liga a Cr1-Cr5" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;verticalAlign=top;spacing=10;fontColor=#000000;" parent="L62mICw2ZrYi1D68OOFe-13" vertex="1">
<mxGeometry x="205.6637168141593" width="176.28318584070794" height="101.38888888888889" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-2" value="&lt;b&gt;Cr1&lt;/b&gt; (IntersectionProcess)&lt;br&gt;Porta: 8001&lt;br&gt;Servidor + Cliente&lt;hr&gt;• ServerSocket (8001)&lt;br&gt;• Thread Semáforo - Sul&lt;br&gt;• Thread Semáforo - Este&lt;br&gt;• Fila Eventos (DES)&lt;br&gt;• ReentrantLock" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;align=left;verticalAlign=top;spacing=10;fontColor=#000000;" parent="L62mICw2ZrYi1D68OOFe-13" vertex="1">
<mxGeometry y="162.22" width="160" height="162.22" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-3" value="&lt;b&gt;Cr2&lt;/b&gt; (IntersectionProcess)&lt;br&gt;Porta: 8002&lt;br&gt;Servidor + Cliente&lt;hr&gt;• ServerSocket (8002)&lt;br&gt;• Thread Semáforo - Sul&lt;br&gt;• Thread Semáforo - Este&lt;br&gt;• Thread Semáforo - Oeste&lt;br&gt;• Fila Eventos (DES)&lt;br&gt;• ReentrantLock" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;align=left;verticalAlign=top;spacing=10;fontColor=#000000;" parent="L62mICw2ZrYi1D68OOFe-13" vertex="1">
<mxGeometry x="227.7" y="162.22" width="162.3" height="162.22" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-5" value="&lt;b&gt;Cr4&lt;/b&gt; (IntersectionProcess)&lt;br&gt;Porta: 8004&lt;br&gt;Servidor + Cliente&lt;hr&gt;• ServerSocket (8004)&lt;br&gt;• Thread Semáforo - Este&lt;br&gt;• Fila Eventos (DES)&lt;br&gt;• ReentrantLock" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;align=left;verticalAlign=top;spacing=10;fontColor=#000000;" parent="L62mICw2ZrYi1D68OOFe-13" vertex="1">
<mxGeometry y="486.67" width="160" height="133.33" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-6" value="&lt;b&gt;Cr5&lt;/b&gt; (IntersectionProcess)&lt;br&gt;Porta: 8005&lt;br&gt;Servidor + Cliente&lt;hr&gt;• ServerSocket (8005)&lt;br&gt;• Thread Semáforo - Este&lt;br&gt;• Fila Eventos (DES)&lt;br&gt;• ReentrantLock" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;align=left;verticalAlign=top;spacing=10;fontColor=#000000;" parent="L62mICw2ZrYi1D68OOFe-13" vertex="1">
<mxGeometry x="220.35" y="486.67" width="169.65" height="162.22" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-7" value="&lt;b&gt;ExitNode (S)&lt;/b&gt;&lt;br&gt;Porta: 9001&lt;br&gt;Servidor Socket&lt;hr&gt;• Recebe veículos finais&lt;br&gt;• Calcula estatísticas:&lt;br&gt; - Tempo no sistema&lt;br&gt; - Tempo de espera&lt;br&gt; - Métricas por tipo&lt;br&gt;• Envia para o Dashboard" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;align=left;verticalAlign=top;spacing=10;fontColor=#000000;" parent="L62mICw2ZrYi1D68OOFe-13" vertex="1">
<mxGeometry x="464.07" y="476.53" width="154.6" height="172.36" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-8" value="&lt;b&gt;DashboardServer&lt;/b&gt;&lt;br&gt;Porta: 9000&lt;br&gt;Servidor Socket&lt;hr&gt;• Thread Pool (10 threads)&lt;br&gt;• ConcurrentHashMap&lt;br&gt;• Agrega estatísticas&lt;br&gt;• Display a cada 5s:&lt;br&gt; - Throughput&lt;br&gt; - Tempos médios&lt;br&gt; - Tamanhos de filas" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;align=left;verticalAlign=top;spacing=10;fontColor=#000000;" parent="L62mICw2ZrYi1D68OOFe-13" vertex="1">
<mxGeometry x="683.1" y="540" width="166.9" height="180" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-9" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#0000FF;strokeWidth=2;" parent="L62mICw2ZrYi1D68OOFe-13" source="0K4eb2koB2xQ8duQ1-_a-1" target="0K4eb2koB2xQ8duQ1-_a-2" edge="1">
<mxGeometry x="-0.2105" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-10" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#0000FF;strokeWidth=2;" parent="L62mICw2ZrYi1D68OOFe-13" source="0K4eb2koB2xQ8duQ1-_a-1" target="0K4eb2koB2xQ8duQ1-_a-3" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="309" y="120" />
<mxPoint x="309" y="120" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-11" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#0000FF;strokeWidth=2;" parent="L62mICw2ZrYi1D68OOFe-13" source="0K4eb2koB2xQ8duQ1-_a-1" target="0K4eb2koB2xQ8duQ1-_a-4" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-12" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#00AA00;strokeWidth=2;endArrow=classic;startArrow=classic;" parent="L62mICw2ZrYi1D68OOFe-13" source="0K4eb2koB2xQ8duQ1-_a-2" target="0K4eb2koB2xQ8duQ1-_a-3" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-13" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#00AA00;strokeWidth=2;endArrow=classic;startArrow=classic;" parent="L62mICw2ZrYi1D68OOFe-13" source="0K4eb2koB2xQ8duQ1-_a-3" target="0K4eb2koB2xQ8duQ1-_a-4" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-14" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#00AA00;strokeWidth=2;endArrow=classic;startArrow=none;startFill=0;" parent="L62mICw2ZrYi1D68OOFe-13" source="0K4eb2koB2xQ8duQ1-_a-2" target="0K4eb2koB2xQ8duQ1-_a-5" edge="1">
<mxGeometry x="0.125" y="100" relative="1" as="geometry">
<Array as="points">
<mxPoint x="66.10619469026548" y="446.11111111111114" />
<mxPoint x="66.10619469026548" y="446.11111111111114" />
</Array>
<mxPoint y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-16" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#00AA00;strokeWidth=2;endArrow=classic;startArrow=none;startFill=0;exitX=1.005;exitY=0.63;exitDx=0;exitDy=0;exitPerimeter=0;align=center;" parent="L62mICw2ZrYi1D68OOFe-13" source="0K4eb2koB2xQ8duQ1-_a-5" edge="1">
<mxGeometry x="-0.0178" y="-49" relative="1" as="geometry">
<mxPoint x="139.55752212389382" y="588.0555555555555" as="sourcePoint" />
<mxPoint x="220" y="571" as="targetPoint" />
<Array as="points">
<mxPoint x="220" y="571" />
</Array>
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-19" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#b46504;strokeWidth=2;fillColor=#fad7ac;" parent="L62mICw2ZrYi1D68OOFe-13" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="390" y="580" as="sourcePoint" />
<mxPoint x="462.74" y="580.22" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-22" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#9933FF;strokeWidth=2;dashed=1;exitX=0.981;exitY=0.08;exitDx=0;exitDy=0;exitPerimeter=0;" parent="L62mICw2ZrYi1D68OOFe-13" source="0K4eb2koB2xQ8duQ1-_a-4" target="0K4eb2koB2xQ8duQ1-_a-8" edge="1">
<mxGeometry x="0.1427" y="-60" relative="1" as="geometry">
<Array as="points">
<mxPoint x="593" y="175" />
<mxPoint x="593" y="140" />
<mxPoint x="764" y="140" />
</Array>
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-4" value="&lt;b&gt;Cr3&lt;/b&gt; (IntersectionProcess)&lt;br&gt;Porta: 8003&lt;br&gt;Servidor + Cliente&lt;hr&gt;• ServerSocket (8003)&lt;br&gt;• Thread Semáforo - Sul&lt;br&gt;• Thread Semáforo - Oeste&lt;br&gt;• Fila Eventos (DES)&lt;br&gt;• ReentrantLock" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;align=left;verticalAlign=top;spacing=10;fontColor=#000000;" parent="L62mICw2ZrYi1D68OOFe-13" vertex="1">
<mxGeometry x="462.74" y="162.22" width="167.26" height="162.22" as="geometry" />
</mxCell>
<mxCell id="0K4eb2koB2xQ8duQ1-_a-30" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#9933FF;strokeWidth=2;dashed=1;entryX=0.186;entryY=0.998;entryDx=0;entryDy=0;entryPerimeter=0;" parent="L62mICw2ZrYi1D68OOFe-13" target="0K4eb2koB2xQ8duQ1-_a-8" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="103" y="620" as="sourcePoint" />
<mxPoint x="710" y="730" as="targetPoint" />
<Array as="points">
<mxPoint x="103" y="730" />
<mxPoint x="714" y="730" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="L62mICw2ZrYi1D68OOFe-2" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#00AA00;strokeWidth=2;endArrow=none;startArrow=classic;startFill=1;endFill=0;" parent="L62mICw2ZrYi1D68OOFe-13" edge="1">
<mxGeometry x="-0.2214" y="26" relative="1" as="geometry">
<mxPoint x="293.8053097345133" y="486.6666666666666" as="sourcePoint" />
<mxPoint x="293.8053097345133" y="324.44444444444446" as="targetPoint" />
<Array as="points" />
<mxPoint x="-17" y="6" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="L62mICw2ZrYi1D68OOFe-3" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#b46504;strokeWidth=2;endArrow=classic;startArrow=none;startFill=0;fillColor=#fad7ac;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="L62mICw2ZrYi1D68OOFe-13" target="0K4eb2koB2xQ8duQ1-_a-7" edge="1">
<mxGeometry x="0.3659" relative="1" as="geometry">
<mxPoint as="offset" />
<mxPoint x="541" y="324" as="sourcePoint" />
<mxPoint x="528.8495575221239" y="435.9722222222221" as="targetPoint" />
<Array as="points">
<mxPoint x="541" y="360" />
<mxPoint x="541" y="360" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="L62mICw2ZrYi1D68OOFe-10" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#9933FF;strokeWidth=2;dashed=1;exitX=0.621;exitY=-0.003;exitDx=0;exitDy=0;exitPerimeter=0;" parent="L62mICw2ZrYi1D68OOFe-13" source="0K4eb2koB2xQ8duQ1-_a-3" edge="1">
<mxGeometry x="0.1427" y="-60" relative="1" as="geometry">
<mxPoint x="330.53097345132744" y="141.94444444444443" as="sourcePoint" />
<mxPoint x="780" y="540" as="targetPoint" />
<Array as="points">
<mxPoint x="329" y="130" />
<mxPoint x="780" y="130" />
</Array>
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="L62mICw2ZrYi1D68OOFe-11" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#9933FF;strokeWidth=2;dashed=1;" parent="L62mICw2ZrYi1D68OOFe-13" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="326" y="654" as="sourcePoint" />
<mxPoint x="683.1" y="700" as="targetPoint" />
<Array as="points">
<mxPoint x="326.1" y="700" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="L62mICw2ZrYi1D68OOFe-12" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#9933FF;strokeWidth=2;dashed=1;" parent="L62mICw2ZrYi1D68OOFe-13" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="556" y="650" as="sourcePoint" />
<mxPoint x="683.0973451327434" y="663.0833333333331" as="targetPoint" />
<Array as="points">
<mxPoint x="556" y="663" />
</Array>
</mxGeometry>
</mxCell>
</root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

BIN
Enunciado.pdf Normal file

Binary file not shown.

134
STEP2_SUMMARY.md Normal file
View File

@@ -0,0 +1,134 @@
# 🏁 Single-Process Prototype — Implementation Summary
**Status:** ✅ Complete
**Date:** October 22, 2025
**Branch:** `8-single-process-prototype`
---
## Overview
The single-process prototype implements a **discrete event simulation (DES)** of a 3×3 urban grid with five intersections, realistic vehicle behavior, and fully synchronized traffic lights. Everything runs under one process, laying the groundwork for the distributed architecture in Phase 3.
---
## Core Architecture
### **SimulationEngine**
Drives the DES loop with a priority queue of timestamped events — vehicles, lights, crossings, and periodic stats updates. Handles five intersections (Cr1Cr5) and six event types.
**Main loop:**
```
while (events && time < duration):
event = nextEvent()
time = event.timestamp
handle(event)
```
### **VehicleGenerator**
Spawns vehicles via:
* **Poisson arrivals** (λ = 0.5 veh/s) or fixed intervals
* **Probabilistic routes** from E1E3
* **Type distribution**: 20% BIKE, 60% LIGHT, 20% HEAVY
### **StatisticsCollector**
Tracks system-wide and per-type metrics: throughput, avg. wait, queue sizes, light cycles — updated every 10 s and at simulation end.
---
## Model Highlights
* **Vehicle** type, route, timings, lifecycle.
* **Intersection** routing tables, traffic lights, queues.
* **TrafficLight** red/green cycles with FIFO queues.
* **Event** timestamped, comparable; 6 types for all DES actions.
---
## Configuration (`simulation.properties`)
```properties
simulation.duration=60.0
simulation.arrival.model=POISSON
simulation.arrival.rate=0.5
vehicle.bike.crossingTime=1.5
vehicle.light.crossingTime=2.0
vehicle.heavy.crossingTime=4.0
statistics.update.interval=10.0
```
**Speed logic:**
`t_bike = 0.5×t_car`, `t_heavy = 2×t_car`.
---
## Topology
```
E1→Cr1→Cr4→Cr5→S
E2→Cr2→Cr5→S
E3→Cr3→S
Bi-dir: Cr1↔Cr2, Cr2↔Cr3
```
---
## Results
**Unit Tests:** 7/7 ✅
**60-Second Simulation:**
* Generated: 22 vehicles
* Completed: 5 (22.7%)
* Avg system time: 15.47 s
* Throughput: 0.08 veh/s
* All lights & intersections operational
**Performance:**
~0.03 s real-time run (≈2000× speed-up), < 50 MB RAM.
---
## Code Structure
```
sd/
├── engine/SimulationEngine.java
├── model/{Vehicle,Intersection,TrafficLight,Event}.java
├── util/{VehicleGenerator,StatisticsCollector}.java
└── config/SimulationConfig.java
```
---
## Key Flow
1. Initialize intersections, lights, first events.
2. Process events chronologically.
3. Vehicles follow routes queue cross exit.
4. Lights toggle, queues drain, stats update.
5. Print summary and performance metrics.
---
## Next Steps — Phase 3
* Split intersections into independent **processes**.
* Add **socket-based communication**.
* Run **traffic lights as threads**.
* Enable **distributed synchronization** and fault handling.
---
## TL;DR
Solid single-process DES
Everythings working traffic lights, routing, vehicles, stats.
Ready to go distributed next.

27
TODO.md
View File

@@ -1,3 +1,26 @@
## ✅ SINGLE-PROCESS PROTOTYPE - COMPLETED
### Phase 2 Status: DONE ✅
All components for the single-process prototype have been successfully implemented and tested:
-**SimulationEngine** - Priority queue-based discrete event simulation
-**VehicleGenerator** - Poisson and Fixed arrival models
-**StatisticsCollector** - Comprehensive metrics tracking
-**Entry point** - Main simulation runner
-**60s test simulation** - Successfully validated event processing and routing
### Test Results:
- All 7 unit tests passing
- 60-second simulation completed successfully
- Generated 22 vehicles with 5 completing their routes
- Traffic light state changes working correctly
- Vehicle routing through intersections validated
---
## NEXT: Distributed Architecture Implementation
### Compreender os Conceitos Fundamentais
Primeiro, as tecnologias e paradigmas chave necessários para este projeto devem ser totalmente compreendidos.
@@ -16,7 +39,7 @@ Primeiro, as tecnologias e paradigmas chave necessários para este projeto devem
- 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.
- **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.
---
@@ -172,4 +195,4 @@ Assim que o sistema completo estiver a funcionar, as experiências exigidas pela
- **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.
- **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.

View File

@@ -42,6 +42,26 @@
<mainClass>sd.Entry</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>sd.Entry</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

View File

@@ -31,7 +31,7 @@ public class SimulationConfig {
* (por exemplo quando executado a partir do classpath/jar),
* faz fallback para carregar a partir do classpath usando o ClassLoader.
*/
IOException lastException = null;
IOException lastException = null; //FIXME: melhorar esta parte para reportar erros de forma mais clara
try {
try (InputStream input = new FileInputStream(filePath)) {

View File

@@ -264,32 +264,19 @@ public class SimulationEngine {
*/
private void processEvent(Event event) {
switch (event.getType()) {
case VEHICLE_GENERATION:
handleVehicleGeneration();
break;
case VEHICLE_GENERATION -> handleVehicleGeneration();
case VEHICLE_ARRIVAL:
handleVehicleArrival(event);
break;
case VEHICLE_ARRIVAL -> handleVehicleArrival(event);
case TRAFFIC_LIGHT_CHANGE:
handleTrafficLightChange(event);
break;
case TRAFFIC_LIGHT_CHANGE -> handleTrafficLightChange(event);
case CROSSING_START:
handleCrossingStart(event);
break;
case CROSSING_START -> handleCrossingStart(event);
case CROSSING_END:
handleCrossingEnd(event);
break;
case CROSSING_END -> handleCrossingEnd(event);
case STATISTICS_UPDATE:
handleStatisticsUpdate();
break;
case STATISTICS_UPDATE -> handleStatisticsUpdate();
default:
System.err.println("Unknown event type: " + event.getType());
default -> System.err.println("Unknown event type: " + event.getType());
}
}
@@ -386,7 +373,7 @@ public class SimulationEngine {
* @param vehicle The vehicle to process.
* @param intersection The intersection where the vehicle is.
*/
private void tryProcessVehicle(Vehicle vehicle, Intersection intersection) {
private void tryProcessVehicle(Vehicle vehicle, Intersection intersection) { //FIXME
// Find the direction (and light) this vehicle is queued at
// This logic is a bit flawed: it just finds the *first* non-empty queue
// A better approach would be to get the light from the vehicle's route
@@ -591,16 +578,12 @@ public class SimulationEngine {
* @return The crossing time in seconds.
*/
private double getCrossingTime(VehicleType type) {
switch (type) {
case BIKE:
return config.getBikeVehicleCrossingTime();
case LIGHT:
return config.getLightVehicleCrossingTime();
case HEAVY:
return config.getHeavyVehicleCrossingTime();
default:
return 2.0; // Default fallback
}
return switch (type) {
case BIKE -> config.getBikeVehicleCrossingTime();
case LIGHT -> config.getLightVehicleCrossingTime();
case HEAVY -> config.getHeavyVehicleCrossingTime();
default -> 2.0;
}; // Default fallback
}
/**

View File

@@ -43,7 +43,7 @@ class SimulationTest {
assertEquals("TEST1", vehicle.getId());
assertNotNull(vehicle.getType());
assertNotNull(vehicle.getRoute());
assertTrue(vehicle.getRoute().size() > 0);
assertTrue(!vehicle.getRoute().isEmpty());
}
@Test