Commit 1ff8497e authored by Mohcine Chraibi's avatar Mohcine Chraibi

Merge branch 'v0.8' into 'master'

Release 0.8 V0.8



See merge request !1
parents a8c89c4b 40bcb059
Pipeline #4590 passed with stage
in 2 minutes and 24 seconds
# compile jpscore and run light tests
before_script:
- mkdir build && cd build/
build:
script:
- cmake .. -DBUILD_TESTING=ON
- make -j$(nproc)
- ctest
\ No newline at end of file
...@@ -80,7 +80,7 @@ Analysis::Analysis() ...@@ -80,7 +80,7 @@ Analysis::Analysis()
_getProfile = false; // Whether make field analysis or not _getProfile = false; // Whether make field analysis or not
_outputGraph = false; // Whether output the data for plot the fundamental diagram each frame _outputGraph = false; // Whether output the data for plot the fundamental diagram each frame
_calcIndividualFD = false; //Adjust whether analyze the individual density and velocity of each pedestrian in stationary state (ALWAYS VORONOI-BASED) _calcIndividualFD = false; //Adjust whether analyze the individual density and velocity of each pedestrian in stationary state (ALWAYS VORONOI-BASED)
_vComponent = 'B'; // to mark whether x, y or x and y coordinate are used when calculating the velocity _vComponent = "B"; // to mark whether x, y or x and y coordinate are used when calculating the velocity
_grid_size_X = 0.10; // the size of the grid _grid_size_X = 0.10; // the size of the grid
_grid_size_Y = 0.10; _grid_size_Y = 0.10;
...@@ -92,6 +92,12 @@ Analysis::Analysis() ...@@ -92,6 +92,12 @@ Analysis::Analysis()
_cutRadius=1.0; _cutRadius=1.0;
_circleEdges=6; _circleEdges=6;
_trajFormat=FileFormat::FORMAT_PLAIN; _trajFormat=FileFormat::FORMAT_PLAIN;
_isOneDimensional=false;
_plotGraph=false;
_plotTimeseriesA=false;
_plotTimeseriesC=false;
_plotTimeseriesD=false;
} }
Analysis::~Analysis() Analysis::~Analysis()
...@@ -180,11 +186,18 @@ void Analysis::InitArgs(ArgumentParser* args) ...@@ -180,11 +186,18 @@ void Analysis::InitArgs(ArgumentParser* args)
_cutByCircle = args->GetIsCutByCircle(); _cutByCircle = args->GetIsCutByCircle();
_getProfile = args->GetIsGetProfile(); _getProfile = args->GetIsGetProfile();
_outputGraph = args->GetIsOutputGraph(); _outputGraph = args->GetIsOutputGraph();
_plotGraph = args->GetIsPlotGraph();
_plotTimeseriesA=args->GetIsPlotTimeSeriesA();
_plotTimeseriesC=args->GetIsPlotTimeSeriesC();
_plotTimeseriesD=args->GetIsPlotTimeSeriesD();
_isOneDimensional=args->GetIsOneDimensional();
_calcIndividualFD = args->GetIsIndividualFD(); _calcIndividualFD = args->GetIsIndividualFD();
_areaIndividualFD= args->GetAreaIndividualFD();
_vComponent = args->GetVComponent(); _vComponent = args->GetVComponent();
_grid_size_X = int(args->GetGridSizeX()); _grid_size_X = int(args->GetGridSizeX());
_grid_size_Y = int(args->GetGridSizeY()); _grid_size_Y = int(args->GetGridSizeY());
_geoPoly = ReadGeometry(args->GetGeometryFilename(), _areaForMethod_D); _geoPoly = ReadGeometry(args->GetGeometryFilename(), _areaForMethod_D);
_geometryFileName=args->GetGeometryFilename();
_projectRootDir=args->GetProjectRootDir(); _projectRootDir=args->GetProjectRootDir();
_trajFormat=args->GetFileFormat(); _trajFormat=args->GetFileFormat();
_cutRadius=args->GetCutRadius(); _cutRadius=args->GetCutRadius();
...@@ -211,7 +224,7 @@ std::map<int, polygon_2d> Analysis::ReadGeometry(const std::string& geometryFile ...@@ -211,7 +224,7 @@ std::map<int, polygon_2d> Analysis::ReadGeometry(const std::string& geometryFile
//loop over all areas //loop over all areas
for(auto&& area: areas) for(auto&& area: areas)
{ {
//search for the subroom that containst that area //search for the subroom that containst that area
for (auto&& it_room : _building->GetAllRooms()) for (auto&& it_room : _building->GetAllRooms())
{ {
for (auto&& it_sub : it_room.second->GetAllSubRooms()) for (auto&& it_sub : it_room.second->GetAllSubRooms())
...@@ -281,44 +294,46 @@ int Analysis::RunAnalysis(const string& filename, const string& path) ...@@ -281,44 +294,46 @@ int Analysis::RunAnalysis(const string& filename, const string& path)
std::map<int , std::vector<int> > _peds_t=data.GetPedsFrame(); std::map<int , std::vector<int> > _peds_t=data.GetPedsFrame();
for(int frameNr = 0; frameNr < data.GetNumFrames(); frameNr++ ) for(int frameNr = 0; frameNr < data.GetNumFrames(); frameNr++ )
{ {
vector<int> ids=_peds_t[frameNr]; vector<int> ids=_peds_t[frameNr];
vector<int> IdInFrame = data.GetIdInFrame(ids); vector<int> IdInFrame = data.GetIdInFrame(ids);
vector<double> XInFrame = data.GetXInFrame(frameNr, ids); vector<double> XInFrame = data.GetXInFrame(frameNr, ids);
vector<double> YInFrame = data.GetYInFrame(frameNr, ids); vector<double> YInFrame = data.GetYInFrame(frameNr, ids);
for( unsigned int i=0;i<IdInFrame.size();i++) for( unsigned int i=0;i<IdInFrame.size();i++)
{ {
bool IsInBuilding=false; bool IsInBuilding=false;
for (auto&& it_room : _building->GetAllRooms()) for (auto&& it_room : _building->GetAllRooms())
{ {
for (auto&& it_sub : it_room.second->GetAllSubRooms()) for (auto&& it_sub : it_room.second->GetAllSubRooms())
{ {
SubRoom* subroom = it_sub.second.get(); SubRoom* subroom = it_sub.second.get();
if(subroom->IsInSubRoom(Point(XInFrame[i]*CMtoM,YInFrame[i]*CMtoM))) if(subroom->IsInSubRoom(Point(XInFrame[i]*CMtoM,YInFrame[i]*CMtoM)))
{ {
IsInBuilding=true; IsInBuilding=true;
break; break;
} }
} }
if(IsInBuilding) if(IsInBuilding)
{ {
break; break;
} }
} }
if(false==IsInBuilding) if(false==IsInBuilding)
{ {
Log->Write("Warning:\tAt %dth frame pedestrian at <x=%.4f, y=%.4f> is not in geometry!", frameNr+data.GetMinFrame(), XInFrame[i]*CMtoM, YInFrame[i]*CMtoM ); Log->Write("Warning:\tAt %dth frame pedestrian at <x=%.4f, y=%.4f> is not in geometry!", frameNr+data.GetMinFrame(), XInFrame[i]*CMtoM, YInFrame[i]*CMtoM );
} }
} }
} }
//----------------------------------------------------------------------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------------------------------------------------------------------
if(_DoesUseMethodA) //Method A if(_DoesUseMethodA) //Method A
{ {
for(unsigned int i=0; i<_areaForMethod_A.size(); i++) #pragma omp parallel for
for(signed int i=0; i<_areaForMethod_A.size(); i++)
{ {
Method_A method_A ; Method_A method_A ;
method_A.SetMeasurementArea(_areaForMethod_A[i]); method_A.SetMeasurementArea(_areaForMethod_A[i]);
method_A.SetTimeInterval(_deltaT); method_A.SetTimeInterval(_deltaT);
method_A.SetPlotTimeSeries(_plotTimeseriesA);
bool result_A=method_A.Process(data,_scriptsLocation); bool result_A=method_A.Process(data,_scriptsLocation);
if(result_A) if(result_A)
{ {
...@@ -333,7 +348,8 @@ int Analysis::RunAnalysis(const string& filename, const string& path) ...@@ -333,7 +348,8 @@ int Analysis::RunAnalysis(const string& filename, const string& path)
if(_DoesUseMethodB) //Method_B if(_DoesUseMethodB) //Method_B
{ {
for(unsigned int i=0; i<_areaForMethod_B.size(); i++) #pragma omp parallel for
for(signed int i=0; i<_areaForMethod_B.size(); i++)
{ {
Method_B method_B; Method_B method_B;
method_B.SetMeasurementArea(_areaForMethod_B[i]); method_B.SetMeasurementArea(_areaForMethod_B[i]);
...@@ -351,7 +367,8 @@ int Analysis::RunAnalysis(const string& filename, const string& path) ...@@ -351,7 +367,8 @@ int Analysis::RunAnalysis(const string& filename, const string& path)
if(_DoesUseMethodC) //Method C if(_DoesUseMethodC) //Method C
{ {
for(unsigned int i=0; i<_areaForMethod_C.size(); i++) #pragma omp parallel for
for(signed int i=0; i<_areaForMethod_C.size(); i++)
{ {
Method_C method_C; Method_C method_C;
method_C.SetMeasurementArea(_areaForMethod_C[i]); method_C.SetMeasurementArea(_areaForMethod_C[i]);
...@@ -359,6 +376,13 @@ int Analysis::RunAnalysis(const string& filename, const string& path) ...@@ -359,6 +376,13 @@ int Analysis::RunAnalysis(const string& filename, const string& path)
if(result_C) if(result_C)
{ {
Log->Write("INFO:\tSuccess with Method C using measurement area id %d!\n",_areaForMethod_C[i]->_id); Log->Write("INFO:\tSuccess with Method C using measurement area id %d!\n",_areaForMethod_C[i]->_id);
if(_plotTimeseriesC)
{
string parameters_Timeseries="python \""+_scriptsLocation+"/_Plot_timeseries_rho_v.py\" -p \""+ _projectRootDir+VORO_LOCATION + "\" -n "+filename+
" -f "+boost::lexical_cast<std::string>(data.GetFps());
int res=system(parameters_Timeseries.c_str());
Log->Write("INFO:\t time series result: %d ",res);
}
} }
else else
{ {
...@@ -369,14 +393,19 @@ int Analysis::RunAnalysis(const string& filename, const string& path) ...@@ -369,14 +393,19 @@ int Analysis::RunAnalysis(const string& filename, const string& path)
if(_DoesUseMethodD) //method_D if(_DoesUseMethodD) //method_D
{ {
for(unsigned int i=0; i<_areaForMethod_D.size(); i++) #pragma omp parallel for
for(signed int i=0; i<_areaForMethod_D.size(); i++)
{ {
Method_D method_D; Method_D method_D;
method_D.SetGeometryPolygon(_geoPoly[_areaForMethod_D[i]->_id]); method_D.SetGeometryPolygon(_geoPoly[_areaForMethod_D[i]->_id]);
method_D.SetGeometryFileName(_geometryFileName);
method_D.SetGeometryBoundaries(_lowVertexX, _lowVertexY, _highVertexX, _highVertexY); method_D.SetGeometryBoundaries(_lowVertexX, _lowVertexY, _highVertexX, _highVertexY);
method_D.SetGridSize(_grid_size_X, _grid_size_Y); method_D.SetGridSize(_grid_size_X, _grid_size_Y);
method_D.SetOutputVoronoiCellData(_outputGraph); method_D.SetOutputVoronoiCellData(_outputGraph);
method_D.SetPlotVoronoiGraph(_plotGraph);
method_D.SetDimensional(_isOneDimensional);
method_D.SetCalculateIndividualFD(_calcIndividualFD); method_D.SetCalculateIndividualFD(_calcIndividualFD);
method_D.SetAreaIndividualFD(_areaIndividualFD);
method_D.SetCalculateProfiles(_getProfile); method_D.SetCalculateProfiles(_getProfile);
if(_cutByCircle) if(_cutByCircle)
{ {
...@@ -386,7 +415,14 @@ int Analysis::RunAnalysis(const string& filename, const string& path) ...@@ -386,7 +415,14 @@ int Analysis::RunAnalysis(const string& filename, const string& path)
bool result_D = method_D.Process(data,_scriptsLocation); bool result_D = method_D.Process(data,_scriptsLocation);
if(result_D) if(result_D)
{ {
Log->Write("INFO:\tSuccess with Method D using measurement area id %d!\n",_areaForMethod_D[i]->_id); Log->Write("INFO:\tSuccess with Method D using measurement area id %d!\n",_areaForMethod_D[i]->_id);
if(_plotTimeseriesD)
{
string parameters_Timeseries="python \""+_scriptsLocation+"/_Plot_timeseries_rho_v.py\" -p \""+ _projectRootDir+VORO_LOCATION + "\" -n "+filename+
" -f "+boost::lexical_cast<std::string>(data.GetFps());
int res=system(parameters_Timeseries.c_str());
Log->Write("INFO:\t time series result: %d ",res);
}
} }
else else
{ {
...@@ -394,12 +430,6 @@ int Analysis::RunAnalysis(const string& filename, const string& path) ...@@ -394,12 +430,6 @@ int Analysis::RunAnalysis(const string& filename, const string& path)
} }
} }
} }
if(_DoesUseMethodC || _DoesUseMethodD)
{
string parameters_Timeseries="python "+_scriptsLocation+"/_Plot_timeseries_rho_v.py -p \""+ _projectRootDir+VORO_LOCATION + "\" -n "+filename+
" -f "+boost::lexical_cast<std::string>(data.GetFps());
system(parameters_Timeseries.c_str());
}
return 0; return 0;
} }
......
...@@ -129,11 +129,18 @@ private: ...@@ -129,11 +129,18 @@ private:
double _cutRadius; double _cutRadius;
int _circleEdges; int _circleEdges;
bool _getProfile; // Whether make field analysis or not bool _getProfile; // Whether make field analysis or not
bool _outputGraph; // Whether output the data for plot the fundamental diagram each frame bool _outputGraph; // Whether output the data for plot the voronoi diagram each frame
bool _plotGraph; // Whether plot the voronoi diagram each frame
bool _plotTimeseriesA;
bool _plotTimeseriesC;
bool _plotTimeseriesD;
bool _isOneDimensional;
bool _calcIndividualFD; //Adjust whether analyze the individual density and velocity of each pedestrian in stationary state (ALWAYS VORONOI-BASED) bool _calcIndividualFD; //Adjust whether analyze the individual density and velocity of each pedestrian in stationary state (ALWAYS VORONOI-BASED)
char _vComponent; // to mark whether x, y or x and y coordinate are used when calculating the velocity polygon_2d _areaIndividualFD;
std::string _vComponent; // to mark whether x, y or x and y coordinate are used when calculating the velocity
std::string _projectRootDir; std::string _projectRootDir;
std::string _scriptsLocation; std::string _scriptsLocation;
std::string _geometryFileName;
FileFormat _trajFormat; // format of the trajectory file FileFormat _trajFormat; // format of the trajectory file
std::vector<MeasurementArea_L*> _areaForMethod_A; std::vector<MeasurementArea_L*> _areaForMethod_A;
......
# JPSreport v0.9
## Added
## Changed
## Fixed
# JPSreport v0.8
## Added
- A switch is added in the infile for `method_D` to turn off plotting Voronoi diagrams. Now it is possible to only output data for the diagram but not plot figures.
- Switches for plotting time series of density and velocity are added for `method_C` and `method_D` in inifile.
- A switch for plotting N-t diagram is added for `method_A` in inifile.
- An option for analyzing one dimensional trajectory data is added in `method_D`.
- Issue a warning when the voronoi cell cannot be calculated.
- A warning will will be given and the program stops if trajectory for a given pedestrian ID is not continuous.
## Changed
- Scripts "_Plot_cell_rho.py" and "_Plot_cell_v.py" are modified. Now the geometry is also plotted when plotting voronoi cells.
- The indicator for velocity component can be specified in trajectory files now (.TXT and .XML)
- Scripts "_Plot_FD.py" is modified!
## Fixed
- Output data file "Folw\_NT\_xxxx.dat" is closed before calling script for plotting N-t diagram.
- A bug relating to transformation of units in `method_B` is fixed.
- Fixed error where all trajectories were co-linear.
- A bug for legend in the script "_Plot_timeseries_rho_v.py" is fixed.
- The case that frame ID and Ped ID in trajectory file are not coutinuous can also be analyzed correctly.
- Now when the given file paths in inifile include blank, it still works on windows system.
- when path of trajectory is not given absolutely, the default location is the same folder with the inifile
# JPSreport v0.7
## Added
- Added four demos as examples for using JPSreport
- Added the option for specifying the location of scripts in configuration file.
- Embedded python scripts (**\_Plot_N\_t.py**, **\_Plot_timeseries\_rho_v.py**) for plotting N-t diagram (Method A), time series of density/velocity diagram (Method C and D) and Voronoi diagrams (Method D).
- Added python script (**SteadyState.py**) for automatically detecting steady state of pedestrian flow based on time series of density and velocity. When plotting fundamental diagrams normally only data under steady state are used due to its generality.
- Added python script (**\_Plot_FD.py**) for plotting fundamenatl diagram based on the detected steady state.
## Changed
- Changed name of some variables in configuration file:
**measurementAreas** ---> **measurement_areas**
**Length_in_movement_direction** ---> **length_in_movement_direction**
**useXComponent** ---> **use_x_component**
**useYComponent** ---> **use_y_component**
**halfFrameNumberToUse** ---> **frame_step**
**timeInterval** ---> **frame_interval**
**measurementArea** ---> **measurement_area**
**outputGraph** ---> **output_graph**
**individualFDdata** ---> **individual_FD**
**cutByCircle** ---> **cut_by_circle**
**getProfile** ---> **profiles**
**scale_x** ---> **grid_size_x**
**scale_y** ---> **grid_size_y**
- Changed the data type of frame rate (fps) from integer to float
- Changed the way for dealing with pedestrian outside geometry. In old version JPSreport stops when some pedestrians are outside geometry but now it continue working by
removing these pedestrians from the list.
- More than one sub rooms in one geometry can be analysed independently.
## Fixed
- Fixed bug for dealing with obstacles inside geometry.
...@@ -71,6 +71,21 @@ if(PROCESSOR_COUNT) ...@@ -71,6 +71,21 @@ if(PROCESSOR_COUNT)
set(CTEST_BUILD_FLAGS "-j${PROCESSOR_COUNT}") set(CTEST_BUILD_FLAGS "-j${PROCESSOR_COUNT}")
endif(PROCESSOR_COUNT) endif(PROCESSOR_COUNT)
# find the correct OpenMP flag
FIND_PACKAGE(OpenMP)
if(OPENMP_FOUND)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
else(OPENMP_FOUND)
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp")
# somehow find_package(openmp) does not work properly with clang
else(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
message( STATUS "Disabling OpenMP support" )
endif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
endif(OPENMP_FOUND)
# test all cpp-files in Utest # test all cpp-files in Utest
if(BUILD_TESTING) if(BUILD_TESTING)
file(GLOB test_files "${CMAKE_TEST_DIR}/*.cpp") file(GLOB test_files "${CMAKE_TEST_DIR}/*.cpp")
...@@ -135,6 +150,7 @@ set ( header_files ...@@ -135,6 +150,7 @@ set ( header_files
#-------------------- #--------------------
if(NOT CMAKE_GENERATOR MATCHES "Xcode|Visual Studio")
include(CheckCXXCompilerFlag) include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
...@@ -147,6 +163,7 @@ elseif(COMPILER_SUPPORTS_CXX0X) ...@@ -147,6 +163,7 @@ elseif(COMPILER_SUPPORTS_CXX0X)
else() else()
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no c++11 support. Please use a different C++ compiler.") message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no c++11 support. Please use a different C++ compiler.")
endif() endif()
endif()
#--------------------- #---------------------
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
message(STATUS "Using Clang " ${CMAKE_CXX_COMPILER_VERSION}) message(STATUS "Using Clang " ${CMAKE_CXX_COMPILER_VERSION})
......
# JPSreport v0.7 # JPSreport
================
## Running Documentation can be found [here](http://jupedsim.github.io/jpsreport/)
```
./JPSreport.exe inifile.xml"
```
From the command line trajectory files mentioned in the inifile will be analysed by using the methods and parameters specified in the `inifile`.
The output results will be saved in the sub-folder of the folder where the inifile exists.
## Added
- Added four demos as examples for using JPSreport
- Added the option for specifying the location of scripts in configuration file.
- Embedded python scripts (**\_Plot_N\_t.py**, **\_Plot_timeseries\_rho_v.py**) for plotting N-t diagram (Method A), time series of density/velocity diagram (Method C and D) and Voronoi diagrams (Method D).
- Added python script (**SteadyState.py**) for automatically detecting steady state of pedestrian flow based on time series of density and velocity. When plotting fundamental diagrams normally only data under steady state are used due to its generality.
- Added python script (**\_Plot_FD.py**) for plotting fundamenatl diagram based on the detected steady state.
## Changed
- Changed name of some variables in configuration file:
**measurementAreas** ---> **measurement_areas**
**Length_in_movement_direction** ---> **length_in_movement_direction**
**useXComponent** ---> **use_x_component**
**useYComponent** ---> **use_y_component**
**halfFrameNumberToUse** ---> **frame_step**
**timeInterval** ---> **frame_interval**
**measurementArea** ---> **measurement_area**
**outputGraph** ---> **output_graph**
**individualFDdata** ---> **individual_FD**
**cutByCircle** ---> **cut_by_circle**
**getProfile** ---> **profiles**
**scale_x** ---> **grid_size_x**
**scale_y** ---> **grid_size_y**
- Changed the data type of frame rate (fps) from integer to float
- Changed the way for dealing with pedestrian outside geometry. In old version JPSreport stops when some pedestrians are outside geometry but now it continue working by
removing these pedestrians from the list.
- More than one sub rooms in one geometry can be analysed independently.
## Fixed
- Fixed bug for dealing with obstacles inside geometry.
\ No newline at end of file
python ../../scripts/SteadyState.py -f ./rho_v_Voronoi_traj_AO_b240.txt_id_1.dat -rs 240 -re 640 -vs 240 -ve 640 -p yes python ../../scripts/SteadyState.py
\ No newline at end of file -f ./rho_v_Voronoi_traj_AO_b240.txt_id_1.dat # file name with the data
-a
-c 0 1 2 # column indexes. 0 for the frame column (first).
-rs 240 240 # start references
-re 640 640 # end references
-xl "t" # xlabel. alternative: "frame"
-yl "\rho\; / 1/m" "v\; m/s" -p yes # ylabels for every column (optionally with unit)
# start end # start end ratio mean std
121 838 121 838 70.95 3.4702 0.2974
# start end # start end ratio mean std
202 938 202 938 72.83 0.7240 0.0323
# frame s
0 100.0000
1 100.0000
2 100.0000
3 100.0000
4 100.0000
5 100.0000
6 100.0000
7 100.0000
8 100.0000
9 100.0000
10 100.0000
11 100.0000
12 100.0000
13 100.0000
14 100.0000
15 100.0000
16 100.0000
17 100.0000
18 100.0000
19 100.0000
20 100.0000
21 100.0000
22 100.0000
23 100.0000
24 100.0000
25 100.0000
26 100.0000
27 100.0000
28 100.0000
29 100.0000
30 100.0000
31 100.0000
32 100.0000
33 100.0000
34 100.0000
35 100.0000
36 100.0000
37 100.0000
38 100.0000
39 100.0000
40 100.0000
41 100.0000
42 100.0000
43 100.0000
44 100.0000
45 100.0000
46 100.0000
47 100.0000
48 100.0000
49 100.0000
50 100.0000
51 100.0000
52 100.0000
53 100.0000
54 100.0000
55 100.0000
56 100.0000
57 100.0000
58 100.0000
59 100.0000
60 100.0000
61 100.0000
62 100.0000
63 100.0000
64 100.0000
65 100.0000
66 100.0000
67 99.0000
68 98.0000
69 97.0000
70 96.0000
71 95.0000
72 94.0000
73 93.0000