diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..fc0ac63
Binary files /dev/null and b/.DS_Store differ
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/VictimSim.iml b/.idea/VictimSim.iml
new file mode 100644
index 0000000..8e5446a
--- /dev/null
+++ b/.idea/VictimSim.iml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..3f3e15f
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..401c506
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/datasets/.DS_Store b/datasets/.DS_Store
new file mode 100644
index 0000000..961a5ca
Binary files /dev/null and b/datasets/.DS_Store differ
diff --git a/datasets/data_12x12_10vic/env_size.txt b/datasets/data_12x12_10vic/env_size.txt
index e9d492a..9992dd6 100644
--- a/datasets/data_12x12_10vic/env_size.txt
+++ b/datasets/data_12x12_10vic/env_size.txt
@@ -3,4 +3,4 @@ GRID_WIDTH 12
GRID_HEIGHT 12
WINDOW_WIDTH 300
WINDOW_HEIGHT 300
-DELAY 0.01
\ No newline at end of file
+DELAY 0.1
\ No newline at end of file
diff --git a/datasets/data_20x20_42vic/env_size.txt b/datasets/data_20x20_42vic/env_size.txt
index 07b33b3..55312f8 100644
--- a/datasets/data_20x20_42vic/env_size.txt
+++ b/datasets/data_20x20_42vic/env_size.txt
@@ -1,6 +1,6 @@
-BASE 0,0
+BASE 10,10
GRID_WIDTH 20
GRID_HEIGHT 20
WINDOW_WIDTH 400
WINDOW_HEIGHT 400
-DELAY 0.02
\ No newline at end of file
+DELAY 0.01
\ No newline at end of file
diff --git a/datasets/data_20x20_42vic/explorer_config.txt b/datasets/data_20x20_42vic/explorer_config.txt
index db3e9c3..33250da 100644
--- a/datasets/data_20x20_42vic/explorer_config.txt
+++ b/datasets/data_20x20_42vic/explorer_config.txt
@@ -1,7 +1,7 @@
NAME EXPLORER
COLOR (0, 0, 255)
TRACE_COLOR (153, 153, 255)
-TLIM 600
+TLIM 100
COST_LINE 1.0
COST_DIAG 1.5
COST_READ 2.0
diff --git a/datasets/data_teste_sala/env_size.txt b/datasets/data_teste_sala/env_size.txt
new file mode 100644
index 0000000..b09115e
--- /dev/null
+++ b/datasets/data_teste_sala/env_size.txt
@@ -0,0 +1,6 @@
+BASE 25,33
+GRID_WIDTH 100
+GRID_HEIGHT 80
+WINDOW_WIDTH 940
+WINDOW_HEIGHT 720
+DELAY 0.02
\ No newline at end of file
diff --git a/datasets/data_teste_sala/env_victims.txt b/datasets/data_teste_sala/env_victims.txt
new file mode 100644
index 0000000..44b320a
--- /dev/null
+++ b/datasets/data_teste_sala/env_victims.txt
@@ -0,0 +1,132 @@
+0,47
+0,74
+0,77
+2,48
+2,75
+4,78
+4,79
+5,1
+5,5
+5,40
+5,43
+6,2
+7,39
+7,69
+9,20
+10,0
+13,4
+13,10
+13,21
+14,39
+16,2
+16,23
+17,20
+18,42
+20,8
+20,16
+20,21
+20,25
+21,2
+23,13
+25,16
+26,12
+26,14
+28,2
+28,68
+28,75
+30,58
+32,72
+33,8
+33,62
+34,8
+35,9
+35,54
+36,7
+36,50
+36,72
+37,23
+37,32
+37,48
+38,47
+38,70
+39,12
+39,52
+40,49
+40,74
+41,37
+41,41
+42,77
+43,4
+43,66
+44,12
+44,14
+44,51
+44,65
+45,29
+45,53
+45,75
+45,78
+47,19
+47,49
+48,50
+48,58
+49,8
+50,16
+50,61
+52,1
+52,22
+53,45
+54,42
+56,6
+57,28
+58,13
+59,3
+61,22
+65,15
+66,31
+66,58
+66,61
+67,30
+68,10
+68,27
+69,29
+69,33
+69,39
+69,60
+70,77
+72,12
+72,20
+72,74
+74,6
+75,75
+76,27
+76,61
+77,9
+79,13
+79,17
+79,29
+79,69
+79,78
+82,13
+83,17
+83,67
+85,20
+86,6
+87,74
+89,70
+90,18
+91,23
+91,77
+92,53
+92,66
+95,31
+96,12
+96,23
+96,29
+97,13
+97,41
+97,71
+98,25
+98,35
+98,52
+98,74
diff --git a/datasets/data_teste_sala/env_walls.txt b/datasets/data_teste_sala/env_walls.txt
new file mode 100644
index 0000000..6859146
--- /dev/null
+++ b/datasets/data_teste_sala/env_walls.txt
@@ -0,0 +1,856 @@
+0,0
+0,44
+0,48
+0,60
+0,79
+1,1
+1,61
+1,78
+1,79
+2,2
+2,51
+2,62
+2,77
+2,78
+3,43
+3,45
+3,63
+3,76
+3,77
+4,6
+4,40
+4,53
+4,63
+4,64
+4,65
+4,75
+4,76
+5,7
+5,37
+5,38
+5,39
+5,45
+5,65
+5,74
+5,75
+6,8
+6,37
+6,47
+6,53
+6,66
+6,73
+6,74
+7,9
+7,27
+7,28
+7,29
+7,30
+7,31
+7,32
+7,36
+7,37
+7,49
+7,51
+7,67
+7,72
+7,73
+8,0
+8,1
+8,2
+8,3
+8,4
+8,5
+8,6
+8,7
+8,8
+8,9
+8,10
+8,26
+8,27
+8,33
+8,36
+8,71
+8,72
+9,26
+9,33
+9,36
+9,70
+9,71
+10,26
+10,34
+10,35
+10,36
+10,68
+10,69
+10,70
+11,26
+11,36
+12,26
+12,36
+12,38
+12,39
+13,36
+13,37
+13,40
+14,37
+15,43
+16,8
+16,9
+16,10
+16,12
+16,14
+16,16
+16,38
+17,6
+17,7
+17,8
+17,12
+17,17
+17,39
+17,45
+18,5
+18,7
+18,12
+18,14
+18,40
+19,7
+19,12
+19,14
+19,18
+19,45
+20,4
+20,14
+20,18
+20,41
+20,44
+20,60
+21,42
+21,60
+22,3
+22,19
+22,20
+22,29
+22,30
+22,31
+22,32
+22,33
+22,34
+22,35
+22,36
+22,37
+22,38
+22,61
+23,2
+23,20
+23,29
+23,38
+23,61
+24,20
+24,29
+24,38
+24,62
+25,2
+25,14
+25,19
+25,29
+25,38
+25,62
+25,64
+25,66
+25,68
+25,70
+25,72
+25,74
+25,76
+25,77
+25,78
+26,3
+26,11
+26,19
+26,29
+26,36
+26,38
+26,62
+26,78
+27,24
+27,25
+27,26
+27,27
+27,28
+27,29
+27,35
+27,36
+27,38
+27,63
+27,67
+27,70
+27,78
+28,4
+28,18
+28,24
+28,26
+28,27
+28,28
+28,34
+28,35
+28,36
+28,38
+28,60
+28,63
+28,67
+28,70
+28,76
+28,77
+28,78
+29,18
+29,24
+29,25
+29,26
+29,27
+29,28
+29,32
+29,33
+29,34
+29,35
+29,36
+29,60
+29,63
+29,64
+29,67
+29,70
+29,76
+30,5
+30,16
+30,17
+30,24
+30,26
+30,27
+30,28
+30,31
+30,32
+30,33
+30,34
+30,35
+30,36
+30,60
+30,61
+30,64
+30,67
+30,68
+30,69
+30,70
+30,71
+30,72
+30,73
+30,74
+30,76
+31,3
+31,4
+31,6
+31,8
+31,10
+31,12
+31,14
+31,16
+31,24
+31,25
+31,26
+31,27
+31,28
+31,56
+31,60
+31,61
+31,64
+31,70
+31,74
+31,76
+32,3
+32,4
+32,7
+32,9
+32,11
+32,13
+32,15
+32,28
+32,29
+32,56
+32,57
+32,59
+32,60
+32,64
+32,65
+32,70
+32,74
+32,76
+33,3
+33,5
+33,10
+33,12
+33,57
+33,58
+33,59
+33,65
+33,70
+34,2
+34,3
+34,4
+34,6
+34,11
+34,48
+34,49
+34,50
+34,57
+34,58
+34,65
+34,66
+34,70
+34,71
+34,72
+35,2
+35,3
+35,4
+35,7
+35,10
+35,46
+35,47
+35,48
+35,50
+35,51
+35,52
+35,57
+35,58
+35,66
+35,71
+35,72
+35,75
+35,76
+35,77
+35,78
+35,79
+36,3
+36,8
+36,46
+36,47
+36,52
+36,59
+36,66
+36,67
+36,68
+36,71
+37,3
+37,9
+37,10
+37,44
+37,45
+37,46
+37,52
+37,53
+37,59
+37,60
+37,66
+37,67
+37,71
+37,72
+37,73
+37,74
+37,75
+37,76
+37,77
+37,78
+38,10
+38,42
+38,43
+38,44
+38,53
+38,54
+38,60
+38,67
+38,78
+39,10
+39,42
+39,43
+39,54
+39,60
+39,61
+39,67
+39,68
+39,72
+39,73
+39,74
+39,75
+39,76
+39,78
+40,11
+40,12
+40,54
+40,61
+40,62
+40,68
+40,72
+40,76
+40,78
+41,11
+41,14
+41,54
+41,55
+41,62
+41,68
+41,69
+41,72
+41,74
+41,75
+41,76
+41,78
+42,10
+42,12
+42,27
+42,55
+42,56
+42,62
+42,63
+42,69
+42,72
+42,74
+42,78
+43,9
+43,15
+43,16
+43,28
+43,29
+43,30
+43,31
+43,56
+43,57
+43,62
+43,63
+43,69
+43,70
+43,72
+43,74
+43,75
+43,76
+43,77
+43,78
+44,8
+44,28
+44,31
+44,34
+44,35
+44,36
+44,37
+44,42
+44,43
+44,57
+44,58
+44,63
+44,69
+44,70
+44,72
+45,7
+45,17
+45,28
+45,31
+45,34
+45,36
+45,37
+45,44
+45,58
+45,59
+45,63
+45,64
+45,67
+45,68
+45,69
+45,72
+45,76
+46,8
+46,9
+46,11
+46,13
+46,14
+46,22
+46,25
+46,28
+46,31
+46,34
+46,37
+46,45
+46,59
+46,60
+46,64
+46,65
+46,66
+46,67
+46,71
+46,72
+46,73
+46,74
+46,75
+46,76
+46,77
+46,78
+46,79
+47,25
+47,28
+47,30
+47,31
+47,34
+47,37
+47,46
+47,60
+47,64
+47,65
+48,25
+48,26
+48,27
+48,28
+48,30
+48,34
+48,36
+48,37
+48,47
+48,60
+48,62
+48,63
+48,64
+49,30
+49,31
+49,32
+49,33
+49,34
+49,36
+49,48
+49,59
+49,60
+49,61
+49,62
+50,36
+50,49
+50,57
+50,58
+50,59
+51,36
+51,38
+51,39
+51,40
+51,41
+51,42
+51,43
+51,44
+51,45
+51,46
+51,47
+51,48
+51,49
+51,55
+51,56
+51,57
+52,36
+52,53
+52,54
+52,55
+53,36
+53,51
+53,52
+53,53
+54,10
+54,49
+54,50
+54,51
+55,14
+55,47
+55,48
+55,49
+56,15
+56,45
+56,46
+56,47
+57,44
+57,45
+57,51
+57,55
+57,58
+57,59
+57,67
+58,17
+58,40
+58,41
+58,42
+58,43
+58,68
+59,39
+59,40
+59,41
+59,69
+60,37
+60,38
+60,39
+60,70
+61,17
+61,35
+61,36
+61,37
+61,45
+61,71
+62,35
+62,43
+62,45
+62,58
+62,60
+62,61
+62,73
+63,32
+63,33
+63,34
+63,35
+63,57
+63,62
+63,74
+63,78
+64,17
+64,32
+64,56
+64,63
+64,75
+65,29
+65,30
+65,31
+65,32
+65,55
+65,64
+65,75
+66,26
+66,27
+66,28
+66,29
+66,48
+66,55
+66,64
+67,15
+67,26
+67,53
+67,55
+67,64
+67,74
+68,14
+68,23
+68,24
+68,25
+68,26
+68,55
+68,64
+68,72
+69,10
+69,11
+69,13
+69,23
+69,24
+69,25
+69,26
+69,27
+69,55
+69,64
+69,70
+69,72
+70,3
+70,4
+70,5
+70,6
+70,7
+70,8
+70,9
+70,10
+70,27
+70,28
+70,29
+70,30
+70,31
+70,56
+70,63
+70,69
+71,2
+71,31
+71,32
+71,57
+71,62
+72,1
+72,32
+72,33
+72,58
+72,59
+72,60
+72,61
+72,68
+73,1
+73,33
+73,34
+73,67
+74,1
+74,34
+74,35
+74,54
+74,55
+74,56
+74,57
+74,58
+74,59
+74,60
+74,61
+74,62
+74,63
+74,68
+75,1
+75,15
+75,35
+75,36
+75,37
+75,63
+75,70
+76,1
+76,15
+76,37
+76,38
+76,63
+77,2
+77,15
+77,38
+77,39
+77,63
+77,73
+78,2
+78,3
+78,15
+78,39
+78,40
+78,41
+78,43
+78,45
+78,63
+79,3
+79,4
+79,5
+79,15
+79,40
+79,49
+79,63
+79,66
+80,5
+80,6
+80,15
+80,36
+80,66
+80,67
+80,74
+81,6
+81,9
+81,10
+81,11
+81,12
+81,13
+81,14
+81,15
+81,16
+81,17
+81,18
+81,19
+81,20
+81,21
+81,22
+81,23
+81,24
+81,66
+81,68
+82,15
+82,16
+82,66
+82,69
+82,76
+83,15
+83,33
+83,49
+83,66
+83,70
+84,15
+84,66
+85,15
+85,28
+85,77
+86,15
+86,47
+86,68
+87,15
+87,29
+87,30
+87,68
+87,69
+87,78
+88,15
+88,68
+88,70
+89,15
+89,32
+89,45
+89,68
+89,71
+89,79
+90,14
+90,28
+90,33
+90,36
+90,68
+91,14
+91,42
+91,68
+92,14
+92,35
+92,68
+93,14
+93,20
+93,21
+93,22
+93,23
+93,24
+93,25
+93,26
+93,27
+93,28
+93,29
+93,30
+93,31
+93,32
+93,33
+93,34
+93,35
+93,68
+94,14
+94,20
+94,21
+94,35
+94,68
+95,14
+95,20
+95,35
+95,36
+95,37
+95,68
+95,70
+96,14
+96,20
+96,35
+96,36
+96,37
+96,70
+96,71
+97,20
+97,37
+97,38
+97,39
+97,70
+97,72
+98,13
+98,20
+98,39
+98,70
+99,13
+99,39
+99,70
diff --git a/datasets/data_teste_sala/explorer_config.txt b/datasets/data_teste_sala/explorer_config.txt
new file mode 100644
index 0000000..3a28974
--- /dev/null
+++ b/datasets/data_teste_sala/explorer_config.txt
@@ -0,0 +1,8 @@
+NAME EXPLORER
+COLOR (0, 0, 255)
+TRACE_COLOR (153, 153, 255)
+TLIM 1000
+COST_LINE 1.0
+COST_DIAG 1.5
+COST_READ 2.0
+COST_FIRST_AID 1.0
diff --git a/datasets/data_teste_sala/rescuer_config.txt b/datasets/data_teste_sala/rescuer_config.txt
new file mode 100644
index 0000000..ceeff24
--- /dev/null
+++ b/datasets/data_teste_sala/rescuer_config.txt
@@ -0,0 +1,8 @@
+NAME RESCUER
+COLOR (255, 0, 127)
+TRACE_COLOR (255, 153, 204)
+TLIM 1000
+COST_LINE 1.0
+COST_DIAG 1.5
+COST_READ 2.0
+COST_FIRST_AID 1.0
diff --git a/datasets/data_teste_sala/sinais_vitais.txt b/datasets/data_teste_sala/sinais_vitais.txt
new file mode 100644
index 0000000..12a2db2
--- /dev/null
+++ b/datasets/data_teste_sala/sinais_vitais.txt
@@ -0,0 +1,132 @@
+1,18.907009,12.220855,8.733333,134.454047,17.972046,34.192304,2
+2,14.698109,13.586879,8.614814,86.302237,4.168373,40.000000,2
+3,16.428095,1.904802,-4.333333,138.880782,2.721256,27.122605,2
+4,14.616501,13.700638,8.602531,51.356913,18.061923,47.188993,2
+5,10.955766,9.485389,-0.000000,1.951730,14.033748,68.333333,3
+6,14.621462,1.463106,-4.362660,106.456614,0.354636,41.428771,2
+7,10.037773,4.177473,-3.780947,55.878393,19.711002,50.696989,3
+8,17.223722,8.203223,4.666667,189.246031,11.338251,37.278451,2
+9,20.084017,14.362603,8.733333,181.288653,11.979483,31.981457,2
+10,18.862776,14.473328,8.733333,78.536915,13.341729,63.470950,3
+11,16.895326,2.364196,-4.337934,4.971047,16.729597,46.806638,2
+12,16.306264,14.558892,8.733333,134.287359,18.817631,31.196184,2
+13,19.974414,14.357504,8.733333,167.434127,8.423106,13.222719,1
+14,21.567229,7.280635,4.666667,194.299928,1.862282,25.170490,2
+15,20.669863,12.004207,8.733333,11.386577,16.145213,39.496205,2
+16,3.841922,2.128295,0.000000,90.064763,7.303765,68.268108,3
+17,12.069793,6.326419,0.211387,116.494060,18.474490,62.226541,3
+18,16.787080,13.736033,8.733333,137.327563,8.177913,13.222719,1
+19,18.813468,11.883110,8.710609,143.886551,18.220736,32.960275,2
+20,18.941295,14.392386,8.733333,130.008150,3.883410,19.327424,1
+21,19.437846,9.836110,4.749161,145.382910,2.849437,24.652787,1
+22,8.427097,0.535675,-5.509081,74.769533,19.357439,69.419681,3
+23,14.645388,12.736940,8.606922,116.316417,0.969741,29.251559,2
+24,14.702373,14.009899,8.615446,23.223703,15.107840,40.000000,2
+25,19.304493,10.181027,4.982862,11.530872,16.143004,46.018998,2
+26,13.553224,11.366102,5.639167,195.953045,9.617794,17.943211,1
+27,15.360904,11.146987,8.696152,56.964745,8.356456,33.697171,2
+28,14.776196,5.883405,4.468720,118.994860,21.552464,42.904831,2
+29,12.618033,9.832168,1.569744,192.432206,8.777855,36.655909,2
+30,15.042119,2.567800,-4.348994,37.155653,9.684112,31.615823,2
+31,16.118277,10.590691,6.418728,38.607963,3.449774,20.577727,1
+32,3.745589,0.477493,0.000000,68.328821,7.172754,66.339246,3
+33,18.108324,4.153845,-0.744046,186.579579,6.909362,38.470552,2
+34,2.836233,0.692571,0.000000,78.133507,19.679015,85.495664,4
+35,7.497988,1.456977,-6.713589,54.643342,5.434532,32.185656,2
+36,14.642074,12.351867,8.606421,30.389416,6.834938,13.263466,1
+37,16.568640,10.422429,5.728301,79.421769,8.995116,41.948075,2
+38,6.334251,4.756492,-0.635086,74.944493,15.576240,85.297977,4
+39,17.393175,14.253331,8.733333,26.222941,3.160027,13.222719,1
+40,2.769136,0.516691,0.000000,87.008144,19.169085,84.912249,4
+41,8.312453,6.581165,0.000000,18.302633,1.829430,40.000000,2
+42,18.491214,5.723377,4.833042,122.925392,10.158232,36.525665,2
+43,14.549269,11.482752,7.155830,2.195818,0.668559,13.896490,1
+44,18.006788,11.927999,8.722314,114.652077,16.570412,51.829730,3
+45,21.317025,2.803089,-4.352375,157.945972,15.400939,67.990734,3
+46,13.683900,7.346466,3.297574,47.073355,4.719269,45.111710,2
+47,17.324761,6.683793,4.681215,89.603943,14.957903,71.874432,3
+48,19.023338,9.694695,4.726229,113.871637,12.260439,49.589482,2
+49,15.555085,10.640472,6.638480,12.280288,18.714936,30.977739,2
+50,18.320822,11.320300,8.617869,99.257777,12.288441,51.822081,3
+51,6.100560,4.140376,-4.094402,128.463047,19.839021,41.337470,2
+52,21.218071,10.195540,5.011175,44.253146,9.229389,34.489500,2
+53,12.108530,9.826470,0.325684,167.411289,7.878824,39.334247,2
+54,7.645853,2.439176,-6.397811,194.215046,10.757725,32.113758,2
+55,17.913132,1.784965,-4.333333,169.274578,5.631167,27.122605,2
+56,14.557681,7.475461,4.238231,101.199891,20.441724,49.903183,2
+57,20.243195,14.396159,8.733333,55.775122,10.268650,34.918227,2
+58,11.796009,5.105786,-0.000000,149.323444,5.588173,40.000000,2
+59,12.387536,8.779016,1.056502,47.386077,9.486806,50.144025,3
+60,4.051338,3.357179,0.000000,191.469056,15.455660,68.333333,3
+61,18.494130,11.269006,8.646427,124.052007,8.851257,24.653839,1
+62,11.633148,3.826427,-4.462620,120.052429,4.000482,38.454967,2
+63,14.099209,7.589356,3.764001,34.520900,18.837525,42.806290,2
+64,17.507954,10.486151,5.983553,18.069348,12.852427,35.693471,2
+65,13.876582,13.363549,8.473727,51.052441,8.218733,30.674276,2
+66,16.792895,14.389371,8.733333,171.714106,4.877280,13.222719,1
+67,18.865437,8.208233,4.666667,182.213411,4.817871,25.170490,2
+68,15.952753,2.079367,-4.333726,139.926753,11.489114,41.990883,2
+69,4.716048,2.239410,0.000000,145.036471,9.535300,40.000000,2
+70,6.223230,3.862624,-8.401810,45.977216,16.308688,50.358357,3
+71,13.477877,12.610759,8.393752,115.210691,1.549892,29.784412,2
+72,3.956451,3.814233,0.000000,162.125621,18.641336,55.267187,3
+73,16.354706,12.214272,8.733333,80.768674,14.957365,68.308631,3
+74,15.680758,3.652875,-4.398136,197.687853,3.006333,26.758771,2
+75,19.766466,13.938954,8.733333,17.999763,18.884848,30.048193,2
+76,14.147642,5.249756,3.815389,64.188207,4.396351,48.559575,2
+77,5.022027,2.948929,-8.620209,102.281788,13.361478,59.889172,3
+78,15.285723,3.766258,-4.406177,12.121273,11.946990,40.934288,2
+79,10.854724,9.240670,-0.000000,145.137585,3.571143,40.000000,2
+80,9.100542,7.099333,-0.000000,111.311150,0.124367,55.439661,3
+81,6.923889,5.274893,-0.000000,105.871980,16.972673,72.608126,3
+82,13.817024,12.462429,8.461833,165.996486,16.825326,37.177427,2
+83,11.003418,8.778961,-0.000000,171.751807,9.263526,40.000000,2
+84,10.945090,8.245854,-0.000000,157.805785,1.249890,40.000000,2
+85,16.374603,13.757905,8.733333,63.566611,12.886434,55.577327,3
+86,9.892307,4.287585,-3.011415,90.441491,3.831415,55.818306,3
+87,13.673311,11.358003,5.795235,150.445594,16.029435,41.349520,2
+88,13.990594,11.305936,6.257891,21.972341,11.754403,30.744626,2
+89,20.255351,5.706688,4.835485,21.948474,5.567414,24.092859,1
+90,17.998655,8.517325,4.666667,53.976733,20.175248,42.607589,2
+91,12.731722,1.137814,-4.397289,104.927469,16.680280,61.873631,3
+92,4.717539,0.809252,0.000000,194.530215,19.514676,48.018356,2
+93,10.938460,7.961963,-0.000000,142.081737,1.513560,40.000000,2
+94,12.485147,11.687508,5.837070,62.371989,4.037620,36.670451,2
+95,21.311279,14.010160,8.733333,58.291426,16.215598,57.538745,3
+96,16.119228,1.948593,-4.333333,170.071467,15.327727,67.989083,3
+97,16.044459,8.532355,4.666667,182.329485,17.093844,43.584188,2
+98,11.729488,7.040860,-0.000000,127.855229,11.041875,53.286788,3
+99,3.805337,0.178531,0.000000,51.074060,9.360930,54.637262,3
+100,15.603911,5.056840,4.672637,17.733168,13.447217,45.907548,2
+101,21.763916,2.432735,-4.339415,167.651118,18.826982,42.988034,2
+102,13.633200,11.914268,6.971202,116.943724,14.757536,52.869162,3
+103,9.136223,4.668226,-1.140008,189.621747,11.519025,49.401727,2
+104,13.511758,7.927997,3.082556,12.205786,6.573939,32.481027,2
+105,3.928759,2.484731,0.000000,116.928261,15.487320,75.708580,4
+106,17.902640,9.029729,4.667063,57.021617,8.395439,40.144849,2
+107,11.209864,3.944569,-4.629273,165.546435,12.489070,49.011064,2
+108,21.790781,9.811186,4.744786,38.197288,19.532941,38.674387,2
+109,15.028400,10.338218,5.396578,88.505992,18.544884,55.870930,3
+110,17.911706,11.222274,8.669639,78.682301,19.773568,44.240630,2
+111,9.111009,6.758124,-0.000000,165.314796,20.658068,40.000000,2
+112,9.167442,1.257321,-5.098045,135.374219,17.939573,47.646390,2
+113,6.426162,3.434655,-8.513265,41.520607,0.029872,23.268835,1
+114,19.992348,13.700060,8.733333,63.620945,0.067995,36.768421,2
+115,19.459042,2.285670,-4.336124,26.762197,1.924314,27.107022,2
+116,15.759182,12.387255,8.724978,134.292578,5.736002,14.175797,1
+117,17.621128,8.075137,4.666667,114.198215,0.501571,37.221759,2
+118,17.018116,14.942021,8.733333,33.953413,9.329866,13.585059,1
+119,12.224244,1.172633,-4.379033,29.531155,7.503429,26.866534,2
+120,19.426052,6.640174,4.685234,95.215944,11.909787,55.664525,3
+121,13.788716,1.599792,-4.398726,181.620483,20.375720,26.755431,2
+122,16.967291,14.428471,8.733333,110.435005,6.566988,31.905775,2
+123,6.631664,0.069513,-8.661248,6.587979,7.437865,13.245825,1
+124,16.319912,11.623657,8.583405,10.772585,18.908562,29.902073,2
+125,16.376308,12.259548,8.733333,161.012646,7.490523,13.222719,1
+126,16.255938,13.030421,8.733333,90.274971,3.038649,39.884135,2
+127,12.842428,1.266538,-4.402501,76.529246,11.171577,55.821514,3
+128,17.879886,5.996740,4.778407,157.928741,18.846442,36.597067,2
+129,11.579341,3.898056,-4.488050,72.857374,8.454900,49.378694,2
+130,16.294144,12.001027,8.733333,106.469987,15.305200,57.604290,3
+131,8.410331,6.471207,-0.000000,142.331341,13.813892,66.823875,3
+132,13.863501,13.659714,8.471160,174.295304,9.908539,14.083613,1
diff --git a/environment.py b/environment.py
index 7a30200..c733b43 100644
--- a/environment.py
+++ b/environment.py
@@ -9,6 +9,7 @@
import time
from abstract_agent import AbstractAgent
from physical_agent import PhysAgent
+from fuzzy import Fuzzy
## Class Environment
@@ -47,6 +48,8 @@ def __init__(self, data_folder):
self.found = [[]] # positional: Physical agents that found each victim [[ag1] [ag2, ag3], ...] ag1 found vict 0, ag2 and 3, vict 1, ...
self.saved = [[]] # positional: Physical agents that saved each victim
+ self.fuz = Fuzzy() #Cria objeto fuzzy
+
# Read the environment config file
self.__read_config()
# print(self.dic)
@@ -104,6 +107,15 @@ def __init__(self, data_folder):
if self.nb_of_victims < len(self.signals):
print("from env: nb of victims of env_victims.txt less than vital signals")
print("from env: Assuming nb of victims of env_victims.txt")
+
+ victims = [[var[3], var[4], var[5]] for var in self.signals] #Cria vetor de vitimas contendo variaveis pressao, batimentos e respiração
+ out = self.fuz.defuzzyfy(victims) #Saida do fuzzy
+
+ real_gravity = [] #Vetor com grupos originais, para comparação
+ for vic in self.signals:
+ real_gravity.append(vic[7])
+
+ self.fuz.measurement(out,real_gravity) #Realiza as contas entre o vetor inferido e o original
# Set up found and saved victims' lists
self.found = [[] for v in range(self.nb_of_victims)]
@@ -343,6 +355,3 @@ def print_results(self):
saved = body.get_saved_victims()
self.__print_victims(saved, "saved","s")
-
-
-
diff --git a/explorer.py b/explorer.py
index 414677c..fdf3292 100644
--- a/explorer.py
+++ b/explorer.py
@@ -7,11 +7,14 @@
import random
from abstract_agent import AbstractAgent
from physical_agent import PhysAgent
+from map import Map
from abc import ABC, abstractmethod
-
+import heapq
+from node import Node
+import time
class Explorer(AbstractAgent):
- def __init__(self, env, config_file, resc):
+ def __init__(self, env, config_file, resc, path_priorities):
""" Construtor do agente random on-line
@param env referencia o ambiente
@config_file: the absolute path to the explorer's config file
@@ -22,56 +25,256 @@ def __init__(self, env, config_file, resc):
# Specific initialization for the rescuer
self.resc = resc # reference to the rescuer agent
- self.rtime = self.TLIM # remaining time to explore
+ self.rtime = self.TLIM # remaining time to explore
+ self.horizontal = 0 # Incrementa se andar para a direita e decrementa se andar para a esquerda
+ self.vertical = 0 # Incrementa se andar para baixo e decrementa se andar para cima
+ self.number_of_moves = 0
+ self.known_victims = []
+ self.known_map = []
+ self.best_route = []
+ self.map_graph = {}
+ self.returning_to_base = False
-
+ self.map = Map(path_priorities)
def deliberate(self) -> bool:
""" The agent chooses the next action. The simulator calls this
method at each cycle. Must be implemented in every agent"""
- # No more actions, time almost ended
- if self.rtime < 10.0:
- # time to wake up the rescuer
- # pass the walls and the victims (here, they're empty)
- print(f"{self.NAME} I believe I've remaining time of {self.rtime:.1f}")
- self.resc.go_save_victims([],[])
- return False
+ self.update_known_map() # Adiciona base na lista
- dx = random.choice([-1, 0, 1])
+ if self.time_to_get_back():
+ # Returns to base and notify the rescuer
+ # If agent is not at the base, returns True
+ return self.get_back_to_base()
- if dx == 0:
- dy = random.choice([-1, 1])
- else:
- dy = random.choice([-1, 0, 1])
+ return self.explore()
+
+ def calc_best_return_route(self, graphed_map):
+ init_pos, init_neighbours = list(graphed_map.items())[-1]
+ base_pos = (0, 0)
+ result = self.astar(graphed_map, init_pos, base_pos)
+ return result
+
+ def astar(self, graph, start, goal):
- # Check the neighborhood obstacles
- obstacles = self.body.check_obstacles()
+ open_list = [] # Lista de nós a serem avaliados
+ closed_set = set() # Conjunto de nós já avaliados
+ heur = self.get_heuristic_estimate(start[0], start[1])
+
+ start_node = Node(start, None, 0, heur)
+ heapq.heappush(open_list, start_node)
+
+ while open_list:
+ current_node = heapq.heappop(open_list)
+ if current_node.state == goal:
+ # Se chegamos ao objetivo, reconstrua o caminho e retorne-o
+ return self.build_path(current_node)
+ closed_set.add(current_node.state)
+
+ for neighbor, cost in graph[current_node.state]:
+ if neighbor not in closed_set:
+ # Cria um novo nó para o vizinho
+ neighbor_node = Node(neighbor, current_node, current_node.cost + cost,
+ self.get_heuristic_estimate(neighbor[0], neighbor[1]))
+
+ # Se o vizinho já está na lista aberta com um custo menor, ignore-o
+ if not any(neighbor_node.state == node.state and neighbor_node.cost >= node.cost for node in
+ open_list):
+ heapq.heappush(open_list, neighbor_node)
+ # Se não encontramos um caminho, retornamos None
+ return None
+
+ def build_path(self, node):
+ # Reconstrói o caminho de volta do objetivo para o início
+ path = []
+ while node:
+ path.append(node.state)
+ node = node.parent
+ return list(reversed(path))
+
+ def movement_cost(self, pos1, pos2):
+ if pos1[0] != pos2[0] and pos1[1] != pos2[1]: # Diagonal
+ return self.COST_DIAG
+ return self.COST_LINE
+
+
+ def explore(self):
+ # Check the neighborhood obstacles
+ obstacles = self.body.check_obstacles()
+
+ mov = self.map.get_action()
+ dy = mov[0]
+ dx = mov[1]
+
+ while not self.authorize(obstacles, dx, dy):
+ mov = self.map.get_action()
+ dy = mov[0]
+ dx = mov[1]
+
# Moves the body to another position
result = self.body.walk(dx, dy)
- # Update remaining time
- if dx != 0 and dy != 0:
- self.rtime -= self.COST_DIAG
- else:
- self.rtime -= self.COST_LINE
+ # Updates travel information
+ self.update_distance_to_base(dx, dy)
+ self.update_known_map()
+ self.update_number_of_moves()
- # Test the result of the walk action
- if result == PhysAgent.BUMPED:
- walls = 1 # build the map- to do
- # print(self.name() + ": wall or grid limit reached")
+ # Update remaining time
+ self.update_remaining_time(dx, dy)
if result == PhysAgent.EXECUTED:
# check for victim returns -1 if there is no victim or the sequential
# the sequential number of a found victim
+ self.map.update_agent_position(dx,dy)
seq = self.body.check_for_victim()
if seq >= 0:
vs = self.body.read_vital_signals(seq)
self.rtime -= self.COST_READ
+ if [self.horizontal, self.vertical] not in self.known_victims:
+ self.known_victims.append(((self.horizontal, self.vertical), vs))
# print("exp: read vital signals of " + str(seq))
# print(vs)
return True
+ def get_back_to_base(self):
+
+ init_pos = (self.horizontal, self.vertical)
+ movements = self.best_route
+ mov = movements.pop(0)
+
+ dx = mov[0] - init_pos[0]
+ dy = mov[1] - init_pos[1]
+
+ self.update_distance_to_base(dx, dy)
+
+ # Moves the body to another position
+ result = self.body.walk(dx, dy)
+ # Update remaining time
+ self.update_remaining_time(dx, dy)
+
+ if not self.at_base():
+ return True
+ else:
+ for i, r in enumerate(self.resc):
+ self.resc[i].merge_maps(list(self.known_map), list(self.known_victims))
+ return False
+
+ def time_to_get_back(self):
+
+ if self.returning_to_base:
+ return True
+
+ self.best_route = self.calc_best_return_route(self.map_graph)
+ cost = self.calculate_cost_to_base(list(self.best_route))
+
+ if(cost + 2*self.COST_DIAG + self.COST_READ >= self.rtime):
+ self.returning_to_base = True
+ self.best_route.pop(0)
+ return True
+
+ return False
+
+ def calculate_cost_to_base(self, best_route):
+ cost = 0
+ for i in range(len(best_route) - 1):
+ x1 = best_route[i][0]
+ y1 = best_route[i][1]
+ x2 = best_route[i + 1][0]
+ y2 = best_route[i + 1][1]
+
+ mov = (x2 - x1, y2 - y1)
+
+ if(mov == (0,1) or mov == (0,-1) or mov == (1,0) or mov == (-1,0)):
+ cost += self.COST_LINE
+ else:
+ cost += self.COST_DIAG
+
+ return cost
+
+
+ def update_remaining_time(self, dx, dy):
+ # Update remaining time
+ if dx != 0 and dy != 0:
+ self.rtime -= self.COST_DIAG
+ else:
+ self.rtime -= self.COST_LINE
+
+ def at_base(self):
+ return self.horizontal == 0 and self.vertical == 0
+
+ def update_distance_to_base(self, dx, dy):
+ self.horizontal += dx
+ self.vertical += dy
+
+ def update_number_of_moves(self):
+ self.number_of_moves += 1
+
+ def update_known_map(self):
+ if [self.horizontal, self.vertical] not in self.known_map:
+ self.known_map.append([self.horizontal, self.vertical])
+ discovered = (self.horizontal, self.vertical)
+ self.map_graph[discovered] = []
+ for coord in self.map_graph.keys():
+ cost = self.is_neighbour(discovered, coord)
+ if cost != None:
+ self.map_graph[discovered].append([coord, cost])
+ self.map_graph[coord].append([discovered, cost])
+ end_time = time.time()
+
+ def is_neighbour(self, coord1, coord2):
+ if (coord1[0] - 1, coord1[1]) == coord2:
+ return self.COST_LINE
+ if (coord1[0], coord1[1] - 1) == coord2:
+ return self.COST_LINE
+ if (coord1[0] - 1, coord1[1] - 1) == coord2:
+ return self.COST_DIAG
+ if (coord1[0] + 1, coord1[1]) == coord2:
+ return self.COST_LINE
+ if (coord1[0], coord1[1] + 1) == coord2:
+ return self.COST_LINE
+ if (coord1[0] + 1, coord1[1] + 1) == coord2:
+ return self.COST_DIAG
+ if (coord1[0] + 1, coord1[1] - 1) == coord2:
+ return self.COST_DIAG
+ if (coord1[0] - 1, coord1[1] + 1) == coord2:
+ return self.COST_DIAG
+ return None
+
+ def get_heuristic_estimate(self, dx, dy):
+ # Estima o gasto necessário para voltar para a base a partir da coord atual
+ valor = min(abs(dx), abs(dy)) * self.COST_DIAG # Anda o máximo que pode na diagonal
+ valor += abs((abs(dx) - abs(dy))) * self.COST_LINE # Anda o restante na vertical/horizontal
+ return valor
+
+ def authorize(self, obstacles, x, y):
+ if x == 0 and y == -1:
+ if obstacles[0] != 0:
+ return False
+ if x == 1 and y == -1:
+ if obstacles[1] != 0:
+ return False
+ if x == 1 and y == 0:
+ if obstacles[2] != 0:
+ return False
+ if x == 1 and y == 1:
+ if obstacles[3] != 0:
+ return False
+ if x == 0 and y == 1:
+ if obstacles[4] != 0:
+ return False
+ if x == -1 and y == 1:
+ if obstacles[5] != 0:
+ return False
+ if x == -1 and y == 0:
+ if obstacles[6] != 0:
+ return False
+ if x == -1 and y == -1:
+ if obstacles[7] != 0:
+ return False
+ return True
+
+
diff --git a/fuzzy.py b/fuzzy.py
new file mode 100644
index 0000000..848e2c4
--- /dev/null
+++ b/fuzzy.py
@@ -0,0 +1,279 @@
+from enum import Enum
+from collections import defaultdict
+import os
+import csv
+
+class Fuzzy:
+ def __init__(self):
+ self.small_rules_set = {} #Mapa das regras inferidas pelo Wang-Mendel
+ self.medium_rules_set = {}
+ self.big_rules_set = {}
+ self.small_dictionary = defaultdict(int) #Dicionario, conta quantas vezes uma regra aparece - 2 passo do wang mendel
+ self.medium_dictionary = defaultdict(int)
+ self.big_dictionary = defaultdict(int)
+ self.wang_mendel("datasets/data_800vic/sinais_vitais_com_label.txt") #Treina com varios arquivos
+ self.wang_mendel("datasets/data_12x12_10vic/sinais_vitais.txt")
+ self.wang_mendel("datasets/data_20x20_42vic/sinais_vitais.txt")
+ self.wang_mendel("datasets/data_teste_sala/sinais_vitais.txt")
+ #self.teste_800vit()
+
+ def small_fuzzyfy(self,max,var): #Divide cada variavel em 5 grupos - fuzzy triangular
+ fuz_vec = [0,0,0,0,0] #Cada posicao indica o valor fuzzy
+ if(var < max/4):
+ fuz_vec[0] = -(800/max) * var + 100
+ fuz_vec[1] = (800/max) * var
+ elif(var >= max/4 and var < max/2):
+ fuz_vec[1] = -(800/max) * var + 200
+ fuz_vec[2] = (800/max) * var - 100
+ elif(var >= max/2 and var < max*3/4):
+ fuz_vec[2] = -(800/max) * var + 300
+ fuz_vec[3] = (800/max) * var - 200
+ else:
+ fuz_vec[3] = -(800/max) * var + 400
+ fuz_vec[4] = (800/max) * var - 300
+ return fuz_vec
+
+ def medium_fuzzyfy(self,max,var): #Divide cada variavel em 9 grupos - fuzzy triangular
+ fuz_vec = [0,0,0,0,0,0,0,0,0] #Cada posicao indica o valor fuzzy
+ if(var < max/8):
+ fuz_vec[0] = -(800/max) * var + 100
+ fuz_vec[1] = (800/max) * var
+ elif(var >= max/8 and var < max/4):
+ fuz_vec[1] = -(800/max) * var + 200
+ fuz_vec[2] = (800/max) * var - 100
+ elif(var >= max/4 and var < max*3/8):
+ fuz_vec[2] = -(800/max) * var + 300
+ fuz_vec[3] = (800/max) * var - 200
+ elif(var >= max*3/8 and var < max/2):
+ fuz_vec[3] = -(800/max) * var + 400
+ fuz_vec[4] = (800/max) * var - 300
+ elif(var >= max/2 and var < max*5/8):
+ fuz_vec[4] = -(800/max) * var + 500
+ fuz_vec[5] = (800/max) * var - 400
+ elif(var >= max*5/8 and var < max*3/4):
+ fuz_vec[5] = -(800/max) * var + 600
+ fuz_vec[6] = (800/max) * var - 500
+ elif(var >= max*3/4 and var < max*7/8):
+ fuz_vec[6] = -(800/max) * var + 700
+ fuz_vec[7] = (800/max) * var - 600
+ else:
+ fuz_vec[7] = -(800/max) * var + 800
+ fuz_vec[8] = (800/max) * var - 700
+ return fuz_vec
+
+ def big_fuzzyfy(self,max,var): #Divide cada variavel em 17 grupos - fuzzy triangular
+ fuz_vec = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] #Cada posicao indica o valor fuzzy
+ if(var < max/8):
+ fuz_vec[0] = -(1600/max) * var + 100
+ fuz_vec[1] = (1600/max) * var
+ elif(var >= max/16 and var < max/8):
+ fuz_vec[1] = -(1600/max) * var + 200
+ fuz_vec[2] = (1600/max) * var - 100
+ elif(var >= max/8 and var < max*3/16):
+ fuz_vec[2] = -(1600/max) * var + 300
+ fuz_vec[3] = (1600/max) * var - 200
+ elif(var >= max*3/16 and var < max/4):
+ fuz_vec[3] = -(1600/max) * var + 400
+ fuz_vec[4] = (1600/max) * var - 300
+ elif(var >= max/4 and var < max*5/16):
+ fuz_vec[4] = -(1600/max) * var + 500
+ fuz_vec[5] = (1600/max) * var - 400
+ elif(var >= max*5/16 and var < max*3/8):
+ fuz_vec[5] = -(1600/max) * var + 600
+ fuz_vec[6] = (1600/max) * var - 500
+ elif(var >= max*3/8 and var < max*7/16):
+ fuz_vec[6] = -(1600/max) * var + 700
+ fuz_vec[7] = (1600/max) * var - 600
+ elif(var >= max*7/16 and var < max/2):
+ fuz_vec[7] = -(1600/max) * var + 800
+ fuz_vec[8] = (1600/max) * var - 700
+ elif(var >= max/2 and var < max*9/16):
+ fuz_vec[8] = -(1600/max) * var + 900
+ fuz_vec[9] = (1600/max) * var - 800
+ elif(var >= max*9/16 and var < max*5/8):
+ fuz_vec[9] = -(1600/max) * var + 1000
+ fuz_vec[10] = (1600/max) * var - 900
+ elif(var >= max*5/8 and var < max*11/16):
+ fuz_vec[10] = -(1600/max) * var + 1100
+ fuz_vec[11] = (1600/max) * var - 1000
+ elif(var >= max*11/16 and var < max*3/4):
+ fuz_vec[11] = -(1600/max) * var + 1200
+ fuz_vec[12] = (1600/max) * var - 1100
+ elif(var >= max*3/4 and var < max*13/16):
+ fuz_vec[12] = -(1600/max) * var + 1300
+ fuz_vec[13] = (1600/max) * var - 1200
+ elif(var >= max*13/16 and var < max*7/8):
+ fuz_vec[13] = -(1600/max) * var + 1400
+ fuz_vec[14] = (1600/max) * var - 1300
+ elif(var >= max*7/8 and var < max*15/16):
+ fuz_vec[14] = -(1600/max) * var + 1500
+ fuz_vec[15] = (1600/max) * var - 1400
+ else:
+ fuz_vec[15] = -(1600/max) * var + 1600
+ fuz_vec[16] = (1600/max) * var - 1500
+ return fuz_vec
+
+ def wang_mendel(self, path):
+ s_rules = [] #Todas as regras geradas, mesmo as repetidas
+ m_rules = []
+ b_rules = []
+ signals = [] #Vetor das caracteristicas da vitima (pressão, batimentos, etc)
+
+ vs_file = os.path.join(path) #Arquivo de teste
+
+ with open(vs_file, 'r') as csvfile:
+ csvreader = csv.reader(csvfile)
+ for row in csvreader:
+ qp = float(row[3]) #Pressao
+ pf = float(row[4]) #Batimentos
+ rf = float(row[5]) #Respiração
+ lb = int(row[7]) #Grupo verdadeiro
+
+ signals.append([qp, pf, rf, lb])
+
+ for vic in signals:
+ fuz_qPA = self.small_fuzzyfy(20,vic[0]+10) #Chama a fuzzyfy para as tres caracteristicas
+ fuz_pulse = self.small_fuzzyfy(200,vic[1])
+ fuz_fResp = self.small_fuzzyfy(22,vic[2])
+ s_rules.append([fuz_qPA.index(max(fuz_qPA)),fuz_pulse.index(max(fuz_pulse)),fuz_fResp.index(max(fuz_fResp)),vic[3]]) #cria uma regra, usando o grupo com maior valor obtido para cada variavel
+ fuz_qPA = self.medium_fuzzyfy(20,vic[0]+10) #Chama a fuzzyfy para as tres caracteristicas
+ fuz_pulse = self.medium_fuzzyfy(200,vic[1])
+ fuz_fResp = self.medium_fuzzyfy(22,vic[2])
+ m_rules.append([fuz_qPA.index(max(fuz_qPA)),fuz_pulse.index(max(fuz_pulse)),fuz_fResp.index(max(fuz_fResp)),vic[3]])
+ fuz_qPA = self.big_fuzzyfy(20,vic[0]+10) #Chama a fuzzyfy para as tres caracteristicas
+ fuz_pulse = self.big_fuzzyfy(200,vic[1])
+ fuz_fResp = self.big_fuzzyfy(22,vic[2])
+ b_rules.append([fuz_qPA.index(max(fuz_qPA)),fuz_pulse.index(max(fuz_pulse)),fuz_fResp.index(max(fuz_fResp)),vic[3]])
+
+ for rule in s_rules:
+ precedent = tuple(rule[:3]) #A tupla das variaveis precedentes
+ consequent = rule[3] #O grupo de gravidade (Verdadeiro)
+
+ if precedent not in self.small_rules_set or self.small_dictionary[precedent] < self.small_dictionary[precedent + (consequent,)]: #Adiciona as regras unicas se for a primeira aparição, ou se a regra apareceu mais vezes
+ self.small_rules_set[precedent] = consequent
+
+ self.small_dictionary[precedent + (consequent,)] += 1
+
+ for rule in m_rules:
+ precedent = tuple(rule[:3]) #A tupla das variaveis precedentes
+ consequent = rule[3] #O grupo de gravidade (Verdadeiro)
+
+ if precedent not in self.medium_rules_set or self.medium_dictionary[precedent] < self.medium_dictionary[precedent + (consequent,)]: #Adiciona as regras unicas se for a primeira aparição, ou se a regra apareceu mais vezes
+ self.medium_rules_set[precedent] = consequent
+
+ self.medium_dictionary[precedent + (consequent,)] += 1
+
+ for rule in b_rules:
+ precedent = tuple(rule[:3]) #A tupla das variaveis precedentes
+ consequent = rule[3] #O grupo de gravidade (Verdadeiro)
+
+ if precedent not in self.big_rules_set or self.big_dictionary[precedent] < self.big_dictionary[precedent + (consequent,)]: #Adiciona as regras unicas se for a primeira aparição, ou se a regra apareceu mais vezes
+ self.big_rules_set[precedent] = consequent
+
+ self.big_dictionary[precedent + (consequent,)] += 1
+
+
+ def defuzzyfy(self,vec): #Para um vetor de vitimas com pressao, batimentos e respiração, retorna um vetor com os grupos inferidos pelo processo fuzzy
+ out = []
+ for vic in vec:
+ grav = [0,0,0,0] #Vetor que armazena a maior inferencia para cada grupo, dentre todas as regras
+ big_fuz_qPA = self.big_fuzzyfy(20,vic[0]+10)
+ big_fuz_pulse = self.big_fuzzyfy(200,vic[1])
+ big_fuz_fResp = self.big_fuzzyfy(22,vic[2])
+ medium_fuz_qPA = self.medium_fuzzyfy(20,vic[0]+10)
+ medium_fuz_pulse = self.medium_fuzzyfy(200,vic[1])
+ medium_fuz_fResp = self.medium_fuzzyfy(22,vic[2])
+ small_fuz_qPA = self.small_fuzzyfy(20,vic[0]+10)
+ small_fuz_pulse = self.small_fuzzyfy(200,vic[1])
+ small_fuz_fResp = self.small_fuzzyfy(22,vic[2])
+ for rule, value in self.big_rules_set.items(): #Testa todas as regras
+ smallest_fuzzy = min(big_fuz_qPA[rule[0]], big_fuz_pulse[rule[1]], big_fuz_fResp[rule[2]]) #Como é um and, pega sempre o menor valor
+ if smallest_fuzzy > grav[value - 1]: #Armazena se o resultado for maior que o ja existente (para o grupo)
+ grav[value - 1] = smallest_fuzzy
+ if grav == [0,0,0,0]:
+ for rule, value in self.medium_rules_set.items(): #Testa todas as regras
+ smallest_fuzzy = min(medium_fuz_qPA[rule[0]], medium_fuz_pulse[rule[1]], medium_fuz_fResp[rule[2]]) #Como é um and, pega sempre o menor valor
+ if smallest_fuzzy > grav[value - 1]: #Armazena se o resultado for maior que o ja existente (para o grupo)
+ grav[value - 1] = smallest_fuzzy
+ if grav == [0,0,0,0]:
+ for rule, value in self.small_rules_set.items(): #Testa todas as regras
+ smallest_fuzzy = min(small_fuz_qPA[rule[0]], small_fuz_pulse[rule[1]], small_fuz_fResp[rule[2]]) #Como é um and, pega sempre o menor valor
+ if smallest_fuzzy > grav[value - 1]: #Armazena se o resultado for maior que o ja existente (para o grupo)
+ grav[value - 1] = smallest_fuzzy
+ out.append(grav.index(max(grav))+1)
+ return out
+
+ def measurement(self, generated, original): #Calcula as métricas
+ matrix = [[0 for _ in range(4)] for _ in range(4)]
+
+ for i in range(len(original)):
+ matrix[original[i]-1][generated[i]-1] += 1
+
+ precision_1 = matrix[0][0]/sum(matrix[0])
+ precision_2 = matrix[1][1]/sum(matrix[1])
+ precision_3 = matrix[2][2]/sum(matrix[2])
+ precision_4 = matrix[3][3]/sum(matrix[3])
+
+ recall_1 = matrix[0][0]/sum(line[0] for line in matrix)
+ recall_2 = matrix[1][1]/sum(line[1] for line in matrix)
+ recall_3 = matrix[2][2]/sum(line[2] for line in matrix)
+ recall_4 = matrix[3][3]/sum(line[3] for line in matrix)
+
+ accuracy = (matrix[0][0] + matrix[1][1] + matrix[2][2] + matrix[3][3])/ len(original)
+
+ f_measure_1 = 2 * precision_1 * recall_1 / (precision_1 + recall_1)
+ f_measure_2 = 2 * precision_2 * recall_2 / (precision_2 + recall_2)
+ f_measure_3 = 2 * precision_3 * recall_3 / (precision_3 + recall_3)
+ f_measure_4 = 2 * precision_4 * recall_4 / (precision_4 + recall_4)
+
+ print("\n\n*****MEASUREMENT*****")
+ print("Inferred groups:")
+ print(generated)
+ print("Real groups:")
+ print(original)
+ print("\nConfusion Matrix:")
+ print(matrix[0])
+ print(matrix[1])
+ print(matrix[2])
+ print(matrix[3])
+ print("\nPrecision:")
+ print(f"Group 1: {precision_1:.3f}")
+ print(f"Group 2: {precision_2:.3f}")
+ print(f"Group 3: {precision_3:.3f}")
+ print(f"Group 4: {precision_4:.3f}")
+ print("\nRecall:")
+ print(f"Group 1: {recall_1:.3f}")
+ print(f"Group 2: {recall_2:.3f}")
+ print(f"Group 3: {recall_3:.3f}")
+ print(f"Group 4: {recall_4:.3f}")
+ print("\nF-Measure:")
+ print(f"Group 1: {f_measure_1:.3f}")
+ print(f"Group 2: {f_measure_2:.3f}")
+ print(f"Group 3: {f_measure_3:.3f}")
+ print(f"Group 4: {f_measure_4:.3f}")
+ print(f"\nTOTAL ACCURACY: {accuracy:.3f}\n")
+
+ def teste_800vit(self):
+ signals = []
+
+ vs_file = os.path.join("datasets/data_800vic/sinais_vitais_com_label.txt")
+
+ with open(vs_file, 'r') as csvfile:
+ csvreader = csv.reader(csvfile)
+ for row in csvreader:
+ qp = float(row[3]) #Pressao
+ pf = float(row[4]) #Batimentos
+ rf = float(row[5]) #Respiração
+ lb = int(row[7]) #Grupo verdadeiro
+
+ signals.append([qp, pf, rf, lb])
+
+ original = []
+ saida = []
+ for x in signals:
+ original.append(tuple(x[:3]))
+ saida.append(x[3])
+
+ teste = self.defuzzyfy(original)
+
+ self.measurement(teste,saida)
\ No newline at end of file
diff --git a/genetic.py b/genetic.py
new file mode 100644
index 0000000..b7016c1
--- /dev/null
+++ b/genetic.py
@@ -0,0 +1,9 @@
+import math
+
+class Genetic:
+
+ def __init__(self):
+ pass
+
+ def fitness(self, individual):
+ pass
\ No newline at end of file
diff --git a/kmeans.py b/kmeans.py
new file mode 100644
index 0000000..ad44c14
--- /dev/null
+++ b/kmeans.py
@@ -0,0 +1,121 @@
+import random
+import math
+
+class KMeans():
+
+ def __init__(self):
+ self.redistributed = True
+
+ def execute(self, victims, n):
+
+ groups = self.generate_random_groups(victims, n)
+
+ while self.redistributed:
+ groups = self.update_groups(groups)
+
+ return groups
+
+ def update_groups(self, groups):
+
+ for group in groups:
+ new_centroid = self.centroid(group[1])
+ if(new_centroid != None):
+ group[0] = new_centroid
+
+ return self.redistribute(groups)
+
+ def generate_random_groups(self, victims, n):
+ centroids = self.initial_centroids(victims, n)
+ return self.distribute(victims, centroids)
+
+ def distribute(self, victims, centroids):
+ # Distribuição das vítimas para formar os grupos iniciais
+ groups = [[centroid, []] for centroid in centroids]
+
+ for victim in victims:
+ minor_distance = float(9999)
+ centroid_index = 0
+ # Checa a qual centróide a vítima da iteração irá pertencer
+ for i, centroid in enumerate(centroids):
+ distance_to_centroid = self.distance_to_centroid(victim, centroid)
+ if distance_to_centroid < minor_distance:
+ minor_distance = distance_to_centroid
+ centroid_index = i
+
+ groups[centroid_index][1].append(victim)
+
+ return groups
+
+
+ def redistribute(self, groups):
+ self.redistributed = False
+
+ centroids = [group[0] for group in groups]
+ new_groups = [[centroid, []] for centroid in centroids]
+ victim_groups = [group[1] for group in groups]
+
+ for i, victims in enumerate(victim_groups):
+
+ for victim in victims:
+ minor_distance = float(9999)
+ current_centroid_index = i
+ next_centroid_index = i
+
+ # Checa a qual centróide a vítima da iteração irá pertencer
+ for j, centroid in enumerate(centroids):
+ distance_to_centroid = self.distance_to_centroid(victim, centroid)
+ if distance_to_centroid < minor_distance:
+ minor_distance = distance_to_centroid
+ next_centroid_index = j
+
+ # Caso a vítima tenha que ser redirecionada a outro grupo
+ if next_centroid_index != current_centroid_index:
+ self.redistributed = True
+
+ new_groups[next_centroid_index][1].append(victim)
+
+ return new_groups
+
+ def initial_centroids(self, victims, n):
+ centroids = []
+
+ for i in range(0, n):
+ min_x = 9999
+ max_x = -9999
+ min_y = 9999
+ max_y = -9999
+
+ for victim in victims:
+ if victim[0][0] > max_x:
+ max_x = victim[0][0]
+ if victim[0][0] < min_x:
+ min_x = victim[0][0]
+ if victim[0][1] > max_y:
+ max_y = victim[0][1]
+ if victim[0][1] < min_y:
+ min_y = victim[0][1]
+
+ x = random.randint(min_x, max_x)
+ y = random.randint(min_y, max_y)
+ centroids.append((x, y))
+
+ return centroids
+
+ def centroid(self, group):
+ # Caso não haja ninguém no grupo
+ if(len(group) == 0):
+ return None
+
+ x_average = 0
+ y_average = 0
+
+ for victim in group:
+ x_average += victim[0][0]
+ y_average += victim[0][1]
+
+ x_average /= len(group)
+ y_average /= len(group)
+ return (x_average, y_average)
+
+ def distance_to_centroid(self, victim, centroid):
+ return math.sqrt((centroid[0] - victim[0][0])**2 + (centroid[1] - victim[0][1])**2)
\ No newline at end of file
diff --git a/main.py b/main.py
old mode 100644
new mode 100755
index e2fcaaa..0ffad15
--- a/main.py
+++ b/main.py
@@ -1,3 +1,4 @@
+import random
import sys
import os
import time
@@ -13,12 +14,11 @@ def main(data_folder_name):
# Set the path to config files and data files for the environment
current_folder = os.path.abspath(os.getcwd())
data_folder = os.path.abspath(os.path.join(current_folder, data_folder_name))
-
# Instantiate the environment
env = Env(data_folder)
- # config files for the agents
+ # config files for the agen5ts
rescuer_file = os.path.join(data_folder, "rescuer_config.txt")
explorer_file = os.path.join(data_folder, "explorer_config.txt")
@@ -27,7 +27,15 @@ def main(data_folder_name):
# Explorer needs to know rescuer to send the map
# that's why rescuer is instatiated before
- exp = Explorer(env, explorer_file, resc)
+ # lista = ['E', 'N', 'NW', 'SW', 'NE', 'SE', 'W', 'S']
+ # exp = Explorer(env, explorer_file, [resc], random.sample(lista, len(lista)))
+ # exp = Explorer(env, explorer_file, [resc], random.sample(lista, len(lista)))
+ # exp = Explorer(env, explorer_file, [resc], random.sample(lista, len(lista)))
+ # exp = Explorer(env, explorer_file, [resc], random.sample(lista, len(lista)))
+ exp = Explorer(env, explorer_file, [resc], ['E', 'N', 'S', 'W', 'NE', 'NW', 'SW', 'SE'])
+ exp = Explorer(env, explorer_file, [resc], ['N', 'W', 'E', 'S', 'NW', 'NE', 'SE', 'SW'])
+ exp = Explorer(env, explorer_file, [resc], ['W', 'S', 'N', 'E', 'SW', 'SE', 'NE', 'NW'])
+ exp = Explorer(env, explorer_file, [resc], ['S', 'E', 'W', 'N', 'SE', 'NE', 'NW', 'SW'])
# Run the environment simulator
env.run()
@@ -40,6 +48,6 @@ def main(data_folder_name):
if len(sys.argv) > 1:
data_folder_name = sys.argv[1]
else:
- data_folder_name = os.path.join("datasets", "data_12x12_10vic")
+ data_folder_name = os.path.join("datasets", "data_teste_sala")
main(data_folder_name)
diff --git a/map.py b/map.py
new file mode 100644
index 0000000..3145ee2
--- /dev/null
+++ b/map.py
@@ -0,0 +1,89 @@
+
+
+class Map:
+ def __init__(self, path_priorities):
+ self.coord_x = 0
+ self.coord_y = 0
+ self.coordinates_map = {'SE': [1,1], 'S': [1,0], 'SW': [1,-1], 'W': [0,-1], 'NW': [-1,-1], 'N': [-1,0], 'NE': [-1,1], 'E': [0,1]}
+ self.path_priorities = path_priorities
+ self.position = Position(self.path_priorities)
+ self.last_position = Position(self.path_priorities)
+ self.last_action = ''
+ self.backtracking = False
+ self.map = {(0,0)}
+ self.map = {(0, 0): self.position}
+
+ def get_action(self):
+ self.backtracking = False
+ mov = (0,0)
+ action = ''
+ while (self.coord_x+mov[1],self.coord_y+mov[0]) in self.map and action is not None:
+ action = self.position.pop_untried()
+ if action is not None:
+ mov = self.coordinates_map[action]
+ self.last_action = action
+ if action is None:
+ action = self.get_opposite_action(self.position.last_action)
+ mov = self.coordinates_map[action]
+ self.backtracking = True
+ self.last_action = action
+ return mov
+
+ def get_opposite_action(self,action):
+ if action == 'E':
+ return 'W'
+ elif action == 'NE':
+ return 'SW'
+ elif action == 'N':
+ return 'S'
+ elif action == 'NW':
+ return 'SE'
+ elif action == 'W':
+ return 'E'
+ elif action == 'SW':
+ return 'NE'
+ elif action == 'S':
+ return 'N'
+ elif action == 'SE':
+ return 'NW'
+ else:
+ return
+
+ def update_agent_position(self, dx, dy):
+ self.coord_x = self.coord_x + dx
+ self.coord_y = self.coord_y + dy
+ if (self.coord_x,self.coord_y) not in self.map:
+ pos = Position(self.path_priorities)
+ pos.coord_x = self.coord_x
+ pos.coord_y = self.coord_y
+ self.map[(self.coord_x,self.coord_y)] = pos
+ pos.last_action = self.last_action
+ else:
+ pos = self.map[(self.coord_x,self.coord_y)]
+ if self.backtracking is not True:
+ pos.last_action = self.last_action
+ self.position.set_results(self.last_action,pos)
+ pos.set_results(self.get_opposite_action(self.last_action),self.position)
+ self.last_position = self.position
+ self.position = pos
+
+ def get_map(self):
+ return self.map
+
+class Position:
+ def __init__(self, path_priorities):
+ self.coord_x = 0
+ self.coord_y = 0
+ self.results = {'SE': None, 'S': None, 'SW': None, 'W': None, 'NW': None, 'N': None, 'NE': None, 'E': None}
+ self.untried = list(path_priorities)
+ self.last_action = ''
+
+ def pop_untried(self):
+ if len(self.untried) != 0:
+ return self.untried.pop(0)
+ else:
+ return
+
+ def set_results(self,res,pos):
+ self.results[(res)] = pos
+
\ No newline at end of file
diff --git a/node.py b/node.py
new file mode 100644
index 0000000..c098790
--- /dev/null
+++ b/node.py
@@ -0,0 +1,11 @@
+
+class Node:
+ def __init__(self, state, parent=None, cost=0, heuristic=0):
+ self.state = state # O estado deste nó no grafo
+ self.parent = parent # O nó pai (nó anterior) neste caminho
+ self.cost = cost # Custo acumulado para alcançar este nó
+ self.heuristic = heuristic # Valor heurístico estimado para o objetivo
+
+ def __lt__(self, other):
+ # Comparação com base no custo total (f = custo + heurística)
+ return (self.cost + self.heuristic) < (other.cost + other.heuristic)
\ No newline at end of file
diff --git a/rescue_route.py b/rescue_route.py
new file mode 100644
index 0000000..50304b2
--- /dev/null
+++ b/rescue_route.py
@@ -0,0 +1,26 @@
+import math
+
+class RescueRoute:
+
+ def __init__(self):
+ self.victim_sequence = []
+
+ def fitness(self):
+ pass
+
+ def add_victim(self, victim):
+ self.victim_sequence(victim)
+
+ def total_distance(self):
+
+ distance = 0
+
+ for i in range(len(self.victim_sequence) - 1):
+ distance += self.distance_between_victims(self.victim_sequence[i], self.victim_sequence[i + 1])
+
+ return distance
+
+
+ def distance_between_victims(self, v1, v2):
+ #A* para encontrar a melhor rota entre duas vítimas
+ pass
\ No newline at end of file
diff --git a/rescuer.py b/rescuer.py
index ce516ab..3927477 100644
--- a/rescuer.py
+++ b/rescuer.py
@@ -7,6 +7,7 @@
from abstract_agent import AbstractAgent
from physical_agent import PhysAgent
from abc import ABC, abstractmethod
+from kmeans import KMeans
## Classe que define o Agente Rescuer com um plano fixo
@@ -25,17 +26,37 @@ def __init__(self, env, config_file):
# Starts in IDLE state.
# It changes to ACTIVE when the map arrives
self.body.set_state(PhysAgent.IDLE)
+ self.known_map = []
+ self.known_victims = []
+ self.received_maps = 0
# planning
self.__planner()
- def go_save_victims(self, walls, victims):
+ def go_save_victims(self):
""" The explorer sends the map containing the walls and
victims' location. The rescuer becomes ACTIVE. From now,
the deliberate method is called by the environment"""
+ print(len(self.known_victims))
+ #exit()
self.body.set_state(PhysAgent.ACTIVE)
-
-
+ cluster = KMeans()
+ cluster.execute(self.known_victims, 4)
+
+ def merge_maps(self, path, victims):
+ # for i, coord in enumerate(path):
+ # if coord not in self.known_map:
+ # self.known_map.append(coord)
+ self.received_maps +=1
+
+ for i, victim in enumerate(victims):
+ if victim not in self.known_victims:
+ self.known_victims.append(victim)
+
+ if self.received_maps == 4:
+ self.go_save_victims()
+ #self.go_save_victims()
+
def __planner(self):
""" A private method that calculates the walk actions to rescue the
victims. Further actions may be necessary and should be added in the
@@ -53,7 +74,7 @@ def __planner(self):
self.plan.append((-1,-1))
self.plan.append((-1,1))
self.plan.append((1,1))
-
+
def deliberate(self) -> bool:
""" This is the choice of the next action. The simulator calls this
method at each reasonning cycle if the agent is ACTIVE.
diff --git a/results.txt b/results.txt
new file mode 100644
index 0000000..587a7d9
--- /dev/null
+++ b/results.txt
@@ -0,0 +1,125 @@
+pygame 2.4.0 (SDL 2.28.4, Python 3.11.5)
+Hello from the pygame community. https://www.pygame.org/contribute.html
+from env: ag EXPLORER succesfully terminated, it is at the base
+from env: ag EXPLORER succesfully terminated, it is at the base
+from env: ag EXPLORER succesfully terminated, it is at the base
+35
+from env: ag EXPLORER succesfully terminated, it is at the base
+from env: ag RESCUER succesfully terminated, it is at the base
+from env: no active or idle agent scheduled for execution... terminating
+
+
+
+*** Numbers of Victims in the Environment ***
+Critical victims (V1) = 5
+Instable victims (V2) = 21
+Pot. inst. victims (V3) = 8
+Stable victims (V4) = 8
+--------------------------------------
+Total of victims (V) = 42
+
+
+*** Final results per agent ***
+
+[ Agent RESCUER ]
+
+*** Used time ***
+15.0 of 400.0
+No found victims
+
+saved victims: (id, severity, gravity)
+(9, 3, 73.4) (15, 1, 24.4)
+
+Critical victims saved (Vs1) = 1 out of 5 (20.0)%
+Instable victims saved (Vs2) = 0 out of 21 (0.0)%
+Pot. inst. victims saved (Vs3) = 1 out of 8 (12.5)%
+Stable victims saved (Vs4) = 0 out of 8 (0.0)%
+--------------------------------------
+Total of saved victims (Vs) = 2 (4.76%)
+Weighted saved victims per severity (Vsg) = 0.07
+
+Sum of gravities of all saved victims = 97.77 of a total of 1983.64
+ % of gravities of all saved victims = 0.05
+
+[ Agent EXPLORER ]
+
+*** Used time ***
+95.0 of 100.0
+
+found victims: (id, severity, gravity)
+(7, 3, 56.7) (8, 2, 43.8) (15, 1, 24.4) (21, 1, 13.3) (25, 4, 81.5) (31, 3, 68.3) (41, 4, 85.2)
+
+Critical victims found (Ve1) = 2 out of 5 (40.0)%
+Instable victims found (Ve2) = 1 out of 21 (4.8)%
+Pot. inst. victims found (Ve3) = 2 out of 8 (25.0)%
+Stable victims found (Ve4) = 2 out of 8 (25.0)%
+--------------------------------------
+Total of found victims (Ve) = 7 (16.67%)
+Weighted found victims per severity (Veg) = 0.18
+
+Sum of gravities of all found victims = 373.21 of a total of 1983.64
+ % of gravities of all found victims = 0.19
+No saved victims
+
+[ Agent EXPLORER ]
+
+*** Used time ***
+96.5 of 100.0
+
+found victims: (id, severity, gravity)
+(0, 1, 19.1) (12, 3, 61.6) (23, 2, 39.9) (26, 2, 49.0) (27, 3, 57.6) (28, 4, 77.6) (29, 4, 77.2) (34, 3, 56.4) (36, 2, 41.5) (40, 2, 27.1)
+
+Critical victims found (Ve1) = 1 out of 5 (20.0)%
+Instable victims found (Ve2) = 4 out of 21 (19.0)%
+Pot. inst. victims found (Ve3) = 3 out of 8 (37.5)%
+Stable victims found (Ve4) = 2 out of 8 (25.0)%
+--------------------------------------
+Total of found victims (Ve) = 10 (23.81%)
+Weighted found victims per severity (Veg) = 0.22
+
+Sum of gravities of all found victims = 506.83 of a total of 1983.64
+ % of gravities of all found victims = 0.26
+No saved victims
+
+[ Agent EXPLORER ]
+
+*** Used time ***
+96.5 of 100.0
+
+found victims: (id, severity, gravity)
+(6, 2, 37.2) (10, 3, 50.3) (16, 2, 40.5) (30, 4, 76.5) (38, 2, 42.8) (39, 2, 25.6)
+
+Critical victims found (Ve1) = 0 out of 5 (0.0)%
+Instable victims found (Ve2) = 4 out of 21 (19.0)%
+Pot. inst. victims found (Ve3) = 1 out of 8 (12.5)%
+Stable victims found (Ve4) = 1 out of 8 (12.5)%
+--------------------------------------
+Total of found victims (Ve) = 6 (14.29%)
+Weighted found victims per severity (Veg) = 0.13
+
+Sum of gravities of all found victims = 272.98 of a total of 1983.64
+ % of gravities of all found victims = 0.14
+No saved victims
+
+[ Agent EXPLORER ]
+
+*** Used time ***
+97.5 of 100.0
+
+found victims: (id, severity, gravity)
+(3, 2, 47.1) (4, 2, 25.2) (5, 2, 28.0) (9, 3, 73.4) (11, 4, 80.2) (13, 4, 85.1) (17, 2, 36.3) (19, 1, 13.3) (32, 2, 36.8) (33, 2, 44.0) (35, 2, 28.1) (37, 3, 68.2)
+
+Critical victims found (Ve1) = 1 out of 5 (20.0)%
+Instable victims found (Ve2) = 7 out of 21 (33.3)%
+Pot. inst. victims found (Ve3) = 2 out of 8 (25.0)%
+Stable victims found (Ve4) = 2 out of 8 (25.0)%
+--------------------------------------
+Total of found victims (Ve) = 12 (28.57%)
+Weighted found victims per severity (Veg) = 0.28
+
+Sum of gravities of all found victims = 565.54 of a total of 1983.64
+ % of gravities of all found victims = 0.29
+No saved victims
+
+--------------
+from env: Tecle qualquer coisa para encerrar >>
\ No newline at end of file