diff --git a/.gitignore b/.gitignore
index 31444c82cee7bdbb39d5e3604d717e29d270117e..283c9403c7f9043893bf590425d41eb51790c6d6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,5 @@
 .vscode
 practical_work/tp_vec2/main
 practical_work/tp_vec2/tests
+practical_work/planets/skeleton/main
+practical_work/planets/skeleton/tests
\ No newline at end of file
diff --git a/practical_work/electric_fl/ennonce.md b/practical_work/electric_fl/enonce.md
similarity index 97%
rename from practical_work/electric_fl/ennonce.md
rename to practical_work/electric_fl/enonce.md
index 1a829f69170ed261d8ad7d150bf1d1e47df53fb5..c0befed530861b37b3b36a5c9f97a2e896a6f660 100644
--- a/practical_work/electric_fl/ennonce.md
+++ b/practical_work/electric_fl/enonce.md
@@ -36,7 +36,7 @@ $$
 
 En ce qui concerne sa direction, si $Q>0$ alors le vecteur va chercher à s'éloigner de la particule, et si $Q<0$ alors le vecteur est dirigé vers la particule.
 
-![Champs de vecteurs représentant de champs électrique d'une charge positive. Source: Wikipédia, <https://bit.ly/3bTIJDx>.](https://upload.wikimedia.org/wikipedia/commons/thumb/f/f0/E_FieldOnePointCharge.svg/langfr-1024px-E_FieldOnePointCharge.svg.png){#fig:champ_e width=50%}
+![Champs de vecteurs représentant de champs électrique d'une charge positive. Source: Wikipédia, <https://bit.ly/3kUEcGu>.](https://upload.wikimedia.org/wikipedia/commons/f/f0/E_FieldOnePointCharge.svg){#fig:champ_e width=50%}
 
 En réalité, on rencontre souvent (très souvent) plus d'une particule chargée, dans ce cas, on se sert du principe de superposition des champs électriques. Le vecteur en un point représente alors la résultante des actions induites par chacune de nos particules chargées.
 
diff --git a/practical_work/planets/Exemple_force.svg b/practical_work/planets/Exemple_force.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0c823d8a7ab591ccfb195d7cee45c44937ff53df
--- /dev/null
+++ b/practical_work/planets/Exemple_force.svg
@@ -0,0 +1 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="989" height="775"><defs><clipPath id="ZNxznfRplkyb"><path fill="none" stroke="none" d=" M 0 0 L 989 0 L 989 775 L 0 775 L 0 0 Z"/></clipPath></defs><g transform="scale(1,1)" clip-path="url(#ZNxznfRplkyb)"><g><rect fill="rgb(255,255,255)" stroke="none" x="0" y="0" width="989" height="775" fill-opacity="1"/><path fill="rgb(21,101,192)" stroke="none" paint-order="stroke fill markers" d=" M 425.74752862300124 584.4329932425899 C 425.74752862300124 674.531164865674 352.70852933798386 747.5701641506912 262.6103577148996 747.5701641506912 C 172.5121860918153 747.5701641506912 99.47318680679794 674.531164865674 99.47318680679794 584.4329932425899 C 99.47318680679794 494.33482161950565 172.5121860918153 421.29582233448843 262.6103577148996 421.29582233448843 C 352.70852933798386 421.29582233448843 425.74752862300124 494.33482161950565 425.74752862300124 584.4329932425899 Z" fill-opacity="1"/><path fill="none" stroke="rgb(21,101,192)" paint-order="fill stroke markers" d=" M 425.74752862300124 584.4329932425899 C 425.74752862300124 674.531164865674 352.70852933798386 747.5701641506912 262.6103577148996 747.5701641506912 C 172.5121860918153 747.5701641506912 99.47318680679794 674.531164865674 99.47318680679794 584.4329932425899 C 99.47318680679794 494.33482161950565 172.5121860918153 421.29582233448843 262.6103577148996 421.29582233448843 C 352.70852933798386 421.29582233448843 425.74752862300124 494.33482161950565 425.74752862300124 584.4329932425899 Z" stroke-opacity="0.6980392156862745" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="0.5"/><path fill="rgb(255,0,0)" stroke="none" paint-order="stroke fill markers" d=" M 895.8370009494233 173.192886789024 C 895.8370009494233 220.10214870531163 857.8095306263009 258.12961902843404 810.9002687100132 258.12961902843404 C 763.9910067937254 258.12961902843404 725.963536470603 220.10214870531163 725.963536470603 173.192886789024 C 725.963536470603 126.28362487273633 763.9910067937254 88.25615454961394 810.9002687100132 88.25615454961394 C 857.8095306263009 88.25615454961394 895.8370009494233 126.28362487273633 895.8370009494233 173.192886789024 Z" fill-opacity="1"/><path fill="none" stroke="rgb(255,0,0)" paint-order="fill stroke markers" d=" M 895.8370009494233 173.192886789024 C 895.8370009494233 220.10214870531163 857.8095306263009 258.12961902843404 810.9002687100132 258.12961902843404 C 763.9910067937254 258.12961902843404 725.963536470603 220.10214870531163 725.963536470603 173.192886789024 C 725.963536470603 126.28362487273633 763.9910067937254 88.25615454961394 810.9002687100132 88.25615454961394 C 857.8095306263009 88.25615454961394 895.8370009494233 126.28362487273633 895.8370009494233 173.192886789024 Z" stroke-opacity="0.6980392156862745" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2.5"/><path fill="none" stroke="rgb(255,0,0)" paint-order="fill stroke markers" d=" M 262.6103577148996 584.4329932425899 L 505.55593250745994 402.21376571971524" stroke-opacity="1" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="6.5"/><path fill="rgb(255,0,0)" stroke="none" paint-order="stroke fill markers" fill-rule="evenodd" d=" M 536.7553132124564 378.81294001580693 L 511.40613893343703 410.01361089596435 L 499.70572608148285 394.41392054346613 Z" fill-opacity="1"/><path fill="none" stroke="rgb(0,0,255)" paint-order="fill stroke markers" d=" M 810.9002687100132 173.192886789024 L 567.9546939174528 355.4121143118986" stroke-opacity="1" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="6.5"/><path fill="rgb(0,0,255)" stroke="none" paint-order="stroke fill markers" fill-rule="evenodd" d=" M 536.7553132124564 378.81294001580693 L 562.1044874914758 347.6122691356495 L 573.8049003434298 363.2119594881477 Z" fill-opacity="1"/><path fill="none" stroke="rgb(51,0,0)" paint-order="fill stroke markers" d=" M 257.6103577148996 579.4329932425899 L 267.6103577148996 589.4329932425899" stroke-opacity="1" stroke-linecap="square" stroke-miterlimit="10" stroke-width="2.5"/><path fill="none" stroke="rgb(51,0,0)" paint-order="fill stroke markers" d=" M 257.6103577148996 589.4329932425899 L 267.6103577148996 579.4329932425899" stroke-opacity="1" stroke-linecap="square" stroke-miterlimit="10" stroke-width="2.5"/><path fill="none" stroke="rgb(0,0,0)" paint-order="fill stroke markers" d=" M 805.9002687100132 168.192886789024 L 815.9002687100132 178.192886789024" stroke-opacity="1" stroke-linecap="square" stroke-miterlimit="10" stroke-width="2.5"/><path fill="none" stroke="rgb(0,0,0)" paint-order="fill stroke markers" d=" M 805.9002687100132 178.192886789024 L 815.9002687100132 168.192886789024" stroke-opacity="1" stroke-linecap="square" stroke-miterlimit="10" stroke-width="2.5"/><text fill="rgb(0,0,0)" stroke="none" font-family="geogebra-sans-serif, sans-serif" font-size="64px" font-style="normal" font-weight="normal" text-decoration="normal" x="149" y="402" text-anchor="start" dominant-baseline="alphabetic" fill-opacity="1">A</text><text fill="rgb(0,0,0)" stroke="none" font-family="geogebra-sans-serif, sans-serif" font-size="64px" font-style="normal" font-weight="normal" text-decoration="normal" x="762" y="71" text-anchor="start" dominant-baseline="alphabetic" fill-opacity="1">B</text><g transform="scale(35,35)"><g transform="translate(10.661285714285714,11.656857142857143)"><path fill="rgb(0,0,0)" stroke="none" paint-order="stroke fill markers" d=" M 0.537 -0.595 L 0.217 -0.595 Q 0.186 -0.595 0.183 -0.609 Q 0.182 -0.612 0.182 -0.615 Q 0.188 -0.635 0.217 -0.635 L 0.554 -0.635 Q 0.534 -0.661 0.53 -0.6930000000000001 Q 0.53 -0.709 0.544 -0.713 Q 0.547 -0.714 0.55 -0.714 Q 0.5650000000000001 -0.714 0.5700000000000001 -0.6920000000000001 Q 0.583 -0.654 0.611 -0.635 Q 0.625 -0.625 0.625 -0.615 Q 0.625 -0.604 0.608 -0.594 Q 0.5630000000000001 -0.5720000000000001 0.529 -0.529 Q 0.518 -0.516 0.51 -0.516 Q 0.496 -0.516 0.491 -0.53 Q 0.49 -0.533 0.49 -0.536 Q 0.49 -0.552 0.537 -0.595 Z"/></g><g transform="translate(10.514285714285714,11.908857142857144)"><path fill="rgb(0,0,0)" stroke="none" paint-order="stroke fill markers" d=" M 0.303 -0.325 L 0.241 -0.076 Q 0.23700000000000002 -0.061 0.23700000000000002 -0.053 Q 0.23700000000000002 -0.039 0.25 -0.036000000000000004 Q 0.257 -0.034 0.269 -0.033 Q 0.294 -0.031 0.321 -0.031 Q 0.34600000000000003 -0.031 0.34900000000000003 -0.03 L 0.354 -0.023 Q 0.355 -0.021 0.355 -0.019 Q 0.355 0 0.334 0 L 0.186 -0.003 L 0.185 -0.003 L 0.054 0 L 0.053 0 Q 0.038 0 0.038 -0.012 Q 0.038 -0.029 0.054 -0.031 L 0.066 -0.031 Q 0.131 -0.031 0.14400000000000002 -0.045 Q 0.15 -0.052000000000000005 0.156 -0.073 Q 0.156 -0.074 0.157 -0.078 L 0.289 -0.607 Q 0.294 -0.625 0.294 -0.631 Q 0.294 -0.648 0.248 -0.649 L 0.247 -0.649 L 0.229 -0.649 Q 0.203 -0.649 0.201 -0.66 Q 0.201 -0.678 0.217 -0.68 L 0.231 -0.68 L 0.721 -0.68 Q 0.745 -0.68 0.747 -0.673 L 0.748 -0.673 Q 0.75 -0.667 0.748 -0.653 L 0.728 -0.48 Q 0.721 -0.457 0.714 -0.455 Q 0.7020000000000001 -0.455 0.7020000000000001 -0.467 Q 0.7020000000000001 -0.47200000000000003 0.704 -0.485 Q 0.707 -0.512 0.707 -0.539 Q 0.707 -0.606 0.673 -0.628 L 0.672 -0.629 Q 0.64 -0.649 0.561 -0.649 L 0.429 -0.649 Q 0.392 -0.649 0.385 -0.638 L 0.384 -0.638 L 0.384 -0.637 Q 0.381 -0.633 0.379 -0.625 L 0.379 -0.624 L 0.378 -0.623 Q 0.377 -0.619 0.375 -0.61 L 0.311 -0.356 L 0.402 -0.356 Q 0.47500000000000003 -0.356 0.5 -0.383 L 0.501 -0.384 Q 0.518 -0.403 0.531 -0.452 Q 0.536 -0.47100000000000003 0.546 -0.47300000000000003 Q 0.557 -0.47300000000000003 0.558 -0.462 Q 0.558 -0.457 0.555 -0.446 L 0.5 -0.229 Q 0.49 -0.209 0.485 -0.20800000000000002 Q 0.47300000000000003 -0.20800000000000002 0.47300000000000003 -0.22 Q 0.47300000000000003 -0.224 0.47600000000000003 -0.231 Q 0.483 -0.261 0.483 -0.28 Q 0.483 -0.309 0.461 -0.318 L 0.461 -0.318 Q 0.442 -0.325 0.4 -0.325 L 0.303 -0.325 Z"/></g><g transform="translate(11.157285714285715,12.058857142857143) scale(0.7,0.7)"><path fill="rgb(0,0,0)" stroke="none" paint-order="stroke fill markers" d=" M 0.16 -0.078 L 0.294 -0.615 Q 0.298 -0.631 0.298 -0.634 Q 0.298 -0.646 0.28200000000000003 -0.649 L 0.281 -0.649 L 0.28 -0.649 Q 0.277 -0.649 0.271 -0.65 Q 0.254 -0.652 0.233 -0.652 Q 0.20700000000000002 -0.652 0.20500000000000002 -0.663 Q 0.20500000000000002 -0.681 0.22 -0.683 L 0.221 -0.683 L 0.222 -0.683 L 0.234 -0.683 L 0.5700000000000001 -0.683 Q 0.685 -0.683 0.734 -0.615 Q 0.756 -0.583 0.756 -0.545 Q 0.756 -0.464 0.666 -0.404 Q 0.665 -0.404 0.664 -0.403 Q 0.611 -0.369 0.547 -0.357 Q 0.649 -0.34500000000000003 0.687 -0.277 Q 0.7020000000000001 -0.249 0.7020000000000001 -0.216 Q 0.7020000000000001 -0.14300000000000002 0.632 -0.079 L 0.631 -0.078 Q 0.545 0 0.426 0 L 0.069 0 Q 0.044 0 0.042 -0.011 Q 0.042 -0.029 0.057 -0.031 L 0.069 -0.031 Q 0.134 -0.031 0.147 -0.045 Q 0.153 -0.052000000000000005 0.159 -0.073 Q 0.159 -0.074 0.16 -0.078 M 0.311 -0.366 L 0.457 -0.366 Q 0.556 -0.366 0.62 -0.438 Q 0.665 -0.489 0.665 -0.549 Q 0.665 -0.622 0.605 -0.644 Q 0.584 -0.652 0.556 -0.652 L 0.427 -0.652 Q 0.391 -0.652 0.383 -0.642 L 0.383 -0.642 L 0.383 -0.641 L 0.382 -0.641 L 0.382 -0.64 Q 0.378 -0.634 0.373 -0.614 L 0.311 -0.366 M 0.266 -0.031 L 0.402 -0.031 Q 0.498 -0.031 0.561 -0.10300000000000001 Q 0.609 -0.159 0.609 -0.227 Q 0.609 -0.3 0.557 -0.33 Q 0.531 -0.34400000000000003 0.494 -0.34400000000000003 L 0.305 -0.34400000000000003 L 0.23600000000000002 -0.065 Q 0.231 -0.047 0.231 -0.042 Q 0.231 -0.034 0.24 -0.032 L 0.24 -0.032 L 0.24 -0.032 L 0.244 -0.032 Q 0.25 -0.031 0.266 -0.031 Z"/></g><g transform="translate(11.723585714285715,12.058857142857143) scale(0.7,0.7)"><path fill="rgb(0,0,0)" stroke="none" paint-order="stroke fill markers" d=" M 0.179 -0.115 L 0.527 -0.6990000000000001 Q 0.537 -0.715 0.553 -0.716 Q 0.5680000000000001 -0.716 0.5700000000000001 -0.706 Q 0.5710000000000001 -0.7030000000000001 0.5720000000000001 -0.6920000000000001 L 0.633 -0.067 Q 0.636 -0.042 0.645 -0.037 L 0.646 -0.037 L 0.646 -0.037 L 0.646 -0.037 L 0.646 -0.037 L 0.646 -0.036000000000000004 Q 0.658 -0.031 0.6980000000000001 -0.031 Q 0.72 -0.031 0.721 -0.02 Q 0.721 0 0.7030000000000001 0 L 0.591 -0.003 L 0.59 -0.003 L 0.466 0 L 0.465 0 Q 0.451 0 0.451 -0.011 Q 0.459 -0.03 0.47500000000000003 -0.031 Q 0.547 -0.031 0.547 -0.064 Q 0.547 -0.063 0.531 -0.231 L 0.28 -0.231 L 0.20400000000000001 -0.10300000000000001 Q 0.19 -0.078 0.19 -0.066 Q 0.19 -0.035 0.23700000000000002 -0.031 Q 0.253 -0.031 0.253 -0.019 Q 0.253 0 0.234 0 L 0.138 -0.003 L 0.134 -0.003 L 0.05 0 L 0.048 0 Q 0.035 0 0.035 -0.011 Q 0.035 -0.029 0.05 -0.03 L 0.05 -0.031 L 0.056 -0.031 Q 0.11900000000000001 -0.035 0.159 -0.085 Q 0.169 -0.098 0.179 -0.115 M 0.299 -0.262 L 0.528 -0.262 L 0.496 -0.592 L 0.299 -0.262 Z"/></g></g><g transform="scale(35,35)"><g transform="translate(20.061285714285713,8.399714285714285)"><path fill="rgb(0,0,0)" stroke="none" paint-order="stroke fill markers" d=" M 0.537 -0.595 L 0.217 -0.595 Q 0.186 -0.595 0.183 -0.609 Q 0.182 -0.612 0.182 -0.615 Q 0.188 -0.635 0.217 -0.635 L 0.554 -0.635 Q 0.534 -0.661 0.53 -0.6930000000000001 Q 0.53 -0.709 0.544 -0.713 Q 0.547 -0.714 0.55 -0.714 Q 0.5650000000000001 -0.714 0.5700000000000001 -0.6920000000000001 Q 0.583 -0.654 0.611 -0.635 Q 0.625 -0.625 0.625 -0.615 Q 0.625 -0.604 0.608 -0.594 Q 0.5630000000000001 -0.5720000000000001 0.529 -0.529 Q 0.518 -0.516 0.51 -0.516 Q 0.496 -0.516 0.491 -0.53 Q 0.49 -0.533 0.49 -0.536 Q 0.49 -0.552 0.537 -0.595 Z"/></g><g transform="translate(19.914285714285715,8.651714285714286)"><path fill="rgb(0,0,0)" stroke="none" paint-order="stroke fill markers" d=" M 0.303 -0.325 L 0.241 -0.076 Q 0.23700000000000002 -0.061 0.23700000000000002 -0.053 Q 0.23700000000000002 -0.039 0.25 -0.036000000000000004 Q 0.257 -0.034 0.269 -0.033 Q 0.294 -0.031 0.321 -0.031 Q 0.34600000000000003 -0.031 0.34900000000000003 -0.03 L 0.354 -0.023 Q 0.355 -0.021 0.355 -0.019 Q 0.355 0 0.334 0 L 0.186 -0.003 L 0.185 -0.003 L 0.054 0 L 0.053 0 Q 0.038 0 0.038 -0.012 Q 0.038 -0.029 0.054 -0.031 L 0.066 -0.031 Q 0.131 -0.031 0.14400000000000002 -0.045 Q 0.15 -0.052000000000000005 0.156 -0.073 Q 0.156 -0.074 0.157 -0.078 L 0.289 -0.607 Q 0.294 -0.625 0.294 -0.631 Q 0.294 -0.648 0.248 -0.649 L 0.247 -0.649 L 0.229 -0.649 Q 0.203 -0.649 0.201 -0.66 Q 0.201 -0.678 0.217 -0.68 L 0.231 -0.68 L 0.721 -0.68 Q 0.745 -0.68 0.747 -0.673 L 0.748 -0.673 Q 0.75 -0.667 0.748 -0.653 L 0.728 -0.48 Q 0.721 -0.457 0.714 -0.455 Q 0.7020000000000001 -0.455 0.7020000000000001 -0.467 Q 0.7020000000000001 -0.47200000000000003 0.704 -0.485 Q 0.707 -0.512 0.707 -0.539 Q 0.707 -0.606 0.673 -0.628 L 0.672 -0.629 Q 0.64 -0.649 0.561 -0.649 L 0.429 -0.649 Q 0.392 -0.649 0.385 -0.638 L 0.384 -0.638 L 0.384 -0.637 Q 0.381 -0.633 0.379 -0.625 L 0.379 -0.624 L 0.378 -0.623 Q 0.377 -0.619 0.375 -0.61 L 0.311 -0.356 L 0.402 -0.356 Q 0.47500000000000003 -0.356 0.5 -0.383 L 0.501 -0.384 Q 0.518 -0.403 0.531 -0.452 Q 0.536 -0.47100000000000003 0.546 -0.47300000000000003 Q 0.557 -0.47300000000000003 0.558 -0.462 Q 0.558 -0.457 0.555 -0.446 L 0.5 -0.229 Q 0.49 -0.209 0.485 -0.20800000000000002 Q 0.47300000000000003 -0.20800000000000002 0.47300000000000003 -0.22 Q 0.47300000000000003 -0.224 0.47600000000000003 -0.231 Q 0.483 -0.261 0.483 -0.28 Q 0.483 -0.309 0.461 -0.318 L 0.461 -0.318 Q 0.442 -0.325 0.4 -0.325 L 0.303 -0.325 Z"/></g><g transform="translate(20.557285714285715,8.801714285714286) scale(0.7,0.7)"><path fill="rgb(0,0,0)" stroke="none" paint-order="stroke fill markers" d=" M 0.179 -0.115 L 0.527 -0.6990000000000001 Q 0.537 -0.715 0.553 -0.716 Q 0.5680000000000001 -0.716 0.5700000000000001 -0.706 Q 0.5710000000000001 -0.7030000000000001 0.5720000000000001 -0.6920000000000001 L 0.633 -0.067 Q 0.636 -0.042 0.645 -0.037 L 0.646 -0.037 L 0.646 -0.037 L 0.646 -0.037 L 0.646 -0.037 L 0.646 -0.036000000000000004 Q 0.658 -0.031 0.6980000000000001 -0.031 Q 0.72 -0.031 0.721 -0.02 Q 0.721 0 0.7030000000000001 0 L 0.591 -0.003 L 0.59 -0.003 L 0.466 0 L 0.465 0 Q 0.451 0 0.451 -0.011 Q 0.459 -0.03 0.47500000000000003 -0.031 Q 0.547 -0.031 0.547 -0.064 Q 0.547 -0.063 0.531 -0.231 L 0.28 -0.231 L 0.20400000000000001 -0.10300000000000001 Q 0.19 -0.078 0.19 -0.066 Q 0.19 -0.035 0.23700000000000002 -0.031 Q 0.253 -0.031 0.253 -0.019 Q 0.253 0 0.234 0 L 0.138 -0.003 L 0.134 -0.003 L 0.05 0 L 0.048 0 Q 0.035 0 0.035 -0.011 Q 0.035 -0.029 0.05 -0.03 L 0.05 -0.031 L 0.056 -0.031 Q 0.11900000000000001 -0.035 0.159 -0.085 Q 0.169 -0.098 0.179 -0.115 M 0.299 -0.262 L 0.528 -0.262 L 0.496 -0.592 L 0.299 -0.262 Z"/></g><g transform="translate(21.082285714285714,8.801714285714286) scale(0.7,0.7)"><path fill="rgb(0,0,0)" stroke="none" paint-order="stroke fill markers" d=" M 0.16 -0.078 L 0.294 -0.615 Q 0.298 -0.631 0.298 -0.634 Q 0.298 -0.646 0.28200000000000003 -0.649 L 0.281 -0.649 L 0.28 -0.649 Q 0.277 -0.649 0.271 -0.65 Q 0.254 -0.652 0.233 -0.652 Q 0.20700000000000002 -0.652 0.20500000000000002 -0.663 Q 0.20500000000000002 -0.681 0.22 -0.683 L 0.221 -0.683 L 0.222 -0.683 L 0.234 -0.683 L 0.5700000000000001 -0.683 Q 0.685 -0.683 0.734 -0.615 Q 0.756 -0.583 0.756 -0.545 Q 0.756 -0.464 0.666 -0.404 Q 0.665 -0.404 0.664 -0.403 Q 0.611 -0.369 0.547 -0.357 Q 0.649 -0.34500000000000003 0.687 -0.277 Q 0.7020000000000001 -0.249 0.7020000000000001 -0.216 Q 0.7020000000000001 -0.14300000000000002 0.632 -0.079 L 0.631 -0.078 Q 0.545 0 0.426 0 L 0.069 0 Q 0.044 0 0.042 -0.011 Q 0.042 -0.029 0.057 -0.031 L 0.069 -0.031 Q 0.134 -0.031 0.147 -0.045 Q 0.153 -0.052000000000000005 0.159 -0.073 Q 0.159 -0.074 0.16 -0.078 M 0.311 -0.366 L 0.457 -0.366 Q 0.556 -0.366 0.62 -0.438 Q 0.665 -0.489 0.665 -0.549 Q 0.665 -0.622 0.605 -0.644 Q 0.584 -0.652 0.556 -0.652 L 0.427 -0.652 Q 0.391 -0.652 0.383 -0.642 L 0.383 -0.642 L 0.383 -0.641 L 0.382 -0.641 L 0.382 -0.64 Q 0.378 -0.634 0.373 -0.614 L 0.311 -0.366 M 0.266 -0.031 L 0.402 -0.031 Q 0.498 -0.031 0.561 -0.10300000000000001 Q 0.609 -0.159 0.609 -0.227 Q 0.609 -0.3 0.557 -0.33 Q 0.531 -0.34400000000000003 0.494 -0.34400000000000003 L 0.305 -0.34400000000000003 L 0.23600000000000002 -0.065 Q 0.231 -0.047 0.231 -0.042 Q 0.231 -0.034 0.24 -0.032 L 0.24 -0.032 L 0.24 -0.032 L 0.244 -0.032 Q 0.25 -0.031 0.266 -0.031 Z"/></g></g></g></g></svg>
\ No newline at end of file
diff --git a/practical_work/planets/Makefile b/practical_work/planets/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..3ba1e797414d652127de10f0c621d72e30cd29fe
--- /dev/null
+++ b/practical_work/planets/Makefile
@@ -0,0 +1,28 @@
+OPTIONS = --filter=pandoc-numbering
+OPTIONS += --filter=pandoc-crossref
+
+PDFOPTIONS = --highlight-style kate
+PDFOPTIONS += --pdf-engine pdflatex
+PDFOPTIONS += --number-sections
+PDFOPTIONS += --template=./default.latex
+
+HTMLOPTIONS += -t html5
+HTMLOPTIONS += -c ../../css/tufte-css/tufte.css
+HTMLOPTIONS += --self-contained
+HTMLOPTIONS += --mathjax=MathJax.js
+
+MD=$(wildcard *.md)
+HTML=$(MD:%.md=%.html)
+PDF=$(MD:%.md=%.pdf)
+
+
+all: $(HTML) $(PDF)
+
+%.pdf: %.md Makefile
+	pandoc -s $(OPTIONS) $(PDFOPTIONS) -o $@ $<
+
+%.html: %.md Makefile
+	pandoc -s $(OPTIONS) $(HTMLOPTIONS) -o $@ $<
+
+clean:
+	rm -rf *.html *.pdf
diff --git a/practical_work/planets/MathJax.js b/practical_work/planets/MathJax.js
new file mode 100644
index 0000000000000000000000000000000000000000..3c5458cf56ca84c856384c74f5f51a6b349569f6
--- /dev/null
+++ b/practical_work/planets/MathJax.js
@@ -0,0 +1,4 @@
+var fileref=document.createElement('script')
+fileref.setAttribute("type","text/javascript")
+fileref.setAttribute("src", "https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML")
+document.getElementsByTagName("head")[0].appendChild(fileref)
diff --git a/practical_work/planets/enonce.md b/practical_work/planets/enonce.md
new file mode 100644
index 0000000000000000000000000000000000000000..cd5fcbece7e16421fbcfaa3f6cc849a4ae270485
--- /dev/null
+++ b/practical_work/planets/enonce.md
@@ -0,0 +1,168 @@
+---
+# author:
+# - El Kharroubi Michaël
+title: Travail pratique
+subtitle: Simulation d'un système planétaire sur un plan à l'aide des lois de Newton 
+autoSectionLabels: true
+autoEqnLabels: true
+eqnPrefix: 
+  - "éq."
+  - "éqs."
+chapters: true
+numberSections: false
+chaptersDepth: 1
+sectionsDepth: 3
+lang: fr
+documentclass: article
+papersize: A4
+cref: false
+pandoc-numbering:
+  - category: TP
+urlcolor: blue
+---
+
+\newcommand{\vectwo}[2]{\begin{pmatrix}#1 \\ #2 \end{pmatrix}}
+
+# But
+
+- Simuler un phénomène physique vu en cours à l'aide du langage C
+- Visualiser les interactions gravitationnelles au sein d'un système planétaire.
+
+# Théorie
+
+## Rappel théorique
+
+Dans notre univers, tous les corps sont soumis à des forces. Une force est une grandeur permettant de quantifier pour un corps : la direction, le sens et l'intensité de l'interaction, avec les autres corps, subie. Dans le cadre de ce travail pratique, nous nous intéresserons à l'une des quatre forces fondamentales, la force de gravitation. Pour rappel, les forces suivent les trois lois de Newton.
+
+ 1. Si un corps est immobile, alors la somme des forces qu'il subit, appelée force résultante, est nulle. ($\vec{F} = \vec{0}$)
+ 2. La force résultante subit par un corps est égale à la masse de ce dernier multipliée par son accélération. ($\vec{F} = m\vec{a}_p$)
+ 3. Si un corps *A* subit une force de la part d'un corps *B*, alors le corps *B* subit une force de réaction de sens opposé et de même intensité. ($\vec{F}_{BA} = -\vec{F}_{AB}$)
+
+![Exemple d'interaction gravitationnelle](./Exemple_force.svg){#fig:gravity width=50%}
+
+La force de gravitation est une force qui apparaît entre tous les objets ayant une masse (un corps). Elle régit le mouvements des objets massifs (planètes, étoiles, trou noir, galaxies...). La force de gravité causée par un corps *B* et subie par un corps *A* s'obtient avec la formule suivante :
+
+$$
+\vec{F}_{BA} = G\displaystyle\frac{m_Am_B}{\| \vec{r}_{AB} \|^3}\vec{r}_{AB}
+$$
+
+Avec $G$ en [$\frac{\text{m}^3}{\text{kg}\cdot \text{s}^2}$], $m_a$,$m_b$ en [kg] et $\| \vec{r}_{AB} \|$ en [m]. 
+
+\pagebreak
+
+L'orbite d'une planète n'est pas un cercle parfait, il s'agit en réalité d'une ellipsoïde. Cette orbite ellipsoïdale est définie par trois paramètres :
+
+  1. Le demi-grand axe ($a$ en mètres, **!!! à ne pas confondre avec l'accélération $\vec{a}$**)
+  2. Le demi-petit axe ($b$ en mètres)
+  3. L'excentricité ($e$ sans unité)
+
+![Exemple (volontairement exagéré) de l'orbite de la terre autour du soleil. Source: Alexis Durgnat (Bureau A403).](./perihelie.svg){#fig:orbite width=50%}
+
+Sur la figure \ref{fig:e}, vous observer différentes orbites pour différentes valeurs de $e$.
+
+![Différentes orbites en fonction de l'excentricité. Source: Wikipédia, <https://bit.ly/3x53F4A>.](https://upload.wikimedia.org/wikipedia/commons/8/89/OrbitalEccentricityDemo.svg){#fig:e width=30%}
+
+\pagebreak
+
+
+## Simulation d'un système planétaire
+
+### Idée générale
+
+Dans notre simulation, nous représentrons un système planétaire sur un plan, basé sur notre système solaire. Au centre nous aurons une étoile (fixe) et un certain nombre de planètes qui orbitent autour de cette dernière.
+
+Pour simuler un système planétaire, on peut effectuer les étapes suivantes :
+
+  1. Créer une étoile au centre de notre domaine.
+  2. On ajoute autant de planètes que l'on désire autour de l'étoile.
+  3. On définit nos conditions initiales.
+  4. On affiche puis on simule l'évolution :
+      1. [On affiche notre système.]{#here4} 
+      2. On calcule la force résultante sur chacune des planètes.
+      3. On calcule la prochaine position de chacune des planètes ($\vec{x}_p(t + \Delta t)$).
+      4. On met à jour la position des planètes de notre système.
+      5. On revient à l'étape [4.1](#here4).
+
+# Évolution
+
+Concentrons nous tout d'abord sur l'évolution de la simulation, nous verrons les conditions initiales dans un second temps. Pour déterminer les informations néccéssaires, on commence par calculer la force résultante :
+
+$$
+  \vec{F}_p = \sum_{\{q \in \mathcal{C}\ |\ q \neq p\}}\vec{F}_{qp}
+$$
+
+Où $\mathcal{C}$ est l'ensemble des corps célèstes (les planètes et l'étoile) de votre simulation.
+
+Ensuite, on calcule la nouvelle position à partir de l'ancienne. En reprenant les équations du mouvement uniformément accéléré on a :
+
+$$
+\label{eq:verlet}
+\begin{aligned}
+  \vec{x}_p(t+\Delta t) &= \vec{x}_p(t) + \Delta t\vec{v}_p(t) + \frac{(\Delta t)^2}{2}\vec{a}_p(t)\\
+  \vec{x}_p(t-\Delta t) &= \vec{x}_p(t) - \Delta t\vec{v}_p(t) + \frac{(\Delta t)^2}{2}\vec{a}_p(t)
+\end{aligned}
+$$
+
+Avec $t$ et $\Delta t$ en [s], $\| \vec{x}_p(t) \|$ en [m], $\| \vec{v}_p(t) \|$ en [$\frac{m}{s}$] et $\| \vec{a}_p(t) \|$ en [$\frac{m}{s^2}$].
+
+En additionnant les deux équations de \eqref{eq:verlet}, on obtient :
+
+$$
+\label{eq:mouvement}
+\begin{aligned}
+  \vec{x}_p(t+\Delta t) + \vec{x}_p(t-\Delta t) &= 2\vec{x}_p(t) + (\Delta t)^2\vec{a}_p(t)\\
+  \vec{x}_p(t+\Delta t) &= 2\vec{x}_p(t) - \vec{x}_p(t-\Delta t) + (\Delta t)^2\vec{a}_p(t)\\
+\end{aligned}
+$$
+
+On remarque donc qu'il n'est pas nécessaire de retenir l'évolution de $\vec{v}_p$ pour calculer le prochain état de notre simulation. Nous n'avons besoin que des deux dernières positions ($\vec{x}_p(t), \vec{x}_p(t-\Delta t)$) et de l'accélération ($\vec{a}_p(t)$). Nous calculerons donc les $\vec{x}_p$ itérativement et je vous laisse le soin de déduire comment nous pouvons obtenir $\vec{a}_p(t)$ à partir des formules données. 
+
+### Conditions initiales
+
+Si l'on regarde \eqref{eq:mouvement}, on remarque que pour calculer $\vec{x}_p(t + \Delta t)$ en $t=0$ ($\vec{x}_p(\Delta t)$), il nous faudrait la position $\vec{x}_p(t-\Delta t)$. Comme nous ne considirons pas de temps négatif dans notre simulation, nous allons fixer la valeur en $t=0$ avec la formule \eqref{eq:mouvement}. Ce qui nous donne :
+
+$$
+\vec{x}_p(\Delta t) = \vec{x}_p(0) + \Delta t\vec{v}_p(0) + \frac{(\Delta t)^2}{2}\vec{a}_p(0)
+$$
+
+Commencons par $\vec{v}_p(0)$. Pour rappel, l'orbite d'une planète est éllipsoïdale. Sans rentrer dans des détails qui dépassent le cadre de ce tp, nous pouvons connaître la vitesse à la périhélie (voir \ref{fig:orbite}) de l'orbite d'une planète autour de notre étoile. La périhélie est la distance la plus courte dans l'orbite d'une planète (autour du soleil, -hélie=soleil). Nous avons donc :
+
+$$
+\vec{v}_p(0) = \displaystyle\sqrt{\frac{GM_{\odot}(1+e_p)}{a_p(1-e_p)}}\cdot\frac{\vec{r}_{p\bot}}{\| \vec{r}_{p\bot} \|}
+$$
+
+Où $M_{\odot}$ est la masse de l'étoile en [kg], $a_p$ est le demi-grand axe, de l'orbite de la planète $p$, en [m], $e$ l'exentricité, de l'orbite de la planète $p$, sans unité et $\vec{r}_{\bot}$ est le vecteur perdiculaire ($\vec{r}_{p\bot} = \vectwo{-{r_p}_y}{{r_p}_x}$) au vecteur allant de la planète $p$ à son étoile.
+
+Par conséquent, puisque que nous connaissons la vitesse à la périhélie, nous placerons intelligement $\vec{x}_p(0)$ à la périhélie. Pour $\vec{a}_p(0)$, on peut le calculer de la même manière qu'avec n'importe quelle autre valeur de $t$.
+
+Dans votre simulation vous utiliserez des données en mètres, vous aurez donc vraisemblablement (vu l'échelle cosmique) des valeurs en millions de kilomètres. Lors d'un précédent travail pratique, vous avez implementé une fonction permettant de convertir un vecteur en deux dimensions $\vec{r}\in\{[-1;1]\}^2$ en coordonnées d'écran $\vec{c}\in\{[0;lignes[\}\times\{[0;colonnes[\}$. Pour obtenir un vecteur $\vec{r}$, vous devrez définir le rayon de votre écran en mètres $R_S$ (p.ex : 110% du demi-grand axe de l'orbite de la planète la plus éloignée de l'étoile). Puis à partir de votre vecteur position en mètres $\vec{x}_p$, vous obtiendrez la nouvelle position $\vec{r} = \frac{\vec{x}_p}{R_S}$. Vous pourrez ensuite convertir cette position en coordonnées d'écran $\vec{c}$ grâce à votre fonction.  
+
+# Énoncé
+
+Dans le cadre de ce travail pratique, vous allez devoir implementer une simulation de système planétaire semblable à notre système solaire. Pour cela vous avez à votre disposition un squelette de code nommé `skeleton.zip`. Ce squelette est uniquement là dans le but de vous aider. Vous pouvez donc vous en passer (ce que je vous déconseille). En revanche, vous devez impérativement utiliser la méthode et les équations présentées dans la partie théorique de cet énoncé.
+
+Si toutefois vous décidiez de prendre ce squelette (excellente décision, je vous en félicite), une fois téléchargé et décompressé, vous devrez effectuer les actions suivantes :
+
+  1. Remplacer le fichier `skeleton/vec2/vec2.c` par celui que vous avez réalisé durant un précédent travail pratique.
+  2. Prendre connaisance des fichiers `skeleton/planet/planet.h` et `skeleton/main.c`. Ces fichiers contiennent des commentaires pour vous guider.
+  3. Réaliser le travail pratique.
+
+Ce travail est séparé en deux parties, qui valent respectivement 4.5 et 1.5 points (Pour un total de 6 (c'est dingue !!!)). 
+
+La première partie, consiste à simuler un système planétaire avec les quatres premières planètes (par ordre de distance) du système solaire (Mercure, Vénus, Terre (souriez, vous êtes simulé), Mars). 
+
+Dans un second temps vous devrez ajouter quelques planètes fictives ($\geq 2$), et essayez de faire varier les différents paramètres. C'est à dire :
+
+  * La masse
+  * La distance à l'étoile
+  * La forme de l'orbite en changeant la vitesse initiale via le demi-grand axe et l'excentricité.
+
+Pour dessiner vos planètes et votre étoile, vous pouvez utiliser la fonction `draw_full_circle` qui a été ajoutée à cette occasion dans la librairie `skeleton/gfx`. Elle prend en paramètre un contexte SDL, un centre, un rayon et une couleur.
+
+Pour que votre simulation marche, vous serez amené, à un moment ou à un autre, à devoir mettre des données (position de vos planètes, choix du $\Delta t$, masse, etc...). Vous devez dans le cadre de ce travail aller chercher ces données, et ce dans les bonnes unités (p.ex : distance en mètre et non en années lumière). Vous devrez indiquer dans votre rapport les données choisies (dans les bonnes unités) et leur source. 
+
+# Travail à rendre par groupe de deux (strictement égal à deux)
+
+- Un rapport succint (moins de 6 pages) présentant le travail réalisé, avec des images de ce dernier.
+- Le repos git contenant le code réalisé.
+- (Bonus) Une vidéo du résultat, si vous réussissez à créer un système cool.
diff --git a/practical_work/planets/perihelie.svg b/practical_work/planets/perihelie.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f4f724473b5fbbf26b7b93738f98e1ad9e81157e
--- /dev/null
+++ b/practical_work/planets/perihelie.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 500 250" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;"><g id="Calque1"><ellipse cx="246.823" cy="115.152" rx="211.245" ry="87.675" style="fill:#ebebeb;fill-opacity:0;stroke:#000;stroke-opacity:0.73;stroke-width:0.83px;"/><path d="M35.578,115.152l422.491,0l-306.871,0" style="fill:none;stroke:#000;stroke-width:1px;"/><path d="M35.578,115.152l115.62,0" style="fill:none;stroke:#07ff00;stroke-opacity:0.73;stroke-width:1.67px;"/><path d="M246.506,115.152l211.563,0" style="fill:none;stroke:#f00;stroke-width:1.67px;"/><ellipse cx="148.983" cy="114.47" rx="6.671" ry="6.036" style="fill:#ffeb00;"/><ellipse cx="33.99" cy="114.376" rx="6.671" ry="6.036" style="fill:#001aff;"/><path d="M246.823,27.478l0,175.349" style="fill:none;stroke:#000;stroke-width:1px;"/><path d="M246.823,27.478l0,88.31" style="fill:none;stroke:#0600ff;stroke-opacity:0.73;stroke-width:1.67px;"/><text x="333.545px" y="133.577px" style="font-family:'LucidaCalligraphy-Italic', 'Lucida Calligraphy', cursive;font-style:italic;font-size:17.739px;fill:#f00;">a</text><text x="254.765px" y="73.221px" style="font-family:'LucidaSans-TypewriterOblique', 'Lucida Sans Typewriter', monospace;font-style:italic;font-stretch:semi-condensed;font-size:17.739px;fill:#01f;">b</text><text x="56.544px" y="106.893px" style="font-family:'LucidaSans-TypewriterOblique', 'Lucida Sans Typewriter', monospace;font-style:italic;font-stretch:semi-condensed;font-size:12.5px;fill:#16ba00;">périhélie</text><text x="138.501px" y="134.848px" style="font-family:'LucidaSans-TypewriterOblique', 'Lucida Sans Typewriter', monospace;font-style:italic;font-stretch:semi-condensed;font-size:12.5px;">Soleil</text><g transform="matrix(0.579483,-0.814984,0.814984,0.579483,-341.887,-216.219)"><text x="-46.92px" y="481.765px" style="font-family:'LucidaSans-TypewriterOblique', 'Lucida Sans Typewriter', monospace;font-style:italic;font-stretch:semi-condensed;font-size:12.5px;">Terre</text></g></g></svg>
\ No newline at end of file
diff --git a/practical_work/planets/skeleton/Makefile b/practical_work/planets/skeleton/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..228efce7defc6232e5058eaa2814bcf653500d7f
--- /dev/null
+++ b/practical_work/planets/skeleton/Makefile
@@ -0,0 +1,28 @@
+#The compiler
+CC:=gcc
+#The flags passed to the compiler
+CFLAGS:=-g -Ofast -Wall -Wextra -fsanitize=address -fsanitize=leak -std=gnu11
+#The flags passed to the linker
+LDFLAGS:=-lm -lSDL2
+#Path to the lib Vec2
+VPATH:=vec2 gfx planet
+
+
+
+main: main.o vec2.o gfx.o planet.o
+	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+
+run_tests: tests
+	./$<
+
+tests: vec_tests.o vec2.o
+	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+
+planet.o: planet.h
+
+vec2.o: vec2.h
+
+gfx.o: gfx.h
+
+clean:
+	rm -f *.o main tests
diff --git a/practical_work/planets/skeleton/gfx/gfx.c b/practical_work/planets/skeleton/gfx/gfx.c
new file mode 100644
index 0000000000000000000000000000000000000000..0d7ca416e10337dddd73d89bf9fe2be71fc16c70
--- /dev/null
+++ b/practical_work/planets/skeleton/gfx/gfx.c
@@ -0,0 +1,150 @@
+/// @file gfx.c
+/// @author Florent Gluck
+/// @date November 6, 2016
+/// Helper routines to render pixels in fullscreen graphic mode.
+/// Uses the SDL2 library.
+/// Update : Add full circle
+/// @author Michaël El Kharroubi
+/// @date 19 November 2021
+
+#include "gfx.h"
+#include <assert.h>
+
+/// Create a fullscreen graphic window.
+/// @param title Title of the window.
+/// @param width Width of the window in pixels.
+/// @param height Height of the window in pixels.
+/// @return a pointer to the graphic context or NULL if it failed.
+struct gfx_context_t *gfx_create(char *title, uint32_t width, uint32_t height)
+{
+    if (SDL_Init(SDL_INIT_VIDEO) != 0)
+        goto error;
+    SDL_Window *window = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED,
+                                          SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_RESIZABLE);
+    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
+    SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
+                                             SDL_TEXTUREACCESS_STREAMING, width, height);
+    uint32_t *pixels = malloc(width * height * sizeof(uint32_t));
+    struct gfx_context_t *ctxt = malloc(sizeof(struct gfx_context_t));
+
+    if (!window || !renderer || !texture || !pixels || !ctxt)
+        goto error;
+
+    ctxt->renderer = renderer;
+    ctxt->texture = texture;
+    ctxt->window = window;
+    ctxt->width = width;
+    ctxt->height = height;
+    ctxt->pixels = pixels;
+
+    SDL_ShowCursor(SDL_DISABLE);
+    gfx_clear(ctxt, COLOR_BLACK);
+    return ctxt;
+
+error:
+    return NULL;
+}
+
+/// Draw a pixel in the specified graphic context.
+/// @param ctxt Graphic context where the pixel is to be drawn.
+/// @param column X coordinate of the pixel.
+/// @param row Y coordinate of the pixel.
+/// @param color Color of the pixel.
+void gfx_putpixel(struct gfx_context_t *ctxt, uint32_t column, uint32_t row, uint32_t color)
+{
+    if (column < ctxt->width && row < ctxt->height)
+        ctxt->pixels[ctxt->width * row + column] = color;
+}
+
+/// Clear the specified graphic context.
+/// @param ctxt Graphic context to clear.
+/// @param color Color to use.
+void gfx_clear(struct gfx_context_t *ctxt, uint32_t color)
+{
+    int n = ctxt->width * ctxt->height;
+    while (n)
+        ctxt->pixels[--n] = color;
+}
+
+/// Display the graphic context.
+/// @param ctxt Graphic context to clear.
+void gfx_present(struct gfx_context_t *ctxt)
+{
+    SDL_UpdateTexture(
+        ctxt->texture, NULL, ctxt->pixels, ctxt->width * sizeof(uint32_t));
+    SDL_RenderCopy(ctxt->renderer, ctxt->texture, NULL, NULL);
+    SDL_RenderPresent(ctxt->renderer);
+}
+
+/// Destroy a graphic window.
+/// @param ctxt Graphic context of the window to close.
+void gfx_destroy(struct gfx_context_t *ctxt)
+{
+    SDL_ShowCursor(SDL_ENABLE);
+    SDL_DestroyTexture(ctxt->texture);
+    SDL_DestroyRenderer(ctxt->renderer);
+    SDL_DestroyWindow(ctxt->window);
+    free(ctxt->pixels);
+    ctxt->texture = NULL;
+    ctxt->renderer = NULL;
+    ctxt->window = NULL;
+    ctxt->pixels = NULL;
+    SDL_Quit();
+    free(ctxt);
+}
+
+/// If a key was pressed, returns its key code (non blocking call).
+/// List of key codes: https://wiki.libsdl.org/SDL_Keycode
+/// @return the key that was pressed or 0 if none was pressed.
+SDL_Keycode gfx_keypressed()
+{
+    SDL_Event event;
+    if (SDL_PollEvent(&event))
+    {
+        if (event.type == SDL_KEYDOWN)
+            return event.key.keysym.sym;
+    }
+    return 0;
+}
+
+/// Draw a full circle using Andres's discrete circle algorithm.
+/// @param ctxt Graphic context to clear.
+/// @param c_column X coordinate of the circle center.
+/// @param c_row Y coordinate of the circle center.
+/// @param r The radius of circle (in pixels).
+/// @param color Color to use.
+void draw_full_circle(struct gfx_context_t *ctxt, uint32_t c_column, uint32_t c_row, uint32_t r, uint32_t color)
+{
+    int32_t x = 0, y = r, d = r - 1;
+    while (y >= x)
+    {
+        gfx_putpixel(ctxt, c_column + x, c_row + y, color);
+        gfx_putpixel(ctxt, c_column + y, c_row + x, color);
+        gfx_putpixel(ctxt, c_column - x, c_row + y, color);
+        gfx_putpixel(ctxt, c_column - y, c_row + x, color);
+
+        gfx_putpixel(ctxt, c_column + x, c_row - y, color);
+        gfx_putpixel(ctxt, c_column + y, c_row - x, color);
+        gfx_putpixel(ctxt, c_column - x, c_row - y, color);
+        gfx_putpixel(ctxt, c_column - y, c_row - x, color);
+
+        if ((2 * x) <= d)
+        {
+            d -= 2 * x + 1;
+            x += 1;
+        }
+        else if (d < (2 * (((int32_t)r) - y)))
+        {
+            d += 2 * y - 1;
+            y -= 1;
+        }
+        else
+        {
+            d -= 2 * (x - y + 1);
+            y -= 1;
+            x += 1;
+        }
+    }
+    if (r > 0)
+        draw_full_circle(ctxt, c_column, c_row, r - 1, color);
+}
\ No newline at end of file
diff --git a/practical_work/planets/skeleton/gfx/gfx.h b/practical_work/planets/skeleton/gfx/gfx.h
new file mode 100644
index 0000000000000000000000000000000000000000..20b7815e4c5ef7a8daa871153c3f4affeeb448b6
--- /dev/null
+++ b/practical_work/planets/skeleton/gfx/gfx.h
@@ -0,0 +1,41 @@
+#ifndef _GFX_H_
+#define _GFX_H_
+
+#include <SDL2/SDL.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#define MAKE_COLOR(r, g, b) \
+    ((uint32_t)b | ((uint32_t)g << 8) | ((uint32_t)r << 16))
+
+#define COLOR_GET_B(color) (color & 0xff)
+#define COLOR_GET_G(color) ((color >> 8) & 0xff)
+#define COLOR_GET_R(color) ((color >> 16) & 0xff)
+
+#define COLOR_BLACK 0x00000000
+#define COLOR_RED 0x00FF0000
+#define COLOR_GREEN 0x0000FF00
+#define COLOR_BLUE 0x000000FF
+#define COLOR_WHITE 0x00FFFFFF
+#define COLOR_YELLOW 0x00FFFF00
+
+struct gfx_context_t
+{
+    SDL_Window *window;
+    SDL_Renderer *renderer;
+    SDL_Texture *texture;
+    uint32_t *pixels;
+    uint32_t width;
+    uint32_t height;
+};
+
+extern void gfx_putpixel(
+    struct gfx_context_t *ctxt, uint32_t column, uint32_t row, uint32_t color);
+extern void gfx_clear(struct gfx_context_t *ctxt, uint32_t color);
+extern struct gfx_context_t *gfx_create(char *text, uint32_t width, uint32_t height);
+extern void gfx_destroy(struct gfx_context_t *ctxt);
+extern void gfx_present(struct gfx_context_t *ctxt);
+extern SDL_Keycode gfx_keypressed();
+extern void draw_full_circle(struct gfx_context_t *ctxt, uint32_t c_column, uint32_t c_row, uint32_t r, uint32_t color);
+
+#endif
diff --git a/practical_work/planets/skeleton/main.c b/practical_work/planets/skeleton/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..5b38f570d80c598d1c52677e7d6a796a12591739
--- /dev/null
+++ b/practical_work/planets/skeleton/main.c
@@ -0,0 +1,39 @@
+#include "gfx/gfx.h"
+#include "vec2/vec2.h"
+#include "planet/planet.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#define SCREEN_WIDTH 1000
+#define SCREEN_HEIGHT 1000
+
+int main()
+{
+    srand(time(NULL));
+    struct gfx_context_t *ctxt =
+        gfx_create("Planetary system", SCREEN_WIDTH, SCREEN_HEIGHT);
+    if (!ctxt)
+    {
+        fprintf(stderr, "Graphics initialization failed!\n");
+        return EXIT_FAILURE;
+    }
+
+    // TODO : create your system
+
+    while (true)
+    {
+        gfx_present(ctxt);
+        // TODO : draw the current state of your system
+        // TODO : update your system
+        gfx_clear(ctxt, COLOR_BLACK);
+        if (gfx_keypressed() == SDLK_ESCAPE)
+        {
+            break;
+        }
+    }
+
+    // TODO : Free your system
+    gfx_destroy(ctxt);
+    return EXIT_SUCCESS;
+}
diff --git a/practical_work/planets/skeleton/planet/planet.c b/practical_work/planets/skeleton/planet/planet.c
new file mode 100644
index 0000000000000000000000000000000000000000..735290653cacaaf39ffdf054fd3d04efa6132b3c
--- /dev/null
+++ b/practical_work/planets/skeleton/planet/planet.c
@@ -0,0 +1,7 @@
+#include "planet.h"
+#include <stdlib.h>
+
+#define G 6.67e-11
+#define M_SOLEIL 1.989e30
+
+// TODO : magic
\ No newline at end of file
diff --git a/practical_work/planets/skeleton/planet/planet.h b/practical_work/planets/skeleton/planet/planet.h
new file mode 100644
index 0000000000000000000000000000000000000000..f21984e64616f0d91d3a502c8b6273f49556b172
--- /dev/null
+++ b/practical_work/planets/skeleton/planet/planet.h
@@ -0,0 +1,29 @@
+#ifndef _PLANET_H_
+#define _PLANET_H_
+
+#include "../vec2/vec2.h"
+#include "../gfx/gfx.h"
+
+typedef struct _planet
+{
+    double mass;
+    vec2 pos;      // x(t)
+    vec2 prec_pos; // x(t - dt)
+} planet_t;
+
+typedef struct _system
+{
+    planet_t star;       // ex. The sun
+    uint32_t nb_planets; // The number of orbiting planets
+    planet_t *planets;   // An array of orbiting planets
+} system_t;
+
+// Those function are not mandatory to implement,
+// it's rather a hint of what you should have.
+planet_t create_planet(double mass, vec2 pos);
+system_t create_system(double delta_t);
+void show_system(struct gfx_context_t *ctxt, system_t *system);
+void update_system(system_t *system, double delta_t);
+void free_system(system_t *system);
+
+#endif
\ No newline at end of file
diff --git a/practical_work/planets/skeleton/vec2/vec2.c b/practical_work/planets/skeleton/vec2/vec2.c
new file mode 100644
index 0000000000000000000000000000000000000000..4a58ad8dddd742783aab8d2df1ec2020494fc4e5
--- /dev/null
+++ b/practical_work/planets/skeleton/vec2/vec2.c
@@ -0,0 +1 @@
+// TODO : Replace this file by your vec2.c from last tp.
diff --git a/practical_work/planets/skeleton/vec2/vec2.h b/practical_work/planets/skeleton/vec2/vec2.h
new file mode 100644
index 0000000000000000000000000000000000000000..ed0403544e09df2d1a4af16e4f2a77f3d6b058de
--- /dev/null
+++ b/practical_work/planets/skeleton/vec2/vec2.h
@@ -0,0 +1,41 @@
+#ifndef _VEC2_H_
+#define _VEC2_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+
+typedef struct _vec2
+{
+    double x, y;
+} vec2;
+
+typedef struct _coordinates
+{
+    uint32_t row, column;
+} coordinates;
+
+vec2 vec2_create(double x_, double y_);
+
+vec2 vec2_create_zero();
+
+vec2 vec2_add(vec2 lhs, vec2 rhs);
+
+vec2 vec2_sub(vec2 lhs, vec2 rhs);
+
+vec2 vec2_mul(double scalar, vec2 rhs);
+
+double vec2_dot(vec2 lhs, vec2 rhs);
+
+double vec2_norm_sqr(vec2 v);
+
+double vec2_norm(vec2 v);
+
+vec2 vec2_normalize(vec2 v);
+
+bool vec2_is_approx_equal(vec2 lhs, vec2 rhs, double eps);
+
+coordinates vec2_to_coordinates(vec2 v, uint32_t width, uint32_t height);
+
+void vec2_print(vec2 v);
+
+#endif
diff --git a/practical_work/planets/skeleton/vec2/vec_tests.c b/practical_work/planets/skeleton/vec2/vec_tests.c
new file mode 100644
index 0000000000000000000000000000000000000000..119d02675d003348a25e7b4402665687012a6933
--- /dev/null
+++ b/practical_work/planets/skeleton/vec2/vec_tests.c
@@ -0,0 +1,309 @@
+#include "vec2.h"
+#include <stdio.h>
+#include <stdbool.h>
+#include <math.h>
+
+typedef struct _test_result
+{
+    bool passed;
+    const char *name;
+} test_result;
+
+typedef test_result (*unit_test_t)(void);
+
+void print_in_color(char *color, char *text)
+{
+    printf("\033%s", color);
+    printf("%s", text);
+    printf("\033[0m");
+}
+void print_in_red(char *text)
+{
+    print_in_color("[0;31m", text);
+}
+void print_in_green(char *text)
+{
+    print_in_color("[0;32m", text);
+}
+
+bool dbl_eq(double a, double b)
+{
+    return fabs(a - b) < 1e-6;
+}
+
+/*
+*
+* Write your tests here
+*
+*/
+/* TODO
+vec2 vec2_create(double x_, double y_); -- Ok
+vec2 vec2_create_zero(); -- Ok
+vec2 vec2_add(vec2 lhs, vec2 rhs); -- Ok
+vec2 vec2_sub(vec2 lhs, vec2 rhs); -- Ok
+vec2 vec2_mul(double scalar, vec2 lhs); -- Ok
+double vec2_dot(vec2 lhs, vec2 rhs); -- Ok
+double vec2_norm_sqr(vec2 v); -- Ok
+double vec2_norm(vec2 v); -- Ok
+vec2 vec2_normalize(vec2 v); -- Ok
+bool vec2_is_approx_equal(vec2 lhs, vec2 rhs, double eps);
+coordinates vec2_to_coordinates(vec2 v, uint32_t width, uint32_t height);
+*/
+const double u_x[] = {1.25, 3.53, 2.64, 8.8};
+const double u_y[] = {3.42, 7.22, 5.32, 2.44};
+const double v_x[] = {4.32, 6.21, 7.42, 9.32};
+const double v_y[] = {5.22, 3.56, 8.65, 6.44};
+const uint32_t nb_tests = sizeof(u_x) / sizeof(double);
+
+test_result t_vec2_create_0()
+{
+    bool passed = true;
+    for (uint32_t i = 0; i < nb_tests; i++)
+    {
+        vec2 v = vec2_create(u_x[i], u_y[i]);
+        if (u_x[i] != v.x || u_y[i] != v.y)
+        {
+            passed = false;
+            break;
+        }
+    }
+
+    return (test_result){.passed = passed,
+                         .name = "Test vec2_create 0"};
+}
+test_result t_vec2_create_zero_0()
+{
+    vec2 v = vec2_create_zero();
+
+    return (test_result){.passed = v.x == 0.0 && v.y == 0.0,
+                         .name = "Test vec2_create_zero 0"};
+}
+test_result t_vec2_add_0()
+{
+    double r_x[] = {5.57, 9.74, 10.06, 18.12};
+    double r_y[] = {8.64, 10.78, 13.97, 8.88};
+
+    bool passed = true;
+    for (uint32_t i = 0; i < nb_tests; i++)
+    {
+        vec2 u = vec2_create(u_x[i], u_y[i]);
+        vec2 v = vec2_create(v_x[i], v_y[i]);
+        vec2 r = vec2_add(u, v);
+        if (!(dbl_eq(r.x, r_x[i]) && dbl_eq(r.y, r_y[i])))
+        {
+            passed = false;
+            break;
+        }
+    }
+
+    return (test_result){.passed = passed,
+                         .name = "Test vec2_add 0"};
+}
+test_result t_vec2_sub_0()
+{
+    double r_x[] = {-3.07, -2.68, -4.78, -0.52};
+    double r_y[] = {-1.80, 3.66, -3.33, -4.00};
+
+    bool passed = true;
+    for (uint32_t i = 0; i < nb_tests; i++)
+    {
+        vec2 u = vec2_create(u_x[i], u_y[i]);
+        vec2 v = vec2_create(v_x[i], v_y[i]);
+        vec2 r = vec2_sub(u, v);
+        if (!(dbl_eq(r.x, r_x[i]) && dbl_eq(r.y, r_y[i])))
+        {
+            passed = false;
+            break;
+        }
+    }
+
+    return (test_result){.passed = passed,
+                         .name = "Test vec2_sub 0"};
+}
+test_result t_vec2_mul_0()
+{
+    double r_x[] = {5.40, 21.9213, 19.5888, 82.016};
+    double r_y[] = {14.7744, 44.8362, 39.4744, 22.740800};
+
+    bool passed = true;
+    for (uint32_t i = 0; i < nb_tests; i++)
+    {
+        double alpha = v_x[i];
+        vec2 u = vec2_create(u_x[i], u_y[i]);
+        vec2 r = vec2_mul(alpha, u);
+        if (!(dbl_eq(r.x, r_x[i]) && dbl_eq(r.y, r_y[i])))
+        {
+            passed = false;
+            break;
+        }
+    }
+
+    return (test_result){.passed = passed,
+                         .name = "Test vec2_mul 0"};
+}
+test_result t_vec2_dot_0()
+{
+    double r[] = {23.2524, 47.6245, 65.6068, 97.7296};
+
+    bool passed = true;
+    for (uint32_t i = 0; i < nb_tests; i++)
+    {
+        vec2 u = vec2_create(u_x[i], u_y[i]);
+        vec2 v = vec2_create(v_x[i], v_y[i]);
+        double res = vec2_dot(u, v);
+        if (!dbl_eq(res, r[i]))
+        {
+            passed = false;
+            break;
+        }
+    }
+
+    return (test_result){.passed = passed,
+                         .name = "Test vec2_dot 0"};
+}
+test_result t_vec2_norm_sqr_0()
+{
+    double r[] = {13.2589, 64.5893, 35.272, 83.3936};
+
+    bool passed = true;
+    for (uint32_t i = 0; i < nb_tests; i++)
+    {
+        vec2 u = vec2_create(u_x[i], u_y[i]);
+        double res = vec2_norm_sqr(u);
+        if (!dbl_eq(res, r[i]))
+        {
+            passed = false;
+            break;
+        }
+    }
+
+    return (test_result){.passed = passed,
+                         .name = "Test vec2_norm_sqr 0"};
+}
+test_result t_vec2_norm_0()
+{
+    double r[] = {3.641277, 8.036747, 5.939023, 9.132010};
+
+    bool passed = true;
+    for (uint32_t i = 0; i < nb_tests; i++)
+    {
+        vec2 u = vec2_create(u_x[i], u_y[i]);
+        double res = vec2_norm(u);
+        if (!dbl_eq(res, r[i]))
+        {
+            passed = false;
+            break;
+        }
+    }
+
+    return (test_result){.passed = passed,
+                         .name = "Test vec2_norm 0"};
+}
+test_result t_vec2_normalize_0()
+{
+    double r_x[] = {0.343286, 0.439232, 0.444518, 0.963643};
+    double r_y[] = {0.939231, 0.898373, 0.895770, 0.267192};
+
+    bool passed = true;
+    for (uint32_t i = 0; i < nb_tests; i++)
+    {
+        vec2 u = vec2_create(u_x[i], u_y[i]);
+        vec2 r = vec2_normalize(u);
+        if (!(dbl_eq(r.x, r_x[i]) && dbl_eq(r.y, r_y[i])))
+        {
+            passed = false;
+            break;
+        }
+    }
+
+    return (test_result){.passed = passed,
+                         .name = "Test vec2_normalize 0"};
+}
+test_result t_vec2_is_approx_equal_0()
+{
+    bool r[] = {true, true, false, false};
+
+    double t_x[] = {u_x[0], u_x[1] + 1e-4, u_x[2] + 15.0, u_x[3] + 1e-2};
+    double t_y[] = {u_y[0], u_y[1] - 1e-4, u_y[2] + 15.0, u_y[3] + 1e-2};
+
+    bool passed = true;
+    for (uint32_t i = 0; i < nb_tests; i++)
+    {
+        vec2 u = vec2_create(u_x[i], u_y[i]);
+        vec2 t = vec2_create(t_x[i], t_y[i]);
+        if (vec2_is_approx_equal(u, t, 1e-3) != r[i])
+        {
+            passed = false;
+            break;
+        }
+    }
+
+    return (test_result){.passed = passed,
+                         .name = "Test vec2_is_approx_equal 0"};
+}
+test_result t_vec2_to_coordinates_0()
+{
+    uint32_t height = 300;
+    uint32_t width = 100;
+    double t_x[] = {0.25, 0.5, 0.75, 1};
+    double t_y[] = {0, 1.0 / 3.0, 2.0 / 3.0, 1};
+    uint32_t r_col[] = {62, 74, 87, 99};
+    uint32_t r_row[] = {150, 199, 249, 299};
+
+    bool passed = true;
+    for (uint32_t i = 0; i < nb_tests; i++)
+    {
+        vec2 t = vec2_create(t_x[i], t_y[i]);
+        coordinates r = vec2_to_coordinates(t, width, height);
+        if (r.row != r_row[i] || r.column != r_col[i])
+        {
+            passed = false;
+            break;
+        }
+    }
+
+    return (test_result){.passed = passed,
+                         .name = "Test vec2_to_coordinates 0"};
+}
+//Add or remove your test function name here
+const unit_test_t tests[] = {
+    t_vec2_create_0,
+    t_vec2_create_zero_0,
+    t_vec2_add_0,
+    t_vec2_sub_0,
+    t_vec2_mul_0,
+    t_vec2_dot_0,
+    t_vec2_norm_sqr_0,
+    t_vec2_norm_0,
+    t_vec2_normalize_0,
+    t_vec2_is_approx_equal_0,
+    t_vec2_to_coordinates_0};
+
+int main()
+{
+    uint32_t nb_tests = sizeof(tests) / sizeof(unit_test_t);
+    char message[256];
+    bool all_passed = true;
+
+    for (uint32_t i = 0; i < nb_tests; i++)
+    {
+        printf("Running test n°%d: ...\n", i);
+        test_result r = tests[i]();
+        if (r.passed)
+        {
+            sprintf(message, "\t- %s : OK", r.name);
+            print_in_green(message);
+        }
+        else
+        {
+            all_passed = false;
+            sprintf(message, "\t- %s : FAILED", r.name);
+            print_in_red(message);
+        }
+        printf("\n");
+    }
+    if (all_passed)
+        print_in_green("\nTests suite result : OK\n");
+    else
+        print_in_red("\nTests suite result : FAILED\n");
+}
\ No newline at end of file