Commit af8972af authored by Clouard Regis's avatar Clouard Regis
Browse files

Added route statistics (length).

parent aa2304e6
......@@ -4,6 +4,7 @@
use App\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\ErrorHandler\Debug;
if (!in_array(PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) {
......@@ -14,8 +15,8 @@ set_time_limit(0);
require dirname(__DIR__).'/vendor/autoload.php';
if (!class_exists(Application::class)) {
throw new LogicException('You need to add "symfony/framework-bundle" as a Composer dependency.');
if (!class_exists(Application::class) || !class_exists(Dotenv::class)) {
throw new LogicException('You need to add "symfony/framework-bundle" and "symfony/dotenv" as Composer dependencies.');
}
$input = new ArgvInput();
......@@ -27,7 +28,7 @@ if ($input->hasParameterOption('--no-debug', true)) {
putenv('APP_DEBUG='.$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0');
}
require dirname(__DIR__).'/config/bootstrap.php';
(new Dotenv())->bootEnv(dirname(__DIR__).'/.env');
if ($_SERVER['APP_DEBUG']) {
umask(0000);
......
......@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "9e9339edc1447f741153d406a4fcd12e",
"content-hash": "a9da9547a740aa65053c4d34385b0ebc",
"packages": [
{
"name": "composer/package-versions-deprecated",
......@@ -63,16 +63,16 @@
},
{
"name": "doctrine/annotations",
"version": "1.10.3",
"version": "1.10.4",
"source": {
"type": "git",
"url": "https://github.com/doctrine/annotations.git",
"reference": "5db60a4969eba0e0c197a19c077780aadbc43c5d"
"reference": "bfe91e31984e2ba76df1c1339681770401ec262f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/annotations/zipball/5db60a4969eba0e0c197a19c077780aadbc43c5d",
"reference": "5db60a4969eba0e0c197a19c077780aadbc43c5d",
"url": "https://api.github.com/repos/doctrine/annotations/zipball/bfe91e31984e2ba76df1c1339681770401ec262f",
"reference": "bfe91e31984e2ba76df1c1339681770401ec262f",
"shasum": ""
},
"require": {
......@@ -82,7 +82,8 @@
},
"require-dev": {
"doctrine/cache": "1.*",
"phpunit/phpunit": "^7.5"
"phpstan/phpstan": "^0.12.20",
"phpunit/phpunit": "^7.5 || ^9.1.5"
},
"type": "library",
"extra": {
......@@ -128,7 +129,7 @@
"docblock",
"parser"
],
"time": "2020-05-25T17:24:27+00:00"
"time": "2020-08-10T19:35:50+00:00"
},
{
"name": "doctrine/cache",
......@@ -1058,16 +1059,16 @@
},
{
"name": "doctrine/persistence",
"version": "1.3.7",
"version": "1.3.8",
"source": {
"type": "git",
"url": "https://github.com/doctrine/persistence.git",
"reference": "0af483f91bada1c9ded6c2cfd26ab7d5ab2094e0"
"reference": "7a6eac9fb6f61bba91328f15aa7547f4806ca288"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/persistence/zipball/0af483f91bada1c9ded6c2cfd26ab7d5ab2094e0",
"reference": "0af483f91bada1c9ded6c2cfd26ab7d5ab2094e0",
"url": "https://api.github.com/repos/doctrine/persistence/zipball/7a6eac9fb6f61bba91328f15aa7547f4806ca288",
"reference": "7a6eac9fb6f61bba91328f15aa7547f4806ca288",
"shasum": ""
},
"require": {
......@@ -1076,7 +1077,7 @@
"doctrine/collections": "^1.0",
"doctrine/event-manager": "^1.0",
"doctrine/reflection": "^1.2",
"php": "^7.1"
"php": "^7.1 || ^8.0"
},
"conflict": {
"doctrine/common": "<2.10@dev"
......@@ -1084,7 +1085,8 @@
"require-dev": {
"doctrine/coding-standard": "^6.0",
"phpstan/phpstan": "^0.11",
"phpunit/phpunit": "^7.0"
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
"vimeo/psalm": "^3.11"
},
"type": "library",
"extra": {
......@@ -1137,7 +1139,7 @@
"orm",
"persistence"
],
"time": "2020-03-21T15:13:52+00:00"
"time": "2020-06-20T12:56:16+00:00"
},
{
"name": "doctrine/reflection",
......@@ -1272,16 +1274,16 @@
},
{
"name": "egulias/email-validator",
"version": "2.1.18",
"version": "2.1.19",
"source": {
"type": "git",
"url": "https://github.com/egulias/EmailValidator.git",
"reference": "cfa3d44471c7f5bfb684ac2b0da7114283d78441"
"reference": "840d5603eb84cc81a6a0382adac3293e57c1c64c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/egulias/EmailValidator/zipball/cfa3d44471c7f5bfb684ac2b0da7114283d78441",
"reference": "cfa3d44471c7f5bfb684ac2b0da7114283d78441",
"url": "https://api.github.com/repos/egulias/EmailValidator/zipball/840d5603eb84cc81a6a0382adac3293e57c1c64c",
"reference": "840d5603eb84cc81a6a0382adac3293e57c1c64c",
"shasum": ""
},
"require": {
......@@ -1326,7 +1328,7 @@
"validation",
"validator"
],
"time": "2020-06-16T20:11:17+00:00"
"time": "2020-08-08T21:28:19+00:00"
},
{
"name": "laminas/laminas-code",
......@@ -6651,7 +6653,7 @@
},
{
"name": "twig/extra-bundle",
"version": "v3.0.4",
"version": "v3.0.5",
"source": {
"type": "git",
"url": "https://github.com/twigphp/twig-extra-bundle.git",
......@@ -6710,16 +6712,16 @@
},
{
"name": "twig/twig",
"version": "v3.0.4",
"version": "v3.0.5",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "582bdbdc173027ebfba3c93dc750a40b8f9ebc02"
"reference": "9b76b1535483cdf4edf01bb787b0217b62bd68a5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/582bdbdc173027ebfba3c93dc750a40b8f9ebc02",
"reference": "582bdbdc173027ebfba3c93dc750a40b8f9ebc02",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/9b76b1535483cdf4edf01bb787b0217b62bd68a5",
"reference": "9b76b1535483cdf4edf01bb787b0217b62bd68a5",
"shasum": ""
},
"require": {
......@@ -6768,7 +6770,7 @@
"keywords": [
"templating"
],
"time": "2020-07-05T13:18:14+00:00"
"time": "2020-08-05T15:13:19+00:00"
},
{
"name": "webimpress/safe-writer",
......@@ -7118,16 +7120,16 @@
},
{
"name": "nikic/php-parser",
"version": "v4.7.0",
"version": "v4.8.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "21dce06dfbf0365c6a7cc8fdbdc995926c6a9300"
"reference": "8c58eb4cd4f3883f82611abeac2efbc3dbed787e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/21dce06dfbf0365c6a7cc8fdbdc995926c6a9300",
"reference": "21dce06dfbf0365c6a7cc8fdbdc995926c6a9300",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8c58eb4cd4f3883f82611abeac2efbc3dbed787e",
"reference": "8c58eb4cd4f3883f82611abeac2efbc3dbed787e",
"shasum": ""
},
"require": {
......@@ -7135,8 +7137,8 @@
"php": ">=7.0"
},
"require-dev": {
"ircmaxell/php-yacc": "0.0.5",
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0"
"ircmaxell/php-yacc": "^0.0.6",
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
},
"bin": [
"bin/php-parse"
......@@ -7144,7 +7146,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.7-dev"
"dev-master": "4.8-dev"
}
},
"autoload": {
......@@ -7166,7 +7168,7 @@
"parser",
"php"
],
"time": "2020-07-25T13:18:53+00:00"
"time": "2020-08-09T10:23:20+00:00"
},
{
"name": "symfony/browser-kit",
......@@ -7573,20 +7575,19 @@
},
{
"name": "symfony/profiler-pack",
"version": "v1.0.4",
"version": "v1.0.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/profiler-pack.git",
"reference": "99c4370632c2a59bb0444852f92140074ef02209"
"reference": "29ec66471082b4eb068db11eb4f0a48c277653f7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/profiler-pack/zipball/99c4370632c2a59bb0444852f92140074ef02209",
"reference": "99c4370632c2a59bb0444852f92140074ef02209",
"url": "https://api.github.com/repos/symfony/profiler-pack/zipball/29ec66471082b4eb068db11eb4f0a48c277653f7",
"reference": "29ec66471082b4eb068db11eb4f0a48c277653f7",
"shasum": ""
},
"require": {
"php": "^7.0",
"symfony/stopwatch": "*",
"symfony/twig-bundle": "*",
"symfony/web-profiler-bundle": "*"
......@@ -7597,7 +7598,7 @@
"MIT"
],
"description": "A pack for the Symfony web profiler",
"time": "2018-12-10T12:11:44+00:00"
"time": "2020-08-12T06:50:46+00:00"
},
{
"name": "symfony/test-pack",
......
#OLD VERSION
#doctrine_migrations:
# dir_name: '%kernel.project_dir%/src/Migrations'
# namespace: DoctrineMigrations
doctrine_migrations:
migrations_paths:
# namespace is arbitrary but should be different from App\Migrations
# as migrations classes should NOT be autoloaded
'DoctrineMigrations': '%kernel.project_dir%/src/Migrations'
# As of Symfony 5.1, deprecations are logged in the dedicated "deprecation" channel when it exists
#monolog:
# channels: [deprecation]
# handlers:
# deprecation:
# type: stream
# channels: [deprecation]
# path: "%kernel.logs_dir%/%kernel.environment%.deprecations.log"
......@@ -14,11 +14,3 @@ monolog:
type: console
process_psr_3_messages: false
channels: ["!event", "!doctrine"]
deprecation:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.deprecations.log"
deprecation_filter:
type: filter
handler: deprecation
max_level: info
channels: ["php"]
framework:
router:
utf8: true
# Configure how to generate URLs in non-HTTP contexts, such as CLI commands.
# See https://symfony.com/doc/current/routing.html#generating-urls-in-commands
#default_uri: http://localhost
......@@ -10,12 +10,14 @@ security:
entity:
class: App\Entity\User
property: username
users_in_memory: { memory: null }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: lazy
anonymous: true
lazy: true
provider: app_user_provider
guard:
authenticators:
......@@ -24,7 +26,6 @@ security:
path: app_logout
# where to redirect after logout
# target: app_any_route
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#firewalls-authentication
......
......@@ -49,21 +49,22 @@ function renderTimeSheet(distances) {
let cps = timeSheetData[0][1];
for (let $i = 0; $i < cps.length; $i++) {
const index = cps[$i]["controlPoint"];
let cell1 = document.createElement("th");
let cell2 = document.createElement("td");
cell1.setAttribute("scope", "col");
let controlCell = document.createElement("th");
let lengthCell = document.createElement("td");
controlCell.setAttribute("scope", "col");
if (index === 0) {
cell1.innerHTML = "Départ";
controlCell.innerHTML = "Départ";
} else if (index === timeSheetData[0][1].length - 1) {
cell1.innerHTML = "Arrivée";
cell2.innerHTML = Math.floor(distances[$i]) + " m";
controlCell.innerHTML = "Arrivée";
lengthCell.innerHTML = distances[$i] + " m";
lengthCell.innerHTML = distances[$i];
} else {
cell1.innerHTML = index;
cell2.innerHTML = Math.floor(distances[$i]) + " m";
controlCell.innerHTML = index;
lengthCell.innerHTML = distances[$i] + " m";
}
let row = document.createElement("tr");
row.appendChild(cell1);
row.appendChild(cell2);
row.appendChild(controlCell);
row.appendChild(lengthCell);
body.appendChild(row);
rows.push(row);
}
......
......@@ -62,20 +62,15 @@ class CourseController extends AbstractController
{
$course = $this->getDoctrine()->getRepository(Course::class)->find($id);
$xml = $course->getXml();
$sxml = simplexml_load_string($xml);
$controls = $sxml->RaceCourseData->Control;
$locations = array(0);
for ($i = 1; $i < $controls->count(); $i++) {
$d = $statistics->distanceInMeters($controls[$i - 1]->Position["lat"], $controls[$i - 1]->Position["lng"], $controls[$i]->Position["lat"], $controls[$i]->Position["lng"]);
array_push($locations, $d);
}
$simplexml = simplexml_load_string($xml);
$lengths = $statistics->computeLegLengths($simplexml);
return $this->render(
'course/track.html.twig',
[
'name' => $course->getName(),
'route_map' => $this->generateUrl('course_map', ['id' => $id]),
'control_points_location' => json_encode(array('distances' => $locations)),
'control_points_location' => json_encode(array('distances' => $lengths)),
'route_track' => $this->generateUrl('course_track', ['id' => $id]),
]
);
......@@ -118,11 +113,15 @@ class CourseController extends AbstractController
function course_track($id, TrackStatistics $statistics)
{
$tracks = $this->getDoctrine()->getRepository(Track::class)->findByCourse($id);
$course = $this->getDoctrine()->getRepository(Course::class)->find($id);
$xml = $course->getXml();
$simplexml = simplexml_load_string($xml);
$lengths = $statistics->computeLegLengths($simplexml);
$routes = array();
foreach ($tracks as $track) {
$splitTimes = $statistics->computeSplitTime($track->getControlPoints());
$distances = $statistics->computeActualSplitDistance($track->getControlPoints(), $track->getTrace());
$rk = $statistics->computeSplitPaces($splitTimes, $distances);
$rk = $statistics->computeSplitPaces($splitTimes, $lengths);
array_push(
$routes,
[
......
......@@ -2,6 +2,8 @@
namespace App\Model;
use App\Controller\CourseController;
class TrackStatistics
{
public function distanceInMeters($lat1, $lng1, $lat2, $lng2)
......@@ -56,22 +58,22 @@ class TrackStatistics
}
}
// TODO complete with 0???
for ($i=count($distances) ; $i < count($controlPoints); $i++) {
for ($i = count($distances); $i < count($controlPoints); $i++) {
$distances[] = 0;
}
return $distances;
}
public function computeSplitPaces(array $splitTimes, array $distances)
public function computeSplitPaces(array $splitTimes, array $lengths)
{
$paces = array();
$paces[] = "";
for ($i = 1; $i < count($splitTimes); $i++) {
if (is_numeric($distances[$i]) && intval($distances[$i]) > 0) {
for ($i = 1; $i < min(count($splitTimes), count($lengths)); $i++) {
if (is_numeric($lengths[$i]) && intval($lengths[$i]) > 0) {
$time = $this->convertStringToTimeInMs($splitTimes[$i]);
$distance = intval($distances[$i]);
$pace = $this->convertTimetoString($time * 1000 / $distance);
$length = intval($lengths[$i]);
$pace = $this->convertTimetoString($time * 1000 / $length);
$paces[] = $pace;
} else {
$paces[] = "--:--";
......@@ -83,9 +85,13 @@ class TrackStatistics
private function convertTimetoString(int $time): string
{
$hrs = floor($time / 1000 / 3600);
$min = floor($time / 1000 / 60);
$sec = floor(($time / 1000) % 60);
$timeInS = $time / 1000.0;
$hrs = floor($timeInS / 3600);
$timeInS = $timeInS - $hrs * 3600;
$min = floor($timeInS / 60);
$timeInS = $timeInS - $min * 60;
$min = strlen((string)$min) === 1 ? "0".$min : $min;
$sec = floor($timeInS);
$sec = (string)$sec;
$sec = strlen($sec) === 1 ? "0".$sec : $sec;
if ($hrs > 0) {
......@@ -127,4 +133,33 @@ class TrackStatistics
return $timeInMs * 1000 + $milliseconds;
}
public function computeLegLengths($simplexml): array
{
// 1. Creer la liste des balises.
$root = $simplexml->RaceCourseData->Control;
$controls = array();
for ($i = 0; $i < $root->count(); $i++) {
$controls[(string)$root[$i]->Id] = [$root[$i]->Position["lat"], $root[$i]->Position["lng"]];
}
// 2. Calculer les distances interpostes.
$root = $simplexml->RaceCourseData;
$lengths = array();
$previousId = null;
foreach ($root->Course->children() as $child) {
if ($child->getName() === "CourseControl") {
$id = (string)$child->Control;
if ($previousId != null) {
$length = $this->distanceInMeters($controls[$previousId][0], $controls[$previousId][1], $controls[$id][0], $controls[$id][1]);
array_push($lengths, (int)$length);
} else {
array_push($lengths, 0);
}
$previousId = $id;
}
}
return $lengths;
}
}
\ No newline at end of file
......@@ -66,16 +66,16 @@
]
},
"doctrine/doctrine-migrations-bundle": {
"version": "1.2",
"version": "2.2",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "1.2",
"ref": "c1431086fec31f17fbcfe6d6d7e92059458facc1"
"version": "2.2",
"ref": "baaa439e3e3179e69e3da84b671f0a3e4a2f56ad"
},
"files": [
"config/packages/doctrine_migrations.yaml",
"src/Migrations/.gitignore"
"migrations/.gitignore"
]
},
"doctrine/event-manager": {
......@@ -205,16 +205,15 @@
"version": "v5.0.7"
},
"symfony/console": {
"version": "4.4",
"version": "5.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "4.4",
"ref": "ea8c0eda34fda57e7d5cd8cbd889e2a387e3472c"
"version": "5.1",
"ref": "c6d02bdfba9da13c22157520e32a602dbee8a75c"
},
"files": [
"bin/console",
"config/bootstrap.php"
"bin/console"
]
},
"symfony/css-selector": {
......@@ -350,10 +349,11 @@
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "3.3",
"ref": "877bdb4223245783d00ed1f7429aa7ebc606d914"
"ref": "d7249f7d560f6736115eee1851d02a65826f0a56"
},
"files": [
"config/packages/dev/monolog.yaml",
"config/packages/prod/deprecations.yaml",
"config/packages/prod/monolog.yaml",
"config/packages/test/monolog.yaml"
]
......@@ -425,12 +425,12 @@
"version": "v5.0.7"
},
"symfony/routing": {
"version": "4.2",
"version": "5.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "4.2",
"ref": "683dcb08707ba8d41b7e34adb0344bfd68d248a7"
"version": "5.1",
"ref": "b4f3e7c95e38b606eef467e8a42a8408fc460c43"
},
"files": [
"config/packages/prod/routing.yaml",
......@@ -439,12 +439,12 @@
]
},
"symfony/security-bundle": {
"version": "4.4",
"version": "5.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "4.4",
"ref": "7b4408dc203049666fe23fabed23cbadc6d8440f"
"version": "5.1",
"ref": "0a4bae19389d3b9cba1ca0102e3b2bccea724603"
},
"files": [
"config/packages/security.yaml"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment