forked from root/public
Compare commits
1171 Commits
1258-canyo
...
master
Author | SHA1 | Date |
---|---|---|
Michele Sessa | 1bc3b5d6dd | 1 year ago |
davhojt | 5832f09413 | 1 year ago |
davhojt | dbaa66fe41 | 1 year ago |
davhojt | 45918794ea | 1 year ago |
lee | 629c2369ea | 1 year ago |
lee | 97d7414484 | 1 year ago |
eslopfer | b75b93b83d | 1 year ago |
eslopfer | 9b7c1f3e2b | 1 year ago |
eslopfer | cb024df579 | 1 year ago |
eslopfer | 23beb48880 | 1 year ago |
eslopfer | f7491d2e00 | 1 year ago |
Harry Vasanth | 5a98fe519e | 1 year ago |
Zouhair AMAZZAL | a8e4b56e84 | 1 year ago |
eslopfer | a2572a5d27 | 1 year ago |
eslopfer | 4608e50e83 | 1 year ago |
eslopfer | 8f7ba8f6cd | 1 year ago |
eslopfer | 36234cdbbe | 1 year ago |
nprimo | 06dc3ff388 | 1 year ago |
eslopfer | 27b4d9995e | 1 year ago |
Michele Sessa | 7de1b3a977 | 1 year ago |
Michele Sessa | 21553c4a25 | 1 year ago |
Michele Sessa | 66c7258e6b | 1 year ago |
nprimo | c92b34b7e9 | 1 year ago |
miguel | 36f079db98 | 1 year ago |
miguel | 1f9b277887 | 1 year ago |
miguel | 8182d373d2 | 1 year ago |
miguel | bc64c2cf03 | 1 year ago |
miguel | a1b76b0f0b | 1 year ago |
Whovillage | 89305e4358 | 1 year ago |
eslopfer | b3beafe586 | 1 year ago |
eslopfer | 61901120ad | 1 year ago |
eslopfer | 675b689c38 | 1 year ago |
eslopfer | 8f93971d9b | 1 year ago |
eslopfer | 3eeb99dc38 | 1 year ago |
nprimo | 3152d76b75 | 1 year ago |
nprimo | 13cd960199 | 1 year ago |
nprimo | 75ace2da2f | 1 year ago |
nprimo | 338ad35a46 | 1 year ago |
eslopfer | 9c82f65d21 | 1 year ago |
miguel | 212c7a749f | 1 year ago |
miguel | 1dbc49abbb | 1 year ago |
miguel | 9c0f53dbeb | 1 year ago |
miguel | f9f8f1810b | 1 year ago |
miguel | 07e3a84b7c | 1 year ago |
miguel | 76b3de083d | 1 year ago |
eslopfer | 314138a026 | 1 year ago |
eslopfer | 8e6cb6a558 | 1 year ago |
eslopfer | c6e6d78b66 | 1 year ago |
eslopfer | dad3fd234a | 1 year ago |
eslopfer | 3e7cd64c92 | 1 year ago |
eslopfer | 78f854bc92 | 1 year ago |
eslopfer | b1973d138e | 1 year ago |
eslopfer | b5266d8c8c | 1 year ago |
eslopfer | 0809920ba6 | 1 year ago |
eslopfer | f845339383 | 1 year ago |
eslopfer | 12f7343ad8 | 1 year ago |
eslopfer | 97b32f5721 | 1 year ago |
eslopfer | 4f3ea55b33 | 1 year ago |
eslopfer | 21003c08d9 | 1 year ago |
eslopfer | 8d3597565b | 1 year ago |
eslopfer | b338d80e6f | 1 year ago |
eslopfer | e5fba187a8 | 1 year ago |
eslopfer | f3ed3aa389 | 1 year ago |
eslopfer | 7e21117858 | 1 year ago |
eslopfer | a7487162b8 | 1 year ago |
eslopfer | da556a6082 | 1 year ago |
eslopfer | 59941b69bb | 1 year ago |
eslopfer | da345c7f5a | 1 year ago |
eslopfer | ed8474e3cc | 1 year ago |
eslopfer | 349398405a | 1 year ago |
eslopfer | d8e84c349e | 1 year ago |
eslopfer | e083c4db52 | 1 year ago |
eslopfer | b0e3471c2f | 1 year ago |
eslopfer | 2459ecb941 | 1 year ago |
eslopfer | 47b1f92881 | 1 year ago |
eslopfer | 21f63d3e4d | 1 year ago |
eslopfer | 818bb420c2 | 1 year ago |
eslopfer | 1e0f29a661 | 1 year ago |
eslopfer | dd81c5c8a6 | 1 year ago |
eslopfer | 165515d247 | 1 year ago |
eslopfer | 8460a1140c | 1 year ago |
eslopfer | 6f6e70ccb2 | 1 year ago |
Remington Smith | d88afa7ddc | 1 year ago |
Michele Sessa | 937c38f0bd | 1 year ago |
Michele Sessa | 7e5a55eb5e | 1 year ago |
Michele Sessa | ada74ada7b | 1 year ago |
Michele Sessa | 891d18251f | 1 year ago |
Michele Sessa | cdcac95cc6 | 1 year ago |
Michele Sessa | 0deb60289f | 1 year ago |
miguel | 663fea6e38 | 1 year ago |
miguel | d8e0daac01 | 1 year ago |
miguel | 75e0a216a6 | 1 year ago |
eslopfer | 91a37b1a2d | 1 year ago |
eslopfer | 27cb454673 | 1 year ago |
eslopfer | 571173983c | 1 year ago |
eslopfer | 119f624f44 | 1 year ago |
eslopfer | af780cabea | 1 year ago |
davhojt | 41fc91e649 | 1 year ago |
davhojt | d441a78d1a | 1 year ago |
xalava | a4c3f8db8a | 1 year ago |
nprimo | 2a9823cfee | 1 year ago |
nprimo | 32660b2aa0 | 1 year ago |
miguel | 07b35e898d | 1 year ago |
miguel | 4c09ccd4b7 | 1 year ago |
davhojt | a08e196886 | 1 year ago |
Michele Sessa | 84c56a4741 | 1 year ago |
Michele Sessa | f8201da931 | 1 year ago |
Michele Sessa | 0ff5b55ec5 | 1 year ago |
Michele Sessa | c4ea506acf | 1 year ago |
miguel | 169a5dfb35 | 1 year ago |
Michele Sessa | a720947c82 | 1 year ago |
Michele Sessa | 77a5a1821e | 1 year ago |
Michele Sessa | 4c05e7d7fb | 1 year ago |
Michele Sessa | 41dccb6469 | 1 year ago |
Michele Sessa | d0f04efdaf | 1 year ago |
Michele Sessa | 1984891870 | 1 year ago |
Michele Sessa | 01eaea466d | 1 year ago |
eslopfer | 38f9bcb87f | 1 year ago |
Zouhair AMAZZAL | b49b41fc18 | 1 year ago |
Zouhair AMAZZAL | 0e1ce974df | 1 year ago |
Zouhair AMAZZAL | c4a415e456 | 1 year ago |
miguel | 35aa7fea5e | 1 year ago |
miguel | ac848c2249 | 1 year ago |
davhojt | 149278fa1d | 1 year ago |
Zouhair AMAZZAL | 83d72ea9e8 | 1 year ago |
Zouhair AMAZZAL | 5557be9f3d | 1 year ago |
Zouhair AMAZZAL | 8f261d03fd | 1 year ago |
Zouhair AMAZZAL | 4df23a5b8d | 1 year ago |
Zouhair AMAZZAL | 1225dc0d6a | 1 year ago |
Zouhair AMAZZAL | 875f2aa59e | 1 year ago |
miguel | 2235a8b1d0 | 1 year ago |
miguel | 8ce0dfcac1 | 1 year ago |
eslopfer | b1db3597f9 | 1 year ago |
miguel | 7db7b01db8 | 1 year ago |
miguel | de6caf07f3 | 1 year ago |
miguel | 748344f23d | 1 year ago |
miguel | 0456bc5b5d | 1 year ago |
miguel | 992e531434 | 1 year ago |
miguel | e298d48ed9 | 1 year ago |
Toussaint Louis | a997271b03 | 1 year ago |
eslopfer | a1a27fe0f5 | 1 year ago |
eslopfer | 22068682cb | 1 year ago |
eslopfer | 35cbdf6c85 | 1 year ago |
eslopfer | ef79658c09 | 1 year ago |
eslopfer | 43d7bb21a9 | 1 year ago |
eslopfer | 666cc027fc | 1 year ago |
eslopfer | a2e42772e5 | 1 year ago |
eslopfer | 168fa94c2b | 1 year ago |
eslopfer | 8904b74cd3 | 1 year ago |
eslopfer | c63702c971 | 1 year ago |
eslopfer | 0af1b9f161 | 1 year ago |
eslopfer | ed41ff6929 | 1 year ago |
eslopfer | 8ec5b5023c | 1 year ago |
eslopfer | 1fe8893aaf | 1 year ago |
eslopfer | 5558a83c62 | 1 year ago |
eslopfer | c8511651ff | 1 year ago |
miguel | a72333ab76 | 1 year ago |
Michele | dc8002d92e | 1 year ago |
miguel | 01857cd9cc | 1 year ago |
sagarishere | b7ad774a68 | 1 year ago |
eslopfer | f88cee4371 | 1 year ago |
Michele Sessa | 1d5db2e77c | 1 year ago |
Michele Sessa | d657d1461a | 1 year ago |
Michele Sessa | d39254e5d4 | 1 year ago |
Michele Sessa | 3f21c5d32e | 1 year ago |
eslopfer | 9025836ce8 | 1 year ago |
eslopfer | b6e041ea3f | 1 year ago |
eslopfer | 1cdf6cb27c | 1 year ago |
eslopfer | ed02670e16 | 1 year ago |
Falusvampen | 87abec3e1d | 1 year ago |
Falusvampen | 01297625c4 | 1 year ago |
Toussaint Louis | 4cd69e4cb9 | 1 year ago |
miguel | 107d7ac4ad | 1 year ago |
miguel | 9d0f9d4506 | 1 year ago |
miguel | da685d8b85 | 1 year ago |
miguel | a97ca4ed40 | 1 year ago |
miguel | ab2fea635f | 1 year ago |
miguel | f66634c212 | 1 year ago |
nprimo | 9bdb8f1217 | 1 year ago |
nprimo | 48993bb471 | 1 year ago |
nprimo | f1a7dd0d2b | 1 year ago |
miguel | 6536303937 | 1 year ago |
miguel | 5f517ea08f | 1 year ago |
miguel | 8995643d53 | 1 year ago |
miguel | 594a8329d6 | 1 year ago |
miguel | 6ce50f2bde | 1 year ago |
miguel | 74c7460405 | 1 year ago |
miguel | 9eb5d849d5 | 1 year ago |
miguel | 737ec808b1 | 1 year ago |
Michele Sessa | ed054578b9 | 1 year ago |
Michele Sessa | f3739b2357 | 1 year ago |
Michele Sessa | 0549bcf421 | 1 year ago |
miguel | 5ffb2348f5 | 1 year ago |
miguel | 21a6aace01 | 1 year ago |
miguel | 5245101b91 | 1 year ago |
miguel | 15a88f5137 | 1 year ago |
miguel | 5f8365c19c | 1 year ago |
miguel | 9becc5396a | 1 year ago |
nprimo | 001dc38237 | 1 year ago |
nprimo | ac9cf757a1 | 1 year ago |
Zouhair AMAZZAL | 2b77c87031 | 1 year ago |
nprimo | ce6ef6d186 | 1 year ago |
nprimo | c231898bca | 1 year ago |
nprimo | c9f0245673 | 1 year ago |
nprimo | 3d6b963da9 | 1 year ago |
nprimo | 7e4375aa1e | 1 year ago |
nprimo | 595c044136 | 1 year ago |
nprimo | 9038c5b3dd | 1 year ago |
miguel | 04e90aa8be | 1 year ago |
miguel | fb239fd7d2 | 1 year ago |
miguel | d07a43ebe8 | 1 year ago |
miguel | eb6e281da0 | 1 year ago |
nprimo | ad0ea7ea91 | 1 year ago |
Zouhair AMAZZAL | 60deacdbb2 | 1 year ago |
Zouhair AMAZZAL | d1295b02a8 | 1 year ago |
Michele Sessa | 3d0e7cb960 | 1 year ago |
Zouhair AMAZZAL | f6f7831722 | 1 year ago |
Zouhair AMAZZAL | 95509fae9a | 1 year ago |
miguel | ab5b82d1bd | 1 year ago |
miguel | 447de57f08 | 1 year ago |
miguel | 962b6217b4 | 1 year ago |
Harry | f3538e2633 | 1 year ago |
Michele Sessa | 5a2cd55a02 | 1 year ago |
Michele Sessa | ebc79e5a13 | 1 year ago |
Michele Sessa | fd80d337d2 | 1 year ago |
Michele Sessa | b7197ba49c | 1 year ago |
davhojt | c1c5edba98 | 1 year ago |
davhojt | d3f8c485a1 | 1 year ago |
eslopfer | 8bf61c6a45 | 1 year ago |
eslopfer | 596e6bc683 | 1 year ago |
eslopfer | 82751669c2 | 1 year ago |
eslopfer | cf304b85d4 | 1 year ago |
eslopfer | 08c8ce153b | 1 year ago |
eslopfer | 981ebfd3d4 | 1 year ago |
eslopfer | 97a9250dd5 | 1 year ago |
eslopfer | 46ab89401a | 1 year ago |
eslopfer | 820ae81915 | 1 year ago |
eslopfer | 238aee7edc | 1 year ago |
eslopfer | d50afde56a | 1 year ago |
eslopfer | 4575754057 | 1 year ago |
eslopfer | 52e77c4e57 | 1 year ago |
eslopfer | 1d93072feb | 1 year ago |
davhojt | 2d57018134 | 1 year ago |
Harry | af8a7c5bc5 | 2 years ago |
Harry | a1fed73e76 | 2 years ago |
Harry | 91fb38d886 | 2 years ago |
Harry | d41fea9c13 | 2 years ago |
Harry | cc94a1807a | 2 years ago |
Harry | 9af7ad3e5a | 2 years ago |
Harry | 75ce933bb7 | 2 years ago |
Harry | de7bd6fef3 | 2 years ago |
eslopfer | 19abec613b | 2 years ago |
eslopfer | 37a411afa9 | 2 years ago |
eslopfer | b236264e84 | 2 years ago |
eslopfer | 4ba8a4bb8a | 2 years ago |
eslopfer | b0168a28a7 | 2 years ago |
eslopfer | f848501332 | 2 years ago |
eslopfer | 28572ca566 | 2 years ago |
eslopfer | 18b2cfabf6 | 2 years ago |
eslopfer | 285680e9a7 | 2 years ago |
eslopfer | 8316ebd171 | 2 years ago |
eslopfer | cf4815901f | 2 years ago |
eslopfer | 7b771e1742 | 2 years ago |
eslopfer | 02755bed78 | 2 years ago |
eslopfer | 00129a7a3c | 2 years ago |
eslopfer | 5660faa45f | 2 years ago |
eslopfer | f85c056f72 | 2 years ago |
eslopfer | ccd46489a6 | 2 years ago |
eslopfer | eb20cf5956 | 2 years ago |
eslopfer | 52bc2d7040 | 2 years ago |
eslopfer | 46067ab226 | 2 years ago |
eslopfer | f74f6fbe3b | 2 years ago |
eslopfer | a6183a6820 | 2 years ago |
eslopfer | c46a20e583 | 2 years ago |
nprimo | 21ff0467e4 | 2 years ago |
nprimo | 8d76f63f5c | 2 years ago |
nprimo | 7e594e9177 | 2 years ago |
davhojt | 4328e8f3dc | 2 years ago |
davhojt | 88283b4c47 | 2 years ago |
davhojt | 9f8e0a66dc | 2 years ago |
davhojt | b672ee8715 | 2 years ago |
davhojt | 1a3f95ea2b | 2 years ago |
Zouhair AMAZZAL | 5c1077c6ce | 2 years ago |
Zouhair AMAZZAL | 75d318f5d9 | 2 years ago |
Zouhair AMAZZAL | 944e43772c | 2 years ago |
eslopfer | 2cc7a8a432 | 2 years ago |
eslopfer | 73af4b4d43 | 2 years ago |
eslopfer | f8fae31cf0 | 2 years ago |
eslopfer | d06c09c080 | 2 years ago |
eslopfer | 47baef625c | 2 years ago |
eslopfer | af6a512da9 | 2 years ago |
eslopfer | 6469482d44 | 2 years ago |
eslopfer | 1574f97c6b | 2 years ago |
eslopfer | e530bcf634 | 2 years ago |
eslopfer | 2d937d14cb | 2 years ago |
eslopfer | 4aaa6ccedb | 2 years ago |
eslopfer | c4b718443d | 2 years ago |
eslopfer | a301f988dd | 2 years ago |
eslopfer | 25707e9e94 | 2 years ago |
eslopfer | 40c8c11ed4 | 2 years ago |
eslopfer | 820e926b2c | 2 years ago |
eslopfer | bfd02c9484 | 2 years ago |
eslopfer | 6e6b8bba86 | 2 years ago |
eslopfer | d5359345f3 | 2 years ago |
eslopfer | dcca22eeaa | 2 years ago |
eslopfer | 92307d767c | 2 years ago |
eslopfer | 421baa3c50 | 2 years ago |
eslopfer | d20690dc51 | 2 years ago |
eslopfer | 628ceb1f20 | 2 years ago |
eslopfer | 8fb6444113 | 2 years ago |
eslopfer | 14a685edec | 2 years ago |
eslopfer | bc3d8db02e | 2 years ago |
eslopfer | cefa4d59f2 | 2 years ago |
eslopfer | c8c3eb5a76 | 2 years ago |
eslopfer | 204db46fdf | 2 years ago |
eslopfer | 4faa4927bf | 2 years ago |
davhojt | 48293448a3 | 2 years ago |
davhojt | 6737972d63 | 2 years ago |
davhojt | 10e8cea472 | 2 years ago |
davhojt | 1c1ff5e557 | 2 years ago |
davhojt | b59a56713e | 2 years ago |
davhojt | 5fe9a8b0ce | 2 years ago |
davhojt | dc51eadafa | 2 years ago |
davhojt | 991c7b41b8 | 2 years ago |
davhojt | 90309db9be | 2 years ago |
davhojt | abc4d7fcf8 | 2 years ago |
davhojt | d068c9a012 | 2 years ago |
miguel | df1b00c454 | 2 years ago |
miguel | bbee4a7248 | 2 years ago |
miguel | 0c7c439360 | 2 years ago |
miguel | 88eee63db2 | 2 years ago |
miguel | 526f60501c | 2 years ago |
miguel | 1d78af2f7a | 2 years ago |
miguel | 9b975fdf0f | 2 years ago |
miguel | 8166812c3c | 2 years ago |
miguel | 9a75202406 | 2 years ago |
miguel | 497b331f9d | 2 years ago |
miguel | 13435eb8f1 | 2 years ago |
miguel | b2c81baa39 | 2 years ago |
jrosendo | 7d092df38d | 2 years ago |
Michele Sessa | cc657aa7c3 | 2 years ago |
Michele Sessa | 8259ea702e | 2 years ago |
Michele Sessa | 077f7c4c9b | 2 years ago |
Michele Sessa | 4654dc12cd | 2 years ago |
Michele Sessa | c5a8038e32 | 2 years ago |
Michele Sessa | b8a5834205 | 2 years ago |
Michele Sessa | 7d5f51e374 | 2 years ago |
Michele Sessa | e0dbd353a3 | 2 years ago |
Michele Sessa | cd2cd98f84 | 2 years ago |
Michele Sessa | 0f1f13149b | 2 years ago |
nprimo | b7b8e4795d | 2 years ago |
nprimo | a1843c47f7 | 2 years ago |
nprimo | 09a07b5ea4 | 2 years ago |
nprimo | d6c0b8e3ec | 2 years ago |
nprimo | d382111703 | 2 years ago |
nprimo | c522b283b2 | 2 years ago |
nprimo | de978aee29 | 2 years ago |
nprimo | e6742b2897 | 2 years ago |
nprimo | 6366d196c5 | 2 years ago |
nprimo | e9853b2346 | 2 years ago |
nprimo | 44e4ff870c | 2 years ago |
nprimo | 97512f9066 | 2 years ago |
nprimo | 2f9154f891 | 2 years ago |
nprimo | 51e06fa543 | 2 years ago |
nprimo | d8371b697c | 2 years ago |
nprimo | 65a0a88171 | 2 years ago |
nprimo | 8585bc2a71 | 2 years ago |
nprimo | f20ce6c407 | 2 years ago |
nprimo | 4a42d8f1db | 2 years ago |
nprimo | 829ec0e43f | 2 years ago |
nprimo | 7520b25427 | 2 years ago |
Tiago Collot | ecc6bf9943 | 2 years ago |
estlop | a96274cdab | 2 years ago |
estlop | 8dc30ed978 | 2 years ago |
estlop | 360304de01 | 2 years ago |
estlop | 067acad4bb | 2 years ago |
davhojt | 12aa1223ad | 2 years ago |
nprimo | cd332eec28 | 2 years ago |
nprimo | 69ac2320d6 | 2 years ago |
nprimo | fa4628109a | 2 years ago |
nprimo | ecf94f76ed | 2 years ago |
nprimo | 814f380aff | 2 years ago |
nprimo | b92f3a36eb | 2 years ago |
nprimo | f9c6335c75 | 2 years ago |
nprimo | b32ef63889 | 2 years ago |
nprimo | b13336b953 | 2 years ago |
nprimo | aa5c04cc0f | 2 years ago |
nprimo | a35bf4f4f7 | 2 years ago |
nprimo | 0dae786e3a | 2 years ago |
Roberto Catini | b85a77b28d | 2 years ago |
nprimo | 70ee6a2109 | 2 years ago |
nprimo | b7a11a3fe4 | 2 years ago |
davhojt | 966796fcae | 2 years ago |
xalava | d043ac37a8 | 2 years ago |
eslopfer | 90a0e60450 | 2 years ago |
miguel | 93288bcdfd | 2 years ago |
nprimo | fc2d986a5d | 2 years ago |
Michele Sessa | c53584ed35 | 2 years ago |
miguel | 2e6747da72 | 2 years ago |
miguel | 53aa0b3f92 | 2 years ago |
miguel | fc197de5fd | 2 years ago |
miguel | 3112b89373 | 2 years ago |
miguel | 1fcd020884 | 2 years ago |
miguel | 9dbebae756 | 2 years ago |
miguel | fe31b9677d | 2 years ago |
miguel | 22355f3441 | 2 years ago |
miguel | 3d7497b538 | 2 years ago |
miguel | 7849dc44fb | 2 years ago |
miguel | 18a21bfe6d | 2 years ago |
miguel | 3049697bf4 | 2 years ago |
miguel | 232bbf2b5c | 2 years ago |
miguel | fcf7432c49 | 2 years ago |
miguel | ae0847fbcd | 2 years ago |
miguel | d8e7a606f0 | 2 years ago |
miguel | 2ee882e8a2 | 2 years ago |
miguel | daafc5d465 | 2 years ago |
miguel | cc2dd1c36e | 2 years ago |
miguel | e3d8cd9516 | 2 years ago |
miguel | 8230ba16ee | 2 years ago |
miguel | 3410c9ee5a | 2 years ago |
miguel | e06b028697 | 2 years ago |
Zouhair AMAZZAL | 23d56da262 | 2 years ago |
Zouhair AMAZZAL | 6cf269c441 | 2 years ago |
Christopher Fremond | fc263a8d09 | 2 years ago |
Michele Sessa | 82d6ce3933 | 2 years ago |
Michele Sessa | 504350a830 | 2 years ago |
jrosendo | ceee355156 | 2 years ago |
miguel | 4da285b07f | 2 years ago |
miguel | 4b02c825b7 | 2 years ago |
miguel | 5d6875d0a8 | 2 years ago |
jrosendo | 73fda016e5 | 2 years ago |
jrosendo | 53af9f2ecb | 2 years ago |
jrosendo | 7a960f7d00 | 2 years ago |
jrosendo | 52b4b5545b | 2 years ago |
Chris | dff9dd77ad | 2 years ago |
Chris | 02f28b9695 | 2 years ago |
Chris | 9731c7c0ca | 2 years ago |
Michele Sessa | 96817e90fa | 2 years ago |
Michele Sessa | 6d2677e0f0 | 2 years ago |
Michele Sessa | e1fab8e3ea | 2 years ago |
Michele Sessa | e2a8dc2bbd | 2 years ago |
Michele Sessa | 52c167a390 | 2 years ago |
Michele Sessa | e3e7058507 | 2 years ago |
Michele Sessa | 73d7b44898 | 2 years ago |
Michele Sessa | 9a2a1b7e9d | 2 years ago |
Zouhair AMAZZAL | 266d7dd0ee | 2 years ago |
Zouhair AMAZZAL | 80706806e6 | 2 years ago |
Zouhair AMAZZAL | a60c16dcaf | 2 years ago |
Zouhair AMAZZAL | abc65b2eb2 | 2 years ago |
Zouhair AMAZZAL | b864a26525 | 2 years ago |
Zouhair AMAZZAL | 692e383ff0 | 2 years ago |
Zouhair AMAZZAL | e2e32458af | 2 years ago |
Zouhair AMAZZAL | cabe2e248f | 2 years ago |
Zouhair AMAZZAL | 6b9d5c478b | 2 years ago |
Zouhair AMAZZAL | 0f7814fc4a | 2 years ago |
Zouhair AMAZZAL | 0dea7a8945 | 2 years ago |
Zouhair AMAZZAL | 3531d1b12f | 2 years ago |
Zouhair AMAZZAL | d0e9b91f73 | 2 years ago |
Zouhair AMAZZAL | c2e80f1033 | 2 years ago |
Zouhair AMAZZAL | b1762c3aac | 2 years ago |
Zouhair AMAZZAL | 51c804a135 | 2 years ago |
Zouhair AMAZZAL | 0e0f86dfed | 2 years ago |
Zouhair AMAZZAL | 6467fd10fa | 2 years ago |
Zouhair AMAZZAL | 47aa2ae008 | 2 years ago |
Zouhair AMAZZAL | abf236eac3 | 2 years ago |
Zouhair AMAZZAL | 75dc52bec5 | 2 years ago |
Zouhair AMAZZAL | cbdc5c4a6f | 2 years ago |
Zouhair AMAZZAL | 40395c5dac | 2 years ago |
Zouhair AMAZZAL | 6712ad9dea | 2 years ago |
Zouhair AMAZZAL | ebde98d95d | 2 years ago |
Zouhair AMAZZAL | 1f284b5c43 | 2 years ago |
nprimo | 7f769ef487 | 2 years ago |
nprimo | 722edd9e69 | 2 years ago |
jrosendo | 0cb639701a | 2 years ago |
jrosendo | 6802353d6e | 2 years ago |
jotapero | 3e36a8e0e8 | 2 years ago |
jotapero | 60f5e0bfd4 | 2 years ago |
hamza | a4c46c3378 | 2 years ago |
jrosendo | 2bd32ad039 | 2 years ago |
jotapero | e7d839f162 | 2 years ago |
hamza | 73ea4f4110 | 2 years ago |
jrosendo | 099e1d68ae | 2 years ago |
jrosendo | 29209baacc | 2 years ago |
Roberto Catini | 2cc1009564 | 2 years ago |
jrosendo | 9bbefc7f89 | 2 years ago |
jrosendo | 3a08d55a2f | 2 years ago |
jrosendo | b499b84ce3 | 2 years ago |
jrosendo | 2f46d7e8c6 | 2 years ago |
nprimo | f659ea6d86 | 2 years ago |
nprimo | d58f8e8e38 | 2 years ago |
jotapero | 189ad964c3 | 2 years ago |
jrosendo | b1960dc26b | 2 years ago |
hamza | 36ffad787d | 2 years ago |
hamza | 9c280eaff1 | 2 years ago |
jrosendo | 816f05e228 | 2 years ago |
jrosendo | d72e8f3c1f | 2 years ago |
jrosendo | 5abc1e59a8 | 2 years ago |
jotapero | 256b470992 | 2 years ago |
jotapero | 7942764119 | 2 years ago |
jrosendo | 76155b8086 | 2 years ago |
jrosendo | 2e886a02cd | 2 years ago |
jotapero | 44e4eb1dfe | 2 years ago |
hamza | 27302761e8 | 2 years ago |
jrosendo | 4dd8e9ccca | 2 years ago |
jrosendo | a28ac1ea50 | 2 years ago |
jotapero | 0fe2165844 | 2 years ago |
hamza | 85bec091bb | 2 years ago |
nprimo | de95b3b572 | 2 years ago |
nprimo | ab38fc622a | 2 years ago |
nprimo | d3fa6a5355 | 2 years ago |
nprimo | 446924e348 | 2 years ago |
nprimo | d189e1deea | 2 years ago |
nprimo | e2ece47510 | 2 years ago |
nprimo | 380ad0dc3e | 2 years ago |
nprimo | 50c73c0af3 | 2 years ago |
nprimo | f179d6e09f | 2 years ago |
nprimo | 3f07f9dc5f | 2 years ago |
jrosendo | be637efb0d | 2 years ago |
jrosendo | 740da8eef8 | 2 years ago |
jrosendo | 4a514e6f3a | 2 years ago |
jrosendo | c189bdd64d | 2 years ago |
jrosendo | 08cedb74d3 | 2 years ago |
jrosendo | a8cae3aa7c | 2 years ago |
jrosendo | 3bfd1de5a8 | 2 years ago |
jrosendo | 1e09e6b367 | 2 years ago |
estlop | 493375231a | 2 years ago |
jrosendo | 5c8be6373d | 2 years ago |
Mohamed Zaboub | d601a9ff55 | 2 years ago |
Mohamed Zaboub | be7ac7ee70 | 2 years ago |
jrosendo | 9962ae8f5b | 2 years ago |
jrosendo | f6de74789c | 2 years ago |
MOHAMED | a8ddec8fc3 | 2 years ago |
Mohamed Zaboub | 1982384bbb | 2 years ago |
jrosendo | 61f2b9550f | 2 years ago |
jrosendo | 6ad8474527 | 2 years ago |
jrosendo | 1cb6a5ea01 | 2 years ago |
estlop | e202c2ca27 | 2 years ago |
estlop | ab36a0cd88 | 2 years ago |
jrosendo | 118766b2d7 | 2 years ago |
jrosendo | 3d8156f44c | 2 years ago |
jrosendo | 82ac6cd676 | 2 years ago |
estlop | 2c324911d5 | 2 years ago |
estlop | c98b517c71 | 2 years ago |
estlop | d438e5f04a | 2 years ago |
jrosendo | 39c8bd1683 | 2 years ago |
jrosendo | b57752f5f9 | 2 years ago |
jrosendo | 420d54d1cc | 2 years ago |
Mohamed Zaboub | 3f986cebc1 | 2 years ago |
jrosendo | 2b02ed5fbd | 2 years ago |
jrosendo | 257d088144 | 2 years ago |
jrosendo | a0de7068d6 | 2 years ago |
Hamza elkhatri | 88ff699bc1 | 2 years ago |
Hamza elkhatri | 10c2f1501d | 2 years ago |
Hamza elkhatri | 04bf6eb2b4 | 2 years ago |
Hamza elkhatri | 346cadb3d9 | 2 years ago |
Hamza elkhatri | 88d99aaa97 | 2 years ago |
Hamza elkhatri | b260bda961 | 2 years ago |
Hamza elkhatri | d404e2dc12 | 2 years ago |
Hamza elkhatri | 292e9b8bae | 2 years ago |
hamza | 82762eaac7 | 2 years ago |
jrosendo | 06c15846ef | 2 years ago |
jrosendo | 8450a159e4 | 2 years ago |
MSilva95 | 6ea5f04a3b | 2 years ago |
zainab Dnaya | 52cb3a902d | 2 years ago |
zainab Dnaya | 1431f1512c | 2 years ago |
zainab Dnaya | 7f43129173 | 2 years ago |
zainabdnaya | 379a0543eb | 2 years ago |
zainabdnaya | ebf4c17716 | 2 years ago |
zainabdnaya | 1b9ffc115f | 2 years ago |
zainabdnaya | 8ebe3d1739 | 2 years ago |
zainabdnaya | d272fe67aa | 2 years ago |
jrosendo | e519af63e1 | 2 years ago |
jrosendo | e5928b32f2 | 2 years ago |
MSilva95 | 13ccbfb416 | 2 years ago |
zainab Dnaya | 2b964e5a5a | 2 years ago |
zainab Dnaya | 1652945c13 | 2 years ago |
zainabdnaya | ffe99b1c56 | 2 years ago |
zainabdnaya | cb249fb62f | 2 years ago |
zainabdnaya | f0dede7d26 | 2 years ago |
zainabdnaya | 9e48168481 | 2 years ago |
zainabdnaya | aad7414b31 | 2 years ago |
zainabdnaya | 2cb93a8948 | 2 years ago |
zainabdnaya | 7f5ed6e2a4 | 2 years ago |
zainabdnaya | ae54d0242e | 2 years ago |
zainabdnaya | da3072dbcc | 2 years ago |
zainabdnaya | a9aefbd204 | 2 years ago |
zainabdnaya | 175b79f1ed | 2 years ago |
zainabdnaya | 1e31c9e1ba | 2 years ago |
zainabdnaya | 5d501ff8be | 2 years ago |
zainabdnaya | 8913aa6410 | 2 years ago |
jrosendo | fb90a96eec | 2 years ago |
jrosendo | d5a8d222e7 | 2 years ago |
jrosendo | c18f05927c | 2 years ago |
Hamza elkhatri | e9193c30b7 | 2 years ago |
Hamza elkhatri | 7fd30876e7 | 2 years ago |
hamza | 814fbd2c0e | 2 years ago |
Hamza elkhatri | c86e37cef7 | 2 years ago |
Hamza elkhatri | 9bff4b857b | 2 years ago |
Hamza elkhatri | 7ae7dc15d8 | 2 years ago |
Hamza elkhatri | adc4ca30c6 | 2 years ago |
Hamza elkhatri | 79dac93e46 | 2 years ago |
hamza | da9488a80c | 2 years ago |
hamza | c17271b4f7 | 2 years ago |
hamza | a4b8953fa7 | 2 years ago |
hamza | 6322b1f4e0 | 2 years ago |
jrosendo | 4fad8d25ca | 2 years ago |
jrosendo | f6a0cc925c | 2 years ago |
estlop | 8d36aa1317 | 2 years ago |
estlop | 1d0cf358fc | 2 years ago |
Harry | 139270b565 | 2 years ago |
jrosendo | 76739f7d83 | 2 years ago |
jotapero | fee07c8249 | 2 years ago |
hamza | 304c928293 | 2 years ago |
hamza | de6cfddda6 | 2 years ago |
hamza | 00e8903bc1 | 2 years ago |
jrosendo | 2afc50179b | 2 years ago |
jrosendo | 8d11216438 | 2 years ago |
jrosendo | ab2e4628b0 | 2 years ago |
jotapero | 3a26f0a94c | 2 years ago |
zainab Dnaya | 0429578368 | 2 years ago |
zainab Dnaya | cdf5ac7892 | 2 years ago |
zainab Dnaya | d8b5cb4e2d | 2 years ago |
zainab Dnaya | 4fff8bd5c9 | 2 years ago |
zainabdnaya | b3fb448f62 | 2 years ago |
zainabdnaya | 29524526c4 | 2 years ago |
jrosendo | b07d713253 | 2 years ago |
jrosendo | 8906eab7b6 | 2 years ago |
Hamza elkhatri | e02dce6987 | 2 years ago |
hamza | 2fcf16d697 | 2 years ago |
hamza | 792b2f9b6f | 2 years ago |
jrosendo | 7dea33670b | 2 years ago |
jrosendo | 8ad42033d8 | 2 years ago |
Hamza elkhatri | cf5dd2d70d | 2 years ago |
hamza | 79c96d1a7d | 2 years ago |
davhojt | d94c1c3f4f | 2 years ago |
eslopfer | b391949bfb | 2 years ago |
eslopfer | 00177d71b4 | 2 years ago |
Dani | 0c771833ba | 2 years ago |
Dias Kappassov | 29532816bd | 2 years ago |
eslopfer | 4f0e84fed5 | 2 years ago |
eslopfer | 3dd925866f | 2 years ago |
eslopfer | 64274236fb | 2 years ago |
eslopfer | 800c6067f0 | 2 years ago |
eslopfer | 0f50a371e1 | 2 years ago |
eslopfer | bb0661422d | 2 years ago |
eslopfer | 0fc87521e6 | 2 years ago |
eslopfer | 36fe2fd393 | 2 years ago |
eslopfer | 4c837d150e | 2 years ago |
eslopfer | 982c87d34d | 2 years ago |
Michele Sessa | c6a2e5d80a | 2 years ago |
Michele Sessa | dba6a14d2c | 2 years ago |
mikysett | ccc0a2dc0a | 2 years ago |
miguel | fa28c2e03d | 2 years ago |
eslopfer | bff08d50d9 | 2 years ago |
Michele Sessa | 1910f00925 | 2 years ago |
Michele Sessa | f47d73dd23 | 2 years ago |
nprimo | be03753c56 | 2 years ago |
Maxim Mihajlov | c66a05c621 | 2 years ago |
nprimo | 75da5b3fcd | 2 years ago |
nprimo | 5e828aa968 | 2 years ago |
nprimo | a17977de9b | 2 years ago |
nprimo | 92d91c30f8 | 2 years ago |
nprimo | 6becf34972 | 2 years ago |
nprimo | 6e10678bbc | 2 years ago |
nprimo | 8270fab4d1 | 2 years ago |
nprimo | a769381cbd | 2 years ago |
nprimo | 97e68708b6 | 2 years ago |
nprimo | 6edb6f640e | 2 years ago |
Michele Sessa | 0af2665526 | 2 years ago |
Michele Sessa | fc14783654 | 2 years ago |
Bakdaulet Ye | b3508822d0 | 2 years ago |
eslopfer | 548ee49fef | 2 years ago |
eslopfer | d2bb07b78f | 2 years ago |
eslopfer | ca51a72877 | 2 years ago |
eslopfer | a9e1218ff4 | 2 years ago |
eslopfer | 4b9922772f | 2 years ago |
eslopfer | 3cfd4b2844 | 2 years ago |
eslopfer | 67c543130c | 2 years ago |
eslopfer | 7483b922e8 | 2 years ago |
eslopfer | c7f50f5d24 | 2 years ago |
eslopfer | 6fec3d5899 | 2 years ago |
eslopfer | b1e2b3029a | 2 years ago |
eslopfer | 1c1966f536 | 2 years ago |
Michele Sessa | f1656004ed | 2 years ago |
Michele Sessa | ae3772b29f | 2 years ago |
mikysett | 9d8f2678c4 | 2 years ago |
nprimo | 40007e2650 | 2 years ago |
nprimo | 4b22362c2b | 2 years ago |
nprimo | f99f57537f | 2 years ago |
eslopfer | f579e040dc | 2 years ago |
eslopfer | 71a2c55a83 | 2 years ago |
eslopfer | f6251d8dfe | 2 years ago |
eslopfer | dc80b79745 | 2 years ago |
eslopfer | 3703c92b28 | 2 years ago |
mikysett | 53f7ded2f2 | 2 years ago |
mikysett | 2d8f1bb160 | 2 years ago |
eslopfer | 15f5814f33 | 2 years ago |
eslopfer | b4b9480eec | 2 years ago |
eslopfer | 24329d91b2 | 2 years ago |
eslopfer | aaf6fed9d9 | 2 years ago |
eslopfer | b587916143 | 2 years ago |
eslopfer | 812e336480 | 2 years ago |
eslopfer | 0a83ac648b | 2 years ago |
miguel | da871819d9 | 2 years ago |
miguel | e6b8fe1edd | 2 years ago |
miguel | 1e49439dd3 | 2 years ago |
miguel | 54c0c3b19d | 2 years ago |
miguel | 84392f8ebb | 2 years ago |
miguel | 595368a3ca | 2 years ago |
miguel | cbbc175648 | 2 years ago |
miguel | 987a440971 | 2 years ago |
miguel | 5bb3cf72f2 | 2 years ago |
miguel | 434c117b17 | 2 years ago |
miguel | f2fc936e2f | 2 years ago |
miguel | 9cfef991a1 | 2 years ago |
Hamza elkhatri | dea5debfeb | 2 years ago |
zainabdnaya | 2e8125f4c8 | 2 years ago |
zainabdnaya | 0a4373f6af | 2 years ago |
hamza | cd549fbe74 | 2 years ago |
zainabdnaya | 4894db9f47 | 2 years ago |
nprimo | c0d3cddadc | 2 years ago |
mikysett | 61673c3614 | 2 years ago |
nprimo | c46c81e469 | 2 years ago |
nprimo | 5fd392a741 | 2 years ago |
nprimo | 6c11610c4f | 2 years ago |
nprimo | ac61045fd4 | 2 years ago |
nprimo | f1728e8f8c | 2 years ago |
nprimo | eb8c882ba8 | 2 years ago |
nprimo | e3d0f81d6a | 2 years ago |
nprimo | 118cf8457f | 2 years ago |
mikysett | 286d6f09b6 | 2 years ago |
Harry | 406fe7f6b8 | 2 years ago |
eslopfer | 4e13857c4d | 2 years ago |
Tiago Collot | c0792d627f | 2 years ago |
Harry Vasanth | 43129a46ca | 2 years ago |
Harry Vasanth | 38666ae0c6 | 2 years ago |
Harry Vasanth | 8d9f1d2e89 | 2 years ago |
Harry Vasanth | 9cbae89ef5 | 2 years ago |
Harry Vasanth | f4ce8ea0b8 | 2 years ago |
Michele Sessa | d2fbdeffd9 | 2 years ago |
mikysett | 51bf67e5d7 | 2 years ago |
mikysett | 1e7ae325ac | 2 years ago |
Michele Sessa | 7e04c7ff10 | 2 years ago |
mikysett | 5c8406d6d0 | 2 years ago |
Michele Sessa | 799ca8670b | 2 years ago |
Michele Sessa | 0a3572d111 | 2 years ago |
mikysett | 12b99d2315 | 2 years ago |
mikysett | a87cb5c5e4 | 2 years ago |
Michele Sessa | 31e7b8dcd6 | 2 years ago |
Michele Sessa | 9425070b2e | 2 years ago |
mikysett | 6e969f8b3f | 2 years ago |
mikysett | 187028562b | 2 years ago |
Michele Sessa | ad42d04a89 | 2 years ago |
Tiago Collot | 13b4b0fbf7 | 2 years ago |
Tiago Collot | 38868a8403 | 2 years ago |
Tiago Collot | 4d13d88fa7 | 2 years ago |
Tiago Collot | 7991881a01 | 2 years ago |
Tiago Collot | 7736e2d02e | 2 years ago |
Tiago Collot | e84cda90f9 | 2 years ago |
Tiago Collot | 3e64e028d8 | 2 years ago |
Michele Sessa | 31833e4418 | 2 years ago |
Tiago Collot | 000ba6542c | 2 years ago |
Tiago Collot | 1b29753470 | 2 years ago |
Tiago Collot | 490176cc08 | 2 years ago |
Tiago Collot | 087a16d8ba | 2 years ago |
Tiago Collot | aacf91b934 | 2 years ago |
Tiago Collot | 57ab470299 | 2 years ago |
Tiago Collot | 27ef0d2782 | 2 years ago |
Tiago Collot | f6d0cc58a7 | 2 years ago |
Tiago Collot | 05f680e5d7 | 2 years ago |
Tiago Collot | a420b1f6d5 | 2 years ago |
Tiago Collot | 103a6b5192 | 2 years ago |
Tiago Collot | ad99c887eb | 2 years ago |
Tiago Collot | b26ab24c0e | 2 years ago |
Harry | d2b3bdbd2f | 2 years ago |
miguel | 943ce127ce | 2 years ago |
miguel | efaf2d0595 | 2 years ago |
miguel | 219e7b4cbd | 2 years ago |
miguel | b11528ec4b | 2 years ago |
mikysett | 50ae92c2bd | 2 years ago |
Michele Sessa | 8d1b0b182a | 2 years ago |
Michele Sessa | 9b9f6aed67 | 2 years ago |
Michele Sessa | 5b8b954d75 | 2 years ago |
Michele Sessa | 0f4fb751a5 | 2 years ago |
mikysett | 60f5aa31c6 | 2 years ago |
mikysett | 755249bbb6 | 2 years ago |
mikysett | 71e671c5e5 | 2 years ago |
mikysett | f048c0fa87 | 2 years ago |
Tiago Collot | 1b8355eac1 | 2 years ago |
Tiago Collot | bf3fcb6f50 | 2 years ago |
Tiago Collot | abe64ca1b3 | 2 years ago |
Tiago Collot | ded101b86c | 2 years ago |
Tiago Collot | ee8732c9de | 2 years ago |
Tiago Collot | c34d3141bf | 2 years ago |
Tiago Collot | c6e150901e | 2 years ago |
Tiago Collot | 8647521af3 | 2 years ago |
Tiago Collot | d771054ccc | 2 years ago |
Tiago Collot | 378181a995 | 2 years ago |
Tiago Collot | b36a5f98f2 | 2 years ago |
Tiago Collot | a527e3f2ea | 2 years ago |
Tiago Collot | a46cf4285b | 2 years ago |
Tiago Collot | 9cd626d8b6 | 2 years ago |
Tiago Collot | d1233266f9 | 2 years ago |
Tiago Collot | 43291628d3 | 2 years ago |
Tiago Collot | 5084471315 | 2 years ago |
Tiago Collot | 4dd857f8e9 | 2 years ago |
Tiago Collot | 54addda494 | 2 years ago |
Tiago Collot | 7a4af4d164 | 2 years ago |
Tiago Collot | 460754b7b3 | 2 years ago |
Tiago Collot | 024d17a2c6 | 2 years ago |
Tiago Collot | b2c998ea8f | 2 years ago |
Tiago Collot | aa08580a4d | 2 years ago |
Tiago Collot | e62a381533 | 2 years ago |
Tiago Collot | 7f9f275547 | 2 years ago |
Tiago Collot | 3102b64701 | 2 years ago |
Tiago Collot | a2b515bb38 | 2 years ago |
Tiago Collot | a31d4a2e8c | 2 years ago |
Tiago Collot | cf679aa068 | 2 years ago |
Tiago Collot | 23349eea08 | 2 years ago |
Tiago Collot | cf5befdec6 | 2 years ago |
Tiago Collot | 8bd3f6c935 | 2 years ago |
Tiago Collot | 194ccbb8fe | 2 years ago |
Tiago Collot | b2499e54a5 | 2 years ago |
Tiago Collot | fd4bedd973 | 2 years ago |
Tiago Collot | cc7fbdf495 | 2 years ago |
Tiago Collot | e2629667d5 | 2 years ago |
Tiago Collot | 7e65c830e3 | 2 years ago |
Tiago Collot | 4bf53c9baf | 2 years ago |
Tiago Collot | 79dbc1738a | 2 years ago |
Tiago Collot | c2d0c4f0c1 | 2 years ago |
Tiago Collot | abdf7a39a1 | 2 years ago |
Tiago Collot | c111c07e3c | 2 years ago |
Tiago Collot | e8af487cc6 | 2 years ago |
Tiago Collot | 15004789f6 | 2 years ago |
nprimo | b4fa7403d3 | 2 years ago |
Michele Sessa | 361430938f | 2 years ago |
Michele Sessa | 6f65a96a2e | 2 years ago |
Michele Sessa | 99b9025e19 | 2 years ago |
Michele Sessa | 43c2a6dedc | 2 years ago |
Michele Sessa | 47001cd118 | 2 years ago |
Michele Sessa | 2e2f1eab45 | 2 years ago |
Michele Sessa | 9fff5aa95f | 2 years ago |
Michele Sessa | 0c9296dbcf | 2 years ago |
Maxim Mihajlov | 61c1fd1ac1 | 2 years ago |
Maxim Mihajlov | 1ba87d145a | 2 years ago |
miguel | 074f4c25ac | 2 years ago |
Michele Sessa | ba521bbfb0 | 2 years ago |
nprimo | 68a7268733 | 2 years ago |
nprimo | 689fd07a48 | 2 years ago |
nprimo | 6e2c985149 | 2 years ago |
nprimo | 8d2d144070 | 2 years ago |
nprimo | d976bd6796 | 2 years ago |
nprimo | 286a81b3c6 | 2 years ago |
miguel | ba63d23d05 | 2 years ago |
zoevig | 9120b07fb0 | 2 years ago |
davhojt | 7643f31e6b | 2 years ago |
Michele Sessa | 28bccd6e59 | 2 years ago |
Michele Sessa | cd2b00b135 | 2 years ago |
Michele Sessa | f01fd7ed5e | 2 years ago |
davhojt | 9934ff22b8 | 2 years ago |
nprimo | 6a74ef19df | 2 years ago |
nprimo | f49d01e325 | 2 years ago |
davhojt | d6c61dc527 | 2 years ago |
davhojt | ac86faff7d | 2 years ago |
eslopfer | 26b1e904d2 | 2 years ago |
eslopfer | c0d5dfda49 | 2 years ago |
eslopfer | 751bdf7ba4 | 2 years ago |
eslopfer | de30084743 | 2 years ago |
zoevig | cd5258398a | 2 years ago |
zoevig | 585fdcefbd | 2 years ago |
zoevig | 1d27d04bd4 | 2 years ago |
zoevig | 6d92bd0223 | 2 years ago |
zoevig | 1c2bdf399b | 2 years ago |
eslopfer | e133e63658 | 2 years ago |
eslopfer | e236f59390 | 2 years ago |
eslopfer | 33c0a1c1dd | 2 years ago |
eslopfer | 8566d590e2 | 2 years ago |
eslopfer | 0a329ec69b | 2 years ago |
davhojt | 2dac643de9 | 2 years ago |
nprimo | fb0b19c3b5 | 2 years ago |
nprimo | 9afdda465c | 2 years ago |
Michele Sessa | 850821bd2b | 2 years ago |
Michele Sessa | c977023596 | 2 years ago |
Michele Sessa | 88d3857a61 | 2 years ago |
Michele Sessa | 3a5196a8a6 | 2 years ago |
nprimo | 8f6fec1675 | 2 years ago |
miguel | 6539b5ee88 | 2 years ago |
Christopher Fremond | 78e4da15db | 2 years ago |
Michele Sessa | 519604891e | 2 years ago |
mikysett | dcea19a5d7 | 2 years ago |
Michele Sessa | 0b3538bcca | 2 years ago |
Michele Sessa | dca05bee11 | 2 years ago |
Michele Sessa | 0eaaa00196 | 2 years ago |
miguel | 412d887403 | 2 years ago |
miguel | 6cfb5518b3 | 2 years ago |
davhojt | 2d9309a87f | 2 years ago |
davhojt | 13d8066e11 | 2 years ago |
eslopfer | f9067b837f | 2 years ago |
davhojt | c91da2f110 | 2 years ago |
Michele Sessa | 79fa31ce91 | 2 years ago |
davhojt | a542c738da | 2 years ago |
Tiago Collot | 4a9b929176 | 2 years ago |
Tiago Collot | 65f302e578 | 2 years ago |
Tiago Collot | 0797dd68db | 2 years ago |
Tiago Collot | 606cb972c3 | 2 years ago |
nprimo | b624bf8290 | 2 years ago |
nprimo | daa52c1fd8 | 2 years ago |
nprimo | 2f4900d8d2 | 2 years ago |
nprimo | ec55a11e80 | 2 years ago |
nprimo | e52e60a612 | 2 years ago |
nprimo | 7f220e4b03 | 2 years ago |
eslopfer | 26503936d4 | 2 years ago |
eslopfer | affd3c6c82 | 2 years ago |
eslopfer | 7af4701427 | 2 years ago |
eslopfer | bb91a6ce17 | 2 years ago |
eslopfer | e92b0d5369 | 2 years ago |
eslopfer | 37b2b29f22 | 2 years ago |
eslopfer | 7db94af256 | 2 years ago |
eslopfer | 383fb91a63 | 2 years ago |
eslopfer | 9a6a883829 | 2 years ago |
eslopfer | 949c2cbd5e | 2 years ago |
eslopfer | 4b3b53ad11 | 2 years ago |
Tiago Collot | c9ee2ca990 | 2 years ago |
Tiago Collot | 6eeff20876 | 2 years ago |
zoevig | 615c418bc6 | 2 years ago |
zoevig | 59af6a3a59 | 2 years ago |
zoevig | 439cb401de | 2 years ago |
zoevig | dd3d57b8e4 | 2 years ago |
zoevig | 6f4f3b96b3 | 2 years ago |
zoevig | f55508f76d | 2 years ago |
zoevig | c6d8047775 | 2 years ago |
zoevig | bb2473a509 | 2 years ago |
zoevig | ef28463f0d | 2 years ago |
zoevig | 9ba9326a66 | 2 years ago |
zoevig | c3e8f2975e | 2 years ago |
zoevig | 18c21520af | 2 years ago |
zoevig | 02a2cd7ffc | 2 years ago |
zoevig | a42d27570a | 2 years ago |
zoevig | 4faf75699b | 2 years ago |
zoevig | 45780f9aee | 2 years ago |
miguel | f2f2d2e06c | 2 years ago |
miguel | e97279e9df | 2 years ago |
miguel | fb268fa9ca | 2 years ago |
miguel | b30b47227e | 2 years ago |
miguel | 072f1b6b3c | 2 years ago |
MSilva95 | e9995f5f87 | 2 years ago |
miguel | a140e10bd7 | 2 years ago |
Michele | a1ebd06180 | 2 years ago |
mikysett | 020b1b50a9 | 2 years ago |
Andres Sulg | abda457eda | 2 years ago |
Michele | 5b870400ba | 2 years ago |
Harry | a25112fabb | 2 years ago |
Harry | 0dced086f3 | 2 years ago |
Christopher Fremond | 92294a7f4d | 2 years ago |
MSilva95 | 77c58b0ee1 | 2 years ago |
Hamza elkhatri | 6572a3d247 | 2 years ago |
hamza | fd4ab85798 | 2 years ago |
MSilva95 | 33b0883b42 | 2 years ago |
zainabdnaya | 2bede0ba82 | 2 years ago |
Hamza elkhatri | 12a28bb3c2 | 2 years ago |
zainabdnaya | 22a98fb3c1 | 2 years ago |
zainabdnaya | 5c9af6e07b | 2 years ago |
zainabdnaya | 1a3f9ae1fb | 2 years ago |
zainabdnaya | 2b073bc319 | 2 years ago |
zainabdnaya | b2ddd18a79 | 2 years ago |
zainabdnaya | 81a5c8bdee | 2 years ago |
zainabdnaya | 0a78c83149 | 2 years ago |
zainabdnaya | 891a4fc8ad | 2 years ago |
zainabdnaya | 733dda0c22 | 2 years ago |
zainabdnaya | 40ca316ba0 | 2 years ago |
zainabdnaya | 806176c71b | 2 years ago |
zainabdnaya | f4b184fd3b | 2 years ago |
zainabdnaya | fb3636dff2 | 2 years ago |
zainabdnaya | f7ff499198 | 2 years ago |
MSilva95 | 4fe6da41eb | 2 years ago |
zainabdnaya | 24540b242b | 2 years ago |
zainabdnaya | a0fa67d699 | 2 years ago |
zainabdnaya | 99f3cb92ed | 2 years ago |
zainabdnaya | fa657e75a0 | 2 years ago |
zainabdnaya | 822ffb2746 | 2 years ago |
zainabdnaya | 2ce0f93133 | 2 years ago |
zainabdnaya | e12c0a9c5f | 2 years ago |
zainabdnaya | 3d66c9f78f | 2 years ago |
zainabdnaya | a3350ff8d4 | 2 years ago |
zainabdnaya | e8f3b57009 | 2 years ago |
MSilva95 | 4ff540dcdd | 2 years ago |
zainabdnaya | 54585ff591 | 2 years ago |
zainabdnaya | 7446208834 | 2 years ago |
zainabdnaya | 23117c2764 | 2 years ago |
zainabdnaya | b20ea0e7fa | 2 years ago |
zainabdnaya | dc76a3aa38 | 2 years ago |
MSilva95 | 4901cfa9bc | 2 years ago |
MSilva95 | d3e7be78d1 | 2 years ago |
zainabdnaya | e0dfa67526 | 2 years ago |
zainabdnaya | f32d1a5091 | 2 years ago |
zainabdnaya | 4e86e826c5 | 2 years ago |
zainabdnaya | eb6a195100 | 2 years ago |
zainabdnaya | 8cc2239037 | 2 years ago |
zainabdnaya | 08a24c947f | 2 years ago |
zainabdnaya | 53d1fdbddf | 2 years ago |
zainabdnaya | 2a2f77d8de | 2 years ago |
Michele Sessa | 067b3d6f42 | 2 years ago |
hamza | f9654289c6 | 2 years ago |
zainab Dnaya | 6d2a7bb7f2 | 2 years ago |
zainab Dnaya | 2307966747 | 2 years ago |
zainab Dnaya | bc85ef828d | 2 years ago |
zainab Dnaya | c99147f091 | 2 years ago |
zainabdnaya | 7713f3bd2b | 2 years ago |
zainabdnaya | 3192df2360 | 2 years ago |
zainabdnaya | 8679377f37 | 2 years ago |
zainabdnaya | 4f34cffaf9 | 2 years ago |
zainabdnaya | d8a72d0e05 | 2 years ago |
zainabdnaya | 96436abe98 | 2 years ago |
zainabdnaya | 4264d33019 | 2 years ago |
zainabdnaya | 607270bb38 | 2 years ago |
zainabdnaya | e779196218 | 2 years ago |
zainabdnaya | c9b0d66ebf | 2 years ago |
zainabdnaya | eac91965a8 | 2 years ago |
zainabdnaya | 267b10d31d | 2 years ago |
zainabdnaya | 9bd0487d9e | 2 years ago |
zainabdnaya | f02ddea763 | 2 years ago |
zainabdnaya | 245c0f0785 | 2 years ago |
Hamza elkhatri | 2f765363af | 2 years ago |
hamza | 1395d56768 | 2 years ago |
hamza | 8ff8f1b311 | 2 years ago |
Hamza elkhatri | 1e5c576514 | 2 years ago |
Hamza elkhatri | 13f6181c6c | 2 years ago |
Hamza elkhatri | fe0dfb38eb | 2 years ago |
Hamza elkhatri | ae49b05728 | 2 years ago |
hamza | 7986c7b800 | 2 years ago |
hamza | f5161c6f3b | 2 years ago |
Hamza elkhatri | 21a3749dcc | 2 years ago |
Hamza elkhatri | f81cc27798 | 2 years ago |
Hamza elkhatri | 3c5fb469e0 | 2 years ago |
Hamza elkhatri | 40c2d65b0c | 2 years ago |
Hamza elkhatri | 594cef3d46 | 2 years ago |
Hamza elkhatri | f9383e2fc4 | 2 years ago |
Hamza elkhatri | 8f788a3830 | 2 years ago |
Hamza elkhatri | 4fc920469f | 2 years ago |
hamza | e46d48db59 | 2 years ago |
hamza | 46f8f3ecc7 | 2 years ago |
Hamza elkhatri | 7050516707 | 2 years ago |
Hamza elkhatri | c5193e9d82 | 2 years ago |
Hamza elkhatri | b529e6ecf7 | 2 years ago |
Hamza elkhatri | 11b0dd1e55 | 2 years ago |
Hamza elkhatri | 3137eb63ef | 2 years ago |
hamza | 1aee0b2871 | 2 years ago |
davhojt | 91ac481d9f | 2 years ago |
davhojt | 9848384faa | 2 years ago |
davhojt | 31b4331600 | 2 years ago |
estlop | 975ea7272b | 2 years ago |
Christopher Fremond | 5cca789fd1 | 2 years ago |
Christopher Fremond | 88c3cc52a9 | 2 years ago |
Christopher Fremond | c726f13e09 | 2 years ago |
MSilva95 | 6a3e1be365 | 2 years ago |
MSilva95 | 9ce366c5d4 | 2 years ago |
MSilva95 | f82c13034d | 2 years ago |
MSilva95 | 182a0f0f92 | 2 years ago |
rcatini | a5e8ad8d10 | 2 years ago |
rcatini | 58c92312e9 | 2 years ago |
miguel | 5bd0efff7f | 2 years ago |
Christopher Fremond | 61e9bcda0f | 2 years ago |
eslopfer | c2ba93a8b4 | 2 years ago |
estlop | 14bff2fbb7 | 2 years ago |
estlop | bbe0038638 | 2 years ago |
Christopher Fremond | 2d0a9a04c7 | 2 years ago |
MSilva95 | e164bf6767 | 2 years ago |
Christopher Fremond | 5dbc369084 | 2 years ago |
Christopher Fremond | c8e0689e1a | 2 years ago |
Clément | d3a3888d53 | 2 years ago |
Clément | 722e7b670a | 2 years ago |
estlop | 3e50722419 | 2 years ago |
estlop | 2e97385c73 | 2 years ago |
davhojt | 266a3a941d | 2 years ago |
Clement Denis | 4c65e9e273 | 2 years ago |
zainabdnaya | c0903b687f | 2 years ago |
zainabdnaya | 875846bbdf | 2 years ago |
Hamza elkhatri | 888d46713e | 2 years ago |
zainabdnaya | ea8573457b | 2 years ago |
zainabdnaya | f3a1b74bd9 | 2 years ago |
hamza | 2cc3501e17 | 2 years ago |
estlop | c19bfb50ea | 2 years ago |
estlop | 0bcc0ddfb7 | 2 years ago |
estlop | 5a878eb40c | 2 years ago |
estlop | 2155f4b6fc | 2 years ago |
estlop | 7d9f6eb3e5 | 2 years ago |
estlop | cf5f8e6c1e | 2 years ago |
estlop | e1d2392997 | 2 years ago |
estlop | 5ab429e996 | 2 years ago |
estlop | aab618949e | 2 years ago |
estlop | b974a12074 | 2 years ago |
estlop | 402b138983 | 2 years ago |
estlop | 5ebf4a257a | 2 years ago |
estlop | 2dc5d68381 | 2 years ago |
estlop | 31ded86687 | 2 years ago |
estlop | 2ae3ef00fd | 2 years ago |
estlop | cf26a508d3 | 2 years ago |
estlop | f8b2b6aed0 | 2 years ago |
Hamza elkhatri | 20b24a334a | 2 years ago |
Hamza elkhatri | 17e70838ea | 2 years ago |
hamza | 9f0ee07524 | 2 years ago |
MSilva95 | 55529af70a | 2 years ago |
Hamza elkhatri | e39eaca456 | 2 years ago |
Hamza elkhatri | ae450bee6c | 2 years ago |
Hamza elkhatri | cd276d5ee5 | 2 years ago |
Hamza elkhatri | 4ae7091b8e | 2 years ago |
Hamza elkhatri | d0463615cb | 2 years ago |
hamza | cf0941bf95 | 2 years ago |
MSilva95 | c9790ce688 | 2 years ago |
estlop | 7ed376c50c | 2 years ago |
estlop | bcc4be2d63 | 2 years ago |
estlop | a7e0232720 | 2 years ago |
estlop | a7c012310c | 2 years ago |
estlop | 5a4d2a6387 | 2 years ago |
estlop | c496f96630 | 2 years ago |
Hamza elkhatri | f1fc133bb3 | 2 years ago |
Hamza elkhatri | 5d18e844ab | 2 years ago |
hamza | 5ce527c2d4 | 2 years ago |
Hamza elkhatri | 6a53d215e6 | 2 years ago |
hamza | e5914c14bc | 2 years ago |
MSilva95 | 404c163609 | 2 years ago |
estlop | df8917a7d1 | 2 years ago |
estlop | 34966f26d6 | 2 years ago |
zainabdnaya | 3a6168c881 | 2 years ago |
estlop | 042298332e | 2 years ago |
estlop | 6468a3614b | 2 years ago |
MSilva95 | 6574814741 | 2 years ago |
hamza | 5c11b6e9ec | 2 years ago |
miguel | 12d57a2f64 | 2 years ago |
davidrobert99 | b9fb4c6157 | 2 years ago |
davidrobert99 | 260ae8c7da | 2 years ago |
miguel | 2e9a1d7998 | 2 years ago |
Clement Denis | 8573f049f2 | 2 years ago |
Clement Denis | 711dabdb12 | 2 years ago |
MSilva95 | eb95584405 | 2 years ago |
Hamza elkhatri | 3bdf80b9c6 | 2 years ago |
Hamza elkhatri | 216b1a9efa | 2 years ago |
hamza | e0693e278a | 2 years ago |
davhojt | 25400daa15 | 2 years ago |
estlop | 7e4af38af0 | 2 years ago |
estlop | 7c304d8b30 | 2 years ago |
estlop | f740ba0a03 | 2 years ago |
estlop | 3097cd47f3 | 2 years ago |
estlop | f5679a6ca6 | 2 years ago |
Dav Hojt | fcc042a38e | 2 years ago |
davhojt | c84959b8ba | 2 years ago |
Hamza elkhatri | 5cbf005b3b | 2 years ago |
Hamza elkhatri | fbb90f82d2 | 2 years ago |
hamza | 66624b671d | 2 years ago |
Hamza elkhatri | 69b19b2269 | 2 years ago |
hamza | 69245b40ba | 2 years ago |
hamza | 016714770e | 2 years ago |
hamza | 3266406fb2 | 2 years ago |
Hamza elkhatri | 54c5214072 | 2 years ago |
hamza | 1d8cacc5c6 | 2 years ago |
zainabdnaya | c52e070e8f | 2 years ago |
zainabdnaya | cd1dee9ab3 | 2 years ago |
zainabdnaya | 46b7df8c9e | 2 years ago |
zainabdnaya | 15f6559845 | 2 years ago |
zainabdnaya | a43fa3abd3 | 2 years ago |
zainabdnaya | 4717e47416 | 2 years ago |
zainabdnaya | cd65a41d33 | 2 years ago |
zainabdnaya | 7b677f1ab8 | 2 years ago |
zainabdnaya | 10d16dad52 | 2 years ago |
zainabdnaya | d209193a50 | 2 years ago |
zainabdnaya | 4df40dfcf0 | 2 years ago |
Hamza elkhatri | ef8a775e68 | 2 years ago |
zainab Dnaya | 17fc8ccb9b | 2 years ago |
zainabdnaya | 82b6dd1443 | 2 years ago |
zainabdnaya | fef4b725e3 | 2 years ago |
zainabdnaya | 8467b73de6 | 2 years ago |
863 changed files with 87617 additions and 4155 deletions
@ -0,0 +1,46 @@ |
|||||||
|
name: Docker Image CI |
||||||
|
|
||||||
|
on: |
||||||
|
push: |
||||||
|
branches: ['master'] |
||||||
|
pull_request: |
||||||
|
branches: ['master'] |
||||||
|
|
||||||
|
jobs: |
||||||
|
build: |
||||||
|
runs-on: ubuntu-latest |
||||||
|
|
||||||
|
steps: |
||||||
|
- uses: actions/checkout@v3 |
||||||
|
|
||||||
|
- name: Login to GitHub Container Registry |
||||||
|
uses: docker/login-action@v1 |
||||||
|
with: |
||||||
|
registry: ghcr.io |
||||||
|
username: ${{ github.actor }} |
||||||
|
password: ${{ secrets.GITHUB_TOKEN }} |
||||||
|
|
||||||
|
- name: Login to docker.01-edu.org Registry |
||||||
|
uses: docker/login-action@v2.1.0 |
||||||
|
with: |
||||||
|
registry: docker.01-edu.org |
||||||
|
username: ${{ secrets.USER_DOCKER_01EDU_ORG }} |
||||||
|
password: ${{ secrets.SECRET_DOCKER_01EDU_ORG }} |
||||||
|
|
||||||
|
- name: Build the Sh Docker image |
||||||
|
if: always() |
||||||
|
run: | |
||||||
|
docker build sh/tests/ --file sh/tests/Dockerfile --tag ghcr.io/01-edu/test-sh:latest |
||||||
|
docker push ghcr.io/01-edu/test-sh:latest |
||||||
|
|
||||||
|
- name: Build the JS Docker image |
||||||
|
if: always() |
||||||
|
run: | |
||||||
|
docker build js/tests/ --file js/tests/Dockerfile --tag ghcr.io/01-edu/test-js:latest |
||||||
|
docker push ghcr.io/01-edu/test-js:latest |
||||||
|
|
||||||
|
- name: Build the DOM Docker image |
||||||
|
if: always() |
||||||
|
run: | |
||||||
|
docker build . --file dom/Dockerfile --tag ghcr.io/01-edu/test-dom:latest |
||||||
|
docker push ghcr.io/01-edu/test-dom:latest |
@ -1,278 +0,0 @@ |
|||||||
# THE ADDITION OF EXERCISE PROCEDURE |
|
||||||
|
|
||||||
**Needs to be updated since the refactor** |
|
||||||
|
|
||||||
##### This is for a go exercise in the piscine-go |
|
||||||
|
|
||||||
## **1. Writing the subject and / or writing the solution** |
|
||||||
|
|
||||||
Always address each exceptional cases. |
|
||||||
|
|
||||||
Example: [fprime](https://github.com/01-edu/public/blob/master/subjects/fprime.en.md). |
|
||||||
|
|
||||||
The exceptional cases in the `usage` part. |
|
||||||
|
|
||||||
```console |
|
||||||
$ go run . 225225 |
|
||||||
3*3*5*5*7*11*13 |
|
||||||
$ go run . 8333325 |
|
||||||
3*3*5*5*7*11*13*37 |
|
||||||
|
|
||||||
... |
|
||||||
|
|
||||||
$ go run . 0 |
|
||||||
|
|
||||||
$ go run . 1 |
|
||||||
1 |
|
||||||
$ |
|
||||||
``` |
|
||||||
|
|
||||||
The subject states that only **positive integer** will be tested, however, 0 and 1 are not primes. |
|
||||||
|
|
||||||
The subject writer made a mistake because of forgetting that fact. |
|
||||||
|
|
||||||
During the exam, the test was testing the `1` case and expecting a `1\n` to be printed. The real result should only have been a `\n`. |
|
||||||
|
|
||||||
Some students found this mistake. An update of the subject during the exam treating that special case was immediately necessary. |
|
||||||
|
|
||||||
1. Try to avoid the “you” and contracted “language” |
|
||||||
|
|
||||||
2. Always check the formating md |
|
||||||
|
|
||||||
--- |
|
||||||
|
|
||||||
### fprime <span style="color:#ff3234">(Title of the exercise)</span> |
|
||||||
|
|
||||||
#### Instructions <span style="color:#ff3234">(Instructions of the exercise)</span> |
|
||||||
|
|
||||||
Write a program that takes a positive `int` and displays its prime factors, followed by a newline (`'\n'`). <span style="color:#ff3234">(general guidelines, notice the imperative style tense and the avoidance of “you”. “You” is authorized in the case of a presence of a back story where the player is immersed)</span> |
|
||||||
|
|
||||||
- Factors must be displayed in ascending order and separated by `*`. <span style="color:#ff3234">(formating requirement) </span> |
|
||||||
|
|
||||||
- If the number of arguments is different from 1, the program displays a newline. <span style="color:#ff3234">(special case requirement, this case will need to be tested)</span> |
|
||||||
|
|
||||||
- The input, when there is one, will always be valid. <span style="color:#ff3234">(Clarification on what the tester will do, hence giving the student guidelines on the cases to be handled, the tests have to reflect this instruction as well)</span> |
|
||||||
|
|
||||||
- In this exercise the primes factor of 1 is considered as 1. <span style="color:#ff3234">(Handling of exceptional case: THIS Happens to be a mistake, we will see uses this example for the “UPDATING A SUBJECT/TEST PROCEDURE”)</sapn> |
|
||||||
|
|
||||||
### Usage |
|
||||||
|
|
||||||
```console |
|
||||||
$ go run . 225225 |
|
||||||
3*3*5*5*7*11*13 |
|
||||||
$ go run . 8333325 |
|
||||||
3*3*5*5*7*11*13*37 |
|
||||||
$ go run . 9539 |
|
||||||
9539 |
|
||||||
$ go run . 804577 |
|
||||||
804577 |
|
||||||
$ go run . 42 |
|
||||||
2*3*7 |
|
||||||
$ go run . a |
|
||||||
|
|
||||||
$ go run . 0 |
|
||||||
|
|
||||||
$ go run . 1 |
|
||||||
1 |
|
||||||
$ |
|
||||||
``` |
|
||||||
|
|
||||||
--- |
|
||||||
|
|
||||||
## **2. Creating the files for tests (4 main cases)** |
|
||||||
|
|
||||||
### always in -> _all/tests/go/_ |
|
||||||
|
|
||||||
### **Folder organization** |
|
||||||
|
|
||||||
- Function exercise in a Quest `(strlen)` |
|
||||||
- 2 files: |
|
||||||
- strlen_test.go |
|
||||||
- solutions/strlen.goz |
|
||||||
|
|
||||||
```console |
|
||||||
go |
|
||||||
| strlen_test.go |
|
||||||
| |
|
||||||
| __ solutions |
|
||||||
| |-strlen.go (package solutions) |
|
||||||
| |
|
||||||
| __ student (the same thing as the solutions, just run "cp -aT solutions/ student/") |
|
||||||
``` |
|
||||||
|
|
||||||
- Program exercise in a Quest `(doop)` |
|
||||||
- 2 files |
|
||||||
- doop_test.go |
|
||||||
- solutions/doop/main.go |
|
||||||
|
|
||||||
```console |
|
||||||
go |
|
||||||
| doop_test.go |
|
||||||
| |
|
||||||
| |
|
||||||
| __ solutions |
|
||||||
| |__doop |
|
||||||
| |-main.go (package main) |
|
||||||
| |
|
||||||
| __ student (the same thing as the solutions, just run "cp -aT solutions/ student/") |
|
||||||
``` |
|
||||||
|
|
||||||
- Program exercise in the exam `(dooprog)` |
|
||||||
- 2 files |
|
||||||
- solutions/doopprog/main.go |
|
||||||
- solutions/doopprog/doopprog_test.go |
|
||||||
|
|
||||||
```console |
|
||||||
go |
|
||||||
| |
|
||||||
| __ solutions |
|
||||||
| | __ doopprog |
|
||||||
| |-main.go (package main) |
|
||||||
| |-doopprog_test.go |
|
||||||
| |
|
||||||
| __ student (the same thing as the solutions, just run "cp -aT solutions/ student/") |
|
||||||
``` |
|
||||||
|
|
||||||
- Function exercise in the exam `(atoiprog)` |
|
||||||
- 3 files |
|
||||||
- solutions/atoi.go |
|
||||||
- solutions/atoiprog/main.go |
|
||||||
- solutions/atoiprog/atoiprog_test.go |
|
||||||
|
|
||||||
```console |
|
||||||
go |
|
||||||
| |
|
||||||
| __ solutions |
|
||||||
| | |
|
||||||
| |-atoi.go (package solutions) |
|
||||||
| |__atoiprog |
|
||||||
| |-main.go (package main)(func main(){} stays empty) |
|
||||||
| |-atoiprog_test.go |
|
||||||
| |
|
||||||
| __ student (the same thing as the solutions, just run "cp -aT solutions/ student/") |
|
||||||
``` |
|
||||||
|
|
||||||
--- |
|
||||||
|
|
||||||
## **3. Writing a file_test.go (test file for go)** |
|
||||||
|
|
||||||
### <span style="color:#00bae6">**RULE 1**</span> |
|
||||||
|
|
||||||
- Make the test as independent as possible (no self-made functions imported) |
|
||||||
|
|
||||||
- **If** the source is not in the import section, copy and paste the function, with **lowercase** for the first letter of its name. |
|
||||||
|
|
||||||
- Example: addprimesum_test.go |
|
||||||
|
|
||||||
![isaprime](isaprime.png) |
|
||||||
|
|
||||||
The func isAPrime is fully copied to the file. |
|
||||||
|
|
||||||
### <span style="color:#00bae6">**RULE 2**</span> |
|
||||||
|
|
||||||
Every special case in the subject should be tested. Preferably first. Before the randoms tests |
|
||||||
|
|
||||||
### <span style="color:#00bae6">**RULE 3**</span> |
|
||||||
|
|
||||||
Whenever possible do at least 1 random test! This is to avoid cheating by predictability of the tests. If the tests are fixed, then the student may create a forest of ifs program to bypass the tester. |
|
||||||
|
|
||||||
### z01.functions to be used by tester |
|
||||||
|
|
||||||
- Function exercise in a Quest (strlen) ![z01sl](strlenz01.png) |
|
||||||
|
|
||||||
```go |
|
||||||
z01.Challenge(t, studentSol, studentStu) // if the program doesn’t have arguments |
|
||||||
|
|
||||||
z01.Challenge(t, studentSol, studentStu, args...) //if the program has arguments |
|
||||||
``` |
|
||||||
|
|
||||||
- Program exercise in a Quest (doop) ![z01doop](doopz01.png)<- Screenshots to be added. |
|
||||||
|
|
||||||
```go |
|
||||||
z01.ChallengeMain(t) // if the program doesn’t have arguments |
|
||||||
|
|
||||||
z01.ChallengeMain(t, args...) // if the program has arguments |
|
||||||
``` |
|
||||||
|
|
||||||
- Program exercise in the exam (dooprog) Screenshots to be added. |
|
||||||
|
|
||||||
```go |
|
||||||
z01.ChallengeMainExam(t) // if the program doesn’t have arguments |
|
||||||
|
|
||||||
z01.ChallengeMainExam (t, args...) // if the program has arguments |
|
||||||
``` |
|
||||||
|
|
||||||
- Function exercise in the exam (Atoiprog) Screenshots to be added. |
|
||||||
|
|
||||||
```go |
|
||||||
z01.Challenge(t, studentSol, studentStu) // if the program doesn’t have arguments |
|
||||||
|
|
||||||
z01.Challenge(t, studentSol, studentStu, args...) //if the program has arguments |
|
||||||
``` |
|
||||||
|
|
||||||
--- |
|
||||||
|
|
||||||
## **4. Testing locally (`go test` or `go test -run=Test\<nameOfTheFunction\>`)** |
|
||||||
|
|
||||||
### you do -run=... because you have many test files, so you need to run just one |
|
||||||
|
|
||||||
### Before every PR : a go test has to be executed (in several situations) in the folder(s) of the exercise(s) worked on |
|
||||||
|
|
||||||
**First thing first** |
|
||||||
|
|
||||||
```console |
|
||||||
rm -r student |
|
||||||
cp -aT solutions/ student |
|
||||||
``` |
|
||||||
|
|
||||||
### Execute a go test in the appropriate folder |
|
||||||
|
|
||||||
- Function exercise in a Quest `(strlen)` ![](image.png) |
|
||||||
|
|
||||||
`all/test/go` |
|
||||||
|
|
||||||
```console |
|
||||||
go test -run=TestStrlen |
|
||||||
``` |
|
||||||
|
|
||||||
- Program exercise in a Quest `(doop)` ![](image.png)<- Screenshots to be added. |
|
||||||
|
|
||||||
`all/test/go/` |
|
||||||
|
|
||||||
```console |
|
||||||
go test -run=TestDoop |
|
||||||
``` |
|
||||||
|
|
||||||
- Program exercise in the exam `(dooprog)` Screenshots to be added. |
|
||||||
|
|
||||||
Here you can do just _go test_, because there's only one test file |
|
||||||
|
|
||||||
`all/test/go/student/dooprog` |
|
||||||
|
|
||||||
```console |
|
||||||
go test |
|
||||||
``` |
|
||||||
|
|
||||||
- Function exercise in the exam `(atoiprog)` Screenshots to be added. |
|
||||||
|
|
||||||
`all/test/go/student/atoiprog` |
|
||||||
|
|
||||||
```console |
|
||||||
go test |
|
||||||
``` |
|
||||||
|
|
||||||
### **NOTE:** If a go test gives a (cached) result, use this type of command (example with raid3): |
|
||||||
|
|
||||||
`go test count=1 raid3_test.go` |
|
||||||
|
|
||||||
The result should be an OK message: |
|
||||||
|
|
||||||
- This means that the test is running correctly when the correct solution is given. If this does not work, the test file is likely to have errors inside. |
|
||||||
|
|
||||||
- Time should be under 5-6 seconds. If longer, remove some of the iteration of the random tests (for example, less random tests) |
|
||||||
|
|
||||||
- Be watchful of exercises with challenge function: Always test a copy of the variable and not the same variable for both the student and the solution function. |
|
||||||
|
|
||||||
- Introduce errors in the student solution.go file in order to see the errors message and compare them to the subject examples. |
|
||||||
|
|
||||||
- Error messages for structures exercises (linked lists, binary trees) need to be tailored accordingly. |
|
@ -1,92 +0,0 @@ |
|||||||
## How to do an audit from home |
|
||||||
|
|
||||||
### Introduction |
|
||||||
|
|
||||||
A little reminder first, |
|
||||||
|
|
||||||
Audits, as we have told you many times, are an essential part of leveling up and truly acquiring your skills |
|
||||||
and knowledge. |
|
||||||
|
|
||||||
Normally, they must be done with your physical presence. |
|
||||||
The idea is that they encourage the exchange between the auditors and the members of the group. |
|
||||||
|
|
||||||
If the project fails, the whole group will learn why. And then after all your audits are done you will retry. |
|
||||||
During all those extra audits, you, as a group, will discuss about your failures with the auditors. |
|
||||||
If the project succeed, you will be an inspiration for the auditors. |
|
||||||
In both of those cases you will learn or you will teach. The roles will keep reversing almost every time. |
|
||||||
|
|
||||||
It is, ultimaly, those interactions that are essential for really learning; |
|
||||||
To give and receive feedback, but also to see what you really know as an individual and what you do not. |
|
||||||
This will increase your capacity to solve problems and your capacity to adapt, which is one of the most important |
|
||||||
skill of a good programmer. |
|
||||||
|
|
||||||
Today, once again, we must adapt... |
|
||||||
Knowledge is important but not as essential as health. |
|
||||||
|
|
||||||
We really wish all of you to stay safe and healthy at home. |
|
||||||
|
|
||||||
This is why we created a little guideline in how to conduct your audit from home. |
|
||||||
There is a video here : [youtube.com/watch?v=J8g8P-IJLJw](https://www.youtube.com/watch?v=J8g8P-IJLJw) |
|
||||||
|
|
||||||
But we are also going to summarize the process. |
|
||||||
So here we go. |
|
||||||
|
|
||||||
### Prerequisites for the team captain and the auditor |
|
||||||
|
|
||||||
- A program to communicate and livestream installed (like Discord [discordapp.com](https://discordapp.com/) ) |
|
||||||
- A program to allows the auditor to take charge of the computer |
|
||||||
of the team captain installed (like teamViewer [teamviewer.com](https://www.teamviewer.com/) ) |
|
||||||
|
|
||||||
### Prerequisite for the team captain |
|
||||||
|
|
||||||
The team captain must communicate : |
|
||||||
|
|
||||||
- The contact of his or her teammates to the auditor |
|
||||||
- The git repository of the project to be reviewed (the link must be public or accessible for the auditor) |
|
||||||
- The team captain must be logged in in his or her session to allow the auditor to start its audit |
|
||||||
|
|
||||||
### Prerequisite for the auditor |
|
||||||
|
|
||||||
- The auditor will need to create the group on the communication program |
|
||||||
- The auditor will need to download the project repository |
|
||||||
- The auditor, if the internet bandwith allows it, will livestream the process |
|
||||||
|
|
||||||
### Instructions |
|
||||||
|
|
||||||
1. Let the auditor establish the communication with the group members and the captain. |
|
||||||
|
|
||||||
2. Once all prequisites are done from the team captain and the auditor let the audit begin. |
|
||||||
|
|
||||||
3. If possible, the auditor starts the stream. |
|
||||||
|
|
||||||
4. The captain, after checking that the login is done on his or her computer, allows the auditor |
|
||||||
to take control of its computer (with teamViewer for example) |
|
||||||
|
|
||||||
5. The auditor now has the control to start the audit on the computer of the captain. |
|
||||||
The organization of the windows by the auditor might be the tricky part. We suggest |
|
||||||
to see how we did it in the video if you find it difficult. |
|
||||||
|
|
||||||
6. The auditor conducts the audit, if the auditor can not live stream its audits, he or she |
|
||||||
will then explain by voice (or writing in the chat) what he or she is doing to the rest of the group. |
|
||||||
|
|
||||||
7. The audit is conducted until all questions are validated or until a mistake is made. |
|
||||||
|
|
||||||
8. If a mistake is made the auditor can copy paste the commands that detected the mistakes. |
|
||||||
|
|
||||||
9. The group discusses as much as needed until the audit is completed. |
|
||||||
|
|
||||||
10. Once the audit is completed, all programs can be closed up. Say bye and thank you for your time and make the |
|
||||||
necessary conclusions among the members of the group. |
|
||||||
|
|
||||||
### Conclusion |
|
||||||
|
|
||||||
Thank you for reading until the end. Stay safe. |
|
||||||
|
|
||||||
### Bonus |
|
||||||
|
|
||||||
Did you know that there is a nice `Live Share` extension on `vscode`? |
|
||||||
This allows to do remote group programming easily. It might be an alternative solution |
|
||||||
to the livestream if necessary. |
|
||||||
Try it out! |
|
||||||
|
|
||||||
Stay safe everyone! Happy coding! |
|
@ -1,83 +0,0 @@ |
|||||||
## Как проводить аудиты удаленно |
|
||||||
|
|
||||||
Сначала небольшое напоминание, |
|
||||||
|
|
||||||
Аудиты, как мы неоднократно говорили, являются неотъемлемой частью вашего обучения и получения реальных навыков. |
|
||||||
|
|
||||||
Обычно они должны проводиться оффлайн. |
|
||||||
Идея состоит в том, что это способствует обмену знаний между аудиторами и членами группы. |
|
||||||
|
|
||||||
Если проект провалится, вся группа будет знать точную причину. И после того, как все ваши проверки будут выполнены, вы попытаетесь сдать еще раз, с новообретенными знаниями. |
|
||||||
Во время всех этих дополнительных проверок вы, как группа, будете обсуждать с аудиторами ваши недочеты. |
|
||||||
Если проект будет успешным, вы будете вдохновлять аудиторов. |
|
||||||
В любом случае вы будете либо учиться или либо учить кого-то. Роли учителя/ученика меняются почти каждый раз. |
|
||||||
|
|
||||||
Это, в конечном счете, те взаимодействия, которые необходимы для реального обучения; |
|
||||||
Давать и получать отзывы, а также видеть то, что ты действительно знаешь, а что нет. |
|
||||||
Это улучшит вашу способность решать проблемы, вашу способность адаптироваться, что является одним из наиболее важных навыков хорошего программиста. |
|
||||||
|
|
||||||
Сегодня мы снова должны адаптироваться ... |
|
||||||
Иметь знания конечно хорошо, но здоровье важнее. |
|
||||||
|
|
||||||
Мы действительно желаем всем вам оставаться дома в безопасности. |
|
||||||
|
|
||||||
Поэтому мы разработали небольшое руководство по проведению аудита из дома. |
|
||||||
Ссылка на видео: [youtube.com/watch?v=J8g8P-IJLJw](https://www.youtube.com/watch?v=J8g8P-IJLJw) |
|
||||||
|
|
||||||
Также, можете прочесть: |
|
||||||
|
|
||||||
### Необходимые вещи для коммуникации аудитора и капитана команды |
|
||||||
|
|
||||||
- Программы для коммуникации и стрима (Discord подойдет) |
|
||||||
- teamViewer или что-то похожее чтобы дать аудитору доступ к вашему компьютеру |
|
||||||
|
|
||||||
### Что нужно сделать капитану: |
|
||||||
|
|
||||||
- Собрать команду перед аудитом. |
|
||||||
- Дать аудитору доступ к git, либо сделав репу публичной, либо сделав аудитора коллаборатором |
|
||||||
- Залогиниться в платформе чтобы аудитор начал проверку |
|
||||||
|
|
||||||
### Что нужно сделать аудитору: |
|
||||||
|
|
||||||
- Договориться с командой на счет времени проверки |
|
||||||
- Скачать репу проекта |
|
||||||
- Стримить процесс проверки команде |
|
||||||
|
|
||||||
### Инструкции |
|
||||||
|
|
||||||
1. Аудитор договаривается на счет времени проверки с командой |
|
||||||
|
|
||||||
2. Как только все будет готово, начинает проверку |
|
||||||
|
|
||||||
3. Если возможно, аудитор запускает стрим, чтобы команда видела саму проверку. |
|
||||||
|
|
||||||
4. Капитан, зайдя на платформу, разрешает аудитору взять под контроль свой компьютер (TeamViewer) |
|
||||||
|
|
||||||
5. Теперь аудитор может запустить проверку на компьютере капитана. |
|
||||||
Организация окон со стороны аудитора может быть сложной частью. Мы предлагаем |
|
||||||
посмотреть видео, и узнать как мы это сделали. |
|
||||||
|
|
||||||
6. Аудитор проводит проверку, если аудитор не может в прямом эфире транслировать свою проверку, он или она |
|
||||||
затем объяснит голосом (или в чате), что он или она делает и как проверяет. |
|
||||||
|
|
||||||
7. Аудит проводится до тех пор, пока все вопросы не верны или пока не будет допущена ошибка. |
|
||||||
|
|
||||||
8. Если проект сломался на каком-либо тесте, аудитор может показать команде при каком тесте произошла ошибка. |
|
||||||
|
|
||||||
9. Группа обсуждает потенциальное место ошибки столько, сколько необходимо, до завершения аудита. |
|
||||||
|
|
||||||
10. После завершения аудита все программы могут быть закрыты. Скажите пока и спасибо за ваше время и сделайте |
|
||||||
необходимые выводы среди членов группы. |
|
||||||
|
|
||||||
### Conclusion |
|
||||||
|
|
||||||
Спасибо, что дочитали до конца. Оставайтесь в безопасности. |
|
||||||
|
|
||||||
### Bonus |
|
||||||
|
|
||||||
Знаете ли вы, что есть хорошее расширение `Live Share` в` vscode`? |
|
||||||
Это позволяет легко выполнять дистанционное групповое программирование. Это может быть альтернативным решением |
|
||||||
для прямого эфира, если это необходимо. |
|
||||||
Попробуйте! |
|
||||||
|
|
||||||
Будьте в безопасности! Удачного кодинга! |
|
@ -1,330 +0,0 @@ |
|||||||
# Grand Prix Go curriculum |
|
||||||
|
|
||||||
--- |
|
||||||
|
|
||||||
## Week One (Lundi 02/12/19 au DImanche 08/12/19) |
|
||||||
|
|
||||||
### Sprint 1 |
|
||||||
|
|
||||||
#### Introduction to shell |
|
||||||
|
|
||||||
Notions: basic usage and interaction with a command line terminal. |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- 1-2 `curl` with the GitHub api and Example of shell file | https://www.youtube.com/watch?v=A0Mqc215igw |
|
||||||
- 1-3 `touch`, `chmod` and `echo` | https://www.youtube.com/watch?v=21h-vsuXgDU |
|
||||||
- 1-4 `find` and `grep` | https://www.youtube.com/watch?v=7a1JSWHhJlM |
|
||||||
- 1-5 `cut`, `sed` and `tr` | https://www.youtube.com/watch?v=Nil7rVP3eMI |
|
||||||
- 1-6 `jq` and `wc` | https://www.youtube.com/watch?v=cQmcaOseuiA& |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- introduction | https://public.01-edu.org/subjects/introduction.en |
|
||||||
- make-it-better | https://public.01-edu.org/subjects/make-it-better.en |
|
||||||
- to-git-or-not-to-git | https://public.01-edu.org/subjects/to-git-or-not-to-git.en |
|
||||||
- who-are-you | https://public.01-edu.org/subjects/who-are-you.en |
|
||||||
- cl-camp1 | https://public.01-edu.org/subjects/cl-camp1.en |
|
||||||
- cl-camp2 | https://public.01-edu.org/subjects/cl-camp2.en |
|
||||||
- cl-camp3 | https://public.01-edu.org/subjects/cl-camp3.en |
|
||||||
- cl-camp4 | https://public.01-edu.org/subjects/cl-camp4.en |
|
||||||
- cl-camp5 | https://public.01-edu.org/subjects/cl-camp5.en |
|
||||||
- cl-camp6 | https://public.01-edu.org/subjects/cl-camp6.en |
|
||||||
- cl-camp7 | https://public.01-edu.org/subjects/cl-camp7.en |
|
||||||
- cl-camp8 | https://public.01-edu.org/subjects/cl-camp8.en |
|
||||||
- now-get-to-work | https://public.01-edu.org/subjects/now-get-to-work.en |
|
||||||
|
|
||||||
### Sprint 2 |
|
||||||
|
|
||||||
#### Introduction to Go Lang and basic programmation concepts |
|
||||||
|
|
||||||
Notions: Variables declaration, Loops, if and else statement, usage of z01.PrintRune function. |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- 02-01-If and Else Statements in Go | https://www.youtube.com/watch?v=rnF1_SfeGE4 |
|
||||||
- 02-02-ForLoops | https://www.youtube.com/watch?v=Bt47lx6q2-4 |
|
||||||
- 02-03-PrintRune function | https://www.youtube.com/watch?v=o8JrvI3jqoM |
|
||||||
- 02-04-Variables Declaration and ascii | https://www.youtube.com/watch?v=RCNOV8m0hJQ |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- printalphabet | https://public.01-edu.org/subjects/printalphabet.en |
|
||||||
- printreversealphabet | https://public.01-edu.org/subjects/printreversealphabet.en |
|
||||||
- prindigits | https://public.01-edu.org/subjects/printdigits.en |
|
||||||
- isnegative | https://public.01-edu.org/subjects/isnegative.en |
|
||||||
- printcomb | https://public.01-edu.org/subjects/printcomb.en |
|
||||||
- printcomb2 | https://public.01-edu.org/subjects/printcomb2.en |
|
||||||
- printnbr | https://public.01-edu.org/subjects/printnbr.en |
|
||||||
- printcombn | https://public.01-edu.org/subjects/printcombn.en |
|
||||||
|
|
||||||
### Sprint 3 |
|
||||||
|
|
||||||
#### Introduction to Go Lang and basic programmation concepts II |
|
||||||
|
|
||||||
Notions: String Manupulation, Range Loops, Pointers, Modulo and Division relative to computer science. |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- 03-01-StringsManipulation | https://www.youtube.com/watch?v=8LplJN_8iOU |
|
||||||
- 03-02-RangeLoop | https://www.youtube.com/watch?v=i89N4cjh1-g |
|
||||||
- 03-03-Pointers on variables | https://www.youtube.com/watch?v=owVPa5b1BMc |
|
||||||
- 03-04-Modulo and Division | https://www.youtube.com/watch?v=NVan-9-Ioec |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- pointone | https://public.01-edu.org/subjects/pointone.en |
|
||||||
- ultimatepointone | https://public.01-edu.org/subjects/ultimatepointone.en |
|
||||||
- divmod | https://public.01-edu.org/subjects/divmod.en |
|
||||||
- ultimatedivmod | https://public.01-edu.org/subjects/ultimatedivmod.en |
|
||||||
- printstr | https://public.01-edu.org/subjects/printstr.en |
|
||||||
- strlen | https://public.01-edu.org/subjects/strlen.en |
|
||||||
- swap | https://public.01-edu.org/subjects/swap.en |
|
||||||
- strrev | https://public.01-edu.org/subjects/strrev.en |
|
||||||
- basicatoi | https://public.01-edu.org/subjects/basicatoi.en |
|
||||||
- basicatoi2 | https://public.01-edu.org/subjects/basicatoi2.en |
|
||||||
- atoi | https://public.01-edu.org/subjects/atoi.en |
|
||||||
- sortintegerable | https://public.01-edu.org/subjects/sortintegertable.en |
|
||||||
|
|
||||||
### Checkpoint 1 (4hours) |
|
||||||
|
|
||||||
#### Basic functions and programs skills evaluation, based on Sprint 2 and Sprint 3 |
|
||||||
|
|
||||||
### CLM (Contre La Montre) 1 - Rectangle Drawing |
|
||||||
|
|
||||||
#### First Group project. Problem resolution. Usage of first knowledge (loop and if/else) |
|
||||||
|
|
||||||
--- |
|
||||||
|
|
||||||
## Week Two (Lundi 09/12/2019 à Dimanche 15/12/2019) |
|
||||||
|
|
||||||
### Sprint 4 |
|
||||||
|
|
||||||
#### Algorithm concepts |
|
||||||
|
|
||||||
Notions: Iterative and recursive programmation |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- 04-01-Iterativity and Recursivity | https://www.youtube.com/watch?v=oCZDdAID5Ik |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- iterativefactorial | https://public.01-edu.org/subjects/iterativefactorial.en |
|
||||||
- recursivefactorial | https://public.01-edu.org/subjects/recursivefactorial.en |
|
||||||
- iterativepower | https://public.01-edu.org/subjects/iterativepower.en |
|
||||||
- recursivepower | https://public.01-edu.org/subjects/recursivepower.en |
|
||||||
- fibonacci | https://public.01-edu.org/subjects/fibonacci.en |
|
||||||
- sqrt | https://public.01-edu.org/subjects/sqrt.en |
|
||||||
- isprime | https://public.01-edu.org/subjects/isprime.en |
|
||||||
- findnextprime | https://public.01-edu.org/subjects/findnextprime.en |
|
||||||
- eightqueens | https://public.01-edu.org/subjects/eightqueens.en |
|
||||||
|
|
||||||
### Sprint 5 |
|
||||||
|
|
||||||
#### Application of previously viewed concepts. |
|
||||||
|
|
||||||
Notions: String Manipulation and medium-advanced algorithms |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- 05-01-Runes, Bytes and Strings | https://www.youtube.com/watch?v=-eIU5ISID64 |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- firstrune | https://public.01-edu.org/subjects/firstrune.en |
|
||||||
- nrune | https://public.01-edu.org/subjects/nrune.en |
|
||||||
- lastrune | https://public.01-edu.org/subjects/lastrune.en |
|
||||||
- index | https://public.01-edu.org/subjects/index.en |
|
||||||
- compare | https://public.01-edu.org/subjects/compare.en |
|
||||||
- toupper | https://public.01-edu.org/subjects/toupper.en |
|
||||||
- tolower | https://public.01-edu.org/subjects/tolower.en |
|
||||||
- capitalize | https://public.01-edu.org/subjects/capitalize.en |
|
||||||
- isalpha | https://public.01-edu.org/subjects/isalpha.en |
|
||||||
- isnumeric | https://public.01-edu.org/subjects/isnumeric.en |
|
||||||
- islower | https://public.01-edu.org/subjects/islower.en |
|
||||||
- isupper | https://public.01-edu.org/subjects/isupper.en |
|
||||||
- isprintable | https://public.01-edu.org/subjects/isprintable.en |
|
||||||
- concat | https://public.01-edu.org/subjects/concat.en |
|
||||||
- basicjoin | https://public.01-edu.org/subjects/basicjoin.en |
|
||||||
- join | https://public.01-edu.org/subjects/join.en |
|
||||||
- printnbrbase | https://public.01-edu.org/subjects/printnbrbase.en |
|
||||||
- atoibase | https://public.01-edu.org/subjects/atoibase.en |
|
||||||
|
|
||||||
### Sprint 6 |
|
||||||
|
|
||||||
#### Usage of OS.Args |
|
||||||
|
|
||||||
Notions: Arguments manipulation in programs |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- 06-01-Os.Args | https://www.youtube.com/watch?v=I1xt_TLRhF0 |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- printprogramname | https://public.01-edu.org/subjects/printprogramname.en |
|
||||||
- printparams | https://public.01-edu.org/subjects/printparams.en |
|
||||||
- revparams | https://public.01-edu.org/subjects/revparams.en |
|
||||||
- sortparams | https://public.01-edu.org/subjects/sortparams.en |
|
||||||
|
|
||||||
### Sprint 7 |
|
||||||
|
|
||||||
#### The Memory Allocation in GoLang |
|
||||||
|
|
||||||
Notions: Usage of Make and Append |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- 07-01-Make and Append methods | https://www.youtube.com/watch?v=2HHVUM0YQuI |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- appendrange | https://public.01-edu.org/subjects/apprendrange.en |
|
||||||
- makerange | https://public.01-edu.org/subjects/makerange.en |
|
||||||
- concatparams | https://public.01-edu.org/subjects/concatparams.en |
|
||||||
- splitwhitespaces | https://public.01-edu.org/subjects/splitwhitespaces.en |
|
||||||
- printwordstables | https://public.01-edu.org/subjects/printwordstables.en |
|
||||||
- convertbase | https://public.01-edu.org/subjects/converbase.en |
|
||||||
- split | https://public.01-edu.org/subjects/split.en |
|
||||||
|
|
||||||
### Checkpoint 2 (4hours) |
|
||||||
|
|
||||||
#### Basic functions and programs skills evaluation, based on Sprint 2 and Sprint 6 |
|
||||||
|
|
||||||
### CLM (Contre La Montre) 2 - Sudoku |
|
||||||
|
|
||||||
#### Second Group project. Problem resolution. Usage of Memory manipulation tools |
|
||||||
|
|
||||||
--- |
|
||||||
|
|
||||||
## Week Three + Holiday project (Lundi 16/12/2019 à dimache 05/01/2020 ) |
|
||||||
|
|
||||||
### Sprint 8 |
|
||||||
|
|
||||||
#### Introduction to Structures and advanced types in GoLang |
|
||||||
|
|
||||||
Notions: Creation of struct types and file manipulation (Open, Read, Close methods) |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- 08-01-Structures in Go | https://www.youtube.com/watch?v=-24M7r7VuLY |
|
||||||
- 08-02-File Manipulation in go | https://www.youtube.com/watch?v=8vUgchQGhcQ |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- bool | https://public.01-edu.org/subjects/bool.en |
|
||||||
- point | https://public.01-edu.org/subjects/point.en |
|
||||||
- displayfile | https://public.01-edu.org/subjects/displayfile.en |
|
||||||
- cat | https://public.01-edu.org/subjects/cat.en |
|
||||||
- ztail | https://public.01-edu.org/subjects/ztail.en |
|
||||||
|
|
||||||
### Sprint 9 |
|
||||||
|
|
||||||
#### Functions as argument |
|
||||||
|
|
||||||
Notions: Advance function prototyping |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- 09-01-Functions as Arguments | https://www.youtube.com/watch?v=lw8jUwsluAE |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- foreach | https://public.01-edu.org/subjects/foreach.en |
|
||||||
- map | https://public.01-edu.org/subjects/map.en |
|
||||||
- any | https://public.01-edu.org/subjects/any.en |
|
||||||
- countif | https://public.01-edu.org/subjects/countif.en |
|
||||||
- issorted | https://public.01-edu.org/subjects/issorted.en |
|
||||||
- doop | https://public.01-edu.org/subjects/doop.en |
|
||||||
- sortwordarr | https://public.01-edu.org/subjects/sortwordarr.en |
|
||||||
- advancedsortwordarr | https://public.01-edu.org/subjects/advancedsortwordarr.en |
|
||||||
|
|
||||||
### Sprint 10 |
|
||||||
|
|
||||||
#### Hackathon |
|
||||||
|
|
||||||
Notions: All previously viewed concepts in team work |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- rot14 | https://public.01-edu.org/subjects/rot14.en |
|
||||||
- abort | https://public.01-edu.org/subjects/abort.en |
|
||||||
- collatzcountdown | https://public.01-edu.org/subjects/collatzcountdown.en |
|
||||||
- comcheck | https://public.01-edu.org/subjects/comcheck.en |
|
||||||
- enigma | https://public.01-edu.org/subjects/enigma.en |
|
||||||
- pilot | https://public.01-edu.org/subjects/pilot.en |
|
||||||
- fixthemain | https://public.01-edu.org/subjects/fixthemain.en |
|
||||||
- compact | https://public.01-edu.org/subjects/compact.en |
|
||||||
- activebits | https://public.01-edu.org/subjects/activebits.en |
|
||||||
- max | https://public.01-edu.org/subjects/max.en |
|
||||||
- join | https://public.01-edu.org/subjects/join.en |
|
||||||
- unmatch | https://public.01-edu.org/subjects/unmatch.en |
|
||||||
|
|
||||||
### Checkpoint 3 (4hours) |
|
||||||
|
|
||||||
#### Basic functions and programs skills evaluation, based on Sprint 2 and Sprint 8 |
|
||||||
|
|
||||||
### CLM (Contre La Montre) 3 - File Reader ( Projet pour les 2 semaines de vacances) |
|
||||||
|
|
||||||
#### Second Group project. Problem resolution. File manipulation based on CLM (Contre La Montre) 1 |
|
||||||
|
|
||||||
--- |
|
||||||
|
|
||||||
## Week Four (lundi 06/01/2020 à vendredi 10/01/2020) |
|
||||||
|
|
||||||
### Sprint 11 |
|
||||||
|
|
||||||
#### Linked lists in GoLang |
|
||||||
|
|
||||||
Notions: Pointers manipulation and data structure |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- 11-01-Linked Lists Introduction | https://www.youtube.com/watch?v=EPICVEbylU0 |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- listpushback | https://public.01-edu.org/subjects/listpushback.en |
|
||||||
- listpushfront | https://public.01-edu.org/subjects/listpushfront.en |
|
||||||
- listsize | https://public.01-edu.org/subjects/listsize.en |
|
||||||
- listlast | https://public.01-edu.org/subjects/listlast.en |
|
||||||
- listclear | https://public.01-edu.org/subjects/listclear.en |
|
||||||
- listat | https://public.01-edu.org/subjects/listat.en |
|
||||||
- listreverse | https://public.01-edu.org/subjects/listreverse.en |
|
||||||
- listforeach | https://public.01-edu.org/subjects/listforeach.en |
|
||||||
- listforeachif | https://public.01-edu.org/subjects/listforeachif.en |
|
||||||
- listfind | https://public.01-edu.org/subjects/listfind.en |
|
||||||
- listremoveif | https://public.01-edu.org/subjects/listremoveif.en |
|
||||||
- listmerge | https://public.01-edu.org/subjects/listmerge.en |
|
||||||
- listsort | https://public.01-edu.org/subjects/listsort.en |
|
||||||
- sortlistinsert | https://public.01-edu.org/subjects/sortlistinsert.en |
|
||||||
- sortedlistmerge | https://public.01-edu.org/subjects/sortedlistmerge.en |
|
||||||
|
|
||||||
### Sprint 12 |
|
||||||
|
|
||||||
#### Binary Trees |
|
||||||
|
|
||||||
Notions: Advanced Data Structure using binary trees |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- 12-01-Introduction to Binary Trees | https://www.youtube.com/watch?v=3g2WCqWNIVs |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- btreeinsertdata | https://public.01-edu.org/subjects/btreeinsertdata.en |
|
||||||
- btreeapplyinorder | https://public.01-edu.org/subjects/btreeapplyinorder.en |
|
||||||
- btreeapplypreorder | https://public.01-edu.org/subjects/btreeapplypreorder.en |
|
||||||
- btreesearchitem | https://public.01-edu.org/subjects/btreesearchitem.en |
|
||||||
- btreelevelcount | https://public.01-edu.org/subjects/btreelevelcount.en |
|
||||||
- btreeisbinary | https://public.01-edu.org/subjects/btreeisbinary.en |
|
||||||
- btreeapplylevel | https://public.01-edu.org/subjects/btreeapplylevel.en |
|
||||||
- btreemax | https://public.01-edu.org/subjects/btreemax.en |
|
||||||
- btreemin | https://public.01-edu.org/subjects/btreemin.en |
|
||||||
- btreetransplant | https://public.01-edu.org/subjects/btreetransplant.en |
|
||||||
- btreedeletenode | https://public.01-edu.org/subjects/btreedeletenode.en |
|
||||||
|
|
||||||
### Checkpoint 4 - Final Checkpoint (8hours) |
|
||||||
|
|
||||||
#### Functions and programs skills evaluation, based on Sprint 2 and Sprint 11 |
|
@ -1,65 +0,0 @@ |
|||||||
## Metrics card - Export of students' results |
|
||||||
|
|
||||||
### Where to find the data |
|
||||||
|
|
||||||
Metrics for students from a given campus can be found in the Metrics card in the Admin dashboard. |
|
||||||
|
|
||||||
### Important information |
|
||||||
|
|
||||||
- Data can be exported in csv and json formats |
|
||||||
- Data is filtered by campus, exports include all historical data for that campus. |
|
||||||
- We will later develop a feature that enables filtering information before downloading it |
|
||||||
- Data is updated every hour |
|
||||||
- The download link is valid for 24 hours |
|
||||||
- We recommend sharing the downloaded document itself instead of the download link as the link contains the admin’s authorisation token |
|
||||||
|
|
||||||
### Description of the data included in the exports |
|
||||||
|
|
||||||
| Field | Example | Description | |
|
||||||
| --------------- | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
|
||||||
| **user** | MarieMalarme | Student’s github username | |
|
||||||
| **first_name** | Marie | Student’s first name | |
|
||||||
| **last_name** | Malarme | Student’s last name | |
|
||||||
| **object** | who-are-you | Name of the object for which a result is given | |
|
||||||
| **type** | exercise | There are 3 object types: <br/> - exercise (for quests and exams) <br/> - raid <br/> - project | |
|
||||||
| **parent** | Quest 01 | The object’s hierarchical parent: <br/> - If the object is an exercise, the parent will be either a quest or an exam. <br/> - If the object is a raid or a project, the parent will be the module (piscine or div) | |
|
||||||
| **module** | piscine-go | The part of the curriculum in which the object is included, either a piscine (piscine Go, piscine JS, piscine Rust) or the main curriculum (Div01) | |
|
||||||
| **path** | /madere/piscine-go/quest-01/who-are-you | The url to that object, which outlines the path and hence the hierarchical structure to that object | |
|
||||||
| **attempts** | 2 | Number of submission attempts made by the student | |
|
||||||
| **status** | succeeded | Current status of the student's work on the object: <br/> - "available" indicates that the student has started working on the object but either hasn't submitted it yet to be corrected, or is waiting for the auditing process to be completed <br/> - "succeeded" and "failed" are attributed once the object has been corrected | |
|
||||||
| **xp** | 325 | Number of XPs gained by the student for succeeding | |
|
||||||
| **base_xp** | 325 | Maximum number of XPs the student can get for succeeding for that object | |
|
||||||
| **grade** | 1 | The student’s score for that object is a number between 0 (failed) and 1 (succeeded). If the object is a project, the grade can be superior to 1 when the student successfully passes bonus questions | |
|
||||||
| **last_update** | 2020-07-27T15:39:46.368Z | Date and time of the student’s latest activity for that object | |
|
||||||
|
|
||||||
### Explanation of the XP and Grade calculation |
|
||||||
|
|
||||||
#### Exercises within quests |
|
||||||
|
|
||||||
- _Test mode_: automatic tester |
|
||||||
- _XPs_: fixed value. Students get all the points when succeeding at the exercise, no matter how many attempts they made. |
|
||||||
- _Grade_: 0 (failure) or 1 (success) |
|
||||||
|
|
||||||
#### Exercises within exams |
|
||||||
|
|
||||||
- _Contextual information_: |
|
||||||
- Exams consist of many exercises which are grouped by difficulty levels. The student is randomly assigned an exercise from each level and has to succeed in order to move on to the next exercise level. |
|
||||||
- Each exercise level has a maximum amount of XPs which grows according to the level’s difficulty. |
|
||||||
- Exams are limited in time so students have to successfully complete as many exams as they can as fast as they can with the least amount of errors. |
|
||||||
- _Test mode_: automatic tester |
|
||||||
- _XPs_: variable value. Students get the maximum amount of points when they succeed at the first attempt. Each failed submission reduces the amount of XPs the student can get for that level. |
|
||||||
- _Grade_: 0 (failure) or 1 (success) |
|
||||||
|
|
||||||
#### Raids |
|
||||||
|
|
||||||
- _Test mode_: projects are evaluated by a jury panel in 2 steps: |
|
||||||
- First the jury evaluates the code through an audit, a series of pass / fail questions to be answered by the auditor. Succeeding the audit gives students a certain amount of XPs. |
|
||||||
- The jury then interviews students and can decide to give them bonus / malus XPs based on their evaluation of the code and the students’ answers to their questions. |
|
||||||
- _XPs_: variable value calculated as a fixed value for succeeding the project plus / minus XPs attributed by the jury at their discretion |
|
||||||
- _Grade_: 0 (failure) or 1 (success) |
|
||||||
|
|
||||||
#### Projects |
|
||||||
|
|
||||||
- _Test mode_: audits, which are peer-to-peer evaluations based on a series of pass/fail questions to be answered by the auditor |
|
||||||
- _XPs_: variable value. Students can get more than the maximum value of XPs if they complete bonus exercises. They get no XPs at all if they fail at least one of the questions in the audit |
|
||||||
- _Grade_: number between 0 and 1, proportionate to the number of questions successfully passed in the audit. The grade can be higher than 1 if the student completed bonus exercises. |
|
@ -1,165 +0,0 @@ |
|||||||
# Object Attributes System |
|
||||||
|
|
||||||
> This document cover two notions, the edition of attributes and the impact it has relatively to the others Objects. |
|
||||||
|
|
||||||
## Edition of Attributes |
|
||||||
|
|
||||||
> There is no limit to how many attributes can be defined to an Object. |
|
||||||
|
|
||||||
In the "Object Attributes" section of the "Object Edit" Page, the first row is a form to create and append a new attribute. It requires two elements, the name of the attribute and its type (`String`, `Number`, `Boolean`, `Array`, `Object`, `Function`, `Null`). Click 'Add' to create the attribute. |
|
||||||
|
|
||||||
> Within a same Object, each attribute's name must be unique. |
|
||||||
|
|
||||||
Once created, the new attributes appears right below and the ability to associate a value to it is now available. Depending on the type of the attribute, the interface will vary. |
|
||||||
|
|
||||||
- String value input is type String. |
|
||||||
- Number value input is type Number. |
|
||||||
- Booleans value input appears as a switch, true by default. |
|
||||||
- Arrays and Objects content are hidable / showable via the "Show/Hide content" button on the right of the attribute. There is no limit on the depth of Object/Array, however, after a certain level, the interface will start to feel narrow. |
|
||||||
- String value input is type String. |
|
||||||
- Null will not display any input. |
|
||||||
- Function will offer to select from all available functions, save on select. |
|
||||||
|
|
||||||
Any attribute can be delete by clicking on the 'trash' icon on the right hand of it. |
|
||||||
|
|
||||||
Here an example of how the section looks like. |
|
||||||
![object-attributes](img/object-attributes.png) |
|
||||||
|
|
||||||
## Attributes and RelationShips |
|
||||||
|
|
||||||
When an attributes is set to an Object, other Objects, associated to this particular Object, will have access to it. Which means that, if an Object A is added as a child of an Object B, A will embed its attributes within the instance of B. |
|
||||||
|
|
||||||
Object's attributes follow a hierarchy when associated to an other Object. |
|
||||||
The **defaults attributes** of a child, the ones defined in the original Object are the weakest ones. A **children attribute** is applied to all the children and override the default attributes. Finally, **relation attribute** is the strongest one, it override Default Attributes and Children Attributes. |
|
||||||
|
|
||||||
When an object and its relationship are resolved, the three structures (`attrs`, `childrenAttrs`, `childAttrs`) are merged. |
|
||||||
|
|
||||||
The following json shows how the object would be represented: |
|
||||||
|
|
||||||
```json |
|
||||||
{ |
|
||||||
"children": { |
|
||||||
"printalphabet": { |
|
||||||
"duration": 3600, |
|
||||||
"xp": 800, |
|
||||||
"isBonus": true |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
``` |
|
||||||
|
|
||||||
Children |
|
||||||
![children](img/children.png) |
|
||||||
|
|
||||||
Child |
|
||||||
![child-capture](img/child-capture.png) |
|
||||||
|
|
||||||
## Detailed example |
|
||||||
|
|
||||||
Let's create a few `exercises` objects |
|
||||||
|
|
||||||
> swap |
|
||||||
|
|
||||||
```js |
|
||||||
{ |
|
||||||
"id": 12344, |
|
||||||
"title": "swap", |
|
||||||
"attrs": { |
|
||||||
"language": "go", |
|
||||||
"duration": 7200 |
|
||||||
} |
|
||||||
} |
|
||||||
``` |
|
||||||
|
|
||||||
> printalphabet |
|
||||||
|
|
||||||
```js |
|
||||||
{ |
|
||||||
"id": 12345, |
|
||||||
"title": "printalphabet-v2", |
|
||||||
"attrs": { |
|
||||||
"language": "go", |
|
||||||
"duration": 3600 |
|
||||||
} |
|
||||||
} |
|
||||||
``` |
|
||||||
|
|
||||||
We can now create a parent object that will reference them and link them. |
|
||||||
|
|
||||||
This allow you to specify the structuration of your pedagogical content. |
|
||||||
|
|
||||||
I'll make a quest that regroup those 2 exercises: |
|
||||||
|
|
||||||
> quest-03 |
|
||||||
|
|
||||||
```js |
|
||||||
{ |
|
||||||
"id": 12346, |
|
||||||
"title": "quest-03", |
|
||||||
"attrs": {}, |
|
||||||
"childrenAttrs": { |
|
||||||
"xp": 800, |
|
||||||
"duration": 4800, |
|
||||||
}, |
|
||||||
"children": { |
|
||||||
"printalphabet": { |
|
||||||
"ref": 12345, |
|
||||||
"index": 0, |
|
||||||
"attrs": { |
|
||||||
"duration": 7200 |
|
||||||
} |
|
||||||
}, |
|
||||||
"swap": { |
|
||||||
"ref": 12344, |
|
||||||
"index": 1, |
|
||||||
"attrs": {} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
``` |
|
||||||
|
|
||||||
All done, now when rendering an object, attributes are merged like so: |
|
||||||
|
|
||||||
> rendered quest object |
|
||||||
|
|
||||||
```js |
|
||||||
{ |
|
||||||
"id": 12346, |
|
||||||
"title": "quest-03", |
|
||||||
"attrs": {}, |
|
||||||
"children": { |
|
||||||
"printalphabet": { |
|
||||||
"ref": 12345, |
|
||||||
"index": 0, |
|
||||||
"attrs": { |
|
||||||
"language": "go", |
|
||||||
"xp": 800, |
|
||||||
"duration": 7200 |
|
||||||
} |
|
||||||
}, |
|
||||||
"swap": { |
|
||||||
"ref": 12344, |
|
||||||
"index": 1, |
|
||||||
"attrs": { |
|
||||||
"language": "go", |
|
||||||
"xp": 800, |
|
||||||
"duration": 4800 |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
``` |
|
||||||
|
|
||||||
First we apply the **default attributes** from the referenced object. |
|
||||||
|
|
||||||
> Here `duration` and `language` are applied. |
|
||||||
|
|
||||||
Then we apply the **children attributes** to every child. |
|
||||||
|
|
||||||
> In this case we override every `duration` to 4800 and add the new `xp` attribute. |
|
||||||
|
|
||||||
After that we apply the **relation attributes**, that are the most specific and as such, |
|
||||||
override all others attributes. |
|
||||||
|
|
||||||
> In this case only the `printalphabet` relation had attributes and so we apply |
|
||||||
> the given `duration` to the final merged object. |
|
@ -1,34 +0,0 @@ |
|||||||
# Objects Edition |
|
||||||
|
|
||||||
> Allow you to edit an object, see and manage its relations. |
|
||||||
|
|
||||||
## Page Composition |
|
||||||
|
|
||||||
![object-edit-overview](img/object-edit-overview.png) |
|
||||||
|
|
||||||
### Pin 1 |
|
||||||
|
|
||||||
- Link back to the "Objects" page ; |
|
||||||
- Editable name field, hit 'enter' or 'cmd + s' or click on the floppy-disk icon to save ; |
|
||||||
- Major dependencies visualisation, (where my object is used as a child), click the label to navigate to the dependence ; |
|
||||||
- External URL, this is an optional parameter, it's use to point at an other source of content or information needed by the object. We generaly use to point at a Git repository ; |
|
||||||
|
|
||||||
### Pin 2 |
|
||||||
|
|
||||||
- Delete Button, Warning there, it will destroy your object! ; |
|
||||||
- Type of your Object (`organisation`, `campus`, `onboarding`, `cursus`, `quest`, `exercise`), save on select ; |
|
||||||
- Status of your Object (`draft`, `online`, `offline`), save on select ; |
|
||||||
- The first and last name of the original author ; |
|
||||||
|
|
||||||
### Pin 3 |
|
||||||
|
|
||||||
- Object Attribute edition area, manage all the attributes relative to this Object. These attributes will be exposed to its relationship ; |
|
||||||
|
|
||||||
### Pin 4 |
|
||||||
|
|
||||||
- Object Children edition area ; |
|
||||||
- Children Attributes edition area, these attributes impact and overload all the following children. Works the same way as standard attributes ; |
|
||||||
- Add a child, allows to add a child to the children list, more information here -> [Object Child creation](object-child-creation.md) ; |
|
||||||
- Children List, allows you to reorganise, delete and edit child. Each child can be overload with its own attributes, the edition works the same way as the original attributes ; |
|
||||||
|
|
||||||
More informations about attribute overload system [here](object-attribute-system.md) |
|
@ -1,29 +0,0 @@ |
|||||||
# Objects |
|
||||||
|
|
||||||
> Allow you to create, manage and organize your pedagical and onboarding content. |
|
||||||
|
|
||||||
## Definition |
|
||||||
|
|
||||||
An Object is an highly customizable element, which can be use in many situations. We use it to compose cursuses and onboarding processes. |
|
||||||
Objects can be associated together and then share a vertical or horizontal relationship, which allows to build complex structure of multiple objects. |
|
||||||
|
|
||||||
It structure can be visualized in two parts. The first one is the definition of the object itself and attributes, called `attrs`. The second part is the definition of minor relationships, called `children` and attributes applied to them, called `childrenAttrs`. |
|
||||||
|
|
||||||
This is the minimal structure of an object: |
|
||||||
|
|
||||||
- name |
|
||||||
- type (`organisation`, `campus`, `onboarding`, `cursus`, `quest`, `exercise`) |
|
||||||
- status (`draft`, `online`, `offline`) |
|
||||||
- attrs {} |
|
||||||
- childrenAttrs {} |
|
||||||
- children {} |
|
||||||
|
|
||||||
## Browse Objects: |
|
||||||
|
|
||||||
To access your Objects, go to the admin dashboard and then click on the _manage object_ link within the "Object" card. |
|
||||||
|
|
||||||
![go-to-objects](img/go-to-objects.png) |
|
||||||
|
|
||||||
Objects are sorted by type in different sections. This page offer a search bar that allow you query the objects by name. In the top-right corner, click the _add a new object_ button to create a new object. Fill a name, select a type and click _create_ to validate your creation. You will be redirected to the Object Edition page (document is here). |
|
||||||
|
|
||||||
![all-object-page](img/all-object-page.png) |
|
@ -1,330 +0,0 @@ |
|||||||
# Piscine Go curriculum |
|
||||||
|
|
||||||
--- |
|
||||||
|
|
||||||
## Week One |
|
||||||
|
|
||||||
### Quest 1 |
|
||||||
|
|
||||||
#### Introduction to shell |
|
||||||
|
|
||||||
Notions: basic usage and interaction with a command line terminal. |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- [1-2](https://www.youtube.com/watch?v=A0Mqc215igw) `curl` with the GitHub api and Example of shell file |
|
||||||
- [1-3](https://www.youtube.com/watch?v=21h-vsuXgDU) `touch`, `chmod` and `echo` |
|
||||||
- [1-4](https://www.youtube.com/watch?v=7a1JSWHhJlM) `find` and `grep` |
|
||||||
- [1-5](https://www.youtube.com/watch?v=Nil7rVP3eMI) `cut`, `sed` and `tr` |
|
||||||
- [1-6](https://www.youtube.com/watch?v=cQmcaOseuiA&) `jq` and `wc` |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- [introduction](https://github.com/01-edu/public/tree/master/subjects/introduction/README.md) |
|
||||||
- [make-it-better](https://github.com/01-edu/public/tree/master/subjects/make-it-better/README.md) |
|
||||||
- [to-git-or-not-to-git](https://github.com/01-edu/public/tree/master/subjects/to-git-or-not-to-git/README.md) |
|
||||||
- [who-are-you](https://github.com/01-edu/public/tree/master/subjects/who-are-you/README.md) |
|
||||||
- [cl-camp1](https://github.com/01-edu/public/tree/master/subjects/cl-camp1/README.md) |
|
||||||
- [cl-camp2](https://github.com/01-edu/public/tree/master/subjects/cl-camp2/README.md) |
|
||||||
- [cl-camp3](https://github.com/01-edu/public/tree/master/subjects/cl-camp3/README.md) |
|
||||||
- [cl-camp4](https://github.com/01-edu/public/tree/master/subjects/cl-camp4/README.md) |
|
||||||
- [cl-camp5](https://github.com/01-edu/public/tree/master/subjects/cl-camp5/README.md) |
|
||||||
- [cl-camp6](https://github.com/01-edu/public/tree/master/subjects/cl-camp6/README.md) |
|
||||||
- [cl-camp7](https://github.com/01-edu/public/tree/master/subjects/cl-camp7/README.md) |
|
||||||
- [cl-camp8](https://github.com/01-edu/public/tree/master/subjects/cl-camp8/README.md) |
|
||||||
- [now-get-to-work](https://github.com/01-edu/public/tree/master/subjects/now-get-to-work/README.md) |
|
||||||
|
|
||||||
### Quest 2 |
|
||||||
|
|
||||||
#### Introduction to Go Lang and basic programmation concepts |
|
||||||
|
|
||||||
Notions: Variables declaration, Loops, if and else statement, usage of z01.PrintRune function. |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- [02-01-If](https://www.youtube.com/watch?v=rnF1_SfeGE4) and Else Statements in Go |
|
||||||
- [02-02-ForLoops](https://www.youtube.com/watch?v=Bt47lx6q2-4) |
|
||||||
- [02-03-PrintRune](https://www.youtube.com/watch?v=o8JrvI3jqoM) function |
|
||||||
- [02-04-Variables](https://www.youtube.com/watch?v=RCNOV8m0hJQ) Declaration and ascii |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- [printalphabet](https://github.com/01-edu/public/tree/master/subjects/printalphabet/README.md) |
|
||||||
- [printreversealphabet](https://github.com/01-edu/public/tree/master/subjects/printreversealphabet/README.md) |
|
||||||
- [prindigits](https://github.com/01-edu/public/tree/master/subjects/printdigits/README.md) |
|
||||||
- [isnegative](https://github.com/01-edu/public/tree/master/subjects/isnegative/README.md) |
|
||||||
- [printcomb](https://github.com/01-edu/public/tree/master/subjects/printcomb/README.md) |
|
||||||
- [printcomb2](https://github.com/01-edu/public/tree/master/subjects/printcomb2/README.md) |
|
||||||
- [printnbr](https://github.com/01-edu/public/tree/master/subjects/printnbr/README.md) |
|
||||||
- [printcombn](https://github.com/01-edu/public/tree/master/subjects/printcombn/README.md) |
|
||||||
|
|
||||||
### Quest 3 |
|
||||||
|
|
||||||
#### Introduction to Go Lang and basic programmation concepts II |
|
||||||
|
|
||||||
Notions: String Manupulation, Range Loops, Pointers, Modulo and Division relative to computer science. |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- [03-01-StringsManipulation](https://www.youtube.com/watch?v=8LplJN_8iOU) |
|
||||||
- [03-02-RangeLoop](https://www.youtube.com/watch?v=i89N4cjh1-g) |
|
||||||
- [03-03-Pointers](https://www.youtube.com/watch?v=owVPa5b1BMc) on variables |
|
||||||
- [03-04-Modulo](https://www.youtube.com/watch?v=NVan-9-Ioec) and Division |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- [pointone](https://github.com/01-edu/public/tree/master/subjects/pointone/README.md) |
|
||||||
- [ultimatepointone](https://github.com/01-edu/public/tree/master/subjects/ultimatepointone/README.md) |
|
||||||
- [divmod](https://github.com/01-edu/public/tree/master/subjects/divmod/README.md) |
|
||||||
- [ultimatedivmod](https://github.com/01-edu/public/tree/master/subjects/ultimatedivmod/README.md) |
|
||||||
- [printstr](https://github.com/01-edu/public/tree/master/subjects/printstr/README.md) |
|
||||||
- [strlen](https://github.com/01-edu/public/tree/master/subjects/strlen/README.md) |
|
||||||
- [swap](https://github.com/01-edu/public/tree/master/subjects/swap/README.md) |
|
||||||
- [strrev](https://github.com/01-edu/public/tree/master/subjects/strrev/README.md) |
|
||||||
- [basicatoi](https://github.com/01-edu/public/tree/master/subjects/basicatoi/README.md) |
|
||||||
- [basicatoi2](https://github.com/01-edu/public/tree/master/subjects/basicatoi2/README.md) |
|
||||||
- [atoi](https://github.com/01-edu/public/tree/master/subjects/atoi/README.md) |
|
||||||
- [sortintegerable](https://github.com/01-edu/public/tree/master/subjects/sortintegertable/README.md) |
|
||||||
|
|
||||||
### Exam 1 (4hours) |
|
||||||
|
|
||||||
#### Basic functions and programs skills evaluation, based on Quest 2 and Quest 3 |
|
||||||
|
|
||||||
### Raid 1 - Square Drawing |
|
||||||
|
|
||||||
#### First Group project. Problem resolution. Usage of first knowledge (loop and if/else) |
|
||||||
|
|
||||||
--- |
|
||||||
|
|
||||||
## Week Two |
|
||||||
|
|
||||||
### Quest 4 |
|
||||||
|
|
||||||
#### Algorithm concepts |
|
||||||
|
|
||||||
Notions: Iterative and recursive programmation |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- [04-01-Iterativity and Recursivity](https://www.youtube.com/watch?v=oCZDdAID5Ik) |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- [iterativefactorial](https://github.com/01-edu/public/tree/master/subjects/iterativefactorial/README.md) |
|
||||||
- [recursivefactorial](https://github.com/01-edu/public/tree/master/subjects/recursivefactorial/README.md) |
|
||||||
- [iterativepower](https://github.com/01-edu/public/tree/master/subjects/iterativepower/README.md) |
|
||||||
- [recursivepower](https://github.com/01-edu/public/tree/master/subjects/recursivepower/README.md) |
|
||||||
- [fibonacci](https://github.com/01-edu/public/tree/master/subjects/fibonacci/README.md) |
|
||||||
- [sqrt](https://github.com/01-edu/public/tree/master/subjects/sqrt/README.md) |
|
||||||
- [isprime](https://github.com/01-edu/public/tree/master/subjects/isprime/README.md) |
|
||||||
- [findnextprime](https://github.com/01-edu/public/tree/master/subjects/findnextprime/README.md) |
|
||||||
- [eightqueens](https://github.com/01-edu/public/tree/master/subjects/eightqueens/README.md) |
|
||||||
|
|
||||||
### Quest 5 |
|
||||||
|
|
||||||
#### Application of previously viewed concepts. |
|
||||||
|
|
||||||
Notions: String Manipulation and medium-advanced algorithms |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- [05-01-Runes](https://www.youtube.com/watch?v=-eIU5ISID64), Bytes and Strings |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- [firstrune](https://github.com/01-edu/public/tree/master/subjects/firstrune/README.md) |
|
||||||
- [nrune](https://github.com/01-edu/public/tree/master/subjects/nrune/README.md) |
|
||||||
- [lastrune](https://github.com/01-edu/public/tree/master/subjects/lastrune/README.md) |
|
||||||
- [index](https://github.com/01-edu/public/tree/master/subjects/index/README.md) |
|
||||||
- [compare](https://github.com/01-edu/public/tree/master/subjects/compare/README.md) |
|
||||||
- [toupper](https://github.com/01-edu/public/tree/master/subjects/toupper/README.md) |
|
||||||
- [tolower](https://github.com/01-edu/public/tree/master/subjects/tolower/README.md) |
|
||||||
- [capitalize](https://github.com/01-edu/public/tree/master/subjects/capitalize/README.md) |
|
||||||
- [isalpha](https://github.com/01-edu/public/tree/master/subjects/isalpha/README.md) |
|
||||||
- [isnumeric](https://github.com/01-edu/public/tree/master/subjects/isnumeric/README.md) |
|
||||||
- [islower](https://github.com/01-edu/public/tree/master/subjects/islower/README.md) |
|
||||||
- [isupper](https://github.com/01-edu/public/tree/master/subjects/isupper/README.md) |
|
||||||
- [isprintable](https://github.com/01-edu/public/tree/master/subjects/isprintable/README.md) |
|
||||||
- [concat](https://github.com/01-edu/public/tree/master/subjects/concat/README.md) |
|
||||||
- [basicjoin](https://github.com/01-edu/public/tree/master/subjects/basicjoin/README.md) |
|
||||||
- [join](https://github.com/01-edu/public/tree/master/subjects/join/README.md) |
|
||||||
- [printnbrbase](https://github.com/01-edu/public/tree/master/subjects/printnbrbase/README.md) |
|
||||||
- [atoibase](https://github.com/01-edu/public/tree/master/subjects/atoibase/README.md) |
|
||||||
|
|
||||||
### Quest 6 |
|
||||||
|
|
||||||
#### Usage of OS.Args |
|
||||||
|
|
||||||
Notions: Arguments manipulation in programs |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- [06-01-Os.Args](https://www.youtube.com/watch?v=I1xt_TLRhF0) |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- [printprogramname](https://github.com/01-edu/public/tree/master/subjects/printprogramname/README.md) |
|
||||||
- [printparams](https://github.com/01-edu/public/tree/master/subjects/printparams/README.md) |
|
||||||
- [revparams](https://github.com/01-edu/public/tree/master/subjects/revparams/README.md) |
|
||||||
- [sortparams](https://github.com/01-edu/public/tree/master/subjects/sortparams/README.md) |
|
||||||
|
|
||||||
### Quest 7 |
|
||||||
|
|
||||||
#### The Memory Allocation in GoLang |
|
||||||
|
|
||||||
Notions: Usage of Make and Append |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- [07-01-Make](https://www.youtube.com/watch?v=2HHVUM0YQuI) and Append methods |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- [appendrange](https://github.com/01-edu/public/tree/master/subjects/apprendrange/README.md) |
|
||||||
- [makerange](https://github.com/01-edu/public/tree/master/subjects/makerange/README.md) |
|
||||||
- [concatparams](https://github.com/01-edu/public/tree/master/subjects/concatparams/README.md) |
|
||||||
- [splitwhitespaces](https://github.com/01-edu/public/tree/master/subjects/splitwhitespaces/README.md) |
|
||||||
- [printwordstables](https://github.com/01-edu/public/tree/master/subjects/printwordstables/README.md) |
|
||||||
- [convertbase](https://github.com/01-edu/public/tree/master/subjects/converbase/README.md) |
|
||||||
- [split](https://github.com/01-edu/public/tree/master/subjects/split/README.md) |
|
||||||
|
|
||||||
### Exam 2 (4hours) |
|
||||||
|
|
||||||
#### Basic functions and programs skills evaluation, based on all the quests from 2 to 6 |
|
||||||
|
|
||||||
### Raid 2 - Sudoku |
|
||||||
|
|
||||||
#### Second Group project. Problem resolution. Usage of Memory manipulation tools |
|
||||||
|
|
||||||
--- |
|
||||||
|
|
||||||
## Week Three |
|
||||||
|
|
||||||
### Quest 8 |
|
||||||
|
|
||||||
#### Introduction to Structures and advanced types in GoLang |
|
||||||
|
|
||||||
Notions: Creation of struct types and file manipulation (Open, Read, Close methods) |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- [08-01-Structures](https://www.youtube.com/watch?v=-24M7r7VuLY) in Go |
|
||||||
- [08-02-File](https://www.youtube.com/watch?v=8vUgchQGhcQ) Manipulation in go |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- [bool](https://github.com/01-edu/public/tree/master/subjects/bool/README.md) |
|
||||||
- [point](https://github.com/01-edu/public/tree/master/subjects/point/README.md) |
|
||||||
- [displayfile](https://github.com/01-edu/public/tree/master/subjects/displayfile/README.md) |
|
||||||
- [cat](https://github.com/01-edu/public/tree/master/subjects/cat/README.md) |
|
||||||
- [ztail](https://github.com/01-edu/public/tree/master/subjects/ztail/README.md) |
|
||||||
|
|
||||||
### Quest 9 |
|
||||||
|
|
||||||
#### Functions as argument |
|
||||||
|
|
||||||
Notions: Advance function prototyping |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- [09-01-Functions](https://www.youtube.com/watch?v=lw8jUwsluAE) as Arguments |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- [foreach](https://github.com/01-edu/public/tree/master/subjects/foreach/README.md) |
|
||||||
- [map](https://github.com/01-edu/public/tree/master/subjects/map/README.md) |
|
||||||
- [any](https://github.com/01-edu/public/tree/master/subjects/any/README.md) |
|
||||||
- [countif](https://github.com/01-edu/public/tree/master/subjects/countif/README.md) |
|
||||||
- [issorted](https://github.com/01-edu/public/tree/master/subjects/issorted/README.md) |
|
||||||
- [doop](https://github.com/01-edu/public/tree/master/subjects/doop/README.md) |
|
||||||
- [sortwordarr](https://github.com/01-edu/public/tree/master/subjects/sortwordarr/README.md) |
|
||||||
- [advancedsortwordarr](https://github.com/01-edu/public/tree/master/subjects/advancedsortwordarr/README.md) |
|
||||||
|
|
||||||
### Quest 10 |
|
||||||
|
|
||||||
#### Hackathon |
|
||||||
|
|
||||||
Notions: All previously viewed concepts in team work |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- [rot14](https://github.com/01-edu/public/tree/master/subjects/rot14/README.md) |
|
||||||
- [abort](https://github.com/01-edu/public/tree/master/subjects/abort/README.md) |
|
||||||
- [collatzcountdown](https://github.com/01-edu/public/tree/master/subjects/collatzcountdown/README.md) |
|
||||||
- [comcheck](https://github.com/01-edu/public/tree/master/subjects/comcheck/README.md) |
|
||||||
- [enigma](https://github.com/01-edu/public/tree/master/subjects/enigma/README.md) |
|
||||||
- [pilot](https://github.com/01-edu/public/tree/master/subjects/pilot/README.md) |
|
||||||
- [fixthemain](https://github.com/01-edu/public/tree/master/subjects/fixthemain/README.md) |
|
||||||
- [compact](https://github.com/01-edu/public/tree/master/subjects/compact/README.md) |
|
||||||
- [activebits](https://github.com/01-edu/public/tree/master/subjects/activebits/README.md) |
|
||||||
- [max](https://github.com/01-edu/public/tree/master/subjects/max/README.md) |
|
||||||
- [join](https://github.com/01-edu/public/tree/master/subjects/join/README.md) |
|
||||||
- [unmatch](https://github.com/01-edu/public/tree/master/subjects/unmatch/README.md) |
|
||||||
|
|
||||||
### Exam 3 (4hours) |
|
||||||
|
|
||||||
#### Basic functions and programs skills evaluation, based on all the quests from 2 to 8 |
|
||||||
|
|
||||||
### Raid 3 - File Reader |
|
||||||
|
|
||||||
#### Second Group project. Problem resolution. File manipulation based on Raid 1 |
|
||||||
|
|
||||||
--- |
|
||||||
|
|
||||||
## Week Four |
|
||||||
|
|
||||||
### Quest 11 |
|
||||||
|
|
||||||
#### Linked lists in GoLang |
|
||||||
|
|
||||||
Notions: Pointers manipulation and data structure |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- [11-01-Linked](https://www.youtube.com/watch?v=EPICVEbylU0) Lists Introduction |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- [listpushback](https://github.com/01-edu/public/tree/master/subjects/listpushback/README.md) |
|
||||||
- [listpushfront](https://github.com/01-edu/public/tree/master/subjects/listpushfront/README.md) |
|
||||||
- [listsize](https://github.com/01-edu/public/tree/master/subjects/listsize/README.md) |
|
||||||
- [listlast](https://github.com/01-edu/public/tree/master/subjects/listlast/README.md) |
|
||||||
- [listclear](https://github.com/01-edu/public/tree/master/subjects/listclear/README.md) |
|
||||||
- [listat](https://github.com/01-edu/public/tree/master/subjects/listat/README.md) |
|
||||||
- [listreverse](https://github.com/01-edu/public/tree/master/subjects/listreverse/README.md) |
|
||||||
- [listforeach](https://github.com/01-edu/public/tree/master/subjects/listforeach/README.md) |
|
||||||
- [listforeachif](https://github.com/01-edu/public/tree/master/subjects/listforeachif/README.md) |
|
||||||
- [listfind](https://github.com/01-edu/public/tree/master/subjects/listfind/README.md) |
|
||||||
- [listremoveif](https://github.com/01-edu/public/tree/master/subjects/listremoveif/README.md) |
|
||||||
- [listmerge](https://github.com/01-edu/public/tree/master/subjects/listmerge/README.md) |
|
||||||
- [listsort](https://github.com/01-edu/public/tree/master/subjects/listsort/README.md) |
|
||||||
- [sortlistinsert](https://github.com/01-edu/public/tree/master/subjects/sortlistinsert/README.md) |
|
||||||
- [sortedlistmerge](https://github.com/01-edu/public/tree/master/subjects/sortedlistmerge/README.md) |
|
||||||
|
|
||||||
### Quest 12 |
|
||||||
|
|
||||||
#### Binary Trees |
|
||||||
|
|
||||||
Notions: Advanced Data Structure using binary trees |
|
||||||
|
|
||||||
Videos: |
|
||||||
|
|
||||||
- [12-01-Introduction](https://www.youtube.com/watch?v=3g2WCqWNIVs) to Binary Trees |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- [btreeinsertdata](https://github.com/01-edu/public/tree/master/subjects/btreeinsertdata/README.md) |
|
||||||
- [btreeapplyinorder](https://github.com/01-edu/public/tree/master/subjects/btreeapplyinorder/README.md) |
|
||||||
- [btreeapplypreorder](https://github.com/01-edu/public/tree/master/subjects/btreeapplypreorder/README.md) |
|
||||||
- [btreesearchitem](https://github.com/01-edu/public/tree/master/subjects/btreesearchitem/README.md) |
|
||||||
- [btreelevelcount](https://github.com/01-edu/public/tree/master/subjects/btreelevelcount/README.md) |
|
||||||
- [btreeisbinary](https://github.com/01-edu/public/tree/master/subjects/btreeisbinary/README.md) |
|
||||||
- [btreeapplylevel](https://github.com/01-edu/public/tree/master/subjects/btreeapplylevel/README.md) |
|
||||||
- [btreemax](https://github.com/01-edu/public/tree/master/subjects/btreemax/README.md) |
|
||||||
- [btreemin](https://github.com/01-edu/public/tree/master/subjects/btreemin/README.md) |
|
||||||
- [btreetransplant](https://github.com/01-edu/public/tree/master/subjects/btreetransplant/README.md) |
|
||||||
- [btreedeletenode](https://github.com/01-edu/public/tree/master/subjects/btreedeletenode/README.md) |
|
||||||
|
|
||||||
### Exam 4 - Final Exam (8hours) |
|
||||||
|
|
||||||
#### Functions and programs skills evaluation, based on all the quests from 2 to 11 |
|
@ -1,150 +0,0 @@ |
|||||||
# Piscine Rust curriculum |
|
||||||
|
|
||||||
--- |
|
||||||
|
|
||||||
## Week One |
|
||||||
|
|
||||||
### Quest 01-rust |
|
||||||
|
|
||||||
Exercises: |
|
||||||
|
|
||||||
- fibonacci2 | https://github.com/01-edu/public/tree/master/subjects/fibonacci2 |
|
||||||
- scalar | https://github.com/01-edu/public/tree/master/subjects/scalar |
|
||||||
- temperature_conv | https://github.com/01-edu/public/tree/master/subjects/temperature_conv |
|
||||||
- looping | https://github.com/01-edu/public/tree/master/subjects/looping |
|
||||||
- speed_transformation | https://github.com/01-edu/public/tree/master/subjects/speed_transformation |
|
||||||
- groceries | https://github.com/01-edu/public/tree/master/subjects/groceries |
|
||||||
- reverse_string | https://github.com/01-edu/public/tree/master/subjects/reverse_string |
|
||||||
- find_factorial | https://github.com/01-edu/public/tree/master/subjects/find_factorial |
|
||||||
- matrix_transposition | https://github.com/01-edu/public/tree/master/subjects/matrix_transposition |
|
||||||
- division_and_remainder | https://github.com/01-edu/public/tree/master/subjects/division_and_remainder |
|
||||||
- tuples | https://github.com/01-edu/public/tree/master/subjects/tuples |
|
||||||
|
|
||||||
### Quest 02-rust |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- ownership | https://github.com/01-edu/public/tree/master/subjects/ownership |
|
||||||
- copy | https://github.com/01-edu/public/tree/master/subjects/copy |
|
||||||
- borrow | https://github.com/01-edu/public/tree/master/subjects/borrow |
|
||||||
- doubtful | https://github.com/01-edu/public/tree/master/subjects/doubtful |
|
||||||
- borrow_me_the_reference | https://github.com/01-edu/public/tree/master/subjects/borrow_me_the_reference |
|
||||||
- changes | https://github.com/01-edu/public/tree/master/subjects/changes |
|
||||||
- string_literals | https://github.com/01-edu/public/tree/master/subjects/string_literals |
|
||||||
- name_initials | https://github.com/01-edu/public/tree/master/subjects/name_initials |
|
||||||
- arrange_it | https://github.com/01-edu/public/tree/master/subjects/arrange_it |
|
||||||
- tic_tac_toe | https://github.com/01-edu/public/tree/master/subjects/tic_tac_toe |
|
||||||
|
|
||||||
### Quest 03-rust |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- circle | https://github.com/01-edu/public/tree/master/subjects/circle |
|
||||||
- card_deck | https://github.com/01-edu/public/tree/master/subjects/card_deck |
|
||||||
- arrays | https://github.com/01-edu/public/tree/master/subjects/arrays |
|
||||||
- strings | https://github.com/01-edu/public/tree/master/subjects/strings |
|
||||||
- edit_distance | https://github.com/01-edu/public/tree/master/subjects/edit_distance |
|
||||||
- to_url | https://github.com/01-edu/public/tree/master/subjects/to_url |
|
||||||
- capitalizing | https://github.com/01-edu/public/tree/master/subjects/capitalizing |
|
||||||
- hashing | https://github.com/01-edu/public/tree/master/subjects/hashing |
|
||||||
- string_permutation | https://github.com/01-edu/public/tree/master/subjects/string_permutation |
|
||||||
- bigger | https://github.com/01-edu/public/tree/master/subjects/bigger |
|
||||||
- simple_hash | https://github.com/01-edu/public/tree/master/subjects/simple_hash |
|
||||||
- collect | https://github.com/01-edu/public/tree/master/subjects/collect |
|
||||||
|
|
||||||
--- |
|
||||||
|
|
||||||
## Week Two |
|
||||||
|
|
||||||
## Quest 04-rust |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- unwrap_or_expect | https://github.com/01-edu/public/tree/master/subjects/unwrap_or_expect |
|
||||||
- panic | https://github.com/01-edu/public/tree/master/subjects/panic |
|
||||||
- handling | https://github.com/01-edu/public/tree/master/subjects/handling |
|
||||||
- profanity_filter | https://github.com/01-edu/public/tree/master/subjects/profanity_filter |
|
||||||
- question_mark | https://github.com/01-edu/public/tree/master/subjects/question_mark |
|
||||||
- banner | https://github.com/01-edu/public/tree/master/subjects/banner |
|
||||||
- cipher | https://github.com/01-edu/public/tree/master/subjects/cipher |
|
||||||
- error_types | https://github.com/01-edu/public/tree/master/subjects/error_types |
|
||||||
- boxing_todo | https://github.com/01-edu/public/tree/master/subjects/boxing_todo |
|
||||||
|
|
||||||
## Quest 05-rust |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- middle_day | https://github.com/01-edu/public/tree/master/subjects/middle_day |
|
||||||
- does_it_fit | https://github.com/01-edu/public/tree/master/subjects/does_it_fit |
|
||||||
- macro_calculator | https://github.com/01-edu/public/tree/master/subjects/macro_calculator |
|
||||||
- shopping_mall | https://github.com/01-edu/public/tree/master/subjects/shopping_mall |
|
||||||
- expected_variable | https://github.com/01-edu/public/tree/master/subjects/expected_variable |
|
||||||
- mobs | https://github.com/01-edu/public/tree/master/subjects/mobs |
|
||||||
|
|
||||||
## Quest 06-rust |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- traits | https://github.com/01-edu/public/tree/master/subjects/traits |
|
||||||
- lifetimes | https://github.com/01-edu/public/tree/master/subjects/lifetimes |
|
||||||
- lalgebra_scalar | https://github.com/01-edu/public/tree/master/subjects/lalgebra_scalar |
|
||||||
- matrix | https://github.com/01-edu/public/tree/master/subjects/matrix |
|
||||||
- matrix_ops | https://github.com/01-edu/public/tree/master/subjects/matrix_ops |
|
||||||
- matrix_mult | https://github.com/01-edu/public/tree/master/subjects/matrix_mult |
|
||||||
- lalgebra_vector | https://github.com/01-edu/public/tree/master/subjects/lalgebra_vector |
|
||||||
- blood_types | https://github.com/01-edu/public/tree/master/subjects/blood_types |
|
||||||
- border_cross | https://github.com/01-edu/public/tree/master/subjects/border_cross |
|
||||||
- roman_numbers | https://github.com/01-edu/public/tree/master/subjects/roman_numbers |
|
||||||
- generics | https://github.com/01-edu/public/tree/master/subjects/generics |
|
||||||
- roman_numbers_iter | https://github.com/01-edu/public/tree/master/subjects/roman_numbers_iter |
|
||||||
- vectors_operations | https://github.com/01-edu/public/tree/master/subjects/vector_operations |
|
||||||
- events | https://github.com/01-edu/public/tree/master/subjects/events |
|
||||||
- delete_prefix | https://github.com/01-edu/public/tree/master/subjects/delete_prefix |
|
||||||
- commits_stats | https://github.com/01-edu/public/tree/master/subjects/commits_stats |
|
||||||
|
|
||||||
--- |
|
||||||
|
|
||||||
## Week Three |
|
||||||
|
|
||||||
## Quest 07-rust |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- box_it | https://github.com/01-edu/public/tree/master/subjects/box_it |
|
||||||
- borrow_box | https://github.com/01-edu/public/tree/master/subjects/borrow_box |
|
||||||
- box_recursion | https://github.com/01-edu/public/tree/master/subjects/box_recursion |
|
||||||
- how_many_references | https://github.com/01-edu/public/tree/master/subjects/how_many_references |
|
||||||
- ref_cell | https://github.com/01-edu/public/tree/master/subjects/ref_cell |
|
||||||
- drop_the_thread | https://github.com/01-edu/public/tree/master/subjects/drop_the_thread |
|
||||||
|
|
||||||
## Quest 08-rust |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- closures | https://github.com/01-edu/public/tree/master/subjects/closures |
|
||||||
- sales | https://github.com/01-edu/public/tree/master/subjects/sales |
|
||||||
- adding | https://github.com/01-edu/public/tree/master/subjects/adding |
|
||||||
- adding_twice | https://github.com/01-edu/public/tree/master/subjects/adding_twice |
|
||||||
- get_products | https://github.com/01-edu/public/tree/master/subjects/get_products |
|
||||||
- highest | https://github.com/01-edu/public/tree/master/subjects/highest |
|
||||||
- iterators | https://github.com/01-edu/public/tree/master/subjects/iterators |
|
||||||
- slices_to_map | https://github.com/01-edu/public/tree/master/subjects/slices_to_map |
|
||||||
- step_iterator | https://github.com/01-edu/public/tree/master/subjects/step_iterator |
|
||||||
- project_motion | https://github.com/01-edu/public/tree/master/subjects/project_motion |
|
||||||
|
|
||||||
## Quest 09-rust |
|
||||||
|
|
||||||
Exercices: |
|
||||||
|
|
||||||
- stars | https://github.com/01-edu/public/tree/master/subjects/stars |
|
||||||
- ordinal | https://github.com/01-edu/public/tree/master/subjects/ordinal |
|
||||||
- pangram | https://github.com/01-edu/public/tree/master/subjects/pangram |
|
||||||
- diamond_creation | https://github.com/01-edu/public/tree/master/subjects/diamond_creation |
|
||||||
- scores | https://github.com/01-edu/public/tree/master/subjects/scores |
|
||||||
- talking | https://github.com/01-edu/public/tree/master/subjects/talking |
|
||||||
- searching | https://github.com/01-edu/public/tree/master/subjects/searching |
|
||||||
- logic_number | https://github.com/01-edu/public/tree/master/subjects/logic_number |
|
||||||
- rot | https://github.com/01-edu/public/tree/master/subjects/rot |
|
||||||
- pig_latin | https://github.com/01-edu/public/tree/master/subjects/pig_latin |
|
||||||
- spelling | https://github.com/01-edu/public/tree/master/subjects/spelling |
|
||||||
- rgb_match | https://github.com/01-edu/public/tree/master/subjects/rgb_match |
|
@ -1,25 +0,0 @@ |
|||||||
# Server requirements (Minimum) |
|
||||||
|
|
||||||
Features required: |
|
||||||
|
|
||||||
- Dedicated hardware components (kept in **data centre** conditions) |
|
||||||
- Compatibility with **Linux (Debian x64)** |
|
||||||
|
|
||||||
| Component | Specification | |
|
||||||
| --------- | ---------------------------------------------------------------------------------- | |
|
||||||
| Processor | 8 threads x86-64 (64 bits), [2200 single thread performance](https://www.cpubenchmark.net/singleThread.html) / [1000 single-core score](https://browser.geekbench.com/processor-benchmarks) | |
|
||||||
| Memory | 16 GB DDR4 | |
|
||||||
| Storage | 2 x 500 GB SSD (`RAID 1` for _redundancy_ or `RAID 0` for _performance/capacity_) | |
|
||||||
|
|
||||||
# Server requirements (Recommended) |
|
||||||
|
|
||||||
Features required: |
|
||||||
|
|
||||||
- Dedicated hardware components (kept in **data centre** environment) |
|
||||||
- Compatibility with **Linux (Debian x64)** |
|
||||||
|
|
||||||
| Component | Specification | |
|
||||||
| --------- | ---------------------------------------------------------------------------------- | |
|
||||||
| Processor | 10 threads x86-64 (64 bits), [2600 single thread performance](https://www.cpubenchmark.net/singleThread.html) / [1200 single-core score](https://browser.geekbench.com/processor-benchmarks) | |
|
||||||
| Memory | 32 GB ECC DDR4 | |
|
||||||
| Storage | 2 x 500 GB SSD (`RAID 1` for _redundancy_ or `RAID 0` for _performance/capacity_) | |
|
@ -1,140 +0,0 @@ |
|||||||
# Addition of repository procedure |
|
||||||
|
|
||||||
## Introduction |
|
||||||
|
|
||||||
This document is a guide on how to add your own repository to store your projects and exercises. |
|
||||||
This guide assumes that you have understood the files structures of the repository [public](https://github.com/01-edu/public). |
|
||||||
It will only address the settings part of this task. |
|
||||||
The addition of projects will be treated first as it does not require the knowledge of Docker. |
|
||||||
|
|
||||||
However being familiar with Docker is **mandatory** for adding your own exercises with your own tests. |
|
||||||
|
|
||||||
## Prerequisites |
|
||||||
|
|
||||||
- A GitHub account where your exercises repository will be stored [https://github.com](https://github.com) |
|
||||||
- A Docker Hub account [https://hub.docker.com](https://hub.docker.com) |
|
||||||
|
|
||||||
## Setup of GitHub repository |
|
||||||
|
|
||||||
### Create your own public repository |
|
||||||
|
|
||||||
Once logged into your GitHub account, click on the creation of new repository: |
|
||||||
It is the button `New` (the button is on the top corner right side). |
|
||||||
|
|
||||||
### Git clone your repository and prepare an example for the folder structure for projects |
|
||||||
|
|
||||||
- Create a folder called `subjects`. |
|
||||||
- Inside this folder create a folder called what you wish (example: `firstproject`). |
|
||||||
- Inside the folder `firstproject` create a `README.md` file which you will use as the subject content of your first project. |
|
||||||
- After the subject content `README.md` is created, create a folder `audit` inside the `firstproject` directory. |
|
||||||
- Inside the `audit` folder create a `README.md` that respect the audit type of file. We advise you to take an example such as the |
|
||||||
ascii-art audit `README.md` file. Here is the [link](https://raw.githubusercontent.com/01-edu/public/master/subjects/ascii-art/audit/README.md) to the raw file. |
|
||||||
- Once all those files are done, git push them to your new repository. |
|
||||||
|
|
||||||
### Publish the repository on GitHub pages |
|
||||||
|
|
||||||
- Go to the settings tab of your projects repository. |
|
||||||
- On the option page find the GitHub Pages section. |
|
||||||
- Please see below the settings to follow. |
|
||||||
(Please not that it might take up to 10 mins for your page to be published) |
|
||||||
|
|
||||||
![screenshot 1](img/adding-exercises-repository/1.png) |
|
||||||
|
|
||||||
- You will notice that a message says Your site is published at “https://yourgithublogin.github.io/nameofyourrepo” |
|
||||||
|
|
||||||
### Configuration of Docker image (if exercises tests need to be added) |
|
||||||
|
|
||||||
The container runs with the following settings (options of `docker run`) : |
|
||||||
|
|
||||||
- `--read-only` |
|
||||||
- Mount the container's root filesystem as read only |
|
||||||
- `--network none` |
|
||||||
- Connect a container to a network without Internet |
|
||||||
- `--memory 500M` |
|
||||||
- Memory limit |
|
||||||
- `--cpus 2.0` |
|
||||||
- Number of CPUs |
|
||||||
- `--user 1000:1000` |
|
||||||
- Username or UID (format: <name|uid>[:<group|gid>]) |
|
||||||
- `--env EXERCISE=hello-world` |
|
||||||
- Exercise name |
|
||||||
- `--env USERNAME=aeinstein` |
|
||||||
- Student's login |
|
||||||
- `--env HOME=/jail` |
|
||||||
- Home directory of the container |
|
||||||
- `--env TMPDIR=/jail` |
|
||||||
- Temporary directory of the container |
|
||||||
- `--workdir /jail` |
|
||||||
- Working directory inside the container |
|
||||||
- `--tmpfs /jail:size=100M,noatime,exec,nodev,nosuid,uid=1000,gid=1000,nr_inodes=5k,mode=1700` |
|
||||||
- Mount a tmpfs directory on `/jail`, 100 MB writable. |
|
||||||
- `--volume volume_containing_student_repository:/jail/student:ro` |
|
||||||
- Bind mount a volume containing the student repository. |
|
||||||
|
|
||||||
Example of a [Dockerfile](https://github.com/01-edu/public/blob/master/js/tests/Dockerfile) and its [entrypoint](https://github.com/01-edu/public/blob/master/js/tests/entrypoint.sh). |
|
||||||
|
|
||||||
## The addition of a custom project |
|
||||||
|
|
||||||
**Take note of the paths of a project subject you added and add them to the attributes** |
|
||||||
|
|
||||||
Example: |
|
||||||
If user Frenchris, added an exercise to the nameofyourrepo called `firstproject` |
|
||||||
This is the path where the README.md subject would be. |
|
||||||
https://frenchris.github.io/nameofyourrepo/subjects/firstproject/ |
|
||||||
|
|
||||||
Note that you do not keep the README.md at the end of the path but you do keep the `/`. |
|
||||||
|
|
||||||
This path should be added to the attribute “subject” of type string in the object attribute of the new exercise. |
|
||||||
|
|
||||||
Additionally the README.md audit path would be. |
|
||||||
https://frenchris.github.io/nameofyourrepo/subjects/firstproject/audit/ |
|
||||||
|
|
||||||
This path should be added to the attribute “subject” of type string in the object attribute of the new exercise. |
|
||||||
|
|
||||||
- Once both those path are noted, create your project on your server. |
|
||||||
- Add the regular attributes (`groupMin`, `groupMax`, `language`, `exerciseType`). |
|
||||||
- Add the optional attributes to test if your wish (`auditsRatio`, `auditsRequired`) both set to 1. |
|
||||||
- And add the `audit` and `subject` attributes (of type `string`) with the previously noted paths. |
|
||||||
|
|
||||||
Now that the attributes are filled. |
|
||||||
|
|
||||||
- Create a module, called `Div-custom` for example. Add its standard attributes. |
|
||||||
- Add `firstproject` as a child to `Div-custom`. |
|
||||||
|
|
||||||
**Note**: If you do not wish students from other events to be selected for matches in this new event. |
|
||||||
in the children attributes of the module, |
|
||||||
|
|
||||||
- Add `matchWhere` as a `FUNCTION`. |
|
||||||
- Set its value to `USERINEVENT`. |
|
||||||
This attribute will isole the event during matches to the user of the event. |
|
||||||
- Add this `Div-custom` as a child in your campus object. |
|
||||||
- Go to event, and launch the event `yourcampus/Div-custom`. |
|
||||||
- Add yourself and other testing accounts to the newly launched event. |
|
||||||
- Test your subject by creating a group and launching an audit |
|
||||||
If the paths are correctly inputed and your repository is correctly publicly published on GitHub pages, you will see your subject and your audit in the platform. |
|
||||||
|
|
||||||
## Setup of your Docker repository |
|
||||||
|
|
||||||
1. Sign in your Docker Hub account and link it to your repository. |
|
||||||
2. In your account, go to your settings and link your GitHub account. |
|
||||||
3. Create a repository named “test” and make sure that your GitHub account is linked. |
|
||||||
If you see this image, |
|
||||||
![screenshot 2](img/adding-exercises-repository/2.png) |
|
||||||
It means your GitHub account is correctly linked. |
|
||||||
4. In the Builds tab configure the automated build settings as below (for the go tests). |
|
||||||
![screenshot 3](img/adding-exercises-repository/3.png) |
|
||||||
5. Once the build is complete (it can take 5 to 15 mins). Go back to the attributes of the exercise: |
|
||||||
- Add the attribute **testImage (type string)**. |
|
||||||
The `testImage` attribute is the name of the [Docker](https://docs.docker.com/get-started) image used to run the container responsible for testing the student's code. |
|
||||||
- Fill it with the name of the repository, |
|
||||||
**in this example: frenchris/test** |
|
||||||
6. Once your exercise has both the attributes completed correctly, the exercise is viable and can be tested on the server which was selected for its addition. |
|
||||||
7. As a reminder to test the exercise it is suggested to follow these steps: |
|
||||||
- `Create` a custom `Quest-test` object |
|
||||||
- `Adding` the new `exercise` object as a child to the newly created `Quest-test` object |
|
||||||
- `Create` a `Piscine-test` object |
|
||||||
- `Adding` the new `Quest-test` as a child to the newly created `Piscine-test` object |
|
||||||
- `Adding` the `Piscine-test` to the `campus` object as **first child** |
|
||||||
- Go to the event page and launch the newly created `Piscine-test`. (You may need to refresh the page 2-3 times before the `campus/Piscine-test` option appears) |
|
||||||
- Once the event is launched, use the event page to add yourself as a student in the launched event `Piscine-test` |
|
||||||
- You can now try the exercise. If everything is well set, the subject should be loaded and, when you submit a correct solution, the exercise should pass. |
|
@ -1,67 +0,0 @@ |
|||||||
# Ubuntu |
|
||||||
|
|
||||||
## OS Installation |
|
||||||
|
|
||||||
Download and boot the [latest Ubuntu release](https://releases.ubuntu.com/21.04/ubuntu-21.04-desktop-amd64.iso). |
|
||||||
|
|
||||||
Follow the steps with these customizations: |
|
||||||
|
|
||||||
![img1](img/ubuntu-installation/1.png) |
|
||||||
![img2](img/ubuntu-installation/2.png) |
|
||||||
![img3](img/ubuntu-installation/3.png) |
|
||||||
|
|
||||||
The partitioning is: |
|
||||||
|
|
||||||
1. 256 MB : EFI partition |
|
||||||
2. 20 GB : system partition |
|
||||||
|
|
||||||
![img4](img/ubuntu-installation/4.png) |
|
||||||
![img5](img/ubuntu-installation/5.png) |
|
||||||
|
|
||||||
Remove the installation disk and then reboot. |
|
||||||
|
|
||||||
Skip the welcoming window. |
|
||||||
|
|
||||||
Don't install updates if Ubuntu asks to. The scripts will. |
|
||||||
|
|
||||||
## Admin access |
|
||||||
|
|
||||||
You can add your public SSH key to access the administrator account later: |
|
||||||
|
|
||||||
```shell |
|
||||||
unset HISTFILE |
|
||||||
sudo mkdir /root/.ssh |
|
||||||
sudo wget github.com/xpetit.keys --output-document !$/authorized_keys |
|
||||||
sudo chmod 400 !$ |
|
||||||
``` |
|
||||||
|
|
||||||
## OS configuration |
|
||||||
|
|
||||||
Run a terminal and type these commands: |
|
||||||
|
|
||||||
```shell |
|
||||||
unset HISTFILE |
|
||||||
sudo apt -y install git |
|
||||||
git clone https://github.com/01-edu/public.git |
|
||||||
public/sh/debian/ubuntu/setup.sh |
|
||||||
``` |
|
||||||
|
|
||||||
The script will ask for student user password (which will be deleted after) and then after a long configuration process it will restart the computer. |
|
||||||
|
|
||||||
The system is now read-only, every data is written to a temporary partition. |
|
||||||
|
|
||||||
The session is password-less. |
|
||||||
|
|
||||||
To gain a superuser terminal, use SSH: |
|
||||||
|
|
||||||
```console |
|
||||||
user@remote:~$ ssh -p512 root@IP_ADDRESS |
|
||||||
``` |
|
||||||
|
|
||||||
To gain access with read/write access to the filesystem, use this command: |
|
||||||
|
|
||||||
```console |
|
||||||
root@ubuntu:~# overlayroot-chroot |
|
||||||
INFO: Chrooting into [/media/root-ro] |
|
||||||
root@ubuntu:/# |
|
||||||
``` |
|
@ -1,61 +0,0 @@ |
|||||||
# Ubuntu |
|
||||||
|
|
||||||
## OS Installation |
|
||||||
|
|
||||||
Install the latest version of [Virtual Box](https://www.virtualbox.org/wiki/Downloads). |
|
||||||
|
|
||||||
> The text instructions are more important than the screenshots |
|
||||||
|
|
||||||
Screenshots of the installation of Ubuntu in Virtual Box are [here](https://github.com/xpetit/vbox-ubuntu-install/blob/master/README.md). |
|
||||||
|
|
||||||
Download and boot the [last Ubuntu release](http://releases.ubuntu.com/19.10/ubuntu-19.10-desktop-amd64.iso). |
|
||||||
|
|
||||||
- Create a new virtual machine named "Ubuntu" with at least 4096 MB of RAM |
|
||||||
- Use the fixed size storage allocation (to have more performance) |
|
||||||
- In the settings of the VM |
|
||||||
- System -> Motherboard : check "Enable EFI" |
|
||||||
- System -> Processor : Select at least 2 processors |
|
||||||
- Display -> Screen : Put "Video Memory" to the maximum |
|
||||||
- Enable 3D acceleration |
|
||||||
- Storage |
|
||||||
- Remove IDE controller |
|
||||||
- Add Optical Drive to the SATA controller |
|
||||||
- Choose your Ubuntu ISO image |
|
||||||
- Close the settings (click OK) |
|
||||||
- Run the VM |
|
||||||
|
|
||||||
Follow the screenshots (some settings can be personalized, such as keyboard layout, location, password, login automatically, but **do not change the username**) |
|
||||||
|
|
||||||
Skip the welcoming window. |
|
||||||
|
|
||||||
Don't install updates if Ubuntu asks to. The scripts will. |
|
||||||
|
|
||||||
## OS customization |
|
||||||
|
|
||||||
You can overwrite the files of the folder `system` by setting an environment variable named `OVERWRITE` with the format : `Destination folder;Git URL`. |
|
||||||
|
|
||||||
For example to write the content of the repository [github.com/xpetit/custom](https://github.com/xpetit/custom) in the system folder : |
|
||||||
|
|
||||||
```shell |
|
||||||
export OVERWRITE='.;https://github.com/xpetit/custom.git' |
|
||||||
``` |
|
||||||
|
|
||||||
## OS configuration |
|
||||||
|
|
||||||
Run a terminal and type these commands : |
|
||||||
|
|
||||||
```shell |
|
||||||
unset HISTFILE |
|
||||||
sudo apt-get -y install git |
|
||||||
export PERSISTENT= |
|
||||||
git clone https://github.com/01-edu/public.git |
|
||||||
public/scripts/setup.sh |
|
||||||
``` |
|
||||||
|
|
||||||
After reboot you should install Virtual Box additions (and reboot again) : |
|
||||||
|
|
||||||
```shell |
|
||||||
sudo apt -y install virtualbox-guest-x11 |
|
||||||
``` |
|
||||||
|
|
||||||
Then it is advised to use the virtual machine in full screen mode (Host key - F) |
|
@ -1,39 +0,0 @@ |
|||||||
## Setup Guide |
|
||||||
|
|
||||||
This is a guide with all steps to install the Epic Games Launcher and Unreal Engine to get ready to work. |
|
||||||
|
|
||||||
First up you will need to register on [Epic Games](https://www.epicgames.com/id/register?redirect_uri=https%3A%2F%2Fwww.epicgames.com%2Fstore%2Fen-US%2F&client_id=875a3b57d3a640a6b7f9b4e883463ab4). |
|
||||||
|
|
||||||
Then depending on your operating system, you will need the following steps: |
|
||||||
|
|
||||||
### Windows |
|
||||||
|
|
||||||
- On the [Epic Games main page](https://www.epicgames.com/store/en-US/) click on the top right corner button (`Get Epic Games`). |
|
||||||
- A download pop up box should appear, then proceed to download the installer. |
|
||||||
- After going through all the steps to install the Epic Games Launcher, open it and sign in using your account. |
|
||||||
|
|
||||||
### Linux |
|
||||||
|
|
||||||
- First of all, install `wine` to run Windows programs on Linux systems. |
|
||||||
|
|
||||||
- If you have a 64-bit Linux system use: `sudo apt install wine64` |
|
||||||
- If you have a 32-bit Linux system use: `sudo apt install wine32` |
|
||||||
- Check if it is installed correctly with: `wine --version` |
|
||||||
|
|
||||||
- Then, install `Lutris` in order to download Epic Games with the following commands: |
|
||||||
|
|
||||||
```sh |
|
||||||
sudo add-apt-repository ppa:lutris-team/lutris |
|
||||||
sudo apt update |
|
||||||
sudo apt install lutris |
|
||||||
``` |
|
||||||
|
|
||||||
- After `Lutris` is installed, open it and on the top bar, search for `Epic Games` and you will see the result `Epic Games Store`. Go ahead and click on `install`. |
|
||||||
|
|
||||||
- After installing it, open it and sign in with your account. |
|
||||||
|
|
||||||
### Unreal Engine |
|
||||||
|
|
||||||
- Once the Epic Games Launcher is opened, go to the `Unreal Engine` tab and select the Library tab. |
|
||||||
- Click on the plus icon to add `Unreal Engine 4` and choose the version to install by clicking on the dropdown list. Then click on install. |
|
||||||
- After installing the Unreal Engine, you can click on `Launch` and prepare for the next adventure. |
|
@ -0,0 +1,45 @@ |
|||||||
|
export const tests = [] |
||||||
|
|
||||||
|
tests.push(async ({ eq, page }) => { |
||||||
|
// check the initial class name of the eye left
|
||||||
|
const eyeLeft = await page.$eval('#eye-left', (node) => node.className) |
||||||
|
eq(eyeLeft, 'eye') |
||||||
|
|
||||||
|
// check that the text of the button says 'close'
|
||||||
|
const buttonText = await page.$eval('button', (node) => node.textContent) |
||||||
|
eq(buttonText, 'Click to close the left eye') |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ eq, page }) => { |
||||||
|
// click the button to close the left eye
|
||||||
|
const button = await page.$('button') |
||||||
|
button.click() |
||||||
|
|
||||||
|
// check that the class has been added
|
||||||
|
await page.waitForSelector('#eye-left.eye.eye-closed', { timeout: 150 }) |
||||||
|
|
||||||
|
// check the background color has changed
|
||||||
|
await eq.$('#eye-left.eye.eye-closed', { |
||||||
|
style: { backgroundColor: 'black' }, |
||||||
|
}) |
||||||
|
|
||||||
|
// check that the text of the button changed to 'open'
|
||||||
|
await eq.$('button', { textContent: 'Click to open the left eye' }) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ eq, page }) => { |
||||||
|
// click the button a second time to open the left eye
|
||||||
|
const button = await page.$('button') |
||||||
|
button.click() |
||||||
|
|
||||||
|
// check that the class has been removed
|
||||||
|
await page.waitForSelector('#eye-left.eye:not(.eye-closed)', { timeout: 150 }) |
||||||
|
|
||||||
|
// check the background color has changed
|
||||||
|
await eq.$('#eye-left.eye:not(.eye-closed)', { |
||||||
|
style: { backgroundColor: 'red' }, |
||||||
|
}) |
||||||
|
|
||||||
|
// check that the text of the button changed to 'close'
|
||||||
|
await eq.$('button', { textContent: 'Click to close the left eye' }) |
||||||
|
}) |
@ -1,18 +0,0 @@ |
|||||||
export const tests = [] |
|
||||||
const t = (f) => tests.push(f) |
|
||||||
|
|
||||||
t(() => bloodySunday(new Date('0001-01-01')) === 'Monday') |
|
||||||
t(() => bloodySunday(new Date('0001-01-02')) === 'Tuesday') |
|
||||||
t(() => bloodySunday(new Date('0001-01-03')) === 'Wednesday') |
|
||||||
t(() => bloodySunday(new Date('0001-01-04')) === 'Thursday') |
|
||||||
t(() => bloodySunday(new Date('0001-01-05')) === 'Friday') |
|
||||||
t(() => bloodySunday(new Date('0001-01-06')) === 'Saturday') |
|
||||||
t(() => bloodySunday(new Date('0001-01-07')) === 'Monday') |
|
||||||
|
|
||||||
t(() => bloodySunday(new Date('0001-12-01')) === 'Friday') |
|
||||||
t(() => bloodySunday(new Date('1664-08-09')) === 'Saturday') |
|
||||||
|
|
||||||
t(() => bloodySunday(new Date('2020-01-01')) === 'Monday') |
|
||||||
t(() => bloodySunday(new Date('2048-12-08')) === 'Thursday') |
|
||||||
|
|
||||||
Object.freeze(tests) |
|
@ -0,0 +1,31 @@ |
|||||||
|
export const tests = [] |
||||||
|
|
||||||
|
tests.push(async ({ eq, page }) => { |
||||||
|
// check the class 'eye-closed' has been added in the CSS
|
||||||
|
eq.css('.eye-closed', { |
||||||
|
height: '4px', |
||||||
|
padding: '0px 5px', |
||||||
|
borderRadius: '10px', |
||||||
|
}) |
||||||
|
}) |
||||||
|
|
||||||
|
// tests.push(async ({ eq, page }) => {
|
||||||
|
// check the class of left eye before the JS is loaded
|
||||||
|
// await page.setJavaScriptEnabled(false)
|
||||||
|
// await page.reload()
|
||||||
|
// await eq.$('p#eye-left', { className: 'eye' })
|
||||||
|
// })
|
||||||
|
|
||||||
|
tests.push(async ({ eq, page }) => { |
||||||
|
// check the class of left eye has been updated after the JS is loaded
|
||||||
|
// await page.setJavaScriptEnabled(true)
|
||||||
|
// await page.reload()
|
||||||
|
await eq.$('p#eye-left', { className: 'eye eye-closed' }) |
||||||
|
|
||||||
|
// check the background color of left eye has changed after the JS is loaded
|
||||||
|
const eyeLeftBg = await page.$eval( |
||||||
|
'#eye-left', |
||||||
|
(node) => node.style.backgroundColor, |
||||||
|
) |
||||||
|
eq(eyeLeftBg, 'black') |
||||||
|
}) |
@ -0,0 +1,109 @@ |
|||||||
|
export const tests = [] |
||||||
|
|
||||||
|
export const setup = async ({ page }) => ({ |
||||||
|
getBricksIds: async () => |
||||||
|
await page.$$eval('div', (nodes) => |
||||||
|
nodes.filter((node) => node.id.includes('brick')).map((n) => n.id), |
||||||
|
), |
||||||
|
}) |
||||||
|
|
||||||
|
const between = (expected, min, max) => expected >= min && expected <= max |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check that the brick divs are built at a regular interval of 100ms
|
||||||
|
// the average of the divs built every 100ms must be close to 10
|
||||||
|
let repeat = 0 |
||||||
|
let buildSteps = [] |
||||||
|
|
||||||
|
while (repeat < 3) { |
||||||
|
const divs = await page.$$eval('div', (nodes) => nodes.length) |
||||||
|
console.log(`step ${repeat + 1}: ${divs} bricks`) |
||||||
|
buildSteps.push(divs) |
||||||
|
await page.waitForTimeout(1000) |
||||||
|
repeat++ |
||||||
|
} |
||||||
|
|
||||||
|
const diff1 = buildSteps[1] - buildSteps[0] |
||||||
|
const diff2 = buildSteps[2] - buildSteps[1] |
||||||
|
const average = Math.round((diff1 + diff2) / 2) |
||||||
|
|
||||||
|
if (average < 9) { |
||||||
|
console.log('average too low --> new bricks built / sec:', average) |
||||||
|
} else if (average > 11) { |
||||||
|
console.log('average too high --> new bricks built / sec:', average) |
||||||
|
} else { |
||||||
|
console.log('good average of new bricks built / sec') |
||||||
|
} |
||||||
|
|
||||||
|
eq(between(average, 9, 11), between(10, 9, 11)) |
||||||
|
}) |
||||||
|
|
||||||
|
const allBricksIds = [...Array(54).keys()].map((i) => `brick-${i + 1}`) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq, ctx }) => { |
||||||
|
// check that all the bricks are here and have the correct id
|
||||||
|
await page.waitForTimeout(3000) |
||||||
|
const bricksIds = await ctx.getBricksIds() |
||||||
|
eq(bricksIds, allBricksIds) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check that the middle column bricks have the `foundation` attribute to `true`
|
||||||
|
const expectedIds = allBricksIds.filter( |
||||||
|
(b) => b.replace('brick-', '') % 3 === 2, |
||||||
|
) |
||||||
|
const middleBricksIds = await page.$$eval('div', (nodes) => |
||||||
|
nodes |
||||||
|
.filter((node) => node.id.includes('brick') && node.dataset.foundation) |
||||||
|
.map((n) => n.id), |
||||||
|
) |
||||||
|
eq(middleBricksIds, expectedIds) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check that the bricks to repair have the right repaired attribute
|
||||||
|
const hammer = await page.$('#hammer') |
||||||
|
await hammer.click() |
||||||
|
|
||||||
|
const expectedRepairedIds = await page.$eval('body', (body) => { |
||||||
|
const getIdInt = (str) => str.replace('brick-', '') |
||||||
|
return body.dataset.reparations |
||||||
|
.split(',') |
||||||
|
.sort((a, b) => getIdInt(b) - getIdInt(a)) |
||||||
|
.map((id) => { |
||||||
|
const isMiddleBrick = getIdInt(id) % 3 === 2 |
||||||
|
const status = isMiddleBrick ? 'in progress' : 'repaired' |
||||||
|
return `${id}_${status}` |
||||||
|
}) |
||||||
|
}) |
||||||
|
|
||||||
|
const repairedIds = await page.$$eval('div', (nodes) => { |
||||||
|
const getIdInt = (str) => str.replace('brick-', '') |
||||||
|
return nodes |
||||||
|
.filter( |
||||||
|
(node) => |
||||||
|
node.dataset.repaired === 'true' || |
||||||
|
node.dataset.repaired === 'in progress', |
||||||
|
) |
||||||
|
.sort((a, b) => getIdInt(b.id) - getIdInt(a.id)) |
||||||
|
.map(({ id }) => { |
||||||
|
const isMiddleBrick = getIdInt(id) % 3 === 2 |
||||||
|
const status = isMiddleBrick ? 'in progress' : 'repaired' |
||||||
|
return `${id}_${status}` |
||||||
|
}) |
||||||
|
}) |
||||||
|
|
||||||
|
eq(repairedIds, expectedRepairedIds) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq, getBricksIds }) => { |
||||||
|
// check that the last brick is removed on each dynamite click
|
||||||
|
const dynamite = await page.$('#dynamite') |
||||||
|
|
||||||
|
for (const i of allBricksIds.keys()) { |
||||||
|
await dynamite.click() |
||||||
|
const { length } = allBricksIds |
||||||
|
const expectedRemainingBricks = allBricksIds.slice(0, length - (i + 1)) |
||||||
|
eq(await getBricksIds(), expectedRemainingBricks) |
||||||
|
} |
||||||
|
}) |
@ -0,0 +1,36 @@ |
|||||||
|
export const tests = [] |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check the class 'eye' has been declared properly in the CSS
|
||||||
|
eq.css('.eye', { |
||||||
|
width: '60px', |
||||||
|
height: '60px', |
||||||
|
backgroundColor: 'red', |
||||||
|
borderRadius: '50%', |
||||||
|
}) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check the class 'arm' has been declared properly in the CSS
|
||||||
|
eq.css('.arm', { backgroundColor: 'aquamarine' }) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check the class 'leg' has been declared properly in the CSS
|
||||||
|
eq.css('.leg', { backgroundColor: 'dodgerblue' }) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check the class 'body-member' has been declared properly in the CSS
|
||||||
|
eq.css('.body-member', { width: '50px', margin: '30px' }) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check that the targetted elements have the correct class names
|
||||||
|
await eq.$('p#eye-left', { className: 'eye' }) |
||||||
|
await eq.$('p#eye-right', { className: 'eye' }) |
||||||
|
await eq.$('div#arm-left', { className: 'arm body-member' }) |
||||||
|
await eq.$('div#arm-right', { className: 'arm body-member' }) |
||||||
|
await eq.$('div#leg-left', { className: 'leg body-member' }) |
||||||
|
await eq.$('div#leg-right', { className: 'leg body-member' }) |
||||||
|
}) |
@ -0,0 +1,71 @@ |
|||||||
|
import { colors } from '../subjects/fifty-shades-of-cold/fifty-shades-of-cold.data.js' |
||||||
|
|
||||||
|
colors.sort() |
||||||
|
|
||||||
|
const cold = ['aqua', 'blue', 'turquoise', 'green', 'purple', 'cyan', 'navy'] |
||||||
|
|
||||||
|
const isCold = color => cold.some(coldColor => color.includes(coldColor)) |
||||||
|
const toClass = (a, b) => `.${a} { background: ${b} }` |
||||||
|
const toDiv = (a, b) => `<div class="${a}">${b}</div>` |
||||||
|
|
||||||
|
export const tests = [] |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check that the css is properly generated
|
||||||
|
|
||||||
|
const style = await page.$$eval('style', nodes => nodes[1].innerHTML) |
||||||
|
const classes = style |
||||||
|
.split('}') |
||||||
|
.map(s => s.replace(/(\.|{|:|;|\s+)/g, '')) |
||||||
|
.filter(Boolean) |
||||||
|
.sort() |
||||||
|
|
||||||
|
for (const [i, c] of colors.entries()) { |
||||||
|
if (!classes[i]) throw Error(`Not enough class (expected: ${c})`) |
||||||
|
const [a, b] = classes[i].split('background') |
||||||
|
eq(toClass(a, b), toClass(c, c)) |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check that the divs are properly generated
|
||||||
|
|
||||||
|
const values = await page.$$eval('div', nodes => |
||||||
|
nodes.map(n => [n.className, n.textContent]), |
||||||
|
) |
||||||
|
const divs = values.map(v => toDiv(...v)).sort() |
||||||
|
|
||||||
|
let skipped = 0 |
||||||
|
for (const [i, c] of colors.entries()) { |
||||||
|
if (isCold(c)) { |
||||||
|
if (!values[i - skipped]) throw Error(`Not enough div (expected: ${c})`) |
||||||
|
eq(divs[i - skipped], toDiv(c, c)) |
||||||
|
continue |
||||||
|
} |
||||||
|
skipped++ |
||||||
|
if (divs.includes(toDiv(c, c))) { |
||||||
|
throw Error(`div ${toDiv(c, c)} is not very cold`) |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// test that clicking update the color accordingly
|
||||||
|
|
||||||
|
const coldColors = colors.filter(isCold) |
||||||
|
for (const c of coldColors) { |
||||||
|
await page.$$eval( |
||||||
|
'div', |
||||||
|
(nodes, c) => nodes.find(n => n.textContent === c).click(), |
||||||
|
c, |
||||||
|
) |
||||||
|
|
||||||
|
const count = await page.$$eval( |
||||||
|
'div', |
||||||
|
(nodes, c) => nodes.filter(n => n.className === c).length, |
||||||
|
c, |
||||||
|
) |
||||||
|
|
||||||
|
eq(count, coldColors.length) |
||||||
|
} |
||||||
|
}) |
@ -0,0 +1,46 @@ |
|||||||
|
export const tests = [] |
||||||
|
|
||||||
|
tests.push(async ({ eq, page }) => { |
||||||
|
// check the class words has been added in the CSS
|
||||||
|
await eq.css('.words', { textAlign: 'center', fontFamily: 'sans-serif' }) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ eq, page }) => { |
||||||
|
// check the torso element is initially empty
|
||||||
|
const isEmpty = await page.$eval('#torso', (node) => !node.children.length) |
||||||
|
eq(isEmpty, true) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ eq, page }) => { |
||||||
|
// click on the button
|
||||||
|
const button = await page.$('button#speak-button') |
||||||
|
await button.click() |
||||||
|
|
||||||
|
// check a new text element is added in the torso
|
||||||
|
const torsoChildren = await page.$eval('#torso', (node) => |
||||||
|
[...node.children].map((child) => ({ |
||||||
|
tag: child.tagName, |
||||||
|
text: child.textContent, |
||||||
|
class: child.className, |
||||||
|
})), |
||||||
|
) |
||||||
|
eq(torsoChildren, [textNode]) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ eq, page }) => { |
||||||
|
// click a second time on the button
|
||||||
|
const button = await page.$('button#speak-button') |
||||||
|
await button.click() |
||||||
|
|
||||||
|
// check a second new text element is added in the torso
|
||||||
|
const torsoChildren = await page.$eval('#torso', (node) => |
||||||
|
[...node.children].map((child) => ({ |
||||||
|
tag: child.tagName, |
||||||
|
text: child.textContent, |
||||||
|
class: child.className, |
||||||
|
})), |
||||||
|
) |
||||||
|
eq(torsoChildren, [textNode, textNode]) |
||||||
|
}) |
||||||
|
|
||||||
|
const textNode = { tag: 'DIV', text: 'Hello there!', class: 'words' } |
@ -0,0 +1,135 @@ |
|||||||
|
import { once } from 'node:events' |
||||||
|
import { spawn } from 'node:child_process' |
||||||
|
import { mkdir, writeFile, chmod } from 'fs/promises' |
||||||
|
import { join } from 'path' |
||||||
|
|
||||||
|
export const tests = [] |
||||||
|
const fetch = _fetch // to redefine the real fetch
|
||||||
|
|
||||||
|
const port = 5000 |
||||||
|
|
||||||
|
export const setup = async ({ randStr }) => { |
||||||
|
const dir = '.' |
||||||
|
|
||||||
|
await mkdir(`${dir}/guests`, { recursive: true }) |
||||||
|
|
||||||
|
const randLastName = randStr() |
||||||
|
|
||||||
|
const createFilesIn = ({ files, dirPath }) => { |
||||||
|
Promise.all( |
||||||
|
files.map(([fileName, content]) => |
||||||
|
writeFile(`${dirPath}/${fileName}`, JSON.stringify(content)), |
||||||
|
), |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
const sendRequest = async (path, options) => { |
||||||
|
const response = await fetch(`http://localhost:${port}${path}`, options) |
||||||
|
const { status } = response |
||||||
|
const headers = Object.fromEntries(response.headers) |
||||||
|
let body = '' |
||||||
|
try { |
||||||
|
body = await response.json() |
||||||
|
} catch (err) { |
||||||
|
body = err |
||||||
|
} |
||||||
|
return { status, body, headers } |
||||||
|
} |
||||||
|
|
||||||
|
const startServer = async path => { |
||||||
|
const server = spawn('node', [`${path}`]) |
||||||
|
const message = await Promise.race([ |
||||||
|
once(server.stdout, 'data'), |
||||||
|
Promise.race([ |
||||||
|
once(server.stderr, 'data').then(String).then(Error), |
||||||
|
once(server, 'error'), |
||||||
|
]).then(result => Promise.reject(result)), |
||||||
|
]) |
||||||
|
return { server, message } |
||||||
|
} |
||||||
|
|
||||||
|
return { tmpPath: dir, createFilesIn, randLastName, sendRequest, startServer } |
||||||
|
} |
||||||
|
|
||||||
|
const isServerRunningWell = async ({ path, ctx }) => { |
||||||
|
const { server, message } = await ctx.startServer(path) |
||||||
|
server.kill() |
||||||
|
return message[0].toString().includes(port) |
||||||
|
} |
||||||
|
|
||||||
|
const testOneGuest = async ({ path, eq, ctx, randStr }) => { |
||||||
|
const { server } = await ctx.startServer(path) |
||||||
|
const randMsg = randStr() |
||||||
|
const expBody = { message: randMsg } |
||||||
|
const files = [[`mario_${ctx.randLastName}.json`, expBody]] |
||||||
|
const dirName = 'guests' |
||||||
|
const dirPath = join(ctx.tmpPath, dirName) |
||||||
|
await ctx.createFilesIn({ dirPath, files }) |
||||||
|
const { status, body, headers } = await ctx.sendRequest( |
||||||
|
`/mario_${ctx.randLastName}`, |
||||||
|
{ |
||||||
|
method: 'GET', |
||||||
|
}, |
||||||
|
) |
||||||
|
server.kill() |
||||||
|
return eq( |
||||||
|
{ |
||||||
|
status: status, |
||||||
|
body: body, |
||||||
|
contentType: headers['content-type'], |
||||||
|
}, |
||||||
|
{ |
||||||
|
status: 200, |
||||||
|
body: expBody, |
||||||
|
contentType: 'application/json', |
||||||
|
}, |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
const testServerFail = async ({ path, eq, ctx }) => { |
||||||
|
const { server } = await ctx.startServer(path) |
||||||
|
await chmod(`${ctx.tmpPath}/guests/mario_${ctx.randLastName}.json`, 0) |
||||||
|
const { status, body, headers } = await ctx.sendRequest( |
||||||
|
`/mario_${ctx.randLastName}`, |
||||||
|
{ |
||||||
|
method: 'GET', |
||||||
|
}, |
||||||
|
) |
||||||
|
server.kill() |
||||||
|
return eq( |
||||||
|
{ |
||||||
|
status: status, |
||||||
|
body: body, |
||||||
|
contentType: headers['content-type'], |
||||||
|
}, |
||||||
|
{ |
||||||
|
status: 500, |
||||||
|
body: { error: 'server failed' }, |
||||||
|
contentType: 'application/json', |
||||||
|
}, |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
const testGuestNotThere = async ({ path, eq, ctx }) => { |
||||||
|
const { server } = await ctx.startServer(path) |
||||||
|
const { status, body, headers } = await ctx.sendRequest('/andrea_bianchi', { |
||||||
|
method: 'GET', |
||||||
|
}) |
||||||
|
server.kill() |
||||||
|
return eq( |
||||||
|
{ |
||||||
|
status: status, |
||||||
|
body: body, |
||||||
|
contentType: headers['content-type'], |
||||||
|
}, |
||||||
|
{ |
||||||
|
status: 404, |
||||||
|
body: { error: 'guest not found' }, |
||||||
|
contentType: 'application/json', |
||||||
|
}, |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
tests.push(isServerRunningWell, testOneGuest, testServerFail, testGuestNotThere) |
||||||
|
|
||||||
|
Object.freeze(tests) |
@ -0,0 +1,147 @@ |
|||||||
|
import { once } from 'node:events' |
||||||
|
import { spawn } from 'node:child_process' |
||||||
|
import { mkdir, writeFile, access } from 'fs/promises' |
||||||
|
import { join } from 'path' |
||||||
|
|
||||||
|
export const tests = [] |
||||||
|
const fetch = _fetch // to redefine the real fetch
|
||||||
|
|
||||||
|
const port = 5000 |
||||||
|
|
||||||
|
export const setup = async ({}) => { |
||||||
|
const dir = '.' |
||||||
|
|
||||||
|
await mkdir(`${dir}/guests`, { recursive: true }) |
||||||
|
|
||||||
|
const createFilesIn = ({ files, dirPath }) => |
||||||
|
Promise.all( |
||||||
|
files.map(([fileName, content]) => |
||||||
|
writeFile(`${dirPath}/${fileName}`, JSON.stringify(content)), |
||||||
|
), |
||||||
|
) |
||||||
|
|
||||||
|
const sendRequest = async (path, options) => { |
||||||
|
const response = await fetch(`http://localhost:${port}${path}`, options) |
||||||
|
const { status } = response |
||||||
|
const headers = Object.fromEntries(response.headers) |
||||||
|
let body = '' |
||||||
|
try { |
||||||
|
body = await response.json() |
||||||
|
} catch (err) { |
||||||
|
body = err |
||||||
|
} |
||||||
|
return { status, body, headers } |
||||||
|
} |
||||||
|
|
||||||
|
const sendRequestWithAuth = async (guestName, auth, body) => { |
||||||
|
let options = { |
||||||
|
method: 'POST', |
||||||
|
headers: { |
||||||
|
body: JSON.stringify(body), |
||||||
|
}, |
||||||
|
} |
||||||
|
if (auth.len !== 0) { |
||||||
|
options.headers.authorization = |
||||||
|
'Basic ' + Buffer.from(auth).toString('base64') |
||||||
|
} |
||||||
|
return sendRequest(guestName, options) |
||||||
|
} |
||||||
|
|
||||||
|
const startServer = async path => { |
||||||
|
const server = spawn('node', [`${path}`]) |
||||||
|
const message = await Promise.race([ |
||||||
|
once(server.stdout, 'data'), |
||||||
|
Promise.race([ |
||||||
|
once(server.stderr, 'data').then(String).then(Error), |
||||||
|
once(server, 'error'), |
||||||
|
]).then(result => Promise.reject(result)), |
||||||
|
]) |
||||||
|
return { server, message } |
||||||
|
} |
||||||
|
|
||||||
|
return { |
||||||
|
tmpPath: dir, |
||||||
|
createFilesIn, |
||||||
|
sendRequest, |
||||||
|
sendRequestWithAuth, |
||||||
|
startServer, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const isServerRunningWell = async ({ path, ctx }) => { |
||||||
|
const { server, message } = await ctx.startServer(path) |
||||||
|
server.kill() |
||||||
|
return message[0].toString().includes(port) |
||||||
|
} |
||||||
|
|
||||||
|
const testGoodRequests = async ({ path, eq, fail, ctx }) => { |
||||||
|
const expectedBody = { |
||||||
|
answer: 'yes', |
||||||
|
drink: 'juice', |
||||||
|
food: 'pizza', |
||||||
|
} |
||||||
|
const dirName = 'guests' |
||||||
|
const dirPath = join(ctx.tmpPath, dirName) |
||||||
|
const { server } = await ctx.startServer(path) |
||||||
|
|
||||||
|
const newGuestNames = ['Ana_Riber', 'Rob_Frie', 'George_Harl'] |
||||||
|
const auths = [ |
||||||
|
'Caleb_Squires:abracadabra', |
||||||
|
'Tyrique_Dalton:abracadabra', |
||||||
|
'Rahima_Young:abracadabra', |
||||||
|
] |
||||||
|
for (var i = 0; i < 3; i++) { |
||||||
|
const { status, body, headers } = await ctx.sendRequestWithAuth( |
||||||
|
`/${newGuestNames[i]}`, |
||||||
|
`${auths[i]}`, |
||||||
|
expectedBody, |
||||||
|
) |
||||||
|
|
||||||
|
fail(await access(`${dirPath}/${newGuestNames[i]}.json`)) |
||||||
|
eq( |
||||||
|
{ status: status, contentType: headers['content-type'], body: body }, |
||||||
|
{ status: 200, contentType: 'application/json', body: expectedBody }, |
||||||
|
) |
||||||
|
} |
||||||
|
server.kill() |
||||||
|
return true |
||||||
|
} |
||||||
|
|
||||||
|
const testUnauthorizedRequests = async ({ path, eq, ctx }) => { |
||||||
|
const body = { |
||||||
|
answer: 'yes', |
||||||
|
drink: 'juice', |
||||||
|
food: 'pizza', |
||||||
|
} |
||||||
|
|
||||||
|
const { server } = await ctx.startServer(path) |
||||||
|
|
||||||
|
const newGuestNames = [ |
||||||
|
'Super_Mario', |
||||||
|
'Super_Mario', |
||||||
|
'Super_Mario', |
||||||
|
'Super_Mario', |
||||||
|
] |
||||||
|
const auths = [ |
||||||
|
'', |
||||||
|
'LetMePass', |
||||||
|
'Rahima_Young:wrongpass', |
||||||
|
'Anonymus:abracadabra', |
||||||
|
] |
||||||
|
for (var i = 0; i < 3; i++) { |
||||||
|
const { status } = await ctx.sendRequestWithAuth( |
||||||
|
`/${newGuestNames[i]}`, |
||||||
|
`${auths[i]}`, |
||||||
|
body, |
||||||
|
) |
||||||
|
|
||||||
|
eq({ status: status }, { status: 401 }) |
||||||
|
} |
||||||
|
|
||||||
|
server.kill() |
||||||
|
return true |
||||||
|
} |
||||||
|
|
||||||
|
tests.push(isServerRunningWell, testGoodRequests, testUnauthorizedRequests) |
||||||
|
|
||||||
|
Object.freeze(tests) |
@ -0,0 +1,127 @@ |
|||||||
|
import { people } from './subjects/get-them-all/get-them-all.data.js' |
||||||
|
|
||||||
|
const getIds = predicate => |
||||||
|
people |
||||||
|
.filter(predicate) |
||||||
|
.map(e => e.id) |
||||||
|
.sort((a, b) => a.localeCompare(b)) |
||||||
|
|
||||||
|
const architects = getIds(p => p.tag === 'a') |
||||||
|
const notArchitects = getIds(p => p.tag !== 'a') |
||||||
|
|
||||||
|
const classical = getIds(p => p.classe === 'classical') |
||||||
|
const notClassical = getIds(p => p.tag === 'a' && p.classe !== 'classical') |
||||||
|
|
||||||
|
const active = getIds(p => p.classe === 'classical' && p.active) |
||||||
|
const notActive = getIds( |
||||||
|
p => p.tag === 'a' && p.classe === 'classical' && p.active === false, |
||||||
|
) |
||||||
|
|
||||||
|
const bonanno = people.find(p => p.id === 'BonannoPisano').id |
||||||
|
const notBonanno = getIds( |
||||||
|
p => |
||||||
|
p.tag === 'a' && |
||||||
|
p.classe === 'classical' && |
||||||
|
p.active && |
||||||
|
p.id !== 'BonannoPisano', |
||||||
|
) |
||||||
|
|
||||||
|
export const tests = [] |
||||||
|
|
||||||
|
tests.push(async ({ eq, page }) => { |
||||||
|
// get architects
|
||||||
|
const btnArchitect = await page.$(`#btnArchitect`) |
||||||
|
btnArchitect.click() |
||||||
|
await page.waitForTimeout(150) |
||||||
|
|
||||||
|
const selected = await page.$$eval('a', nodes => |
||||||
|
nodes |
||||||
|
.filter(node => node.textContent === 'Architect') |
||||||
|
.map(node => node.id) |
||||||
|
.sort((a, b) => a.localeCompare(b)), |
||||||
|
) |
||||||
|
|
||||||
|
eq(selected, architects) |
||||||
|
|
||||||
|
const eliminated = await page.$$eval('span', nodes => |
||||||
|
nodes |
||||||
|
.filter(node => node.style.opacity === '0.2') |
||||||
|
.map(node => node.id) |
||||||
|
.sort((a, b) => a.localeCompare(b)), |
||||||
|
) |
||||||
|
|
||||||
|
eq(eliminated, notArchitects) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// get classical
|
||||||
|
const btnClassical = await page.$(`#btnClassical`) |
||||||
|
btnClassical.click() |
||||||
|
await page.waitForTimeout(150) |
||||||
|
|
||||||
|
const selected = await page.$$eval('.classical', nodes => |
||||||
|
nodes |
||||||
|
.filter(node => node.textContent === 'Classical') |
||||||
|
.map(node => node.id) |
||||||
|
.sort((a, b) => a.localeCompare(b)), |
||||||
|
) |
||||||
|
|
||||||
|
eq(selected, classical) |
||||||
|
|
||||||
|
const eliminated = await page.$$eval('a:not(.classical)', nodes => |
||||||
|
nodes |
||||||
|
.filter(node => node.style.opacity === '0.2') |
||||||
|
.map(node => node.id) |
||||||
|
.sort((a, b) => a.localeCompare(b)), |
||||||
|
) |
||||||
|
|
||||||
|
eq(eliminated, notClassical) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check active
|
||||||
|
const btnActive = await page.$(`#btnActive`) |
||||||
|
btnActive.click() |
||||||
|
await page.waitForTimeout(150) |
||||||
|
|
||||||
|
const selected = await page.$$eval('.classical.active', nodes => |
||||||
|
nodes |
||||||
|
.filter(node => node.textContent === 'Active') |
||||||
|
.map(node => node.id) |
||||||
|
.sort((a, b) => a.localeCompare(b)), |
||||||
|
) |
||||||
|
eq(selected, active) |
||||||
|
|
||||||
|
const eliminated = await page.$$eval('.classical:not(.active)', nodes => |
||||||
|
nodes |
||||||
|
.filter(node => node.style.opacity === '0.2') |
||||||
|
.map(node => node.id) |
||||||
|
.sort((a, b) => a.localeCompare(b)), |
||||||
|
) |
||||||
|
|
||||||
|
eq(eliminated, notActive) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// get bonanno
|
||||||
|
const btnBonanno = await page.$(`#btnBonanno`) |
||||||
|
btnBonanno.click() |
||||||
|
await page.waitForTimeout(150) |
||||||
|
|
||||||
|
const selected = await page.$eval('#BonannoPisano', node => { |
||||||
|
if (node.textContent === 'Bonanno Pisano') return node.id |
||||||
|
}) |
||||||
|
|
||||||
|
eq(`bonanno: ${selected}`, `bonanno: ${bonanno}`) |
||||||
|
|
||||||
|
const eliminated = await page.$$eval( |
||||||
|
'a.classical.active:not(#BonannoPisano)', |
||||||
|
nodes => |
||||||
|
nodes |
||||||
|
.filter(node => node.style.opacity === '0.2') |
||||||
|
.map(node => node.id) |
||||||
|
.sort((a, b) => a.localeCompare(b)), |
||||||
|
) |
||||||
|
|
||||||
|
eq(eliminated, notBonanno) |
||||||
|
}) |
@ -0,0 +1,123 @@ |
|||||||
|
import { gossips } from './subjects/gossip-grid/gossip-grid.data.js' |
||||||
|
|
||||||
|
export const tests = [] |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// test that the grid is properly generated
|
||||||
|
|
||||||
|
const content = await page.$$eval('.gossip', nodes => nodes.map(n => n.textContent)) |
||||||
|
|
||||||
|
eq(content, ['Share gossip!', ...gossips]) |
||||||
|
}) |
||||||
|
|
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// test that you can add a gossip
|
||||||
|
|
||||||
|
const rand = Math.random().toString(36).slice(2) |
||||||
|
await page.type('textarea', `coucou ${rand}`) |
||||||
|
await page.click('.gossip button') |
||||||
|
const content = await page.$eval('div.gossip', n => n.textContent) |
||||||
|
|
||||||
|
eq(content, `coucou ${rand}`) |
||||||
|
}) |
||||||
|
|
||||||
|
|
||||||
|
const getStyle = (nodes, key) => nodes.map(n => n.style[key]) |
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// test that you can change the width to the min
|
||||||
|
|
||||||
|
const min = await page.$eval('#width', n => { |
||||||
|
n.value = n.min |
||||||
|
n.dispatchEvent(new Event('input')) |
||||||
|
return Number(n.min) |
||||||
|
}) |
||||||
|
|
||||||
|
eq(min, 200) |
||||||
|
|
||||||
|
const values = await page.$$eval('div.gossip', getStyle, 'width') |
||||||
|
|
||||||
|
eq(Array(gossips.length + 1).fill(`${min}px`), values) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// test that you can change the width to the max
|
||||||
|
|
||||||
|
const max = await page.$eval('#width', n => { |
||||||
|
n.value = n.max |
||||||
|
n.dispatchEvent(new Event('input')) |
||||||
|
return Number(n.max) |
||||||
|
}) |
||||||
|
|
||||||
|
eq(max, 800) |
||||||
|
|
||||||
|
const values = await page.$$eval('div.gossip', getStyle, 'width') |
||||||
|
|
||||||
|
eq(Array(gossips.length + 1).fill(`${max}px`), values) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// test that you can change the font-size to the min
|
||||||
|
|
||||||
|
const min = await page.$eval('#fontSize', n => { |
||||||
|
n.value = n.min |
||||||
|
n.dispatchEvent(new Event('input')) |
||||||
|
return Number(n.min) |
||||||
|
}) |
||||||
|
|
||||||
|
eq(min, 20) |
||||||
|
|
||||||
|
const values = await page.$$eval('div.gossip', getStyle, 'fontSize') |
||||||
|
|
||||||
|
eq(Array(gossips.length + 1).fill(`${min}px`), values) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// test that you can change the font-size to the max
|
||||||
|
|
||||||
|
const max = await page.$eval('#fontSize', n => { |
||||||
|
n.value = n.max |
||||||
|
n.dispatchEvent(new Event('input')) |
||||||
|
return Number(n.max) |
||||||
|
}) |
||||||
|
|
||||||
|
eq(max, 40) |
||||||
|
|
||||||
|
const values = await page.$$eval('div.gossip', getStyle, 'fontSize') |
||||||
|
|
||||||
|
eq(Array(gossips.length + 1).fill(`${max}px`), values) |
||||||
|
}) |
||||||
|
|
||||||
|
const getBackground = (nodes, key) => nodes.map(n => n.style.background || n.style.backgroundColor) |
||||||
|
tests.push(async ({ page, eq, rgbToHsl }) => { |
||||||
|
// test that you can change the background to the darkest
|
||||||
|
|
||||||
|
const min = await page.$eval('#background', n => { |
||||||
|
n.value = n.min |
||||||
|
n.dispatchEvent(new Event('input')) |
||||||
|
return Number(n.min) |
||||||
|
}) |
||||||
|
|
||||||
|
eq(min, 20) |
||||||
|
|
||||||
|
const values = await page.$$eval('div.gossip', getBackground) |
||||||
|
const lightness = values.map(rgbToHsl).map(([h,s,l]) => l) |
||||||
|
eq(Array(gossips.length + 1).fill(min), lightness) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq, rgbToHsl }) => { |
||||||
|
// test that you can change the background to the darkest
|
||||||
|
|
||||||
|
const max = await page.$eval('#background', n => { |
||||||
|
n.value = n.max |
||||||
|
n.dispatchEvent(new Event('input')) |
||||||
|
return Number(n.max) |
||||||
|
}) |
||||||
|
|
||||||
|
eq(max, 75) |
||||||
|
|
||||||
|
const values = await page.$$eval('div.gossip', getBackground) |
||||||
|
const lightness = values.map(rgbToHsl).map(([h,s,l]) => Math.round(l)) |
||||||
|
|
||||||
|
eq(Array(gossips.length + 1).fill(max), lightness) |
||||||
|
}) |
@ -0,0 +1,67 @@ |
|||||||
|
export const tests = [] |
||||||
|
|
||||||
|
export const setup = async ({ page }) => ({ |
||||||
|
content: await page.$$eval('div', nodes => nodes.map(n => ({ |
||||||
|
text: n.textContent, |
||||||
|
size: Number((n.style.fontSize || '').slice(0, -2)), |
||||||
|
weight: Number(n.style.fontWeight), |
||||||
|
}))) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(({ eq, ctx }) => { |
||||||
|
// should contain 120 items
|
||||||
|
eq(ctx.content.length, 120) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(({ eq, ctx }) => { |
||||||
|
// ctx.content should only be one letter long
|
||||||
|
eq(ctx.content.reduce((total, { text }) => total + text.length, 0), 120) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(({ eq, ctx }) => { |
||||||
|
// we expect random to yield at least 10 different letters
|
||||||
|
eq(new Set(ctx.content).size > 10, true) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(({ eq, ctx }) => { |
||||||
|
// only letters from 'A' to 'Z'
|
||||||
|
eq(ctx.content.every(({ text }) => text >= 'A' && text <= 'Z'), true) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(({ eq, ctx }) => { |
||||||
|
// letter size should grow
|
||||||
|
|
||||||
|
// first should be 11
|
||||||
|
eq(ctx.content[0].size, 11) |
||||||
|
|
||||||
|
// last should be 120
|
||||||
|
eq(ctx.content[119].size, 130) |
||||||
|
|
||||||
|
// each letter should be bigger than the previous
|
||||||
|
let prev = 0 |
||||||
|
for (const { size } of ctx.content) { |
||||||
|
if (prev >= size) { |
||||||
|
throw Error('Letters should grow') |
||||||
|
}
|
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(({ eq, ctx }) => { |
||||||
|
// letter weight should increase in thirds
|
||||||
|
const third = n => ({ weight }) => weight === n |
||||||
|
|
||||||
|
// first third should be 300
|
||||||
|
eq(ctx.content[0].weight, 300) |
||||||
|
eq(ctx.content[39].weight, 300) |
||||||
|
eq(ctx.content.slice(0, 40).every(third(300)), true) |
||||||
|
|
||||||
|
// second third should be 400
|
||||||
|
eq(ctx.content[40].weight, 400) |
||||||
|
eq(ctx.content[79].weight, 400) |
||||||
|
eq(ctx.content.slice(40, 80).every(third(400)), true) |
||||||
|
|
||||||
|
// last third should be 600
|
||||||
|
eq(ctx.content[80].weight, 600) |
||||||
|
eq(ctx.content[119].weight, 600) |
||||||
|
eq(ctx.content.slice(80).every(third(600)), true) |
||||||
|
}) |
@ -0,0 +1,18 @@ |
|||||||
|
[ |
||||||
|
{ |
||||||
|
"description": "Log a number in the console", |
||||||
|
"code": "// If you see this code, it means that you failed the first tests.\n// each tests have it's own code to be tested that will appear if\n// your solution doesn't pass it, it is not here to help you.\n// While sometimes it may clarify the instructions\n// this specific test is complex and will most likely confuse you.\n\n// This is to save all the values that you console.log'd\nconst args = saveArguments(console, 'log')\n\n// This comment below will be replaced by your code\n// Your code\n\n// This is where we check that the value are expected.\n// It's pretty advanced code, you don't have to understand it\n// Do not try to use it for the solution, it will not help you.\nconst typeOfLoggedValues = args.flat().map((v) => typeof v)\nif (!typeOfLoggedValues.includes('number')) {\n // this is where we create the error message you see:\n throw Error('you must log a number')\n // that's what you should focus on trying to understand\n // the message, not `throw` or `Error` don't worry about\n // that, worry about showing a number in the console !\n}" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"description": "Log a boolean in the console", |
||||||
|
"code": "const args = saveArguments(console, 'log')\n\n// Your code\n\nconst typeOfLoggedValues = args.flat().map((v) => typeof v)\nif (!typeOfLoggedValues.includes('boolean')) {\n throw Error('you must log a boolean')\n}" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"description": "Log a string in the console", |
||||||
|
"code": "const args = saveArguments(console, 'log')\n\n// Your code\n\nconst typeOfLoggedValues = args.flat().map((v) => typeof v)\nif (!typeOfLoggedValues.includes('string')) {\n throw Error('you must log a string')\n}" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"description": "Log the string Hello There ! in the console", |
||||||
|
"code": "const args = saveArguments(console, 'log')\n\n// Your code\n\nconst loggedValues = args.flat().join(' ')\nif (!loggedValues.includes('Hello There !')) {\n throw Error('you must log the text Hello There !')\n}" |
||||||
|
} |
||||||
|
] |
@ -1,23 +0,0 @@ |
|||||||
import { readFileSync as read } from 'fs' |
|
||||||
|
|
||||||
// /*/ // ⚡
|
|
||||||
export const tests = [ |
|
||||||
({ eq, path }) => // code must use console.log
|
|
||||||
read(path, 'utf8').trim().includes('console.log'), |
|
||||||
|
|
||||||
async ({ eq, code }) => { |
|
||||||
// console.log must have been called with the right value
|
|
||||||
const log = console.log.bind(console) |
|
||||||
const args = [] |
|
||||||
console.log = (..._args) => { |
|
||||||
args.push(..._args) |
|
||||||
log(..._args) |
|
||||||
} |
|
||||||
|
|
||||||
const b64 = Buffer.from(code).toString("base64") |
|
||||||
const url = `data:text/javascript;base64,${b64}` |
|
||||||
await import(url) |
|
||||||
console.log = log |
|
||||||
return eq(args.join(' ').trim(), 'Hello There') |
|
||||||
}, |
|
||||||
] |
|
@ -0,0 +1,56 @@ |
|||||||
|
export const tests = [] |
||||||
|
|
||||||
|
export const setup = async () => { |
||||||
|
const getNotes = async (page) => |
||||||
|
await page.$$eval('.note', (nodes) => { |
||||||
|
return nodes.map((note) => note.textContent) |
||||||
|
}) |
||||||
|
return { getNotes } |
||||||
|
} |
||||||
|
|
||||||
|
const characters = `didyouhandlethekeydowneventcorrectly` |
||||||
|
|
||||||
|
tests.push(async ({ page, eq, ctx }) => { |
||||||
|
// check that a note is created and matches the right letter when a key is pressed
|
||||||
|
for (const [i, character] of characters.split('').entries()) { |
||||||
|
await page.keyboard.down(character) |
||||||
|
const typed = characters.slice(0, i + 1).split('') |
||||||
|
eq(await ctx.getNotes(page), typed) |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq, ctx }) => { |
||||||
|
// check that the last note is removed when Backspace key is pressed
|
||||||
|
let step = 1 |
||||||
|
while (step < 10) { |
||||||
|
await page.keyboard.down('Backspace') |
||||||
|
const typed = characters.slice(0, characters.length - step).split('') |
||||||
|
eq(await ctx.getNotes(page), typed) |
||||||
|
step++ |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq, ctx }) => { |
||||||
|
// check that all the notes are cleared when Escape key is pressed
|
||||||
|
await page.keyboard.down('Escape') |
||||||
|
const cleared = (await ctx.getNotes(page)).length === 0 |
||||||
|
eq(cleared, true) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check that notes have different background colors
|
||||||
|
const test = 'abcdefghijklmnopqrstuvwxyz' |
||||||
|
let step = 0 |
||||||
|
while (step < test.length) { |
||||||
|
await page.keyboard.down(test[step]) |
||||||
|
step++ |
||||||
|
} |
||||||
|
|
||||||
|
const getNotesBg = await page.$$eval('.note', (nodes) => { |
||||||
|
return nodes.map((note) => note.style.backgroundColor) |
||||||
|
}) |
||||||
|
|
||||||
|
const colors = [...new Set(getNotesBg)] |
||||||
|
const allDifferent = colors.length === test.length |
||||||
|
eq(allDifferent, true) |
||||||
|
}) |
@ -0,0 +1,122 @@ |
|||||||
|
export const tests = [] |
||||||
|
|
||||||
|
export const setup = async ({ page }) => ({ |
||||||
|
getCirclesPos: () => |
||||||
|
page.$$eval('.circle', nodes => { |
||||||
|
const circleRadius = 25 |
||||||
|
const formatPos = pos => Number(pos.replace('px', '')) + circleRadius |
||||||
|
return nodes.map(node => [ |
||||||
|
formatPos(node.style.left), |
||||||
|
formatPos(node.style.top), |
||||||
|
]) |
||||||
|
}), |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq, ctx }) => { |
||||||
|
// check that a circle is created on click at the mouse position
|
||||||
|
const { width, height } = await page.evaluate(() => ({ |
||||||
|
width: document.documentElement.clientWidth, |
||||||
|
height: document.documentElement.clientHeight, |
||||||
|
})) |
||||||
|
|
||||||
|
const clicks = [...Array(10).keys()].map(e => [random(width), random(height)]) |
||||||
|
|
||||||
|
for (const [i, click] of clicks.entries()) { |
||||||
|
const [posX, posY] = click |
||||||
|
await page.mouse.click(posX, posY) |
||||||
|
const currentCircle = (await ctx.getCirclesPos())[i] |
||||||
|
eq(currentCircle, click) |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq, ctx }) => { |
||||||
|
// check that the last created circle moves along the mouse
|
||||||
|
let move = 0 |
||||||
|
while (move < 100) { |
||||||
|
move++ |
||||||
|
const x = move |
||||||
|
const y = move * 2 |
||||||
|
await page.mouse.move(x, y) |
||||||
|
const circles = await ctx.getCirclesPos() |
||||||
|
const currentCirclePos = circles[circles.length - 1] |
||||||
|
eq(currentCirclePos, [x, y]) |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq, ctx }) => { |
||||||
|
// check that a circle is trapped and purple when inside the box
|
||||||
|
const box = await page.$eval('.box', box => ({ |
||||||
|
top: box.getBoundingClientRect().top, |
||||||
|
right: box.getBoundingClientRect().right, |
||||||
|
left: box.getBoundingClientRect().left, |
||||||
|
bottom: box.getBoundingClientRect().bottom, |
||||||
|
})) |
||||||
|
|
||||||
|
await page.mouse.click(200, 200) |
||||||
|
|
||||||
|
let move = 200 |
||||||
|
let hasEntered = false |
||||||
|
|
||||||
|
while (move < 500) { |
||||||
|
const x = move + 50 |
||||||
|
const y = move |
||||||
|
await page.mouse.move(x, y) |
||||||
|
|
||||||
|
const circles = await ctx.getCirclesPos() |
||||||
|
const currentCircle = circles[circles.length - 1] |
||||||
|
|
||||||
|
const circleRadius = 25 |
||||||
|
|
||||||
|
const bg = await page.$$eval( |
||||||
|
'.circle', |
||||||
|
nodes => nodes[nodes.length - 1].style.background, |
||||||
|
) |
||||||
|
|
||||||
|
const insideX = x > box.left + circleRadius && x < box.right - circleRadius |
||||||
|
const insideY = y > box.top + circleRadius && y < box.bottom - circleRadius |
||||||
|
const isInside = insideX && insideY |
||||||
|
|
||||||
|
// check that the background is set to the right color
|
||||||
|
if (isInside) { |
||||||
|
hasEntered = true |
||||||
|
eq(bg, 'var(--purple)') |
||||||
|
} else { |
||||||
|
eq(bg, hasEntered ? 'var(--purple)' : 'white') |
||||||
|
} |
||||||
|
|
||||||
|
// check that the mouse is trapped inside the box
|
||||||
|
if (hasEntered) { |
||||||
|
if (insideY) { |
||||||
|
eq(currentCircle[1], y) |
||||||
|
} else { |
||||||
|
const maxY = |
||||||
|
currentCircle[1] === box.top + circleRadius + 1 || |
||||||
|
currentCircle[1] === box.top + circleRadius || |
||||||
|
currentCircle[1] === box.bottom - circleRadius || |
||||||
|
currentCircle[1] === box.bottom - circleRadius - 1 |
||||||
|
eq(maxY, true) |
||||||
|
} |
||||||
|
if (insideX) { |
||||||
|
eq(currentCircle[0], x) |
||||||
|
} else { |
||||||
|
const maxX = |
||||||
|
currentCircle[0] === box.left + circleRadius || |
||||||
|
currentCircle[0] === box.left + circleRadius + 1 || |
||||||
|
currentCircle[0] === box.right - circleRadius || |
||||||
|
currentCircle[0] === box.right - circleRadius - 1 |
||||||
|
eq(maxX, true) |
||||||
|
} |
||||||
|
} |
||||||
|
move++ |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
const random = (min, max) => { |
||||||
|
if (!max) { |
||||||
|
max = min |
||||||
|
min = 0 |
||||||
|
} |
||||||
|
min = Math.ceil(min) |
||||||
|
max = Math.floor(max) |
||||||
|
return Math.floor(Math.random() * (max - min + 1)) + min |
||||||
|
} |
@ -0,0 +1,90 @@ |
|||||||
|
export const tests = [] |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check that the HTML structure is correct & elements are nested properly
|
||||||
|
const elements = await page.$$eval('body', (nodes) => { |
||||||
|
const toNode = (el) => { |
||||||
|
const node = {} |
||||||
|
node.tag = el.tagName.toLowerCase() |
||||||
|
node.id = el.id |
||||||
|
if (el.children.length) { |
||||||
|
node.children = [...el.children].map(toNode) |
||||||
|
} |
||||||
|
return node |
||||||
|
} |
||||||
|
return [...nodes[0].children].map(toNode) |
||||||
|
}) |
||||||
|
eq(expectedStructure, elements) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check the section selector style has been updated properly
|
||||||
|
eq.css('section', { |
||||||
|
display: 'flex', |
||||||
|
justifyContent: 'center', |
||||||
|
}) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check if the provided CSS has been correctly copy pasted
|
||||||
|
eq.css('div, p', { |
||||||
|
border: '1px solid black', |
||||||
|
padding: '10px', |
||||||
|
margin: '0px', |
||||||
|
borderRadius: '30px', |
||||||
|
}) |
||||||
|
|
||||||
|
eq.css('#face', { alignItems: 'center' }) |
||||||
|
|
||||||
|
eq.css('#eyes', { |
||||||
|
display: 'flex', |
||||||
|
backgroundColor: 'yellow', |
||||||
|
justifyContent: 'space-between', |
||||||
|
alignItems: 'center', |
||||||
|
borderRadius: '50px', |
||||||
|
width: '200px', |
||||||
|
}) |
||||||
|
|
||||||
|
eq.css('#torso', { |
||||||
|
width: '200px', |
||||||
|
backgroundColor: 'violet', |
||||||
|
}) |
||||||
|
}) |
||||||
|
|
||||||
|
const expectedStructure = [ |
||||||
|
{ |
||||||
|
tag: 'section', |
||||||
|
|
||||||
|
id: 'face', |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
tag: 'div', |
||||||
|
|
||||||
|
id: 'eyes', |
||||||
|
children: [ |
||||||
|
{ tag: 'p', id: 'eye-left' }, |
||||||
|
{ tag: 'p', id: 'eye-right' }, |
||||||
|
], |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
tag: 'section', |
||||||
|
|
||||||
|
id: 'upper-body', |
||||||
|
children: [ |
||||||
|
{ tag: 'div', id: 'arm-left' }, |
||||||
|
{ tag: 'div', id: 'torso' }, |
||||||
|
{ tag: 'div', id: 'arm-right' }, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
tag: 'section', |
||||||
|
|
||||||
|
id: 'lower-body', |
||||||
|
children: [ |
||||||
|
{ tag: 'div', id: 'leg-left' }, |
||||||
|
{ tag: 'div', id: 'leg-right' }, |
||||||
|
], |
||||||
|
}, |
||||||
|
] |
@ -0,0 +1,110 @@ |
|||||||
|
export const tests = [] |
||||||
|
|
||||||
|
const between = (expected, min, max) => expected >= min && expected <= max |
||||||
|
|
||||||
|
export const setup = async ({ page, rgbToHsl }) => ({ |
||||||
|
bodyBgRgb: async () => |
||||||
|
rgbToHsl(await page.$eval('body', (body) => body.style.background)), |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check that the background color is changing on mouse move
|
||||||
|
// by simulating 20 moves, so there must be 20 different background colors
|
||||||
|
let move = 50 |
||||||
|
let bgs = [] |
||||||
|
while (move < 250) { |
||||||
|
move += 10 |
||||||
|
const x = move |
||||||
|
const y = move * 2 |
||||||
|
await page.mouse.move(x, y) |
||||||
|
const bodyBg = await page.$eval('body', (body) => body.style.background) |
||||||
|
const validColor = bodyBg.includes('rgb') |
||||||
|
if (!validColor) continue |
||||||
|
bgs.push(bodyBg) |
||||||
|
} |
||||||
|
const differentBgs = [...new Set(bgs)].length |
||||||
|
eq(differentBgs, 20) |
||||||
|
}) |
||||||
|
|
||||||
|
const near = (a, b) => a < b + 2.5 && a > b - 2.5 |
||||||
|
const numVal = (n) => n.textContent.replace(/[^0-9,]/g, '') |
||||||
|
const generateCoords = (random) => [ |
||||||
|
[random(125, 500), random(125, 400)], |
||||||
|
[random(125, 500), random(125, 400)], |
||||||
|
[random(125, 500), random(125, 400)], |
||||||
|
] |
||||||
|
|
||||||
|
tests.push(async ({ page, eq, bodyBgRgb, random }) => { |
||||||
|
// check that the hsl value displayed matches the current background color
|
||||||
|
for (const move of generateCoords(random)) { |
||||||
|
await page.mouse.move(...move) |
||||||
|
const a = await bodyBgRgb() |
||||||
|
const b = (await page.$eval('.hsl', numVal)).split(',') |
||||||
|
if (a.every((v, i) => near(v, Number(b[i])))) continue |
||||||
|
throw Error(`hsl(${a.map(Math.round)}) to far from hsl(${b})`) |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq, bodyBgRgb, random }) => { |
||||||
|
// check that the hue value displayed matches the current background color
|
||||||
|
for (const move of generateCoords(random)) { |
||||||
|
await page.mouse.move(...move) |
||||||
|
const [h] = await bodyBgRgb() |
||||||
|
const hue = await page.$eval('.hue', numVal) |
||||||
|
|
||||||
|
if (!near(h, Number(hue))) { |
||||||
|
console.log({ h, hue, c: near(h, Number(hue)) }) |
||||||
|
throw Error(`hue ${Math.round(h)} to far from ${hue}`) |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq, bodyBgRgb, random }) => { |
||||||
|
// check that the luminosity value displayed matches the current background color
|
||||||
|
for (const move of generateCoords(random)) { |
||||||
|
await page.mouse.move(...move) |
||||||
|
const [, , l] = await bodyBgRgb() |
||||||
|
const lum = await page.$eval('.luminosity', numVal) |
||||||
|
|
||||||
|
if (!near(l, Number(lum))) { |
||||||
|
throw Error(`luminosity ${Math.round(l)} to far from ${lum}`) |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq, bodyBgRgb, random }) => { |
||||||
|
// check that the hsl value is copied in the clipboard on click
|
||||||
|
// Override readText if writeText is used due to a puppeteer bug
|
||||||
|
await page.evaluate(() => { |
||||||
|
window.navigator.clipboard.writeText = async (text) => { |
||||||
|
window.navigator.clipboard.readText = async () => text |
||||||
|
} |
||||||
|
}) |
||||||
|
for (const move of generateCoords(random)) { |
||||||
|
await page.mouse.click(...move) |
||||||
|
const clipboard = await page.evaluate(() => |
||||||
|
window.navigator.clipboard.readText() |
||||||
|
) |
||||||
|
const hslValue = await page.$eval('.hsl', (hsl) => hsl.textContent) |
||||||
|
eq(hslValue, clipboard) |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq, bodyBgRgb, random }) => { |
||||||
|
// check that each svg axis is following the mouse
|
||||||
|
const [[mouseX, mouseY]] = generateCoords(random) |
||||||
|
await page.mouse.move(mouseX, mouseY) |
||||||
|
const axisX = await page.$eval('#axisX', (line) => [ |
||||||
|
line.getAttribute('x1'), |
||||||
|
line.getAttribute('x2'), |
||||||
|
]) |
||||||
|
const axisY = await page.$eval('#axisY', (line) => [ |
||||||
|
line.getAttribute('y1'), |
||||||
|
line.getAttribute('y2'), |
||||||
|
]) |
||||||
|
|
||||||
|
const checkAxisCoords = (coords) => Number([...new Set(coords)].join()) |
||||||
|
|
||||||
|
eq(checkAxisCoords(axisX), mouseX) |
||||||
|
eq(checkAxisCoords(axisY), mouseY) |
||||||
|
}) |
@ -0,0 +1,36 @@ |
|||||||
|
import { styles } from './subjects/pimp-my-style/pimp-my-style.data.js' |
||||||
|
|
||||||
|
export const tests = [] |
||||||
|
|
||||||
|
const formatClass = (limit, unpimp) => |
||||||
|
['button', ...styles.slice(0, limit), unpimp && 'unpimp'].filter(Boolean) |
||||||
|
|
||||||
|
const max = styles.length - 1 |
||||||
|
|
||||||
|
export const setup = async ({ page }) => { |
||||||
|
const btn = await page.$('.button') |
||||||
|
|
||||||
|
return { |
||||||
|
btn, |
||||||
|
getClass: async () => |
||||||
|
(await (await btn.getProperty('className')).jsonValue()).split(' '), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
tests.push(async ({ page, eq, btn, getClass }) => { |
||||||
|
// pimp
|
||||||
|
for (const i of styles.keys()) { |
||||||
|
console.log('pimp click', i + 1) |
||||||
|
await btn.click() |
||||||
|
eq(formatClass(i + 1, i === max), await getClass()) |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq, btn, getClass }) => { |
||||||
|
// unpimp !
|
||||||
|
for (const i of styles.keys()) { |
||||||
|
console.log('unpimp click', i + 1) |
||||||
|
await btn.click() |
||||||
|
eq(formatClass(max - i, i !== max), await getClass()) |
||||||
|
} |
||||||
|
}) |
@ -0,0 +1,49 @@ |
|||||||
|
|
||||||
|
export const tests = [] |
||||||
|
|
||||||
|
// this test is commented out because it will not work for editor mode
|
||||||
|
// tests.push(async ({ eq }) => {
|
||||||
|
// // check the CSS stylesheet is linked in the head tag
|
||||||
|
//
|
||||||
|
// await eq.$('head link', {
|
||||||
|
// rel: 'stylesheet',
|
||||||
|
// href: 'http://localhost:9898/select-and-style/select-and-style.css',
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
|
||||||
|
tests.push(async ({ eq }) => { |
||||||
|
// check the universal selector has been declared properly
|
||||||
|
|
||||||
|
await eq.css('*', { |
||||||
|
margin: '0px', |
||||||
|
opacity: '0.85', |
||||||
|
boxSizing: 'border-box', |
||||||
|
}) |
||||||
|
}) |
||||||
|
|
||||||
|
|
||||||
|
tests.push(async ({ eq }) => { |
||||||
|
// check that the body was styled
|
||||||
|
|
||||||
|
await eq.css('body', { height: '100vh' }) |
||||||
|
}) |
||||||
|
|
||||||
|
|
||||||
|
tests.push(async ({ eq }) => { |
||||||
|
// check that sections elements are styled
|
||||||
|
|
||||||
|
await eq.css('section', { |
||||||
|
padding: '20px', |
||||||
|
width: '100%', |
||||||
|
height: 'calc(33.3333%)', |
||||||
|
}) |
||||||
|
}) |
||||||
|
|
||||||
|
|
||||||
|
tests.push(async ({ eq }) => { |
||||||
|
// check that the individual sections are styled
|
||||||
|
|
||||||
|
await eq.css('#face', { backgroundColor: 'cyan' }) |
||||||
|
await eq.css('#upper-body', { backgroundColor: 'blueviolet' }) |
||||||
|
await eq.css('#lower-body', { backgroundColor: 'lightsalmon' }) |
||||||
|
}) |
@ -0,0 +1,25 @@ |
|||||||
|
export const tests = [] |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check that the title tag is present & is set with some text
|
||||||
|
const title = await page.$eval('title', (node) => node.textContent) |
||||||
|
if (!title.length) throw Error('missing title') |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check the face
|
||||||
|
|
||||||
|
return eq.$('section:nth-child(1)', { textContent: 'face' }) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check the upper-body
|
||||||
|
|
||||||
|
return eq.$('section:nth-child(2)', { textContent: 'upper-body' }) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check the lower-body, my favorite part
|
||||||
|
|
||||||
|
return eq.$('section:nth-child(3)', { textContent: 'lower-body' }) |
||||||
|
}) |
@ -0,0 +1,18 @@ |
|||||||
|
export const tests = [] |
||||||
|
const t = (f) => tests.push(f) |
||||||
|
|
||||||
|
t(() => sunnySunday(new Date('0001-01-01')) === 'Monday') |
||||||
|
t(() => sunnySunday(new Date('0001-01-02')) === 'Tuesday') |
||||||
|
t(() => sunnySunday(new Date('0001-01-03')) === 'Wednesday') |
||||||
|
t(() => sunnySunday(new Date('0001-01-04')) === 'Thursday') |
||||||
|
t(() => sunnySunday(new Date('0001-01-05')) === 'Friday') |
||||||
|
t(() => sunnySunday(new Date('0001-01-06')) === 'Saturday') |
||||||
|
t(() => sunnySunday(new Date('0001-01-07')) === 'Monday') |
||||||
|
|
||||||
|
t(() => sunnySunday(new Date('0001-12-01')) === 'Friday') |
||||||
|
t(() => sunnySunday(new Date('1664-08-09')) === 'Saturday') |
||||||
|
|
||||||
|
t(() => sunnySunday(new Date('2020-01-01')) === 'Monday') |
||||||
|
t(() => sunnySunday(new Date('2048-12-08')) === 'Thursday') |
||||||
|
|
||||||
|
Object.freeze(tests) |
@ -0,0 +1,19 @@ |
|||||||
|
export const tests = [] |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check the face
|
||||||
|
|
||||||
|
return eq.$('section#face', { textContent: '' }) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check the upper-body
|
||||||
|
|
||||||
|
return eq.$('section#upper-body', { textContent: '' }) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check the lower-body, my favorite part
|
||||||
|
|
||||||
|
return eq.$('section#lower-body', { textContent: '' }) |
||||||
|
}) |
@ -0,0 +1,197 @@ |
|||||||
|
import { once } from 'node:events' |
||||||
|
import { spawn } from 'node:child_process' |
||||||
|
import { mkdir, writeFile, chmod } from 'fs/promises' |
||||||
|
import { join } from 'path' |
||||||
|
import fs from 'node:fs/promises' |
||||||
|
|
||||||
|
export const tests = [] |
||||||
|
const fetch = _fetch // to redefine the real fetch
|
||||||
|
|
||||||
|
const port = 5000 |
||||||
|
|
||||||
|
export const setup = async ({ randStr }) => { |
||||||
|
const dir = '.' |
||||||
|
|
||||||
|
await mkdir(`${dir}/guests`, { recursive: true }) |
||||||
|
|
||||||
|
const randomName = randStr() |
||||||
|
|
||||||
|
const createFilesIn = ({ files, dirPath }) => { |
||||||
|
Promise.all( |
||||||
|
files.map(([fileName, content]) => |
||||||
|
writeFile(`${dirPath}/${fileName}`, JSON.stringify(content), { |
||||||
|
flag: 'wx', |
||||||
|
}), |
||||||
|
), |
||||||
|
).catch(reason => console.log(reason)) |
||||||
|
|
||||||
|
return true |
||||||
|
} |
||||||
|
|
||||||
|
const sendRequest = async (path, options) => { |
||||||
|
const response = await fetch(`http://localhost:${port}${path}`, options) |
||||||
|
const { status } = response |
||||||
|
const headers = Object.fromEntries(response.headers) |
||||||
|
let body = '' |
||||||
|
try { |
||||||
|
body = await response.json() |
||||||
|
} catch (err) { |
||||||
|
body = err |
||||||
|
} |
||||||
|
return { status, body, headers } |
||||||
|
} |
||||||
|
|
||||||
|
const startServer = async path => { |
||||||
|
const server = spawn('node', [`${path}`]) |
||||||
|
const message = await Promise.race([ |
||||||
|
once(server.stdout, 'data'), |
||||||
|
Promise.race([ |
||||||
|
once(server.stderr, 'data').then(String).then(Error), |
||||||
|
once(server, 'error'), |
||||||
|
]).then(result => Promise.reject(result)), |
||||||
|
]) |
||||||
|
return { server, message } |
||||||
|
} |
||||||
|
|
||||||
|
return { tmpPath: dir, createFilesIn, randomName, sendRequest, startServer } |
||||||
|
} |
||||||
|
|
||||||
|
const testServerRunning = async ({ path, ctx }) => { |
||||||
|
const { server, message } = await ctx.startServer(path) |
||||||
|
server.kill() |
||||||
|
return message[0].toString().includes(port) |
||||||
|
} |
||||||
|
|
||||||
|
const testRightStatusCode = async ({ path, ctx, randStr }) => { |
||||||
|
const { server } = await ctx.startServer(path) |
||||||
|
const { status } = await ctx.sendRequest(`/${ctx.randomName}`, { |
||||||
|
method: 'POST', |
||||||
|
headers: { |
||||||
|
'content-type': 'application/json', |
||||||
|
}, |
||||||
|
body: randStr(), |
||||||
|
}) |
||||||
|
server.kill() |
||||||
|
|
||||||
|
if (status != 201) return false |
||||||
|
return true |
||||||
|
} |
||||||
|
|
||||||
|
const testRightContentType = async ({ path, ctx, randStr }) => { |
||||||
|
const { server } = await ctx.startServer(path) |
||||||
|
const { headers } = await ctx.sendRequest(`/${ctx.randomName}`, { |
||||||
|
method: 'POST', |
||||||
|
headers: { |
||||||
|
'content-type': 'application/json', |
||||||
|
}, |
||||||
|
body: randStr(), |
||||||
|
}) |
||||||
|
server.kill() |
||||||
|
if (headers['content-type'] != 'application/json') return false |
||||||
|
return true |
||||||
|
} |
||||||
|
|
||||||
|
const testServerFail = async ({ path, eq, ctx, randStr }) => { |
||||||
|
const { server } = await ctx.startServer(path) |
||||||
|
await chmod(`${ctx.tmpPath}/guests`, 0).catch(reason => console.log(reason)) |
||||||
|
const { status, body, headers } = await ctx.sendRequest( |
||||||
|
`/${ctx.randomName}`, |
||||||
|
{ |
||||||
|
method: 'POST', |
||||||
|
body: randStr(), |
||||||
|
}, |
||||||
|
) |
||||||
|
await chmod(`${ctx.tmpPath}/guests`, 0o777) |
||||||
|
server.kill() |
||||||
|
return eq( |
||||||
|
{ |
||||||
|
status: status, |
||||||
|
body: body, |
||||||
|
'content-type': headers['content-type'], |
||||||
|
}, |
||||||
|
{ |
||||||
|
status: 500, |
||||||
|
body: { error: 'server failed' }, |
||||||
|
'content-type': 'application/json', |
||||||
|
}, |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
const testFileCreated = async ({ path, ctx, randStr }) => { |
||||||
|
const { server } = await ctx.startServer(path) |
||||||
|
const randomName = randStr() |
||||||
|
await ctx.sendRequest(`/${randomName}`, { |
||||||
|
body: randStr(), |
||||||
|
method: 'POST', |
||||||
|
}) |
||||||
|
const dirName = 'guests' |
||||||
|
const dirPath = join(ctx.tmpPath, dirName) |
||||||
|
let accessWorked = true |
||||||
|
server.kill() |
||||||
|
await fs |
||||||
|
.access(`${dirPath}/${randomName}.json`, fs.constants.F_OK) |
||||||
|
.catch(reason => { |
||||||
|
accessWorked = false |
||||||
|
console.log(reason) |
||||||
|
}) |
||||||
|
return accessWorked |
||||||
|
} |
||||||
|
|
||||||
|
const testFileContent = async ({ path, ctx, randStr }) => { |
||||||
|
const { server } = await ctx.startServer(path) |
||||||
|
const randomName = randStr() |
||||||
|
const body = randStr() |
||||||
|
await ctx.sendRequest(`/${randomName}`, { |
||||||
|
body: body, |
||||||
|
method: 'POST', |
||||||
|
}) |
||||||
|
const dirName = 'guests' |
||||||
|
const dirPath = join(ctx.tmpPath, dirName) |
||||||
|
server.kill() |
||||||
|
let content = '' |
||||||
|
await fs |
||||||
|
.readFile(`./${dirPath}/${randomName}.json`, 'utf8', (err, data) => { |
||||||
|
if (err) { |
||||||
|
console.error(err) |
||||||
|
return 'error when reading file' |
||||||
|
} |
||||||
|
return data |
||||||
|
}) |
||||||
|
.then(data => { |
||||||
|
if (data === 'error when reading file') return |
||||||
|
content = data |
||||||
|
}) |
||||||
|
return body === content |
||||||
|
} |
||||||
|
|
||||||
|
const testBodyOnSuccess = async ({ path, ctx, eq, randStr }) => { |
||||||
|
const { server } = await ctx.startServer(path) |
||||||
|
const randomBody = { message: randStr() } |
||||||
|
const { body } = await ctx.sendRequest(`/${ctx.randomName}`, { |
||||||
|
method: 'POST', |
||||||
|
headers: { |
||||||
|
'content-type': 'application/json', |
||||||
|
}, |
||||||
|
body: JSON.stringify(randomBody), |
||||||
|
}) |
||||||
|
server.kill() |
||||||
|
return eq( |
||||||
|
{ |
||||||
|
body: body, |
||||||
|
}, |
||||||
|
{ |
||||||
|
body: randomBody, |
||||||
|
}, |
||||||
|
) |
||||||
|
} |
||||||
|
tests.push( |
||||||
|
testServerRunning, |
||||||
|
testRightStatusCode, |
||||||
|
testRightContentType, |
||||||
|
testBodyOnSuccess, |
||||||
|
testFileCreated, |
||||||
|
testFileContent, |
||||||
|
testServerFail, |
||||||
|
) |
||||||
|
|
||||||
|
Object.freeze(tests) |
@ -0,0 +1,37 @@ |
|||||||
|
export const tests = [] |
||||||
|
|
||||||
|
const testProperties = () => { |
||||||
|
return ( |
||||||
|
Array.isArray(veterinary.animalKnowledge) && |
||||||
|
typeof veterinary.canTreat === 'function' && |
||||||
|
typeof veterinary.respondClient === 'function' |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
const testCanTreat = () => { |
||||||
|
veterinary.animalKnowledge.push('dog', 'cat', 'elephant') |
||||||
|
return ( |
||||||
|
veterinary.canTreat('dog') && |
||||||
|
veterinary.canTreat('cat') && |
||||||
|
veterinary.canTreat('elephant') && |
||||||
|
!veterinary.canTreat('') && |
||||||
|
!veterinary.canTreat('goldfish') |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
const testRespondClient = () => { |
||||||
|
veterinary.animalKnowledge.push('parrot') |
||||||
|
const vetResponse1 = veterinary.respondClient('Jack', 'parrot') |
||||||
|
const vetResponse2 = veterinary.respondClient('Matias', 'cobra') |
||||||
|
|
||||||
|
return ( |
||||||
|
vetResponse1.includes('Jack') && |
||||||
|
vetResponse1.toLowerCase().includes('yes') && |
||||||
|
vetResponse2.includes('Matias') && |
||||||
|
vetResponse2.toLowerCase().includes('no') |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
tests.push(testProperties, testCanTreat, testRespondClient) |
||||||
|
|
||||||
|
Object.freeze(tests) |
@ -0,0 +1,174 @@ |
|||||||
|
import { places } from './subjects/where-do-we-go/where-do-we-go.data.js' |
||||||
|
|
||||||
|
export const tests = [] |
||||||
|
|
||||||
|
const random = (min, max) => { |
||||||
|
if (!max) { |
||||||
|
max = min |
||||||
|
min = 0 |
||||||
|
} |
||||||
|
min = Math.ceil(min) |
||||||
|
max = Math.floor(max) |
||||||
|
return Math.floor(Math.random() * (max - min + 1)) + min |
||||||
|
} |
||||||
|
|
||||||
|
const getDegree = coordinates => { |
||||||
|
const north = coordinates.includes('N') |
||||||
|
const degree = coordinates.split("'")[0].replace('°', '.') |
||||||
|
return north ? degree : -degree |
||||||
|
} |
||||||
|
|
||||||
|
export const setup = async ({ page }) => { |
||||||
|
return { |
||||||
|
getDirection: async () => |
||||||
|
await page.$eval('.direction', direction => direction.textContent), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const sortedPlaces = places.sort( |
||||||
|
(a, b) => getDegree(b.coordinates) - getDegree(a.coordinates), |
||||||
|
) |
||||||
|
|
||||||
|
const dataNames = sortedPlaces.map(({ name }) => |
||||||
|
name |
||||||
|
.split(',')[0] |
||||||
|
.toLowerCase() |
||||||
|
.split(' ') |
||||||
|
.join('-'), |
||||||
|
) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
const { width, height } = await page.evaluate(() => ({ |
||||||
|
width: window.innerWidth, |
||||||
|
height: window.innerHeight, |
||||||
|
})) |
||||||
|
|
||||||
|
const sections = await page.$$eval('section', sections => |
||||||
|
sections.map(section => { |
||||||
|
return [ |
||||||
|
section.getBoundingClientRect().width, |
||||||
|
section.getBoundingClientRect().height, |
||||||
|
] |
||||||
|
}), |
||||||
|
) |
||||||
|
|
||||||
|
console.log(`Must contain ${places.length} places`) |
||||||
|
// check that the correct amount of sections has been generated
|
||||||
|
eq(sections.length, places.length) |
||||||
|
// check that all the sections are fullscreen-size
|
||||||
|
eq([...new Set(...sections)], [width, height]) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check that the sections have been generated with the correponding images as background,
|
||||||
|
// and sorted in the right order (from the Northest to the Southest)
|
||||||
|
const imageNames = await page.$$eval('section', sections => |
||||||
|
sections.map(section => { |
||||||
|
const test = section.style.background.split('.jpg')[0].split('/') |
||||||
|
return test[test.length - 1] |
||||||
|
}), |
||||||
|
) |
||||||
|
|
||||||
|
console.log(`Must be sorted from North to South`) |
||||||
|
console.log(`Must have the right images in background`) |
||||||
|
eq(imageNames, dataNames) |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check that the location indicator is updating according to the image displayed
|
||||||
|
let step = 1 |
||||||
|
while (step < 6) { |
||||||
|
await page.evaluate(() => { |
||||||
|
window.scrollBy(0, window.innerHeight + 200) |
||||||
|
}) |
||||||
|
|
||||||
|
await page.waitForTimeout(150) |
||||||
|
|
||||||
|
const location = await page.$eval('.location', location => [ |
||||||
|
...location.textContent.split('\n'), |
||||||
|
location.style.color, |
||||||
|
]) |
||||||
|
|
||||||
|
const currentLocationIndex = await page.evaluate(() => |
||||||
|
Math.round(window.scrollY / window.innerHeight), |
||||||
|
) |
||||||
|
const currentLocation = sortedPlaces[currentLocationIndex] |
||||||
|
const { name, coordinates, color } = currentLocation |
||||||
|
const expectedLocation = [name, coordinates, color] |
||||||
|
|
||||||
|
// check that the location indicator and the displayed location contents are matching
|
||||||
|
console.log(`Scroll #${step}: displaying ${location[0]}`) |
||||||
|
eq(location, expectedLocation) |
||||||
|
step++ |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq, getDirection }) => { |
||||||
|
// check that the compass is pointing 'S' when scrolling down
|
||||||
|
await page.evaluate(() => { |
||||||
|
window.scrollBy(0, window.innerHeight) |
||||||
|
}) |
||||||
|
|
||||||
|
await page.waitForTimeout(100) |
||||||
|
|
||||||
|
const direction = (await getDirection()).includes('S') |
||||||
|
? 'S' |
||||||
|
: await getDirection() |
||||||
|
|
||||||
|
console.log('Scroll down: pointing', direction) |
||||||
|
eq(direction, 'S') |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq, getDirection }) => { |
||||||
|
// check that the compass is pointing 'N' when scrolling up
|
||||||
|
await page.evaluate(() => { |
||||||
|
window.scrollBy(0, -100) |
||||||
|
}) |
||||||
|
|
||||||
|
await page.waitForTimeout(100) |
||||||
|
|
||||||
|
const direction = (await getDirection()).includes('N') |
||||||
|
? 'N' |
||||||
|
: await getDirection() |
||||||
|
|
||||||
|
console.log('Scroll up: pointing', direction) |
||||||
|
eq(direction, 'N') |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check that the location target attribute is set to '_blank' to open a new tab
|
||||||
|
const locationTarget = await page.$eval('.location', ({ target }) => target) |
||||||
|
console.log( |
||||||
|
`Location <a> tag target attribute ${ |
||||||
|
locationTarget === '_blank' ? '' : 'not ' |
||||||
|
}set to open a new tab`,
|
||||||
|
) |
||||||
|
eq(locationTarget, '_blank') |
||||||
|
}) |
||||||
|
|
||||||
|
tests.push(async ({ page, eq }) => { |
||||||
|
// check that the location href is valid
|
||||||
|
const location = await page.$eval('.location', ({ href, textContent }) => ({ |
||||||
|
href, |
||||||
|
textContent, |
||||||
|
})) |
||||||
|
const isValidUrl = location.href.includes('google.com/maps') |
||||||
|
const coords = location.textContent.split('\n')[1] |
||||||
|
const convertedUrl = location.href |
||||||
|
.split('%C2%B0') |
||||||
|
.join('°') |
||||||
|
.split('%22') |
||||||
|
.join('"') |
||||||
|
.split('%20') |
||||||
|
.join(' ') |
||||||
|
const isValidCoordinates = convertedUrl.includes(coords) |
||||||
|
|
||||||
|
console.log('URL', location.href, isValidUrl ? 'valid' : 'invalid') |
||||||
|
eq(isValidUrl, true) |
||||||
|
console.log( |
||||||
|
`Matching coordinates ${coords} ${ |
||||||
|
isValidCoordinates ? '' : 'not ' |
||||||
|
}found in URL`,
|
||||||
|
) |
||||||
|
eq(isValidCoordinates, true) |
||||||
|
}) |
@ -0,0 +1,99 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# Unofficial Bash Strict Mode |
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
FILENAME="student/append-output.sh" |
||||||
|
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd) |
||||||
|
|
||||||
|
if test ! -e append-output; then |
||||||
|
mkdir append-output |
||||||
|
cat <<EOF >append-output/results.txt |
||||||
|
"In the End" - Linkin Park |
||||||
|
"Crawling" - Linkin Park |
||||||
|
"Elevation" - U2 |
||||||
|
"Get the Party Started" - Pink |
||||||
|
"Lady Marmalade" - Christina Aguilera, Lil' Kim, Mya, Pink |
||||||
|
EOF |
||||||
|
cat <<EOF >append-output/songs.txt |
||||||
|
"Breathe" - Faith Hill |
||||||
|
"It Wasn't Me" - Shaggy featuring Ricardo "RikRok" Ducent |
||||||
|
"Hanging by a Moment" - Lifehouse |
||||||
|
"Shape of My Heart" - Backstreet Boys |
||||||
|
"Thank You" - Dido |
||||||
|
"I'm Like a Bird" - Nelly Furtado |
||||||
|
"Family Affair" - Mary J. Blige |
||||||
|
"Fallin'" - Alicia Keys |
||||||
|
"All for You" - Janet Jackson |
||||||
|
"I Wanna Know" - Joe |
||||||
|
"U Remind Me" - Usher |
||||||
|
"U Got It Bad" - Usher |
||||||
|
"I'm a Believer" - Smash Mouth |
||||||
|
"Get the Party Started" - Pink |
||||||
|
"Wherever You Will Go" - The Calling |
||||||
|
"In the End" - Linkin Park |
||||||
|
"Loser" - Beck |
||||||
|
"Get Ur Freak On" - Missy Elliott |
||||||
|
"I'm Real" - Jennifer Lopez |
||||||
|
"Butterfly" - Crazy Town |
||||||
|
"Crawling" - Linkin Park |
||||||
|
"I'm a Slave 4 U" - Britney Spears |
||||||
|
"Elevation" - U2 |
||||||
|
"Lady Marmalade" - Christina Aguilera, Lil' Kim, Mya, Pink |
||||||
|
"Play" - Jennifer Lopez |
||||||
|
"I'm Just a Kid" - Simple Plan |
||||||
|
"Imitation of Life" - R.E.M. |
||||||
|
"Big Pimpin'" - Jay-Z |
||||||
|
"Stutter" - Joe featuring Mystikal |
||||||
|
"I Wish" - R. Kelly |
||||||
|
"This Is the Night" - Clay Aiken |
||||||
|
"Hella Good" - No Doubt |
||||||
|
"I Know" - Dionne Farris |
||||||
|
"I'll Be Missing You" - Puff Daddy and Faith Evans featuring 112 |
||||||
|
"I Try" - Macy Gray |
||||||
|
"Thong Song" - Sisqo |
||||||
|
"Survivor" - Destiny's Child |
||||||
|
"I Want It That Way" - Backstreet Boys |
||||||
|
"Bad Day" - Daniel Powter |
||||||
|
"I'm Like a Bird" - Nelly Furtado |
||||||
|
"I Need to Know" - Marc Anthony |
||||||
|
"Follow Me" - Uncle Kracker |
||||||
|
"Hemorrhage (In My Hands)" - Fuel |
||||||
|
"Soak Up the Sun" - Sheryl Crow |
||||||
|
"I Hope You Dance" - Lee Ann Womack |
||||||
|
"Can't Get You Out of My Head" - Kylie Minogue |
||||||
|
"I Just Wanna Love U (Give It 2 Me)" - Jay-Z |
||||||
|
"My Love Is Your Love" - Whitney Houston |
||||||
|
"Bounce with Me" - Lil' Bow Wow |
||||||
|
"Where the Party At" - Jagged Edge |
||||||
|
"I'm Already There" - Lonestar |
||||||
|
"I Don't Want to Miss a Thing" - Aerosmith |
||||||
|
"If You Could Read My Mind" - Stars on 54 |
||||||
|
"My Way" - Usher |
||||||
|
"Always on Time" - Ja Rule featuring Ashanti |
||||||
|
EOF |
||||||
|
fi |
||||||
|
challenge() { |
||||||
|
$(cd "$1" && bash "$script_dirS"/$FILENAME) |
||||||
|
submitted=$(cat $1/results.txt) |
||||||
|
rm $1"/results.txt" |
||||||
|
$(cd "$1" && bash "$script_dirS"/solutions/append-output.sh) |
||||||
|
expected=$(cat $1/results.txt) |
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
||||||
|
} |
||||||
|
|
||||||
|
if [ -s ${FILENAME} ]; then |
||||||
|
if [[ $(cat $FILENAME | grep "cat <<EOF >results.txt" | wc -l) -ne 0 ]]; then |
||||||
|
echo "cheating is not allowed in this exercise!" |
||||||
|
exit 1 |
||||||
|
elif |
||||||
|
[[ $(cat $FILENAME | grep echo | wc -l) -ne 0 ]] |
||||||
|
then |
||||||
|
echo "cheating is not allowed in this exercise!" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
fi |
||||||
|
|
||||||
|
challenge append-output |
||||||
|
rm -r append-output |
@ -0,0 +1,30 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
|
||||||
|
# Unofficial Bash Strict Mode |
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
|
||||||
|
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd) |
||||||
|
|
||||||
|
challenge() { |
||||||
|
submitted=$(bash "$script_dirS"/student/array-selector.sh "$@") |
||||||
|
expected=$(bash "$script_dirS"/solutions/array-selector.sh "$@") |
||||||
|
|
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
||||||
|
} |
||||||
|
|
||||||
|
# Test with numbers - out of range included |
||||||
|
for num in {0..6} |
||||||
|
do |
||||||
|
challenge $num |
||||||
|
done |
||||||
|
|
||||||
|
# Test with a value that is not a digit |
||||||
|
|
||||||
|
challenge "abc" |
||||||
|
|
||||||
|
# Test with wrong number of arguments |
||||||
|
|
||||||
|
challenge |
@ -0,0 +1,54 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# Unofficial Bash Strict Mode |
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
|
||||||
|
FILENAME="student/auto-exec-bin.sh" |
||||||
|
BINFILE="~/myBins/01exec" |
||||||
|
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd) |
||||||
|
|
||||||
|
setupbin() { |
||||||
|
if [ -f ${BINFILE} ]; then |
||||||
|
echo "bin already exists!" |
||||||
|
else |
||||||
|
mkdir -p ~/myBins |
||||||
|
echo "echo Hello 01 Scripting Pool" > $HOME/myBins/01exec |
||||||
|
fi |
||||||
|
chmod +x $HOME/myBins/01exec |
||||||
|
} |
||||||
|
|
||||||
|
challenge() { |
||||||
|
OLD_PATH=$PATH |
||||||
|
# run soultion script |
||||||
|
source "$script_dirS"/$FILENAME |
||||||
|
submitted=$(cd / && 01exec) |
||||||
|
|
||||||
|
PATH=$OLD_PATH |
||||||
|
# run student script |
||||||
|
source "$script_dirS"/solutions/auto-exec-bin.sh |
||||||
|
expected=$(cd / && 01exec) |
||||||
|
|
||||||
|
# diff |
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
||||||
|
} |
||||||
|
|
||||||
|
# True if FILE exists and is a regular file |
||||||
|
if [ -f ${FILENAME} ]; then |
||||||
|
# FILE exists and it's not empty |
||||||
|
if [ -s ${FILENAME} ]; then |
||||||
|
if [[ $(cat $FILENAME | grep echo | wc -l) -ne 0 ]]; then |
||||||
|
echo "echo is not allowed in this exercise!" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
setupbin |
||||||
|
challenge |
||||||
|
else |
||||||
|
echo "The file exist but is empty" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
else |
||||||
|
echo "File does not exist" |
||||||
|
exit 1 |
||||||
|
fi |
@ -0,0 +1,20 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# Unofficial Bash Strict Mode |
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
|
||||||
|
print_content() { |
||||||
|
mkdir -p uncompressed |
||||||
|
tar -xpf auto-jobs.tar -C uncompressed |
||||||
|
cat -e uncompressed/$1 |
||||||
|
} |
||||||
|
|
||||||
|
for i in 1 2 3 4 |
||||||
|
do |
||||||
|
submitted=$(cd student && print_content task$i) |
||||||
|
expected=$(cd solutions && print_content task$i) |
||||||
|
|
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
||||||
|
done |
@ -0,0 +1,34 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# Unofficial Bash Strict Mode |
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
|
||||||
|
FILENAME="student/bin-status.sh" |
||||||
|
|
||||||
|
|
||||||
|
challenge() { |
||||||
|
submitted=$(eval "$@" >/dev/null 2>&1 ; source $FILENAME) |
||||||
|
expected=$(eval "$@" >/dev/null 2>&1 ; source solutions/bin-status.sh) |
||||||
|
|
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
# True if FILE exists and is a regular file |
||||||
|
if [ -f ${FILENAME} ]; then |
||||||
|
# FILE exists and it's not empty |
||||||
|
if [ -s ${FILENAME} ]; then |
||||||
|
challenge true |
||||||
|
challenge false |
||||||
|
challenge ls -l |
||||||
|
challenge ls asdasdasdasdad |
||||||
|
else |
||||||
|
echo "The file exist but is empty" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
else |
||||||
|
echo "File does not exist" |
||||||
|
exit 1 |
||||||
|
fi |
@ -0,0 +1,28 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# Unofficial Bash Strict Mode |
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
|
||||||
|
FILENAME="student/burial.sh" |
||||||
|
|
||||||
|
# True if FILE exists and is a regular file |
||||||
|
if [ -f ${FILENAME} ]; then |
||||||
|
# FILE exists and it's not empty |
||||||
|
if [ -s ${FILENAME} ]; then |
||||||
|
if [[ $(cat $FILENAME | grep echo | wc -l) -ne 0 ]]; then |
||||||
|
echo "echo is not allowed in this exercise!" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
submitted=$(bash $FILENAME) |
||||||
|
expected=$(bash solutions/burial.sh) |
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
||||||
|
else |
||||||
|
echo "The file exist but is empty" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
else |
||||||
|
echo "File does not exist" |
||||||
|
exit 1 |
||||||
|
fi |
@ -0,0 +1,86 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
|
||||||
|
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd) |
||||||
|
|
||||||
|
challenge() { |
||||||
|
submitted="./calculator.sh $@ |
||||||
|
" |
||||||
|
expected="./calculator.sh $@ |
||||||
|
" |
||||||
|
submitted+=$(2>&1 bash "$script_dirS"/student/calculator.sh "$@") |
||||||
|
submitted+=" |
||||||
|
exit status: $?" |
||||||
|
expected+=$(2>&1 bash "$script_dirS"/solutions/calculator.sh "$@") |
||||||
|
expected+=" |
||||||
|
exit status: $?" |
||||||
|
|
||||||
|
diff -U 1 <(echo "$submitted") <(echo "$expected") |
||||||
|
if [ $? != 0 ] |
||||||
|
then |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
} |
||||||
|
|
||||||
|
# Check if student uses case statement |
||||||
|
if [[ $(cat "$script_dirS"/student/calculator.sh | grep case | wc -l) -eq 0 ]] |
||||||
|
then |
||||||
|
echo "Error: the use of case statement is mandatory" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
|
||||||
|
# Valid inputs |
||||||
|
challenge "15" "+" "10" |
||||||
|
challenge "15" "-" "10" |
||||||
|
challenge "15" "/" "10" |
||||||
|
challenge "15" "*" "10" |
||||||
|
|
||||||
|
challenge "3491" "+" "-67" |
||||||
|
challenge "3491" "-" "-67" |
||||||
|
challenge "3491" "/" "-67" |
||||||
|
challenge "3491" "*" "-67" |
||||||
|
|
||||||
|
challenge "-3491" "+" "-67" |
||||||
|
challenge "-3491" "-" "-67" |
||||||
|
challenge "-3491" "/" "-67" |
||||||
|
challenge "-3491" "*" "-67" |
||||||
|
|
||||||
|
# Invalid inputs |
||||||
|
|
||||||
|
challenge |
||||||
|
challenge "-3491" "*" "-67" "10" "12" |
||||||
|
|
||||||
|
challenge "20" "/" "0" |
||||||
|
challenge "20" "@" "10" |
||||||
|
challenge "10" "*" "67invalid" |
||||||
|
|
||||||
|
# Test operators functions |
||||||
|
|
||||||
|
source $script_dirS"/student/calculator.sh" 10 + 10 >/dev/null 2>&1 |
||||||
|
|
||||||
|
if [ $(do_add 11 14) != 25 ] |
||||||
|
then |
||||||
|
echo "error in function do_add" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
|
||||||
|
if [ $(do_sub 11 14) != -3 ] |
||||||
|
then |
||||||
|
echo "error in function do_sub" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
|
||||||
|
if [ $(do_mult 3 5) != 15 ] |
||||||
|
then |
||||||
|
echo "error in function do_mult" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
|
||||||
|
if [ $(do_divide 50 5) != 10 ] |
||||||
|
then |
||||||
|
echo "error in function do_divide" |
||||||
|
exit 1 |
||||||
|
fi |
@ -0,0 +1,16 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# Unofficial Bash Strict Mode |
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
|
||||||
|
print_content() { |
||||||
|
mkdir -p uncompressed |
||||||
|
tar -xpf change-struct.tar -C uncompressed |
||||||
|
tree uncompressed |
||||||
|
} |
||||||
|
|
||||||
|
submitted=$(cd student && print_content) |
||||||
|
expected=$(cd solutions && print_content) |
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
@ -0,0 +1,28 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
|
||||||
|
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd) |
||||||
|
|
||||||
|
challenge() { |
||||||
|
submitted="./check-user.sh $@ |
||||||
|
" |
||||||
|
expected="./check-user.sh $@ |
||||||
|
" |
||||||
|
submitted+=$(bash 2>&1 "$script_dirS"/student/check-user.sh "$@") |
||||||
|
expected+=$(bash 2>&1 "$script_dirS"/solutions/check-user.sh "$@") |
||||||
|
|
||||||
|
diff -U 1 <(echo "$submitted") <(echo "$expected") |
||||||
|
} |
||||||
|
|
||||||
|
challenge "-i" "root" |
||||||
|
challenge "-e" "root" |
||||||
|
|
||||||
|
challenge "-i" "unknown_not_found" |
||||||
|
challenge "-e" "unknown_not_found" |
||||||
|
|
||||||
|
challenge |
||||||
|
challenge "-i" "root" "too" "many" "args" |
||||||
|
challenge "-t" "root" |
@ -0,0 +1,27 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# Unofficial Bash Strict Mode |
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
|
||||||
|
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd) |
||||||
|
|
||||||
|
challenge() { |
||||||
|
submitted=$(bash $script_dirS/student/comparator.sh "$@") |
||||||
|
expected=$(bash $script_dirS/solutions/comparator.sh "$@") |
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
||||||
|
} |
||||||
|
|
||||||
|
for i in $(seq 1 10); do |
||||||
|
n1=$(shuf -i 1-20 -n 1) |
||||||
|
n2=$(shuf -i 1-30 -n 1) |
||||||
|
challenge $n1 $n2 |
||||||
|
done |
||||||
|
|
||||||
|
challenge "0" "0" |
||||||
|
challenge "10" "10" |
||||||
|
challenge "-11" "-11" |
||||||
|
challenge "14" |
||||||
|
challenge "-11" "-11" "4" |
||||||
|
challenge "as" "str" |
@ -0,0 +1,18 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# Unofficial Bash Strict Mode |
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
|
||||||
|
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd) |
||||||
|
|
||||||
|
challenge() { |
||||||
|
submitted=$(cd "$1" && bash "$script_dirS"/student/count-files.sh) |
||||||
|
expected=$(cd "$1" && bash "$script_dirS"/solutions/count-files.sh) |
||||||
|
|
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
||||||
|
} |
||||||
|
|
||||||
|
challenge cl-camp5/folder1 |
||||||
|
challenge cl-camp5/folder2 |
@ -0,0 +1,11 @@ |
|||||||
|
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum venenatis rutrum vehicula. Phasellus vehicula sagittis nibh, sed congue turpis suscipit a. Etiam sed nibh risus. Aenean aliquet urna ornare nisi bibendum, nec vehicula quam sagittis. Quisque varius vel tortor et rhoncus. Aliquam erat volutpat. Quisque sit amet cursus tortor. |
||||||
|
|
||||||
|
Aenean egestas dui est, eu vehicula mi vehicula vitae. Nunc rhoncus sit amet libero id tempus. Fusce mollis at urna sit amet iaculis. Ut dapibus sed enim eu fringilla. Proin pretium, orci eget mollis viverra, nibh nunc feugiat purus, vel consequat felis magna ac felis. Nam gravida imperdiet arcu. Aliquam est felis, iaculis non felis id, cursus convallis metus. Phasellus ac varius arcu. Aenean congue nisi ut urna tempor tempor. Mauris sit amet purus non risus auctor ultricies imperdiet vitae ex. Vestibulum maximus eros quam, a luctus massa condimentum ac. In commodo consequat diam, at rutrum massa interdum non. In sed rutrum dolor. |
||||||
|
|
||||||
|
Ut auctor porta felis, luctus ullamcorper ipsum pulvinar ac. Curabitur non pharetra purus. Nulla euismod leo nec massa convallis, ac facilisis orci lacinia. Maecenas eget magna tristique, eleifend est vehicula, mattis lectus. Etiam lectus sem, rutrum in nisl vitae, congue tincidunt urna. Praesent luctus auctor arcu, quis tristique ex suscipit eleifend. Phasellus congue tempus nisi vitae suscipit. Quisque ut luctus ipsum. Duis eget consequat massa. Vestibulum aliquam ligula quis felis imperdiet luctus. Phasellus efficitur gravida elementum. Sed quis mi tortor. |
||||||
|
|
||||||
|
Pellentesque luctus porttitor est ac tristique. Nulla facilisi. Duis eu tellus ac lectus vehicula tristique. Quisque magna ex, tristique at sollicitudin sed, blandit consequat erat. In hac habitasse platea dictumst. Mauris sodales, enim in scelerisque ullamcorper, leo lectus pharetra justo, eget dignissim eros libero vitae sapien. Donec elementum varius feugiat. Donec porta eu tellus non suscipit. Integer eu diam ultricies, sodales dolor a, ornare odio. Nulla congue commodo libero, facilisis aliquam nulla pellentesque nec. Aliquam et nisi facilisis, mollis est eu, ultricies metus. Praesent rutrum eros eu neque dapibus gravida. Nam et tortor congue, egestas leo et, euismod erat. Pellentesque ut efficitur risus. Integer sodales convallis arcu, eget mattis purus condimentum eu. Mauris urna neque, ornare in convallis eget, viverra varius lectus. |
||||||
|
|
||||||
|
Sed dapibus nibh neque, eget consequat odio placerat ac. Duis vel nunc erat. Suspendisse vel ornare leo. Sed ut augue turpis. Maecenas ullamcorper a est non pretium. Nulla venenatis interdum pretium. Nulla ut velit vel magna blandit lacinia. Etiam dictum vestibulum nulla non gravida. Pellentesque cursus enim euismod massa congue, vitae ullamcorper urna bibendum. Phasellus in tempus ex. Etiam quis ante a erat bibendum auctor. |
@ -0,0 +1 @@ |
|||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque eget nisl leo. Donec gravida tristique velit sit amet vulputate. In bibendum nisi tortor. Cras ullamcorper velit non mauris dapibus blandit. Maecenas rutrum semper mauris sed hendrerit. Morbi pellentesque est at enim suscipit semper. Donec tincidunt sem velit, sit amet cursus quam tincidunt eu. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vivamus non libero vel est posuere ullamcorper sit amet nec lectus. Quisque sagittis augue euismod nulla ultricies elementum sit amet eu leo. |
@ -0,0 +1,199 @@ |
|||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce accumsan nisi vel mi sodales varius. Morbi in maximus ipsum. Maecenas pulvinar mi efficitur nulla luctus, quis tempus neque finibus. Curabitur ut tristique lacus. Donec a arcu vel mi hendrerit fermentum vitae ut urna. Nulla dapibus lacus in tellus tincidunt aliquam. Nullam tortor lorem, posuere sed nibh sed, fringilla mollis justo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec ultricies ac magna sed hendrerit. Donec nec venenatis sapien. Vivamus maximus diam at lorem interdum ullamcorper at eu mauris. Pellentesque ante tortor, sagittis in euismod non, mollis at arcu. Vestibulum vitae eleifend nisl, cursus accumsan felis. Integer a rhoncus sem, at aliquam lectus. |
||||||
|
|
||||||
|
Vivamus molestie hendrerit efficitur. Vestibulum ut hendrerit mi, sed semper arcu. Suspendisse ullamcorper lobortis ante a tristique. Curabitur a placerat erat. Phasellus dapibus vitae ante vitae sollicitudin. Cras porta sit amet ante sed viverra. Curabitur ut elit tincidunt, facilisis ligula id, condimentum erat. Integer sit amet congue elit. |
||||||
|
|
||||||
|
Praesent laoreet suscipit libero finibus convallis. Integer dapibus, sapien ut porta mollis, tortor sapien pellentesque ligula, at consequat mi metus sed nisi. Nulla lacinia nisi vel velit gravida, eu gravida metus faucibus. Phasellus blandit cursus metus quis volutpat. Pellentesque tempus aliquet lorem id varius. Phasellus placerat iaculis porta. Nulla nunc libero, lacinia sit amet odio pretium, malesuada molestie dui. In hac habitasse platea dictumst. Nulla congue consectetur nulla, vitae euismod urna. Aliquam massa risus, elementum ut fringilla mollis, elementum ut neque. Donec odio justo, tempor sit amet commodo nec, malesuada ultricies magna. Vivamus congue ullamcorper velit, nec pulvinar nisi fermentum eu. Morbi sit amet mi egestas, pulvinar augue ut, euismod leo. Ut auctor condimentum elementum. |
||||||
|
|
||||||
|
Sed rhoncus facilisis sem, a congue ex congue ac. Sed dictum est lorem, eget fermentum enim molestie ut. Aenean sed sagittis nunc, in dapibus justo. Sed faucibus hendrerit felis. Duis aliquam tempor erat at porta. Morbi bibendum bibendum risus, non mattis nisl venenatis quis. Aliquam erat volutpat. Nunc ac neque arcu. Vivamus et ipsum maximus, porttitor ante in, pretium mauris. Suspendisse molestie tempus ante ut interdum. Nulla sed ex vehicula nisl fermentum viverra eget a sapien. Aliquam tempus scelerisque dignissim. |
||||||
|
|
||||||
|
Pellentesque massa lorem, rutrum a lorem et, vehicula fermentum orci. Mauris quis viverra eros. Donec lobortis iaculis justo non sollicitudin. Nullam scelerisque volutpat ultrices. Etiam fermentum congue tortor nec molestie. Sed laoreet nisi nec aliquam condimentum. Sed hendrerit tempor lobortis. Sed tempor magna at euismod semper. Donec nec felis orci. Donec sollicitudin placerat lorem, quis semper elit mollis ac. Morbi semper eu odio ac gravida. |
||||||
|
|
||||||
|
Aliquam sollicitudin nisi nec nibh hendrerit fermentum. Quisque laoreet, enim sit amet finibus lobortis, nulla nibh laoreet leo, quis elementum nulla nulla in dolor. Sed id porta enim. Donec eu porttitor purus. Nunc ac augue sagittis, pretium sapien ut, aliquam purus. Curabitur lacus velit, hendrerit nec sagittis sit amet, vulputate sit amet magna. Sed ut molestie magna, sit amet dapibus felis. Proin aliquet nec neque vel molestie. Mauris dictum risus nec tincidunt maximus. Proin sagittis nisi lorem, vel vestibulum purus tincidunt id. Donec pharetra nisi lacus, quis ornare odio vestibulum non. Nunc ut condimentum purus, eget porta libero. In urna nulla, aliquam nec hendrerit a, sodales vel purus. |
||||||
|
|
||||||
|
Suspendisse non semper enim. Nunc varius est ac arcu cursus, accumsan varius lorem porttitor. Morbi viverra diam tortor, ut sodales eros aliquam id. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec blandit sit amet metus sit amet cursus. In faucibus sapien ut dolor blandit, a sollicitudin urna viverra. Vivamus posuere tellus ac elit lobortis, vel dignissim felis sodales. Aliquam ut arcu ligula. Proin nec magna semper, condimentum sem at, fermentum est. Morbi sit amet suscipit lectus. Nam porttitor libero ipsum, in sagittis est efficitur sagittis. Quisque eleifend neque id eros dapibus commodo. Nam in diam vel felis bibendum cursus non ac quam. Sed id sapien mollis, ultricies nisi sed, maximus sapien. Nulla ullamcorper at ante et gravida. Duis quis tortor libero. |
||||||
|
|
||||||
|
Cras vitae mi eget metus scelerisque malesuada. Nulla tempor ipsum enim. Phasellus congue, eros nec dictum dignissim, elit lacus bibendum augue, et pharetra lacus nisi vitae arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. Integer condimentum lacinia nulla in pretium. Vestibulum ipsum ante, rhoncus vitae quam id, faucibus porttitor odio. Donec vulputate, nunc vel bibendum faucibus, mauris metus rutrum lacus, eget pretium ex lacus eu ante. Duis nec nulla cursus, lacinia ipsum ut, placerat nulla. Nulla facilisi. Praesent efficitur nunc a odio pretium fringilla. Nullam viverra ornare mi a feugiat. Proin at posuere orci. Nulla placerat turpis at sem aliquet consequat. Pellentesque in velit id turpis aliquet tempor. |
||||||
|
|
||||||
|
Fusce ullamcorper ultrices mauris, vitae convallis purus consectetur in. Mauris ac nibh arcu. Pellentesque blandit rutrum pretium. Quisque auctor ipsum blandit ante scelerisque, nec hendrerit enim eleifend. Aliquam eros enim, finibus vitae semper a, lobortis ut lorem. Maecenas eget nunc rutrum, vulputate arcu a, suscipit felis. Proin ac nisi neque. Phasellus placerat vestibulum tortor sed tincidunt. Praesent suscipit felis nec purus molestie bibendum. Aenean ornare tincidunt eros fermentum lobortis. Nunc quis augue in ante sodales consectetur id a nisi. |
||||||
|
|
||||||
|
Etiam elit mi, iaculis id urna et, blandit euismod lectus. Proin pharetra, massa vel cursus placerat, dui sapien ullamcorper felis, sed placerat enim risus in neque. Ut metus tellus, bibendum condimentum urna ut, egestas malesuada mauris. Maecenas vel efficitur lacus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Vestibulum dictum a quam quis consequat. Sed nec libero iaculis, mollis enim non, commodo libero. Nunc laoreet interdum purus at tincidunt. Proin rutrum diam ex, nec fringilla ante consequat id. Suspendisse potenti. Vivamus in justo libero. Sed sodales iaculis tellus et ornare. Fusce fermentum interdum libero ut pharetra. Sed eget venenatis mauris. |
||||||
|
|
||||||
|
Suspendisse commodo posuere augue, vitae rutrum massa fermentum vel. Nunc dignissim lobortis convallis. Nam hendrerit egestas aliquam. Ut efficitur sem vitae libero iaculis condimentum. Nam ac dui et ante posuere interdum pulvinar ut ipsum. Integer dictum, tortor in blandit vestibulum, tortor quam mollis diam, et dictum felis tellus quis felis. Mauris sed ex aliquet, sollicitudin enim quis, semper enim. Nam feugiat ut diam ut pulvinar. |
||||||
|
|
||||||
|
Cras eleifend sollicitudin mi vitae molestie. Vivamus facilisis maximus nulla, et vehicula dui sagittis at. Mauris eget augue orci. Sed vitae magna et velit elementum blandit. Curabitur aliquet rutrum mi, finibus aliquet eros egestas a. Ut vestibulum, purus vel lobortis tempus, odio neque lobortis enim, quis pellentesque neque justo eget velit. Aliquam erat volutpat. Aenean vel cursus turpis. Integer vel justo eu nunc dignissim aliquam. Nam vitae diam id lorem interdum vehicula. Donec ut erat molestie sem lacinia efficitur. |
||||||
|
|
||||||
|
Duis vestibulum, ipsum vitae blandit ullamcorper, erat ex sagittis elit, ut elementum dui metus non velit. Praesent semper magna non magna vestibulum, et tempus tortor mattis. Nam ut risus bibendum, consequat mi non, congue arcu. Duis aliquam facilisis massa, et aliquet massa gravida a. Donec et ex orci. Cras mollis mi elit, nec auctor justo semper ut. Curabitur euismod interdum erat. Ut egestas turpis vel magna dictum sagittis. Quisque eu scelerisque ante, pellentesque gravida orci. Vivamus in fermentum ipsum. Vestibulum eu commodo sem. Suspendisse in lectus vel massa tincidunt pharetra sed eget eros. Sed sollicitudin egestas nisl. Aliquam consequat erat in imperdiet pharetra. Vestibulum fermentum dolor tortor, id faucibus lacus blandit mattis. Sed laoreet leo vitae lacinia pretium. |
||||||
|
|
||||||
|
In non lorem sem. Aliquam in finibus ipsum. Nunc et interdum elit. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin posuere bibendum turpis, mattis dignissim dolor convallis vel. Maecenas ac erat quis magna mattis consectetur interdum ornare risus. Curabitur quis neque mauris. |
||||||
|
|
||||||
|
Cras vitae mollis nibh, malesuada vehicula velit. Pellentesque euismod, lacus sed sodales mattis, ipsum ex egestas mauris, non sagittis elit dui nec sem. In vitae fermentum erat. Pellentesque velit diam, pellentesque sit amet dolor ac, dictum vestibulum felis. Nulla hendrerit ex vitae molestie semper. Nam vestibulum accumsan odio, sit amet suscipit ex lacinia a. Quisque rutrum dignissim nunc, ut vehicula nulla scelerisque vel. Integer sollicitudin tempus nibh in vestibulum. Donec non posuere leo. Pellentesque malesuada ullamcorper vulputate. Nam iaculis lectus vel feugiat dictum. In pellentesque purus lorem, ut auctor urna vestibulum sed. Nulla facilisi. In id metus vitae ligula sollicitudin dignissim. Ut commodo vehicula odio, at aliquam arcu volutpat id. |
||||||
|
|
||||||
|
Nunc sed risus molestie, tincidunt tortor ac, ornare mauris. Maecenas vel nisi ac sem malesuada volutpat. Suspendisse finibus, elit in semper sagittis, sapien nisi bibendum nisi, non porta est nulla at eros. Phasellus tristique ex lectus, et aliquet ante vehicula vitae. Duis a tempus enim, vel porttitor velit. Aliquam lacinia augue nec justo ultricies pharetra. Fusce eros dolor, suscipit ut sapien sit amet, sodales vestibulum mauris. Aenean eget sem justo. Quisque consectetur tempor nibh a pellentesque. Nulla fermentum nibh ac tristique mollis. |
||||||
|
|
||||||
|
Sed eget arcu ac purus consequat tincidunt. Fusce auctor rhoncus magna eget bibendum. Cras tempor imperdiet lacus id vehicula. Pellentesque ornare augue nec eros dictum, at ultrices justo suscipit. Aliquam consequat, ex sit amet gravida ultrices, arcu odio finibus tellus, vitae iaculis purus est a est. Fusce vulputate nisi at neque facilisis rutrum. Curabitur sed consectetur sapien, et dapibus mi. |
||||||
|
|
||||||
|
Nunc arcu lorem, pharetra quis mattis non, iaculis vel magna. Phasellus consectetur elit nec iaculis pellentesque. Phasellus lobortis ex ex, sed imperdiet ante posuere a. Phasellus volutpat dui ut orci placerat, id laoreet libero sagittis. Nulla dignissim accumsan arcu, a pellentesque mauris ultricies ut. Ut in metus dolor. Vivamus blandit odio urna, sed euismod ex scelerisque elementum. Nunc lobortis efficitur nunc eget suscipit. Nunc at nisi diam. Fusce blandit, est a condimentum placerat, elit nisl malesuada tellus, sit amet aliquet quam enim sed eros. Morbi eget placerat lorem. Nunc ultrices odio nisl, suscipit porttitor est congue eu. Nunc rhoncus risus eleifend, ultrices nisi nec, laoreet felis. |
||||||
|
|
||||||
|
Phasellus consectetur odio id pellentesque sollicitudin. Pellentesque volutpat sem quis malesuada pretium. Vestibulum a felis sit amet nulla lobortis efficitur consectetur at justo. Sed ut arcu vitae nibh eleifend pulvinar nec vulputate est. Donec pretium, elit sed commodo commodo, metus elit volutpat tortor, eleifend bibendum metus augue vel elit. Fusce placerat justo luctus purus condimentum sollicitudin. Donec magna erat, vehicula eget lectus a, dapibus fringilla enim. Donec varius felis at libero ultricies tempus. Donec ligula lacus, fringilla non metus sed, pellentesque malesuada eros. Aliquam vel libero vitae turpis gravida condimentum sed tristique nunc. Maecenas aliquam urna nec dolor vulputate congue. Morbi mattis purus quis nisi dictum, eu ultricies risus euismod. Pellentesque mi velit, imperdiet a cursus nec, consequat ac dui. Suspendisse ullamcorper elit quis turpis porta, non blandit dui auctor. Nullam et diam facilisis, consequat augue pulvinar, molestie orci. |
||||||
|
|
||||||
|
Etiam ac scelerisque nulla. Cras at justo vel enim lacinia sagittis sit amet nec tellus. Nunc convallis commodo pretium. Maecenas condimentum nulla suscipit, commodo neque sit amet, fermentum enim. Curabitur dui diam, gravida in tellus vitae, luctus feugiat nibh. Vestibulum in aliquam tellus. Nunc tempus odio vel lectus vehicula, sit amet lobortis libero condimentum. |
||||||
|
|
||||||
|
Nam dictum, erat at hendrerit tincidunt, nulla lectus convallis sem, a pretium lectus nunc non nulla. Nulla gravida vulputate justo, eu viverra felis laoreet vel. Suspendisse arcu eros, rutrum sit amet molestie vitae, cursus sed lorem. Fusce orci metus, aliquam vel ex sed, rhoncus commodo augue. Donec a eros a nibh feugiat blandit. Proin venenatis pretium pretium. Praesent nec arcu leo. Fusce lacus turpis, porttitor vitae commodo id, hendrerit eget sem. Etiam cursus tincidunt eros ut venenatis. Vestibulum ultricies consectetur leo, eu imperdiet leo ultricies quis. Donec in enim sit amet mi imperdiet dignissim. In egestas interdum risus, sit amet egestas orci lobortis eu. Cras cursus euismod nisi sit amet euismod. Curabitur malesuada venenatis sem ac maximus. Donec mattis viverra euismod. Curabitur aliquet enim tempus dapibus porttitor. |
||||||
|
|
||||||
|
Nulla sit amet volutpat enim. Nam gravida mauris erat, at sagittis odio iaculis quis. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Suspendisse dapibus id velit ac viverra. Nullam diam massa, condimentum in velit at, eleifend finibus nisi. Aliquam ut tellus non massa semper blandit. Maecenas condimentum venenatis sagittis. Sed quis ante a orci mollis dictum. Etiam interdum tempus purus at aliquam. Vestibulum cursus pulvinar est vitae lacinia. Quisque nibh risus, cursus id scelerisque vitae, elementum quis diam. Aliquam pharetra massa a ex ultrices maximus. Morbi laoreet iaculis leo, vitae maximus odio. |
||||||
|
|
||||||
|
Fusce volutpat, lacus non porttitor venenatis, nulla enim consectetur lorem, vel fermentum leo tellus non ex. Quisque pellentesque magna nec nibh blandit tincidunt. Nulla facilisi. Etiam at vulputate metus. Etiam posuere imperdiet urna, non dictum dui finibus laoreet. Vivamus vitae fringilla velit. Suspendisse tortor odio, malesuada eget nibh in, lacinia placerat felis. Fusce id lobortis ipsum, eu posuere erat. Donec vel justo erat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris molestie gravida tellus, vel suscipit neque accumsan sed. Duis ac felis in mi venenatis rutrum non ac massa. Vivamus orci velit, efficitur non arcu quis, cursus gravida quam. Curabitur elementum felis luctus lobortis laoreet. |
||||||
|
|
||||||
|
Donec pellentesque, lorem a imperdiet faucibus, leo lectus porttitor nulla, eget consequat neque ex ut est. Aenean massa tortor, iaculis id libero in, gravida sagittis justo. Duis sit amet placerat sapien, vel dictum quam. Proin maximus quam libero, a dictum mi tincidunt ultrices. Duis lobortis nisi tempor mauris egestas, in condimentum augue rutrum. Vivamus eget libero eu lorem malesuada tincidunt eu vitae nunc. Nam justo diam, eleifend id enim sit amet, eleifend facilisis purus. Phasellus convallis quam vitae augue auctor pretium. Vivamus et tristique arcu. Maecenas et urna porta, varius dui a, scelerisque mi. Fusce eget ex aliquam, commodo augue sed, ornare lacus. Quisque congue dapibus nisl. |
||||||
|
|
||||||
|
Morbi pretium ac arcu nec accumsan. Nullam non cursus neque. Etiam eget mauris congue, faucibus felis sed, bibendum sapien. In efficitur ipsum eget bibendum pharetra. Aliquam gravida, leo ac dapibus feugiat, turpis ante ornare dui, sit amet consequat metus nunc sed nibh. Morbi pellentesque magna a justo vulputate, sed convallis turpis volutpat. Nulla accumsan odio sed nibh vulputate vulputate in quis tellus. Ut quis dolor cursus, accumsan tellus sed, condimentum mauris. Nam ullamcorper nulla in pellentesque aliquet. |
||||||
|
|
||||||
|
Morbi vulputate finibus odio vitae vulputate. Quisque et imperdiet magna. Suspendisse sem nunc, pulvinar ac cursus sed, finibus vitae est. Suspendisse convallis, erat ornare tincidunt eleifend, turpis orci dapibus dolor, vitae mattis massa lectus ac lacus. Nunc id sem tincidunt, dapibus enim eget, tristique ex. In eu dictum enim. Curabitur ut efficitur enim. Integer ac eros mi. Pellentesque tempus hendrerit nunc, quis placerat quam lobortis at. Ut euismod ornare urna efficitur rhoncus. Duis in lorem enim. |
||||||
|
|
||||||
|
In hac habitasse platea dictumst. Curabitur tincidunt sollicitudin lacus, id interdum velit auctor at. Proin eget risus est. Nunc enim mi, vestibulum ac risus sit amet, tristique rutrum tortor. Fusce quis nulla mattis, fermentum dolor in, semper nulla. Pellentesque vel lectus magna. Nam eget arcu suscipit, varius justo a, ornare quam. Donec vitae sollicitudin nibh, eget iaculis felis. Nullam commodo purus et magna finibus, vitae finibus ipsum aliquam. Vestibulum condimentum dui dolor, ut dictum mi maximus eu. Nunc et pretium sem. Etiam accumsan eu felis in convallis. Nullam pulvinar vestibulum tellus nec rutrum. Suspendisse semper, velit vitae vulputate posuere, nunc dolor egestas neque, at efficitur turpis metus nec leo. Etiam bibendum massa condimentum iaculis vestibulum. Morbi ipsum purus, efficitur eget maximus ac, mattis id massa. |
||||||
|
|
||||||
|
Nam volutpat velit sed nulla ullamcorper facilisis. Sed commodo non turpis sed imperdiet. Pellentesque malesuada nibh eget commodo accumsan. Curabitur iaculis eget sapien ac aliquam. Etiam sed ex lectus. Vivamus et urna erat. Nunc quis efficitur felis. Nulla sagittis lacus a ex tristique, vehicula vulputate enim suscipit. Pellentesque pulvinar vitae leo pellentesque gravida. Sed efficitur pretium interdum. Aenean non rutrum ligula. Etiam ultrices nisl nec tempor efficitur. |
||||||
|
|
||||||
|
Nulla eget nulla dictum, elementum lacus vitae, congue tellus. Proin sit amet pellentesque mauris, sit amet aliquet dolor. Etiam eget nulla ligula. Vestibulum imperdiet pretium mauris, ac tempus erat eleifend at. Ut condimentum fringilla ex ut faucibus. Cras eros nunc, iaculis et maximus vitae, auctor sed sapien. Fusce eu odio non ipsum posuere sagittis. Praesent nunc arcu, vestibulum ut condimentum eu, aliquam eu orci. Fusce in arcu ultricies, dictum enim consequat, facilisis turpis. Pellentesque nunc nisi, ultrices et leo et, consequat tincidunt lorem. |
||||||
|
|
||||||
|
Pellentesque sed faucibus ex. Suspendisse ultrices vulputate dolor. Nam eu dolor suscipit, vehicula sapien non, tempus orci. Quisque eget porta nisi, id tincidunt tellus. Fusce sodales purus et ligula consequat, quis sodales metus tempor. Sed dictum libero placerat nibh tincidunt, eget aliquam orci feugiat. Suspendisse ullamcorper sapien quis porttitor sagittis. Integer vel laoreet elit. Mauris convallis viverra sapien eget accumsan. In hac habitasse platea dictumst. Sed et arcu nibh. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Curabitur quis dictum tortor, at imperdiet lorem. |
||||||
|
|
||||||
|
Sed pulvinar nisi eu ante condimentum rutrum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed malesuada mauris nec dui rhoncus lacinia. Curabitur tincidunt ullamcorper felis ac ullamcorper. Suspendisse dolor est, suscipit ac ligula a, molestie dapibus lectus. Morbi semper, tortor nec tincidunt elementum, nisl tortor consectetur massa, in sodales urna leo sit amet justo. Fusce eu sem eget diam blandit venenatis vel in odio. Vivamus volutpat feugiat sem, sit amet pellentesque orci molestie sed. Proin tincidunt hendrerit nibh, in blandit lacus. Maecenas mattis finibus odio, nec scelerisque ligula aliquam id. Quisque viverra velit eget sem suscipit dapibus. Integer pretium, turpis non commodo condimentum, est felis gravida arcu, vitae elementum lorem erat sed sapien. |
||||||
|
|
||||||
|
Mauris sed urna eu lacus sagittis rhoncus. Sed eleifend id erat quis vestibulum. Suspendisse mattis tempor neque, in vestibulum nisl molestie sit amet. Nulla blandit lectus semper dui accumsan molestie. Ut in dui non augue laoreet imperdiet vitae a orci. Quisque a leo hendrerit, ultrices sem vel, rhoncus augue. Donec quis facilisis enim, ut efficitur enim. Donec finibus libero vitae sem fringilla, at pharetra arcu volutpat. Duis ut mollis dolor. Vestibulum maximus justo nisi, id euismod risus sodales vel. |
||||||
|
|
||||||
|
Sed ut interdum quam, quis mollis lorem. Quisque eget arcu nec justo porta malesuada quis sed odio. Proin tempus enim ac neque efficitur sollicitudin. Fusce a venenatis dui, eget tincidunt sapien. Aliquam sodales hendrerit turpis sit amet commodo. Donec id dui in enim dignissim dignissim a ut lacus. Donec varius bibendum urna sollicitudin aliquet. In hac habitasse platea dictumst. |
||||||
|
|
||||||
|
Donec suscipit cursus porta. Integer interdum ante eget suscipit egestas. Donec ultricies dignissim lectus, a aliquet diam auctor nec. Curabitur sapien turpis, facilisis eleifend metus id, euismod ultricies leo. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus rutrum nisi vel leo vulputate dapibus. Fusce sit amet massa sed velit fermentum maximus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer ante ligula, sollicitudin sit amet facilisis quis, consequat id ex. Sed imperdiet venenatis tellus, vel gravida metus tempor molestie. Phasellus eleifend, neque eu fringilla fermentum, diam odio luctus lacus, ullamcorper viverra urna elit euismod metus. |
||||||
|
|
||||||
|
Vestibulum sed arcu purus. Quisque sed tellus mattis, convallis ipsum eget, finibus turpis. Nulla quis accumsan sapien. Nam risus felis, finibus at sapien ac, commodo pharetra turpis. Vestibulum vel arcu dictum, gravida purus in, volutpat nisi. Vivamus risus felis, faucibus et erat in, tristique mollis nisi. Morbi sollicitudin ipsum vel diam placerat vestibulum. Morbi dictum velit et posuere tincidunt. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque risus eu hendrerit pharetra. |
||||||
|
|
||||||
|
Fusce accumsan tempor est, nec fermentum augue posuere et. Etiam aliquam ullamcorper tortor iaculis condimentum. Aenean vel ullamcorper leo. Quisque consequat sit amet sapien id sodales. Vestibulum pretium dui a eros mollis volutpat. Quisque ac sodales felis. In hac habitasse platea dictumst. |
||||||
|
|
||||||
|
Nullam placerat vestibulum ex sed porta. Pellentesque vel est iaculis, pretium neque eu, condimentum elit. Mauris vitae congue sem. Praesent molestie commodo orci a viverra. Donec consectetur tempus imperdiet. Aenean sed elit at turpis consequat ultricies. Curabitur consequat a orci sit amet feugiat. Donec fringilla, risus sed lobortis efficitur, arcu arcu elementum lorem, eu pulvinar elit eros at massa. |
||||||
|
|
||||||
|
Mauris nec molestie turpis. Sed porttitor, orci vel rutrum accumsan, risus arcu pellentesque ante, a pretium libero sem sed lectus. Quisque ornare ipsum id libero sagittis scelerisque in nec lorem. Nunc sagittis eros diam, in elementum enim mattis vel. Duis rhoncus volutpat aliquam. Mauris hendrerit ex aliquam faucibus vestibulum. In viverra lobortis magna. Nullam tincidunt nunc id neque efficitur, et commodo dolor bibendum. |
||||||
|
|
||||||
|
Duis fermentum massa vitae nisi accumsan, et volutpat libero porttitor. Quisque a nibh et mauris lobortis pharetra nec ac diam. Donec ultricies, tellus nec feugiat porta, felis quam accumsan ipsum, vitae laoreet sapien sem id ligula. Mauris vel erat at sapien consectetur dignissim. Aenean placerat tellus in leo fringilla, non condimentum magna placerat. Ut at justo maximus, tristique quam id, euismod orci. Morbi eget metus erat. Donec ultrices odio eget velit accumsan, vitae blandit leo dignissim. Vivamus quis auctor ipsum. Etiam placerat auctor rhoncus. Curabitur lacus justo, rutrum vitae placerat in, hendrerit ultricies augue. Integer vestibulum bibendum magna vehicula hendrerit. Nulla vehicula leo ut est feugiat imperdiet et id lorem. Maecenas quis lacus lobortis, viverra dui et, dapibus eros. |
||||||
|
|
||||||
|
Fusce ac sapien ut odio blandit pellentesque vitae nec mauris. Aliquam a ipsum id urna condimentum dictum. Proin vehicula bibendum ligula vitae consectetur. Nullam id erat mattis, vehicula velit eu, finibus nisl. Fusce lorem neque, vehicula sed diam non, viverra venenatis ligula. Fusce fermentum turpis at volutpat mollis. Praesent nec lobortis ligula. Nulla magna nulla, consectetur vitae tincidunt ut, eleifend eu nulla. Pellentesque mollis erat et interdum vulputate. |
||||||
|
|
||||||
|
Sed tincidunt pretium dui, et pellentesque ex interdum vitae. Mauris non pretium lectus. Etiam in aliquam dui, nec porttitor turpis. Quisque sagittis, tellus in tincidunt pellentesque, arcu urna fringilla sem, a dictum libero metus ac enim. Mauris mollis nibh quis dui finibus, eu porta arcu efficitur. Vivamus neque ipsum, vulputate a efficitur ut, laoreet eu dui. Sed in nisl mattis, tincidunt orci nec, finibus dui. Donec lobortis vitae nibh eget lobortis. Integer at fringilla dui, consectetur fringilla libero. Pellentesque magna augue, dignissim non sodales nec, convallis quis tellus. Proin tristique, mi et malesuada bibendum, tortor diam consequat felis, et rhoncus quam ante a tellus. Aenean gravida, justo eu fermentum ultricies, elit turpis vehicula felis, nec viverra lorem velit id lorem. |
||||||
|
|
||||||
|
Aenean luctus scelerisque odio at mattis. Suspendisse sit amet malesuada leo. Nunc nec condimentum enim. Maecenas finibus massa diam. Morbi blandit scelerisque enim, id lobortis odio pellentesque in. In quis mi dui. In dignissim, leo et aliquam placerat, erat urna placerat purus, venenatis convallis ligula nibh euismod urna. Ut interdum eget turpis vel tincidunt. Nulla facilisi. Integer scelerisque augue nunc, nec pharetra purus volutpat id. Aliquam bibendum ac enim et tempor. Vivamus sit amet nisi vel lacus tristique euismod at eu eros. Fusce sed nisi ipsum. Aenean felis magna, condimentum non sapien in, pharetra maximus dui. Sed neque felis, sodales sed nisi sollicitudin, congue congue nulla. |
||||||
|
|
||||||
|
Mauris consectetur dolor ac leo luctus venenatis. Proin blandit commodo lacus sed mollis. Nam vel est at justo laoreet finibus vitae vel turpis. Donec at augue libero. Sed accumsan justo sed est tempus blandit. Cras eros diam, pellentesque fermentum tempor in, malesuada non velit. Cras volutpat ante diam. Vivamus luctus tempus nisi, sit amet elementum massa tincidunt vitae. Suspendisse hendrerit, tortor sit amet venenatis interdum, tortor neque dictum nibh, sit amet interdum dui lacus quis lectus. Sed nisi sem, rhoncus sed aliquet sed, finibus et ante. Nulla blandit orci eu nibh ullamcorper porta. Praesent id magna id neque cursus facilisis. |
||||||
|
|
||||||
|
Proin convallis, ligula eu fringilla tempus, risus felis sagittis quam, in tempor nisi magna ac risus. Sed imperdiet accumsan magna. Mauris maximus diam eget tincidunt luctus. Duis libero risus, molestie vitae orci consectetur, elementum tristique nisl. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Duis quis diam nunc. Praesent iaculis lacus ut diam tristique consectetur. Vivamus dui ante, mattis eget eros a, tincidunt lacinia risus. Ut ultrices porttitor odio, ac scelerisque enim efficitur id. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam vehicula accumsan erat, id mollis nisl accumsan eu. Nunc ipsum sapien, egestas et sem congue, consequat consectetur nunc. Vivamus pretium est ipsum, eget condimentum est bibendum sed. Donec lobortis blandit est, sit amet consectetur arcu. Vivamus sapien est, convallis sed laoreet eget, ornare eget tellus. |
||||||
|
|
||||||
|
Sed condimentum, magna gravida dignissim hendrerit, nisl nunc vehicula justo, ut vehicula ipsum purus non dolor. Curabitur quis tellus porttitor, venenatis tortor eu, interdum justo. Suspendisse bibendum orci sit amet malesuada tincidunt. Sed maximus feugiat tempus. Nullam in ante ante. Nullam convallis arcu quis sapien facilisis, id dignissim sapien malesuada. Cras tempor, enim in consequat vestibulum, dui nisi maximus nulla, et dignissim justo odio non orci. |
||||||
|
|
||||||
|
Suspendisse fringilla turpis sed tortor efficitur, a placerat nisi vestibulum. Etiam convallis lacus vitae dignissim tempor. Suspendisse id mauris a risus bibendum maximus. Nullam dignissim sit amet ligula ac lobortis. Nullam feugiat est quis tortor fermentum lobortis eget eget libero. Donec non suscipit nulla. Sed ac lacus neque. Nunc imperdiet mi ut metus sagittis mollis. Sed varius sodales accumsan. Donec auctor elementum sagittis. Donec odio mauris, faucibus quis mollis nec, efficitur at eros. Maecenas massa ligula, fringilla eget mi quis, placerat vehicula lacus. Maecenas leo nibh, bibendum ac sem sed, dignissim iaculis nibh. |
||||||
|
|
||||||
|
Donec in tincidunt arcu. Quisque commodo rutrum ornare. Aenean eu purus pretium, faucibus justo eget, pharetra urna. Fusce pharetra facilisis sapien sed luctus. Cras non elit vestibulum, rutrum lectus ut, bibendum erat. Duis vitae est eu libero vehicula viverra at vitae ipsum. Nunc justo ligula, tempor vitae ex sit amet, consectetur placerat ex. Aenean ligula dui, fermentum vel semper sed, semper eu orci. Etiam gravida sagittis eros, et pellentesque justo. Curabitur et pulvinar velit. In semper odio leo, ut pharetra nunc accumsan nec. Sed velit augue, ultrices in ante blandit, feugiat pretium massa. Maecenas bibendum, nibh eget suscipit ultrices, elit felis auctor risus, nec dictum nibh neque ac diam. Sed consequat arcu id nibh tristique sodales. Phasellus vulputate placerat velit sed condimentum. |
||||||
|
|
||||||
|
Nulla facilisis leo nec efficitur venenatis. Phasellus ac interdum ligula. Curabitur pharetra laoreet ipsum, ac porta nunc tristique eu. Morbi mollis varius massa ac egestas. Vivamus sed nibh tellus. Pellentesque auctor sapien aliquet nunc semper venenatis. Aenean dignissim venenatis feugiat. |
||||||
|
|
||||||
|
Donec ut tincidunt sapien, ut consequat felis. Morbi luctus orci in elit luctus blandit. Proin fringilla odio vel elit tristique tincidunt. Integer tellus metus, vestibulum eu eleifend eu, finibus id velit. Curabitur nec turpis accumsan, aliquam nibh nec, luctus velit. Curabitur id velit eget quam scelerisque pretium et a mauris. Suspendisse vel felis lectus. Maecenas a augue lectus. Sed viverra maximus nisl, at tempor lectus ornare ut. Donec ac semper velit. Nunc hendrerit sapien et tellus fermentum sagittis. |
||||||
|
|
||||||
|
Sed malesuada enim et est tincidunt, a tristique mi porttitor. Sed interdum, orci non sagittis sagittis, ipsum enim aliquet erat, quis pharetra sapien lacus vel tellus. Nunc dictum nunc sed suscipit tempus. In hac habitasse platea dictumst. Maecenas gravida vestibulum faucibus. Nam eget tempus odio. Maecenas a eleifend massa, ut efficitur odio. |
||||||
|
|
||||||
|
Integer fermentum lacus turpis, at aliquet diam convallis non. Ut ac arcu vitae felis dapibus porttitor a sit amet orci. Suspendisse nisl libero, fringilla non posuere vel, pharetra nec nisl. Pellentesque et euismod nibh, eget ornare urna. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In viverra faucibus purus, a congue felis interdum ut. Aliquam vitae tellus sed felis mattis elementum. Fusce eleifend lorem ut ex euismod euismod. Donec ac consectetur augue. Cras posuere neque massa, sed euismod urna mattis ac. Mauris nec sollicitudin lacus. Sed eu massa et lorem viverra bibendum sed sit amet arcu. Vivamus gravida hendrerit mi, cursus iaculis nunc imperdiet a. Quisque purus mauris, viverra sit amet euismod sit amet, rutrum id nibh. Donec dignissim diam nibh, quis rhoncus nulla suscipit at. Mauris dapibus, tellus et efficitur aliquet, tellus diam vehicula enim, ac fermentum ante justo nec turpis. |
||||||
|
|
||||||
|
Nullam sapien orci, pharetra a elit eu, interdum interdum libero. Ut eu pulvinar ipsum. Aliquam hendrerit elit arcu, vel volutpat nisl convallis id. In maximus justo sed magna euismod sagittis. Morbi fermentum ante nisi, id volutpat nisl congue a. Praesent sed efficitur turpis. Pellentesque eu turpis nec massa semper semper. Donec tincidunt ac lacus eget maximus. Quisque vel tortor eros. Nam vitae urna a mi maximus vestibulum. |
||||||
|
|
||||||
|
Phasellus et eros lectus. Mauris luctus diam a dolor sagittis, quis lacinia odio euismod. Ut sed porttitor sem. Mauris faucibus vitae ex et malesuada. Nullam quis tincidunt diam, et lobortis ipsum. Pellentesque scelerisque metus vel luctus porttitor. Donec eu vehicula erat, ornare efficitur elit. Praesent ullamcorper est sit amet odio finibus malesuada. Nulla molestie id odio quis semper. In ultrices, massa quis consequat placerat, mi magna porttitor enim, sed blandit nulla nunc nec nunc. Duis suscipit, mauris sit amet aliquet sodales, arcu massa efficitur enim, et sollicitudin urna nisi sed mi. |
||||||
|
|
||||||
|
Nunc tempus dolor lorem, consectetur semper dolor feugiat in. In imperdiet ullamcorper erat id accumsan. Sed at molestie sem. Phasellus sagittis consequat orci, in feugiat odio imperdiet ac. Aliquam auctor eros vulputate dolor rhoncus, ac hendrerit enim lacinia. Morbi augue orci, sollicitudin sed consequat fermentum, hendrerit sed velit. Sed a turpis aliquet, fringilla elit eu, dictum libero. Donec aliquam urna mauris, vel interdum urna congue vel. Sed ex tellus, consectetur sed imperdiet at, finibus efficitur nisl. Phasellus aliquam semper libero finibus rhoncus. Pellentesque dolor augue, porta eu urna eu, ultricies lacinia metus. Praesent cursus ante dapibus, volutpat nunc id, pharetra diam. Nam iaculis enim non faucibus dapibus. Vivamus est augue, aliquam ac ipsum eget, vestibulum commodo lorem. Proin porttitor nibh vitae est fermentum, id suscipit dolor elementum. |
||||||
|
|
||||||
|
Praesent tempor fermentum tellus, vitae tincidunt turpis mattis a. Etiam eu magna et eros iaculis ullamcorper. Pellentesque pharetra turpis metus, nec bibendum leo fermentum et. Sed arcu nulla, gravida nec leo quis, efficitur suscipit libero. Quisque purus mi, auctor vitae quam quis, tincidunt porta sapien. Proin eu facilisis orci, at eleifend lectus. Aenean blandit viverra nulla non tempor. Duis venenatis tortor nec finibus interdum. |
||||||
|
|
||||||
|
Duis sed tortor nulla. Donec scelerisque sem purus, id varius risus lobortis ut. Proin velit ipsum, vulputate vitae viverra ac, viverra quis ante. Maecenas eget sapien non sem volutpat elementum finibus eu nunc. Pellentesque non ex quis leo gravida malesuada quis mollis eros. Fusce mollis nunc eget risus vehicula eleifend in sed lorem. In hac habitasse platea dictumst. Nulla quis pretium nisl. Vivamus dignissim, nibh in luctus ornare, nunc risus commodo enim, et aliquet libero neque ut orci. Suspendisse sed quam eget urna viverra porta. Aenean ligula ligula, congue vel ullamcorper et, vehicula quis tortor. Sed dictum nec nulla eget sollicitudin. Aliquam molestie ligula justo, sit amet faucibus dolor ultricies eget. |
||||||
|
|
||||||
|
Aliquam et risus posuere, malesuada nibh id, malesuada sapien. Curabitur lacus ex, ullamcorper id pharetra at, maximus vel augue. Interdum et malesuada fames ac ante ipsum primis in faucibus. Donec varius felis quis tortor laoreet volutpat. Quisque iaculis posuere enim, tincidunt rhoncus erat sodales vel. Etiam sit amet purus suscipit, tempus lacus non, semper tellus. Pellentesque in aliquet urna. Vivamus a justo bibendum, tristique tellus pretium, fringilla eros. |
||||||
|
|
||||||
|
Cras eget arcu condimentum, varius eros vel, fermentum quam. Duis ut turpis ut erat laoreet pulvinar et non lectus. Nam mattis libero quis congue pharetra. In vulputate quis massa quis eleifend. Donec eu velit ac urna tempor blandit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Etiam sed lobortis mi. Etiam porttitor, leo sed dictum rutrum, justo massa semper tortor, vel lobortis urna elit a felis. Aliquam odio augue, pellentesque sed ex sed, bibendum pellentesque turpis. Morbi viverra nulla ac ipsum mattis, non auctor tortor condimentum. Vestibulum pretium nec nulla vitae sollicitudin. Integer scelerisque libero id blandit pharetra. |
||||||
|
|
||||||
|
Ut aliquet libero id commodo mattis. Nulla ut ex malesuada, tincidunt nisl in, lacinia nisl. Pellentesque scelerisque semper mauris, nec tincidunt urna bibendum id. Nulla facilisi. Nulla facilisi. Sed id fringilla odio. Fusce tempus egestas mauris nec accumsan. Integer dictum, elit vehicula molestie ultrices, purus sapien luctus enim, nec suscipit felis neque sit amet mi. Nulla sed fermentum orci. |
||||||
|
|
||||||
|
Donec id lorem euismod, posuere leo in, pharetra velit. Nullam sed blandit mauris. Proin vitae congue neque, quis tristique ante. Donec consectetur a velit sed congue. Sed finibus dui luctus, maximus metus et, tempor sapien. Quisque vulputate molestie arcu eu malesuada. Ut consectetur rutrum diam eu viverra. Suspendisse interdum ipsum mattis neque pulvinar posuere. Donec dolor erat, bibendum vitae malesuada ac, hendrerit quis metus. Duis vitae urna orci. Sed lobortis nisl ut tortor eleifend malesuada. Curabitur dapibus ex vitae ante ornare, et aliquet orci bibendum. |
||||||
|
|
||||||
|
Quisque sollicitudin metus turpis, vitae condimentum metus semper id. Duis pharetra facilisis leo vel egestas. Vivamus ut magna justo. Sed quis vehicula turpis, sed dictum augue. Praesent erat tellus, fermentum non vestibulum vitae, commodo in lectus. Integer eu rutrum nibh. Sed pellentesque lacinia mauris, et varius orci laoreet ut. Nulla condimentum ante eros, sed aliquam augue gravida nec. Integer auctor nisl nec mauris vulputate laoreet eget nec lorem. Suspendisse convallis dui a nisi dapibus egestas sit amet non quam. Cras vulputate sapien sit amet lacinia scelerisque. Quisque justo ante, tincidunt in risus ut, dapibus maximus mauris. Vivamus eget lectus nec mi eleifend viverra. Fusce efficitur turpis vel erat auctor aliquam. Nunc volutpat felis massa, sit amet egestas libero mollis non. |
||||||
|
|
||||||
|
In in tempus sapien, sit amet lacinia lacus. Phasellus vehicula sodales cursus. Pellentesque at mollis sapien. Quisque sollicitudin, lorem nec condimentum fringilla, velit arcu vehicula dui, at porttitor turpis leo nec nunc. Mauris elementum eros purus, malesuada consectetur orci sodales eu. Fusce suscipit, turpis vel mattis finibus, leo lacus maximus nibh, ac aliquet nunc enim et lectus. Donec nec nulla est. Duis porta id dolor a vehicula. Mauris accumsan arcu eget metus scelerisque, eget consequat mi rutrum. Aenean placerat tristique feugiat. |
||||||
|
|
||||||
|
Mauris in odio neque. In pretium libero condimentum urna fermentum cursus. Vivamus tincidunt tincidunt volutpat. Aenean sed faucibus dui, tincidunt egestas eros. Nunc velit velit, aliquam eget purus eu, dictum ullamcorper eros. Vestibulum molestie interdum pulvinar. In ac mauris non metus consectetur luctus sed in risus. Sed eget consequat augue. Nulla posuere ligula augue, eu pretium ipsum placerat a. Mauris quis ullamcorper metus, at egestas tellus. |
||||||
|
|
||||||
|
Ut consectetur placerat mauris vel placerat. Nam volutpat sapien ut ornare congue. Vestibulum cursus magna at scelerisque venenatis. Nullam ac lacus quis sapien lobortis ullamcorper eu in libero. Quisque semper vitae urna vitae dictum. Mauris pretium elementum turpis, vel varius odio ullamcorper in. Vestibulum efficitur malesuada est, eu venenatis mauris iaculis sed. Sed suscipit egestas lacus, at porta risus cursus et. Aenean nec augue tempor est elementum bibendum vitae non nisl. Proin molestie porttitor dolor vitae laoreet. Ut sagittis, dui quis pulvinar ultrices, neque tortor auctor nibh, sed ornare mauris mauris vel lacus. Nunc sed ullamcorper lorem. Maecenas facilisis arcu non diam feugiat rhoncus. |
||||||
|
|
||||||
|
Mauris dictum iaculis molestie. Duis viverra pellentesque volutpat. Proin id felis velit. Morbi sed tellus sed ligula molestie ultricies. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque at lobortis ex. Integer pharetra nibh diam, vehicula scelerisque mi vehicula sit amet. Proin lobortis at augue non bibendum. Morbi porttitor varius tortor, et tristique nibh cursus vitae. Maecenas cursus facilisis tortor, aliquet volutpat ante convallis eget. Nunc odio turpis, pellentesque sed enim sit amet, posuere eleifend magna. Duis ultrices felis ipsum, eu ornare ex iaculis et. Curabitur metus diam, rutrum sit amet rhoncus et, imperdiet sit amet neque. Cras nec dui laoreet magna condimentum fringilla vel quis orci. Morbi sit amet nisi luctus, commodo lacus et, aliquam felis. |
||||||
|
|
||||||
|
Integer pharetra lacinia metus, ut gravida enim varius nec. Proin in risus augue. Aenean vel urna elit. Cras sed erat molestie enim fringilla posuere sed vel lorem. Suspendisse mauris massa, tempus quis tortor ut, placerat egestas ligula. Nam eu massa dictum, fermentum est nec, lacinia felis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Pellentesque tellus quam, placerat commodo tincidunt id, tincidunt ut lectus. Integer ut blandit diam. Duis quis rutrum augue. Nulla ex elit, malesuada vel interdum in, commodo a turpis. Quisque pharetra neque at imperdiet ornare. Cras tincidunt arcu tellus, sit amet ultricies nisi congue nec. Curabitur vel est sed dolor euismod tempus. Praesent at sagittis risus, id viverra neque. |
||||||
|
|
||||||
|
Donec augue leo, pellentesque eu volutpat quis, suscipit in mi. Aenean placerat libero id ornare vestibulum. Maecenas nec faucibus nisi. Curabitur elementum aliquam congue. Maecenas nec lobortis purus. Nam aliquam justo erat, in placerat magna rutrum suscipit. Vestibulum non sem et ipsum lobortis consectetur. Sed sed commodo dui, in feugiat ipsum. Proin mattis gravida lectus, non placerat magna fringilla sit amet. |
||||||
|
|
||||||
|
Integer erat sem, hendrerit id venenatis quis, vestibulum in orci. Praesent sed nisl in sem euismod suscipit. Vivamus in lectus est. Nulla sed neque ut dui posuere interdum sed in mi. Maecenas tincidunt porta ornare. Quisque id sapien aliquet eros consectetur ultrices. In dui turpis, tincidunt ac consectetur vel, scelerisque id arcu. Curabitur sed auctor tellus, sit amet congue ex. Vestibulum accumsan, diam id interdum feugiat, ex turpis fermentum enim, nec tristique ante lacus in sem. Fusce vel ante luctus, mollis ante quis, porttitor leo. |
||||||
|
|
||||||
|
Morbi luctus cursus sapien, accumsan pulvinar urna euismod id. Duis fermentum mi a sapien sollicitudin, ac laoreet magna vestibulum. Integer faucibus diam id dui lacinia, et egestas felis faucibus. Vestibulum efficitur quam at condimentum vulputate. Donec et orci mauris. Cras sit amet dictum nulla, eu vestibulum lacus. Suspendisse rhoncus nibh neque, sit amet semper leo eleifend vel. In tortor tellus, ornare a risus at, malesuada porttitor massa. Lorem ipsum dolor sit amet, consectetur adipiscing elit. |
||||||
|
|
||||||
|
Nam urna nunc, ultrices at nulla sit amet, cursus malesuada lacus. Integer nec sem faucibus, placerat sapien ac, placerat sapien. Cras molestie arcu imperdiet nisi accumsan luctus. In in interdum turpis. Aliquam posuere volutpat pharetra. Aenean pharetra volutpat tempor. Aenean quis turpis ut libero interdum gravida. Maecenas ac scelerisque velit. Morbi non nulla dignissim, maximus lacus sit amet, vestibulum metus. Nunc convallis elit non tincidunt ultricies. Suspendisse aliquet vel lectus a facilisis. Nulla sit amet venenatis odio. |
||||||
|
|
||||||
|
Suspendisse magna nisi, varius luctus ipsum et, imperdiet consequat lacus. Nulla quis congue augue. Proin vehicula mi leo, suscipit dignissim ex egestas eu. Quisque interdum erat quis quam facilisis, in feugiat felis tincidunt. Donec orci odio, porttitor vitae pellentesque eu, rhoncus ac risus. Aliquam faucibus commodo orci. Sed eu arcu sed diam venenatis vulputate a ut sem. Integer nec dapibus dolor. Aenean fringilla malesuada quam, non sagittis libero venenatis ac. Integer blandit neque eget leo auctor lobortis. Donec at tincidunt nunc, a efficitur purus. Vestibulum et orci lobortis, cursus lorem dapibus, malesuada nisi. Nunc in ipsum quis ipsum malesuada lacinia eu non tortor. Mauris ac vehicula tellus. |
||||||
|
|
||||||
|
Nullam ut aliquet ipsum, vitae porttitor sapien. Curabitur eleifend sem id venenatis elementum. Nullam non augue eu arcu posuere finibus sit amet eget lorem. Sed vehicula lectus a justo ultrices, eget pharetra augue eleifend. Pellentesque tempor turpis sed leo viverra tempus. Duis volutpat non urna sit amet dictum. Mauris eu orci pellentesque, rhoncus purus a, fermentum dui. Cras accumsan commodo euismod. In suscipit aliquet ex, a scelerisque tortor ultrices ac. Donec ipsum dui, vulputate non gravida et, vulputate ac dolor. Curabitur et hendrerit arcu, et hendrerit erat. Vivamus suscipit risus eu orci sollicitudin, vel convallis enim ultricies. Cras vehicula consequat risus ac gravida. Duis venenatis nisi vel leo pulvinar bibendum. Mauris elementum et quam eu elementum. |
||||||
|
|
||||||
|
Aliquam erat volutpat. Sed a dapibus diam. Quisque laoreet sit amet tortor sodales interdum. Duis congue venenatis odio, suscipit dignissim justo pretium non. Nunc eu arcu ullamcorper, placerat nisl a, euismod libero. Phasellus molestie mi quis est egestas, ac venenatis justo malesuada. Fusce et nisi ullamcorper, pharetra risus non, venenatis libero. In et sodales ante. Ut quis odio at diam interdum laoreet non nec odio. Morbi rutrum metus nisl, sit amet finibus ipsum accumsan vitae. Praesent fringilla rhoncus erat id ultrices. Aenean ut erat non nisl blandit bibendum ac sit amet lectus. Pellentesque scelerisque dui nec fermentum eleifend. Nulla rhoncus magna non orci sollicitudin fermentum. Nullam consequat orci vitae ullamcorper laoreet. Nam congue tincidunt ligula condimentum ultricies. |
||||||
|
|
||||||
|
Donec nec eros vitae ante commodo scelerisque. Donec felis ex, ornare ut neque a, volutpat blandit enim. Fusce a mi a nunc facilisis semper. Fusce mollis justo eu mi tempor eleifend. Sed ultrices urna quis ipsum cursus, et elementum ante posuere. Praesent viverra vestibulum iaculis. Praesent vel faucibus erat. Integer et diam dapibus, convallis arcu quis, pharetra nulla. Mauris enim arcu, fringilla in tincidunt non, suscipit eu erat. Etiam quis ante euismod, gravida nisl vel, tincidunt libero. Vivamus ac eleifend arcu. Mauris egestas, eros ut porttitor vehicula, erat ligula faucibus elit, ut suscipit massa augue ut est. Aliquam dapibus efficitur purus eu pretium. Donec pulvinar turpis orci. Mauris nisl velit, pharetra sed nisl at, pellentesque convallis felis. Etiam vitae lectus lectus. |
||||||
|
|
||||||
|
Aenean eu ligula interdum, feugiat lacus quis, feugiat tortor. Etiam mattis massa vel augue ullamcorper egestas. Vivamus in orci magna. Vivamus a dictum nisl, vitae ornare justo. Sed libero tellus, dapibus in auctor et, porta vel augue. Nullam scelerisque tellus pretium nibh varius vestibulum. Sed et neque turpis. Proin malesuada nisl ut felis iaculis, ac aliquam lorem euismod. Vestibulum pretium sapien sit amet enim egestas elementum. Cras eget est luctus, mollis sapien ac, porta ex. Praesent venenatis dapibus lacus, ut efficitur lacus fringilla non. Integer eu rutrum magna. Integer iaculis venenatis blandit. Vestibulum euismod vitae leo tincidunt dignissim. Interdum et malesuada fames ac ante ipsum primis in faucibus. |
||||||
|
|
||||||
|
Proin sodales neque dui, at sagittis magna fermentum vel. Cras id metus id sapien cursus rhoncus. In hendrerit augue dictum, gravida augue vel, consectetur lorem. Vivamus sollicitudin pellentesque pulvinar. Donec consectetur sem quis odio scelerisque elementum. Ut luctus enim nec nunc venenatis mattis vitae ac lorem. Nullam aliquam nulla et ornare interdum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nullam sollicitudin lacinia tellus et suscipit. |
||||||
|
|
||||||
|
Ut eget orci non est luctus mattis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras vel magna ligula. Donec eu sem ut odio ullamcorper ornare. Sed blandit, felis pellentesque laoreet cursus, diam sem viverra nunc, in auctor orci diam sit amet enim. Maecenas sit amet commodo turpis, nec tristique lectus. Maecenas dictum leo nec rhoncus faucibus. Vestibulum augue quam, varius ac facilisis vitae, commodo in quam. Aenean suscipit tellus non tincidunt viverra. Integer eu ipsum non nibh bibendum euismod id at erat. |
||||||
|
|
||||||
|
Mauris non malesuada sapien. Pellentesque vitae mi nulla. Curabitur laoreet, sapien et facilisis varius, est est dapibus leo, dapibus auctor erat urna vel enim. In vehicula, nisl ac pharetra finibus, tellus ipsum vestibulum mi, venenatis pulvinar ante sem nec risus. Phasellus porta porttitor lectus, id consectetur justo commodo a. Donec in dui ut tellus ultricies aliquet. Praesent ac mi metus. Integer lobortis purus eu justo lobortis, vel imperdiet ex hendrerit. Aliquam erat volutpat. Proin ut ligula nisl. Sed pretium porttitor varius. Nam iaculis ac orci sed pulvinar. Donec mattis orci non dui vehicula, at lobortis nibh efficitur. Vestibulum varius erat ornare posuere convallis. |
||||||
|
|
||||||
|
Vivamus gravida massa feugiat scelerisque maximus. Nam bibendum facilisis vehicula. Vivamus id lacinia nisl. Sed tempus, orci in tincidunt dignissim, nulla nibh fringilla magna, et rutrum erat sapien ac turpis. Curabitur laoreet id mi in luctus. Vestibulum nec erat et nunc bibendum feugiat vitae nec eros. Morbi vitae convallis neque, vitae faucibus leo. Suspendisse sem justo, vestibulum eget nulla varius, molestie vestibulum nibh. Nullam eleifend arcu enim, et porta felis pretium id. Cras eu sapien quis lacus feugiat venenatis. |
||||||
|
|
||||||
|
Sed diam turpis, interdum vel felis imperdiet, posuere venenatis augue. Maecenas sapien nulla, consectetur vitae mattis in, finibus id lorem. Quisque consequat euismod vestibulum. Maecenas congue velit lorem, tincidunt tristique lorem consectetur quis. Proin vulputate porta convallis. Cras id tincidunt nulla. Proin sit amet turpis imperdiet turpis aliquet feugiat sit amet eu augue. Donec ut consequat neque. Morbi laoreet leo eu augue ullamcorper, ut porttitor lectus pulvinar. |
||||||
|
|
||||||
|
Vivamus vitae nisi eu libero vestibulum sollicitudin vitae in metus. Ut nec massa justo. Phasellus euismod consequat massa id tempor. Vestibulum et imperdiet quam. In ipsum nibh, consectetur quis posuere vitae, laoreet et ante. Maecenas cursus eros vel ante tempor, vel tristique neque tincidunt. Ut eget erat vitae sapien posuere luctus. Donec a finibus erat. |
||||||
|
|
||||||
|
Quisque at ligula sit amet arcu molestie feugiat commodo sit amet nisi. Aenean aliquet hendrerit metus vitae lacinia. Pellentesque pulvinar luctus ipsum non condimentum. In fringilla ac dui a fermentum. Nulla sollicitudin, nisl a fermentum rutrum, eros diam posuere nunc, eget luctus risus eros nec ligula. Suspendisse sit amet ante porta, semper est tempor, pulvinar odio. Cras dictum elit sed orci lacinia aliquet. Ut consectetur, nisl sit amet lacinia finibus, leo eros tempus risus, at lacinia nulla nisi vel tellus. Aliquam at nisl egestas, auctor est a, congue diam. Proin fringilla pellentesque arcu sit amet aliquet. |
||||||
|
|
||||||
|
Morbi a lectus ultricies nibh efficitur scelerisque ac ac urna. Nunc molestie risus vitae ipsum ornare vestibulum. Vivamus molestie tincidunt tempus. Maecenas tristique luctus augue ut lobortis. In risus turpis, condimentum mattis posuere eget, sodales ut lorem. Sed vulputate tempor diam in ullamcorper. Aenean aliquet lectus vitae massa laoreet, nec vehicula odio porta. |
||||||
|
|
||||||
|
Aliquam tristique ut nisi sit amet luctus. Quisque nulla mi, vulputate at lobortis vitae, fermentum at lacus. Curabitur non massa in nunc tempus dignissim. Suspendisse erat velit, molestie non vulputate in, lobortis quis purus. Pellentesque quis placerat nisl. In posuere vestibulum nisl eget egestas. Sed non dui posuere, pharetra est eu, ullamcorper mauris. Pellentesque dictum varius erat at condimentum. Sed nisi enim, pellentesque quis enim molestie, imperdiet volutpat arcu. Aenean commodo finibus vulputate. Fusce ornare scelerisque urna, vitae tempus neque vehicula eu. |
||||||
|
|
||||||
|
Fusce lacinia augue id tristique rutrum. Aenean ut elementum augue. Nulla ut lectus tellus. Pellentesque et libero et mauris facilisis rutrum a pharetra dolor. Vivamus lobortis lacus eu ante suscipit, vel commodo nisi venenatis. Sed gravida gravida congue. Aliquam rutrum dictum orci ac condimentum. Aenean ac ex eu diam dapibus venenatis id ut lacus. |
||||||
|
|
||||||
|
Maecenas non porttitor orci. Donec dapibus rhoncus consectetur. Cras porta sagittis magna, at convallis eros consequat non. Quisque consectetur sem in sagittis sollicitudin. Maecenas id eros porta, tristique sem mollis, sagittis enim. Praesent mollis dapibus commodo. Etiam bibendum lacus nec iaculis eleifend. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nullam vitae finibus erat. Fusce sollicitudin eleifend elit in hendrerit. Quisque fermentum rhoncus pulvinar. In lobortis libero ac nisi euismod venenatis sit amet sed ipsum. Nam id molestie quam, eu bibendum diam. |
||||||
|
|
||||||
|
Etiam non augue volutpat, fermentum nunc non, sodales lectus. Curabitur elementum euismod ex, quis porttitor erat tempus accumsan. Morbi fringilla nisl nec hendrerit cursus. Suspendisse egestas massa in nisl gravida sollicitudin. Maecenas maximus, tortor sed lacinia consectetur, nisi magna tincidunt lorem, vel maximus dolor sem in eros. Sed a vulputate nunc. Integer egestas, tortor vitae imperdiet cursus, massa enim pellentesque felis, sit amet sollicitudin velit arcu id lorem. |
||||||
|
|
||||||
|
Nullam nec diam convallis, fermentum quam id, pulvinar velit. Pellentesque ultricies semper metus, cursus pulvinar tortor consectetur vel. Fusce suscipit urna sem, vitae ultrices lacus aliquet vel. Pellentesque tempor tristique mi, quis rhoncus lacus fringilla a. Interdum et malesuada fames ac ante ipsum primis in faucibus. Morbi neque risus, malesuada at lacinia non, posuere elementum mauris. Pellentesque eget egestas est, nec congue leo. Nunc faucibus mi id vulputate sodales. Cras ornare eget justo eu blandit. Fusce id magna lorem. Nunc sit amet dolor placerat, ornare metus non, ultricies augue. |
||||||
|
|
||||||
|
Ut sed auctor dui, ullamcorper pretium sapien. Sed ut felis id nunc mollis consectetur et in nunc. Nunc volutpat nec urna nec facilisis. Ut sagittis ipsum nec aliquam interdum. Donec rutrum dolor eget neque euismod vestibulum. Nulla condimentum neque neque, eget ullamcorper risus cursus scelerisque. Sed bibendum luctus dolor eget dignissim. Etiam non nulla enim. Vestibulum eget semper odio. Sed semper vulputate ipsum ac maximus. Nullam sed libero pellentesque quam rhoncus sagittis vitae sed ipsum. |
||||||
|
|
||||||
|
Sed vitae ex vulputate, scelerisque sapien quis, mattis massa. Duis rutrum neque ante, a vestibulum massa congue at. Nam tincidunt ex luctus ultricies laoreet. Duis cursus magna eu diam malesuada ultricies. Cras porttitor sagittis tellus, eget mollis enim molestie eu. Nunc tristique semper massa. Nullam varius velit sit amet velit suscipit, a bibendum odio facilisis. Nunc et arcu bibendum, fermentum odio id, congue lectus. Phasellus malesuada volutpat justo ut sodales. Integer interdum et nibh non blandit. Nam a vulputate tellus. |
||||||
|
|
||||||
|
Quisque auctor commodo nisl, ut semper lectus tincidunt sed. Integer cursus finibus est. Vivamus dui dui, feugiat nec leo eu, vestibulum interdum nunc. Nam massa dolor, tempor sit amet congue et, maximus at elit. In blandit at nibh et porta. Curabitur elementum efficitur elit, vel sagittis tellus eleifend lacinia. Sed tincidunt elit eu purus fermentum finibus. Aenean egestas dignissim tellus vel semper. |
||||||
|
|
||||||
|
Nulla id condimentum lorem. Donec vitae dui quam. Maecenas sapien dui, facilisis sed tellus sit amet, pharetra iaculis ligula. Fusce sagittis, odio sed aliquam feugiat, nunc ipsum ultrices lorem, vel pellentesque nibh orci finibus leo. Proin a urna tincidunt, porttitor sapien ac, fringilla velit. Suspendisse in vehicula risus. Morbi mattis cursus cursus. Nam vel varius nisi, blandit malesuada lacus. |
||||||
|
|
||||||
|
Nullam laoreet nibh quis erat dictum fringilla. Quisque a tortor dolor. Curabitur pulvinar molestie lectus, eget dapibus nisl tristique id. Nullam pulvinar accumsan arcu, euismod auctor nunc dignissim ac. Vivamus pulvinar massa at metus sollicitudin, dictum convallis arcu vestibulum. Suspendisse at leo nec sem sollicitudin luctus sit amet vitae nisi. Duis lobortis risus id odio luctus, sit amet feugiat mauris ullamcorper. Donec iaculis suscipit nunc eu dictum. Quisque ut lobortis elit. Cras eget auctor lacus. Donec mattis vitae nisi a porta. Morbi quis eros sed ante pharetra euismod. Nullam varius bibendum magna a cursus. |
||||||
|
|
||||||
|
Aenean vestibulum leo magna, sit amet varius eros eleifend mollis. Aenean tempor ullamcorper velit vel sagittis. Aenean maximus enim nulla, nec pellentesque elit ullamcorper eget. Duis tincidunt, dolor id euismod rhoncus, orci dolor auctor augue, eu molestie odio tellus nec sem. Donec gravida arcu ac ex ultrices rhoncus. Nulla tincidunt gravida neque id dictum. Sed lectus lectus, rhoncus ac odio vitae, porttitor elementum nunc. Morbi gravida, leo id sollicitudin iaculis, mi elit volutpat eros, quis venenatis massa dui pharetra neque. Cras sit amet dignissim mi. Donec in lectus sed risus congue consequat. Duis ut malesuada metus. Praesent maximus ac tortor eget feugiat. Nulla in nunc eget quam sodales sagittis. |
||||||
|
|
||||||
|
Nam eu porta enim. Fusce pretium elit sapien, a feugiat nibh tempor a. Etiam feugiat dui nec neque malesuada, quis tristique sapien vestibulum. Sed volutpat eget nulla id imperdiet. Morbi sodales tortor ac ligula vulputate tincidunt. Aliquam placerat orci sem, id fringilla orci facilisis eu. Nullam aliquet odio eget ante placerat blandit. Morbi ut justo cursus, ullamcorper purus id, scelerisque neque. Donec a nisi pellentesque, commodo magna efficitur, feugiat neque. Maecenas at quam eleifend, ornare sem non, pretium ante. Pellentesque eget fringilla ligula. Donec massa arcu, viverra auctor sem at, ultricies blandit odio. Proin sed leo quam. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce elementum efficitur blandit. Morbi tincidunt porttitor odio nec placerat. |
||||||
|
|
||||||
|
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec vel libero pharetra, euismod nulla sit amet, volutpat lorem. Maecenas blandit magna ornare mi imperdiet luctus. Fusce congue risus et enim placerat ornare. Aenean ac magna eget risus rhoncus molestie at et leo. Cras mattis erat lectus, sed dignissim enim pulvinar vel. Donec turpis libero, condimentum sit amet rutrum id, blandit in diam. Praesent tincidunt malesuada lorem, at posuere nisi. Ut rutrum turpis vel mi blandit congue. Aenean viverra metus quis erat hendrerit, nec egestas diam placerat. Praesent vel ipsum enim. Praesent eget sollicitudin dui. Donec semper turpis id magna molestie, sit amet interdum odio lacinia. Curabitur ut mollis metus. Duis luctus leo velit, id accumsan risus sodales non. |
||||||
|
|
||||||
|
Nullam ut arcu sed justo tempus consequat. Donec nisl ante, lacinia ac convallis ac, bibendum sed diam. Duis viverra dolor sed ex convallis, vel facilisis ligula maximus. Pellentesque eu pulvinar nulla. In ante risus, viverra a euismod et, laoreet a dui. In hac habitasse platea dictumst. Nunc ullamcorper tellus non viverra pharetra. Aenean dapibus dolor sit amet dui facilisis placerat. In hac habitasse platea dictumst. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec ac efficitur enim, ac placerat dui. Donec vitae vestibulum leo. |
||||||
|
|
||||||
|
Aliquam vestibulum dictum metus, eget commodo ipsum sollicitudin et. Nam volutpat efficitur magna eu vestibulum. Donec dolor purus, aliquet quis orci ut, finibus molestie sapien. Mauris in libero in lorem pretium commodo eu sit amet justo. Integer eu elit sit amet orci cursus sagittis ac a ligula. Curabitur ac eleifend ante. Nulla placerat lacus eu molestie hendrerit. |
||||||
|
|
||||||
|
Proin eu dignissim ante. Fusce lobortis eu ante sed finibus. Vivamus sed dictum turpis. Ut tristique vitae nibh at laoreet. Nullam eget interdum metus, sit amet porttitor nibh. Maecenas dignissim, lacus ac facilisis volutpat, ante nibh vehicula dui, nec facilisis enim turpis vel turpis. Proin risus tortor, vehicula sit amet congue eget, accumsan a magna. Suspendisse potenti. Praesent lacinia mollis feugiat. Donec a nunc ac nibh tincidunt volutpat. Proin nec urna eros. Sed vitae elit fringilla, congue sem non, mattis arcu. Maecenas euismod neque metus, consectetur vestibulum neque rutrum non. |
||||||
|
|
||||||
|
Morbi magna metus, congue nec lacus id, semper mattis augue. Pellentesque vel dolor eu turpis luctus volutpat. Donec consectetur maximus commodo. Quisque erat elit, iaculis vel leo quis, volutpat mollis quam. Sed dui lectus, pretiu |
@ -0,0 +1 @@ |
|||||||
|
hello |
@ -0,0 +1,42 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# Unofficial Bash Strict Mode |
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
|
||||||
|
shopt -s expand_aliases |
||||||
|
|
||||||
|
FILENAME="student/custom-ls.sh" |
||||||
|
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd) |
||||||
|
|
||||||
|
challenge() { |
||||||
|
|
||||||
|
source "$script_dirS"/$FILENAME |
||||||
|
submitted=$(cd "$1" && custom-ls) |
||||||
|
unalias custom-ls |
||||||
|
|
||||||
|
source "$script_dirS"/solutions/custom-ls.sh |
||||||
|
expected=$(cd "$1" && custom-ls) |
||||||
|
unalias custom-ls |
||||||
|
|
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
||||||
|
} |
||||||
|
|
||||||
|
# True if FILE exists and is a regular file |
||||||
|
if [ -f ${FILENAME} ]; then |
||||||
|
# FILE exists and it's not empty |
||||||
|
if [ -s ${FILENAME} ]; then |
||||||
|
if [[ $(cat $FILENAME | grep echo | wc -l) -ne 0 ]]; then |
||||||
|
echo "echo is not allowed in this exercise!" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
challenge custom-ls/folder1 |
||||||
|
else |
||||||
|
echo "The file exist but is empty" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
else |
||||||
|
echo "File does not exist" |
||||||
|
exit 1 |
||||||
|
fi |
@ -0,0 +1,18 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# Unofficial Bash Strict Mode |
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
|
||||||
|
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd) |
||||||
|
challenge() { |
||||||
|
touch file1.txt |
||||||
|
submitted=$(bash "$script_dirS"/student/details.sh && ls -l file1.txt | awk '{print $1, $2, $5, $6, $7, $8, $9}') |
||||||
|
expected=$(bash "$script_dirS"/solutions/details.sh && ls -l file1.txt | awk '{print $1, $2, $5, $6, $7, $8, $9}') |
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
||||||
|
stat file1.txt |
||||||
|
} |
||||||
|
|
||||||
|
challenge |
||||||
|
rm file1.txt |
@ -0,0 +1,44 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
|
||||||
|
FILENAME="student/dir-info.sh" |
||||||
|
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd) |
||||||
|
|
||||||
|
rm -rf student/dir-info-files |
||||||
|
mkdir student/dir-info-files |
||||||
|
cd student/dir-info-files |
||||||
|
|
||||||
|
directories=(folder1 folder2/aa folder2/ba/aa folder2/aa/ba) |
||||||
|
for dir in "${directories[@]}"; do |
||||||
|
mkdir -p "$dir" |
||||||
|
done |
||||||
|
|
||||||
|
files=(.abc 34 folder1/ab 4 folder1/ac 2 folder1/az 3 folder1/bz 3 \ |
||||||
|
folder1/cz 9 folder1/.hello 21 folder1/za! 3 folder2/ab 7 folder2/ac 0 \ |
||||||
|
folder2/alphabet 0 folder2/az 0 folder2/bz 4 folder2/cz 0 folder2/za! 28 \ |
||||||
|
folder2/aa/aa 3 folder2/aa/az 4 folder2/aa/.salut 7 folder2/aa/ba/ab 0 \ |
||||||
|
folder2/aa/ba/bz 0 folder2/ba/ac 0 folder2/ba/alphabetz 0 folder2/ba/.ola 17 \ |
||||||
|
folder2/ba/aa/alphabetz! 0 folder2/ba/aa/.ciao 7 folder2/ba/aa/cz 0 \ |
||||||
|
folder2/ba/aa/za! 0) |
||||||
|
|
||||||
|
for ((i=0; i<${#files[@]}; i+=2)) do |
||||||
|
dd if=/dev/zero of="${files[i]}" bs=1 count="${files[i + 1]}" 2> /dev/null |
||||||
|
done |
||||||
|
|
||||||
|
cd ../ |
||||||
|
|
||||||
|
challenge () { |
||||||
|
submitted=$(bash "$script_dirS"/"$FILENAME" < <(echo "$1")) |
||||||
|
expected=$(bash "$script_dirS"/solutions/dir-info.sh < <(echo "$1")) |
||||||
|
|
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
||||||
|
} |
||||||
|
|
||||||
|
challenge "dir-info-files/folder1" |
||||||
|
challenge "dir-info-files/folder2" |
||||||
|
challenge "dir-info-files" |
||||||
|
|
||||||
|
rm -rf dir-info-files |
@ -0,0 +1,37 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# Unofficial Bash Strict Mode |
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
|
||||||
|
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd) |
||||||
|
|
||||||
|
challenge() { |
||||||
|
# Test if test command was used |
||||||
|
if grep -q "test" "$script_dirS"/student/division.sh |
||||||
|
then |
||||||
|
echo "Error: the test command cannot be used in the student script" |
||||||
|
return |
||||||
|
fi |
||||||
|
|
||||||
|
# Test with one or two arguments |
||||||
|
if [ $# -eq 1 ] |
||||||
|
then |
||||||
|
submitted=$(bash "$script_dirS"/student/division.sh $1) |
||||||
|
expected=$(bash "$script_dirS"/solutions/division.sh $1) |
||||||
|
else |
||||||
|
submitted=$(bash "$script_dirS"/student/division.sh $1 $2) |
||||||
|
expected=$(bash "$script_dirS"/solutions/division.sh $1 $2) |
||||||
|
fi |
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
||||||
|
} |
||||||
|
|
||||||
|
challenge "10" "2" |
||||||
|
challenge "4" "2" |
||||||
|
challenge "0.5" "0.5" |
||||||
|
challenge "5" "2" |
||||||
|
challenge "0.5" |
||||||
|
challenge "foo" "bar" |
||||||
|
challenge "1" "0" |
||||||
|
challenge "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" "2" |
@ -0,0 +1,15 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# Unofficial Bash Strict Mode |
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd) |
||||||
|
|
||||||
|
for i in $(seq 1 5); do |
||||||
|
export X=$(shuf -i 1-20 -n 1) |
||||||
|
export Y=$(shuf -i 1-30 -n 1) |
||||||
|
submitted=$(bash "$script_dirS"/student/easy-conditions.sh) |
||||||
|
expected=$(bash "$script_dirS"/solutions/easy-conditions.sh) |
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
||||||
|
done |
@ -0,0 +1,12 @@ |
|||||||
|
Q. How did the programmer die in the shower? |
||||||
|
A. He read the shampoo bottle instructions: Lather. Rinse. Repeat. |
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
How many programmers does it take to change a light bulb? |
||||||
|
None – It’s a hardware problem |
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
Why do programmers always mix up Halloween and Christmas? |
||||||
|
Because Oct 31 equals Dec 25. |
@ -0,0 +1,16 @@ |
|||||||
|
“The best TDD can do, is assure that code does what the programmer thinks it should do. That is pretty good BTW.” |
||||||
|
|
||||||
|
“Simply put, things always had to be in a production-ready state: if you wrote it, you darn well had to be there to get it running!” |
||||||
|
|
||||||
|
“If you think it’s expensive to hire a professional, wait until you hire an amateur.” |
||||||
|
|
||||||
|
“Programming is not a zero-sum game. Teaching something to a fellow programmer doesn’t take it away from you.” |
||||||
|
|
||||||
|
“A phased approach to continuous delivery is not only preferable, it’s infinitely more manageable.” |
||||||
|
|
||||||
|
“So, what do you do?” |
||||||
|
“I’m lean” |
||||||
|
“What?” |
||||||
|
“I’m agile” |
||||||
|
“What?” |
||||||
|
“Fine. I make websites.” |
@ -0,0 +1,17 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# Unofficial Bash Strict Mode |
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd) |
||||||
|
|
||||||
|
chmod 303 easy-perm/* |
||||||
|
|
||||||
|
challenge() { |
||||||
|
submitted=$(bash "$script_dirS"/student/easy-perm.sh && ls -l "$1" | awk '{print $1}') |
||||||
|
expected=$(bash "$script_dirS"/solutions/easy-perm.sh && ls -l "$1" | awk '{print $1}') |
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
||||||
|
} |
||||||
|
|
||||||
|
challenge easy-perm/ |
@ -0,0 +1,28 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# Unofficial Bash Strict Mode |
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
|
||||||
|
FILENAME="student/env-format.sh" |
||||||
|
|
||||||
|
# True if FILE exists and is a regular file |
||||||
|
if [ -f ${FILENAME} ]; then |
||||||
|
# FILE exists and it's not empty |
||||||
|
if [ -s ${FILENAME} ]; then |
||||||
|
if [[ $(cat $FILENAME | grep echo | wc -l) -ne 0 ]]; then |
||||||
|
echo "echo is not allowed in this exercise!" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
submitted=$(bash $FILENAME) |
||||||
|
expected=$(bash solutions/env-format.sh) |
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
||||||
|
else |
||||||
|
echo "The file exist but is empty" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
else |
||||||
|
echo "File does not exist" |
||||||
|
exit 1 |
||||||
|
fi |
@ -0,0 +1,38 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd) |
||||||
|
|
||||||
|
# check that test command was not used |
||||||
|
if grep -q "test" "$script_dirS"/student/file-checker.sh |
||||||
|
then |
||||||
|
echo "The 'test' command is not allowed in this exercise" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
|
||||||
|
if test ! -e file-checker; then |
||||||
|
mkdir file-checker |
||||||
|
cd file-checker |
||||||
|
touch readable-and-writable readable-only readable-and-executable readable-writable-executable |
||||||
|
chmod -x "$script_dirS/file-checker/readable-and-writable" |
||||||
|
chmod -xw "$script_dirS/file-checker/readable-only" |
||||||
|
chmod -w "$script_dirS/file-checker/readable-and-executable" |
||||||
|
chmod +x "$script_dirS/file-checker/readable-and-executable" |
||||||
|
chmod +x "$script_dirS/file-checker/readable-writable-executable" |
||||||
|
cd .. |
||||||
|
fi |
||||||
|
|
||||||
|
challenge() { |
||||||
|
submitted=$(bash "$script_dirS"/student/file-checker.sh "$1") |
||||||
|
expected=$(bash "$script_dirS"/solutions/file-checker.sh "$1") |
||||||
|
|
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
||||||
|
} |
||||||
|
|
||||||
|
challenge "$script_dirS/file-checker/readable-only" |
||||||
|
challenge "$script_dirS/file-checker/readable-and-writable" |
||||||
|
challenge "$script_dirS/file-checker/readable-and-executable" |
||||||
|
challenge "$script_dirS/file-checker/readable-writable-executable" |
||||||
|
rm -rf file-checker |
@ -0,0 +1,17 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# Unofficial Bash Strict Mode |
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
|
||||||
|
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd) |
||||||
|
|
||||||
|
challenge() { |
||||||
|
submitted=$(cd "$1" && bash "$script_dirS"/student/file-details.sh) |
||||||
|
expected=$(cd "$1" && bash "$script_dirS"/solutions/file-details.sh) |
||||||
|
|
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
||||||
|
} |
||||||
|
|
||||||
|
challenge hard-perm |
@ -0,0 +1,127 @@ |
|||||||
|
Indonesia consists only of islands - 13,667 total |
||||||
|
During World War II, the very first bomb dropped on Berlin by the Allies killed the only elephant in the Berlin Zoo |
||||||
|
People who ride on roller coasters have a higher chance of having a blood clot in the brain |
||||||
|
The tallest freestanding sculpture in the world is Chief Crazy Horse in South Dakota, USA |
||||||
|
Marie Curie, the Nobel prize winning scientist who discovered radium, died of radiation poisoning |
||||||
|
898 tornadoes were recorded to have occurred in the United States in the year 2000. |
||||||
|
The word Popcorn is derived from the middle English word "poppe," which means "explosive sound" |
||||||
|
The food that is digested in your stomach is called "chyme." |
||||||
|
Alcohol beverages have all 13 minerals necessary for human life |
||||||
|
The sentence "The quick brown fox jumps over the lazy dog." uses every letter in the alphabet. (Developed by Western Union to Test telex/twxcommunications) |
||||||
|
The word housekeeping was invented by Shakespeare |
||||||
|
The only two days of the year in which there are no professional sports games (MLB, NBA, NHL, or NFL) are the day before and the day after theMajorLeague All-Star Game. |
||||||
|
In the great fire of London in 1666 half of London was burnt down but only 6 people were injured |
||||||
|
Lack of sleep can affect your immune system and reduce your ability to fight infections |
||||||
|
All dogs are the descendant of the wolf. These wolves lived in eastern Asia about 15,000 years ago |
||||||
|
It is not possible to tickle yourself. The cerebellum, a part of the brain, warns the rest of the brain that you are about to tickle yourself. Since your brain knows this, it ignores the resulting sensation |
||||||
|
Parma ham is only Parma ham if it is made in the Parma region of Italy. The British chain supermarket Asda, made and packaged its own "Parma ham" and was successfully sued by the real Parma ham people (Parma Ham Trade Association) |
||||||
|
With winds of 50 miles per hour, The Statue of Liberty sways three inches and the torch sways five inches |
||||||
|
A famous bullfighter, Lagarijo, killed 4,867 bulls in the 19th century. |
||||||
|
Police detectives have used snapping turtles to help them locate dead bodies |
||||||
|
In most advertisements, including newspapers, the time displayed on a watch is 10:10 |
||||||
|
The national sport of Japan is sumo wrestling |
||||||
|
The early occurrence of a fetus yawning is at eleven weeks after conception |
||||||
|
In a month, a fingernail grows an eighth of an inch |
||||||
|
Edward VIII did not officially become the King of England as he abdicated the throne to marry an American divorcee |
||||||
|
The book "Little Red Riding Hood" was banned in 1990 by two school districts in California. They did this because in the book there was a picture of a basket that had a bottle of wine in it |
||||||
|
The reason why golf balls have dimples on them is because it helps in the ball to move a farther distance by reducing drag |
||||||
|
Americans consume the most peanut butter in the world |
||||||
|
Celtic warriors sometimes fought their battles naked, their bodies dyed blue from head to toe |
||||||
|
To make butter more attractive in color, carrot juice was used by people in the Middle Ages |
||||||
|
Early hockey games allowed as many as 30 players a side on the ice |
||||||
|
Most fleas do not live past a year old |
||||||
|
It takes seven to ten days to make a jelly belly jellybean |
||||||
|
Some asteroids have other asteroids orbiting them |
||||||
|
Maine is the only state whose name is just one syllable |
||||||
|
The male praying mantis cannot copulate while its head is attached to its body. The female initiates sex by ripping the males head off |
||||||
|
There is enough concrete in the Hoover Dam to pave a two lane highway from San Francisco to New York |
||||||
|
Americans on the average eat 18 acres of pizza every day |
||||||
|
Every 238 years, the orbits of Neptune and Pluto change making Neptune at times the farthest planet from the sun |
||||||
|
There is a certain species of kangaroo that is only 2.5 centimeters long when it is born |
||||||
|
In a lifetime, the average house cat spends approximately 10,950 hours purring |
||||||
|
The real name of Toto the dog in "The Wizard Of Oz" was Terry |
||||||
|
Stannous fluoride, which is the cavity fighter found in toothpaste is made from recycled tin |
||||||
|
It takes 12 honeybees to make one teaspoon of honey |
||||||
|
Thomas Watson, who was the chairman of IBM in 1943 predicted that their would probably only be a world market for five computers. |
||||||
|
The largest hamburger cooked in the world weighed in at 6,040 pounds |
||||||
|
The first lighthouse was in Alexandria in 290 B.C |
||||||
|
Heinz first started making ketchup in 1876 and the recipe has remained the same ever since |
||||||
|
The largest wedding chapel in Las Vegas is the Viva Las Vegas Chapel, which can seat 100 people |
||||||
|
The most popular name for a pet in the United States is Max |
||||||
|
Spiral staircases in medieval castles are running clockwise. This is because all knights used to be right-handed. When the intruding army would climb the stairs they would not be able to use their right hand which was holding the sword because of the difficulties of climbing the stairs. Left-handed knights would have had no troubles, except left-handed people could never become knights because it was assumed that they were descendants of the devil |
||||||
|
The largest shopping mall in the world is the West Edmonton Mall located in Edmonton, Alberta, Canada |
||||||
|
The CN Tower located in Toronto, Ontario Canada took a total construction time of 40 months to complete at an original cost of $63 million |
||||||
|
The 20th president of the United States, James Garfield, was able to write Greek with one hand and Latin with the other at the same time |
||||||
|
The country of Andorra has a zero percent unemployment rate |
||||||
|
In Los Angeles, there are fewer people than there are automobiles |
||||||
|
A woman has approximately 4.5 litres of blood in her body, while men have 5.6 litres |
||||||
|
In India, pickled ginger, minced mutton and a cottage cheese like substance are popular pizza toppings |
||||||
|
Oral-B were the first toothbrushes to go to the moon when they were aboard the Apollo 11 mission |
||||||
|
A maple tree is usually tapped when the tree is at least 45 years old and has a diameter of 12 inches |
||||||
|
In 1998, a law passed in the U.S. state of Virginia allows drivers to keep their road kill, as long as they report it within 12 hours. updated |
||||||
|
A language becomes extinct in this world every two weeks |
||||||
|
An acre of trees can remove about 13 tons of dust and gases every year from the surrounding environment |
||||||
|
The decomposition point of Olive Oil is 220 degrees Celsius |
||||||
|
Ten radishes only contain eight calories |
||||||
|
Annually a thousand people are killed by scorpions in Mexico |
||||||
|
Every year, 100 million sharks are killed by people |
||||||
|
Tug of war was an Olympic event from 1900-1920 |
||||||
|
Of all the countries, Brazil has the most plant species, with over 56,000 |
||||||
|
One female mouse can produce up to 100 babies a year |
||||||
|
Impotence is grounds for divorce in 26 U.S. states |
||||||
|
Women who are romance novel readers are reported to make love 74% more often with their partners than women who do not read romance novels. |
||||||
|
The average lifespan of a human taste bud is ten days |
||||||
|
The monogram "RR" for Rolls-Royce has never been altered, except for when Sir Henry Royce passed away in 1933. Then it was changed from red to black. |
||||||
|
People with darker skin will not wrinkle as fast as people with lighter skin |
||||||
|
Fido means faithful in Latin |
||||||
|
Pebbles cereal was actually named after the shape of the cereal and not the Pebbles Flintstone character |
||||||
|
A group of kangaroos is called a mob |
||||||
|
Cat's urine glows under a blacklight. |
||||||
|
Every three seconds, a new baby is born |
||||||
|
More than 260,000 people have been killed by volcanic activity since 1700 AD. |
||||||
|
The only predator that polar bears have are humans |
||||||
|
Many insects can carry 50 times their own body weight |
||||||
|
The last land battle of the U.S. Civil War was fought in Texas |
||||||
|
Annually 7 million tons of textiles and clothing is thrown out. Out of this, only 12% is used again or recycled |
||||||
|
A scorpion can have up to 12 eyes |
||||||
|
A snake charmer in Bangladesh once found 3,500 poisonous cobras and their eggs hidden underneath the floors of two suburban homes |
||||||
|
The IRS employees tax manual has instructions for collecting taxes after a nuclear war |
||||||
|
There are approximately fifty Bibles sold each minute across the world |
||||||
|
The pectin that is found in apples aids in lowering cholesterol levels |
||||||
|
Post-It Notes, which are adhesive notes, were invented while looking for a way to improve the acrylate adhesive found in tapes |
||||||
|
Crayola Crayons currently has over 120 different crayon colors |
||||||
|
Odontophobia is the fear of teeth |
||||||
|
The width of a tornado can range from less than ten yards to more than a mile. |
||||||
|
In Johannesburg, the average car will be involved in an accident once every four years. |
||||||
|
The youngest actress to be nominated as best actress is Keisha Castle-Hughes who was nominated at just 13 years old |
||||||
|
The Taj Mahal was actually built for use as a tomb |
||||||
|
According to studies, an average roll of toilet paper lasts about five days in the bathroom |
||||||
|
Almonds are members of the peach family |
||||||
|
The oldest known disease in the world is leprosy |
||||||
|
A fall of 30 feet can be survived my most cats |
||||||
|
The largest member of the dolphin family are orcas |
||||||
|
In 1477, the first diamond engagement ring was given to Mary of Burgundy by Archduke Maximillian of Austria |
||||||
|
The hormone replacement drug "Premarin" is made from the urine of pregnant horses |
||||||
|
TWIX Caramel Cookie Bars were first introduced in 1979 |
||||||
|
Nintendo was first establish in 1889 and they started out making special playing cards |
||||||
|
People over the age of fifty will start to lose their dislike for foods that taste bitter |
||||||
|
In Kentucky, 50 percent of the people who get married for the first time are teenagers |
||||||
|
Elephants have been known to learn up to 60 commands |
||||||
|
On average 1,668 gallons of water are used by each person in the United States daily |
||||||
|
Copper is the second most used metal in the world. |
||||||
|
Milton Bradley originally wanted to name the game Twister, Pretzel; but he could not since the name was copyrighted |
||||||
|
According to studies, men prefer to have white bedrooms and women prefer to have blue bedrooms |
||||||
|
If someone was to fly once around the surface of the moon, it would be equal to a round trip from New York to London |
||||||
|
St. Patrick never really drove out any snakes from Ireland. This story was an analogy of how he drove paganism out of Ireland |
||||||
|
Fat is important for the development of children and normal growth |
||||||
|
The most common seasonings found in American homes are chili powder, cinnamon, and seasoned salts |
||||||
|
People who have eaten beetles say that it tastes like apples |
||||||
|
Montreal was named after a local mountain "Mont Royal." |
||||||
|
Millie the White House dog earned more than 4 times as much as President Bush in 1991. And, rightfully so |
||||||
|
In an average lifetime, a person will spend 4 years traveling in an automobile and six months waiting at a red light. |
||||||
|
A small drip from a faucet can waste up to 50 gallons of water daily, which is enough water to run a dishwasher twice on a full cycle |
||||||
|
Kotex was first manufactured as bandages, during W.W.I |
||||||
|
The longest Monopoly game ever played was 1,680 hours long, which is seventy straight days |
||||||
|
The first known contraceptive was crocodile dung, used by Egyptians in 2000 B.C |
||||||
|
Over 1,600 people in North America have been victims of trunk entrapment (being locked inside of a car trunk) |
||||||
|
A rhinoceros horn is made of compacted hair |
@ -0,0 +1,28 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# Unofficial Bash Strict Mode |
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
|
||||||
|
FILENAME="student/file-researcher.sh" |
||||||
|
|
||||||
|
# True if FILE exists and is a regular file |
||||||
|
if [ -f ${FILENAME} ]; then |
||||||
|
# FILE exists and it's not empty |
||||||
|
if [ -s ${FILENAME} ]; then |
||||||
|
if [[ $(cat $FILENAME | grep echo | wc -l) -ne 0 ]]; then |
||||||
|
echo "echo is not allowed in this exercise!" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
submitted=$(bash $FILENAME) |
||||||
|
expected=$(bash solutions/file-researcher.sh) |
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
||||||
|
else |
||||||
|
echo "The file exist but is empty" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
else |
||||||
|
echo "File does not exist" |
||||||
|
exit 1 |
||||||
|
fi |
@ -0,0 +1,16 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# Unofficial Bash Strict Mode |
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
|
||||||
|
print_content() { |
||||||
|
mkdir -p uncompressed |
||||||
|
tar -xpf file-struct.tar -C uncompressed |
||||||
|
tree uncompressed |
||||||
|
} |
||||||
|
|
||||||
|
submitted=$(cd student && print_content) |
||||||
|
expected=$(cd solutions && print_content) |
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
@ -0,0 +1,35 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
# Unofficial Bash Strict Mode |
||||||
|
set -euo pipefail |
||||||
|
IFS=' |
||||||
|
' |
||||||
|
|
||||||
|
FILENAME="student/find-files-extension.sh" |
||||||
|
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd) |
||||||
|
|
||||||
|
challenge() { |
||||||
|
submitted=$(cd "$1" && bash "$script_dirS"/$FILENAME) |
||||||
|
expected=$(cd "$1" && bash "$script_dirS"/solutions/find-files-extension.sh) |
||||||
|
|
||||||
|
diff <(echo "$submitted") <(echo "$expected") |
||||||
|
} |
||||||
|
|
||||||
|
# True if FILE exists and is a regular file |
||||||
|
if [ -f ${FILENAME} ]; then |
||||||
|
# FILE exists and it's not empty |
||||||
|
if [ -s ${FILENAME} ]; then |
||||||
|
if [[ $(cat $FILENAME | grep echo | wc -l) -ne 0 ]]; then |
||||||
|
echo "echo is not allowed in this exercise!"; |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
challenge find-files-extension/folder1 |
||||||
|
challenge find-files-extension/folder2 |
||||||
|
else |
||||||
|
echo "The file exist but is empty" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
else |
||||||
|
echo "File does not exist" |
||||||
|
exit 1 |
||||||
|
fi |
Some files were not shown because too many files changed in this diff diff.show_more
Loading…
Reference in new issue