commit 2b2e239488c6e93744760c6a9071607b16a6ac6b Author: Martin Gerhardy Date: Thu Oct 15 21:54:01 2015 +0200 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..e61c76cde --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +CMakeFiles/ +cmake_install.cmake +CMakeCache.txt +/fips_targets.yml +Makefile +/.project +/.cproject +/.fips-gen.py +/.fips-imports.cmake +*.a +/.settings +/fips-*_* +/valgrind-*.log diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..94128e3dd --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 2.8) +get_filename_component(FIPS_ROOT_DIR "../fips" ABSOLUTE) +get_filename_component(ENGINE_ROOT_DIR "." ABSOLUTE) +include("${FIPS_ROOT_DIR}/cmake/fips.cmake") +include("${ENGINE_ROOT_DIR}/cmake/common.cmake") +set(CMAKE_MODULE_PATH "${ENGINE_ROOT_DIR}/cmake") +include(CheckFunctionExists) +include(CheckLibraryExists) + +set(FIPS_EXCEPTIONS ON) +set(FIPS_UNITTESTS ON) +set(FIPS_RTTI ON) +set(TB_ENABLE_RTTI ON CACHE BOOL "Do not disable RTTI" FORCE) + +if (${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Windows") +elseif (${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Darwin") +elseif (${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Linux") + # TODO: this is for the header only sauce lib + add_definitions(-Wall -Wextra -Wno-deprecated-declarations -Wno-unused-local-typedefs) +endif() + +include_directories(src/modules) +include_directories(src/modules/ui) + +fips_setup(PROJECT engine) +fips_add_subdirectory(src) +fips_finish() + +copy_data_files(shared) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 000000000..5e3015ce5 --- /dev/null +++ b/README.md @@ -0,0 +1,174 @@ +# About +Voxel engine that depends on [PolyVox](http://www.volumesoffun.com/polyvox-about/) and [AccidentalNoise](http://accidentalnoise.sourceforge.net/) + +The build system is a cmake based system that automatically downloads all the needed dependencies. See +[fips homepage](http://floooh.github.io/fips). + +Network message generation depends on [flatbuffers](https://github.com/mgerhardy/fips-flatbuffers) + +Concept: [Link](https://drive.google.com/open?id=0BxzNji4VZ2FaWXplX0I1ZWxOamc&authuser=0) + +# Var +There are vars inside the engine that you can override via commandline. Var instances are runtime changeable +configuration variables that you can influence from within the game. +e.g. run the server with ```./server -set sv_port 1025``` to change the *sv_port* var to 1025 and bind that port. + +* cl_cammaxpitch the max pitch should not be bigger than 89.9 - because at 90 we have a visual switch +* cl_camspeed +* cl_cammousespeed +* sv_seed the server side seed +* cl_name the name of the client +* cl_port the port to connect to +* cl_host e.g. 127.0.0.1 +* cl_fullscreen true|false +* cl_chunksize 16 The size of the chunk that is extracted with each step +* core_loglevel 0 = Error => 4 = Trace +* cl_vsync false|true To disable|enable vsync + +# Dependencies +* You need to have **SDL2** installed + * Windows: env var *SDL2DIR* point to the directory where you extracted it into ([Download link](http://libsdl.org/release/SDL2-devel-2.0.3-VC.zip)) + * Linux: pkg-config support is enough here (e.g. ```apt-get install libsdl2-dev```) +* You need to have **git** installed and in your path +* You need to have **cmake** installed and in your path +* You need to have **python27** installed and in your path +* You need to have **postgre** installed (ubuntu package postgresql, libpq-dev and postgresql-server-dev-9.3 (or another version)) + +# Compilation +* After fulfilling all the above mentioned dependencies, you just have to run ```fips``` + +# Profiling +* There is built-in [Remotery](https://github.com/Celtoys/Remotery) support - just run the application with e.g. + ```./fips run server -- -set core_trace true``` + or without fips: + ```./server -set core_trace true``` + The *core_trace* var will activate all those core_trace_* macros. + +# Check this out: +* [PolyVox and Bullet](http://www.reddit.com/r/VoxelGameDev/comments/2dmfr1/fun_with_polyvox_and_bullet/) +* [PolyVox 3D world generation](http://accidentalnoise.sourceforge.net/minecraftworlds.html) +* [AccidentalNoise islands](http://www.gamedev.net/blog/33/entry-2249282-hooking-into-the-tree-to-build-a-map/) +* [libnoise tutorials](http://libnoise.sourceforge.net/tutorials/) +* [VoxelEditor](https://voxel.codeplex.com/) +* [Voxel Engines](http://www.reddit.com/r/gamedev/wiki/block_engines) +* [Minecraft Protocol](http://wiki.vg/Protocol) +* [CouchDB](http://code.google.com/p/couchdbpp/) +* [Quest Generating AI](http://voxelquest.vanillaforums.com/discussion/comment/11/#Comment_11) (VoxelQuest) +* [VoxelShip Editor](https://blackflux.com/node/11) +* [MagicaVoxel Editor](http://ephtracy.github.io/) + +## PostgreSQL + +first sudo as postgres default superuser 'postgres' on bash + +`sudo -i -u postgres` + +adding an new new user by typing + +`createuser -s dbmaster` + +create a new database + +`createdb engine_db` + +now start postgres and add password for these user + +`psql` + +write this statement + +`ALTER USER dbmaster WITH PASSWORD 'ben711cCefIUit887';` + +now we have done the first initialization. + + +### quick postreSQL guide: + +to leave PSQL type: `\q` +to list all Database type: `\l` +to connect to an specific database type: `\c dbname` (for example `\c engine_db`) +after you are connected to an database, you can use SQL +to list al tables type: `\dt` (`\d+` for all tables. also sequences) + +more stuff: http://wiki.ubuntuusers.de/PostgreSQL + +### console postgres tools + +temporary tools (till rcon is not final) are usable via console. +after db is initialized start the server and type `store init` +this will create the user table + +to add an user type `store useradd ` + + + +# AI +* Request +* Produce +* Consume + +## Production chain +Define a need, to be able to produce something +In order to fulfill this need, the ai should request the needed objects (or walk to a location to get it) +Even food can be handled via "request -> produce" (the production is the health) + +We need a system that is able to define the needs and define how to fulfill them. +* Points of Interest (where is something produced) +* Reference other production chains (The product of something else might be the 'request' to 'produce' my own product +* Price one has to pay (exchange with some other good [e.g. of of the 'requests' of the producer] or money) + +So every npc should have several requests: +* money (used to get the production chain start good) +* food (used to produce health) +* production chain start good (use to produce something to get money/food/production chain start good) + +Each of these requests will get a priority. This way we have unique characters where one is just trying to survive, while another one +is just trying to get rich and yet another one that is already satisfied if he can fulfill the need of others. (The food should always be relative high) + +## Requests +requests[] = { + health + money +} + +## Health +Possibe production chains: +Money -> Food -> Health +InputGood -> OutputGood -> $ReferenceToFoodCreatorRequests + +So we need to save the needed outputs - and then recursively search for stuff that leads to fulfilling the need. If we can +fulfill the need on the first level, skip everything else - otherwise go a level deeper. + +fulfills[health] = { food 100% } +fulfills[food] = { buyfood 80%, createfood 15%, stealfood 5% } +fulfills[createfood] = { huntanimals 50%, producefood 50% } +fulfills[buyfood] = { money 100% } +fulfills[money] = { sellproduction 95%, stealmoney 5% } +fulfills[sellproduction] = { produce 100% } +fulfills[produce] = { work 99%, findprofession 1% } +fulfills[work] = { getmaterial 1%, convertmaterial 99% } +[...] + +I think this can all be modeled into behaviour trees. We need to implement the slot mechanism into SimpleAI to replace +profession slot. So the behaviour tree would e.g. look like this: + + + + CreateFood[IfFoodCreator] + BuyFood[IfEoughMoney] + GetFood[IsHungry] StealFood + StayHealthy + Work + + +## Requests can't be fulfilled +* Walk to the town hall and cry about not being able to fulfill your need. Do that for x time units - after that change your +profession, get new requests and try to fulfill those. +* A player can now walk into the town hall to resolve unfulfilled requests +* After x time units the unfulfilled request is again visible in the town hall for other players. + +# Spawn of npcs +* We need points of interest and a fillrate at those POIs. +* We need to be able to pick a profession (visual appearance will be tight to the profession) +* Do we need a sheriff in each town? One that already investigates unfulfilled requests? +* We need one town master chief rocker in the town hall that gives away the collected quests to the users. diff --git a/cmake/FindSDL2.cmake b/cmake/FindSDL2.cmake new file mode 100644 index 000000000..65d65e52b --- /dev/null +++ b/cmake/FindSDL2.cmake @@ -0,0 +1,18 @@ +if (DEFINED ENV{SDL2DIR}) + set(SDL2_INCLUDE_DIRS ENV{SDL2DIR}/include) + if (FIPS_WINDOWS) + set(SDL2_LIBRARIES ENV{SDL2DIR}/libs/SDL_main.lib ENV{SDL2DIR}/libs/SDL.lib) + endif() +else() + if (FIPS_WINDOWS) + find_package(SDL REQUIRED) + set(SDL2_INCLUDE_DIRS ${SDL_INCLUDE_DIRS}) + set(SDL2_LIBRARIES ${SDL_LIBRARIES}) + else() + #include(FindPkgConfig) + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_search_module(SDL2 REQUIRED sdl2) + endif() + endif() +endif() diff --git a/cmake/common.cmake b/cmake/common.cmake new file mode 100644 index 000000000..589d02241 --- /dev/null +++ b/cmake/common.cmake @@ -0,0 +1,24 @@ +SET(DEFAULT_LUA_EXECUTABLE lua) + +macro(copy_data_files TARGET) + add_custom_target(copy-data-${TARGET} ALL + COMMAND cmake -E copy_directory "${FIPS_PROJECT_DIR}/data/${TARGET}/" ${FIPS_DEPLOY_DIR}/${CMAKE_PROJECT_NAME}/${FIPS_CONFIG} + COMMENT "Copy ${TARGET} data files...") +endmacro() + +macro(check_lua_files TARGET files) + find_program(LUA_EXECUTABLE NAMES ${DEFAULT_LUA_EXECUTABLE}) + if (LUA_EXECUTABLE) + message("${LUA_EXECUTABLE} found") + foreach(_file ${files}) + add_custom_target( + ${_file} + COMMAND ${LUA_EXECUTABLE} ${_file} + WORKING_DIRECTORY ${FIPS_PROJECT_DIR}/data/${TARGET} + ) + add_dependencies(${TARGET} ${_file}) + endforeach() + else() + message(WARNING "No ${DEFAULT_LUA_EXECUTABLE} found") + endif() +endmacro() diff --git a/contrib/.gitignore b/contrib/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/data/client/mesh/animal_rabbit.dae b/data/client/mesh/animal_rabbit.dae new file mode 100644 index 000000000..fa46ec21b --- /dev/null +++ b/data/client/mesh/animal_rabbit.dae @@ -0,0 +1,199 @@ + + + + + gcorson + Maya 8.0 | ColladaMaya v3.02 | FCollada v3.2 + Collada Maya Export Options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0; +curveConstrainSampling=0;exportCameraAsLookat=0; +exportLights=1;exportCameras=1;exportJointsAndSkin=1; +exportAnimations=1;exportTriangles=0;exportInvisibleNodes=0; +exportNormals=1;exportTexCoords=1;exportVertexColors=1;exportTangents=0; +exportTexTangents=0;exportConstraints=1;exportPhysics=0;exportXRefs=1; +dereferenceXRefs=0;cameraXFov=0;cameraYFov=1 + +Copyright 2006 Sony Computer Entertainment Inc. +Licensed under the SCEA Shared Source License, Version 1.0 (the +"License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at: +http://research.scea.com/scea_shared_source_license.html +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + file:///C:/vs2005/sample_data/Complete_Packages/SCEA_Private/Maya_MoonLander/Moonlander/untitled + + 2006-08-23T22:29:59Z + 2007-02-21T22:47:42Z + + Y_UP + + + + + + + 37.8492 + 1.5 + 1 + 10000 + + + + + + + + + + 1 1 1 + + + + + + + ./animal_rabbit.png + + + + + + + + + + + + + file2 + A8R8G8B8 + + + + + file2-surface + LINEAR_MIPMAP_LINEAR + LINEAR + + + + + + 0 0 0 1 + + + 0 0 0 1 + + + + + + 0 0 0 1 + + + 0.3 + + + 0 0 0 1 + + + 0.5 + + + 0 0 0 1 + + + 1 + + + 1 + + + + + + + + + + + 35.0226 89.3874 23.3732 19.5676 89.7173 22.4879 9.22909 91.5427 17.1037 4.33048 88.7008 4.57726 45.0571 89.4178 19.824 -30.5196 11.6272 25.1326 -15.6992 11.4278 34.2321 51.8411 17.7055 36.5602 65.7206 18.372 27.0862 56.0117 11.4345 22.6963 -23.2343 18.1488 41.0429 -40.9218 18.6322 29.6382 62.4487 11.3989 12.9806 60.2326 28.1944 39.5949 71.2984 29.0359 29.3335 -32.9737 29.6914 43.477 -48.95 28.9358 31.4102 73.8118 41.7425 29.8584 65.2513 41.3955 39.884 72.6597 55.003 29.2468 64.6263 55.4849 38.2648 66.5829 66.4165 27.9218 55.5179 67.734 35.7358 43.4971 75.6992 31.8699 56.934 75.0037 25.7495 14.7601 73.8701 35.1574 -12.1248 73.9991 28.9191 14.7016 78.8465 28.8886 -3.37962 78.0576 23.1953 -24.7824 78.2304 7.65121 4.94216 81.4267 15.8195 -54.7257 89.9761 8.84491 -53.6566 74.7375 26.9735 -44.1714 77.8938 26.1268 -64.7587 73.8997 7.15297 -61.5691 65.6958 25.2253 -42.9296 61.2502 39.4496 -64.9663 57.2673 21.7398 -48.9596 49.2561 39.8218 -58.3698 43.9468 28.036 -31.7993 70.8398 33.4366 -33.1153 82.3349 8.62471 48.2452 81.0789 22.327 34.1225 80.5718 26.6473 15.5527 81.3807 24.423 0.65596 81.0723 3.99376 15.1798 11.41 36.4164 17.2973 17.3674 43.2976 43.8649 67.7941 39.8677 55.9835 56.1625 42.7808 56.4187 41.7648 44.4371 46.9566 29.0085 44.2399 18.041 21.337 45.4158 -24.2634 29.7596 46.4694 -37.1346 44.6474 44.4312 -35.8668 57.8953 42.7333 -24.1626 66.8013 39.6298 -14.2645 43.4767 51.8892 10.1522 43.8267 53.9252 -10.3735 36.316 51.8336 -14.5047 52.2745 51.0455 9.35439 52.1796 53.5056 24.5685 36.9247 52.4691 11.2191 35.6243 52.5988 27.0248 44.5585 52.8835 25.4374 55.0852 52.0724 9.23132 59.258 51.2115 21.2751 61.6417 50.3945 -11.0645 57.3325 50.3033 -22.8339 53.8174 48.6047 -22.3883 43.3299 49.8488 -13.3437 34.4469 50.7719 -15.0193 59.7488 48.0109 12.3031 31.6369 51.4681 28.2 34.9703 51.4911 34.9314 44.1559 51.2583 33.7281 55.8993 50.0475 24.8495 63.37 48.6114 9.96162 62.8873 48.4038 6.73344 84.5266 2.83788 10.2211 84.9641 13.1445 19.05 85.0093 20.4734 35.2584 84.9759 22.0089 44.8651 85.199 18.7578 54.1484 90.1992 13.1393 25.84 89.3162 23.5593 14.5318 90.4728 20.5795 5.99276 89.5698 10.1098 59.1034 90.0324 3.37689 -23.9364 11.5353 30.6125 -11.459 10.0413 29.8243 -24.5326 10.1147 22.2069 -35.1528 11.6836 17.7191 61.5472 14.2726 25.2082 43.6854 11.43 30.0164 47.7677 14.1162 33.6212 -19.459 14.309 37.9267 -36.067 14.5054 27.6816 -32.9292 18.5574 36.7248 -46.1733 18.6604 20.5246 73.3418 18.3468 14.9194 68.8732 23.4107 28.4208 55.7803 22.4988 38.5465 -27.0171 23.4671 43.0366 -45.2302 23.6628 30.9246 -41.0731 29.3325 39.4763 79.4615 29.1894 16.0672 76.9844 23.4678 15.5749 72.8865 35.1223 29.8369 63.2406 34.5574 39.8307 81.8608 42.114 16.7292 80.9318 35.3877 16.409 66.0817 48.5555 39.2449 73.9987 48.5347 29.6857 80.1688 55.1853 16.948 81.5894 48.8387 16.9628 61.1927 62.0057 37.295 70.17 61.0152 28.6395 74.8647 66.3268 16.601 77.7874 61.0196 16.7611 61.7637 71.037 26.8557 67.1835 75.4493 16.6366 71.6321 71.1772 16.667 -7.40039 76.1581 26.3759 14.8335 76.3145 32.0471 -20.947 75.0059 21.3995 -9.30957 78.0917 17.6635 2.33308 81.2658 10.7014 -55.3055 81.4823 20.1865 -44.1025 82.8784 21.08 -48.3998 77.2606 26.9595 -63.8341 69.8359 17.705 -58.2579 70.6396 26.4175 -58.1459 60.4109 31.5845 -50.1918 68.7831 33.097 -53.5557 46.1592 34.9928 -63.069 52.729 24.0553 -63.6495 60.7883 23.3658 -54.4261 28.5392 21.6382 -12.4228 39.2454 51.9419 -52.1766 34.1006 30.9987 -39.3582 37.1753 42.8245 -63.2047 33.3562 7.77354 -14.9689 48.0973 51.5712 -13.2184 68.1588 38.5488 -20.841 71.9312 31.5875 -34.0814 73.6573 23.1685 39.0864 77.6536 29.4959 52.286 78.2905 24.2985 28.6752 75.0467 34.74 24.5284 79.4248 29.0977 58.2456 81.6454 14.9372 62.5867 78.8584 16.1198 -40.058 73.3058 29.0169 -62.4832 42.7738 19.6053 -66.2542 57.7677 16.0138 -46.3972 55.562 40.3341 46.1403 83.2928 20.059 52.8472 87.516 12.3304 24.3957 81.2413 26.4145 17.5457 83.2299 21.6568 35.0308 86.9496 21.9178 5.66061 83.0193 2.97282 39.2717 10.0042 25.9897 49.7414 9.99683 19.7068 14.6156 10.0124 31.7958 28.2119 11.4278 34.5791 55.179 10.0309 11.4214 16.1259 13.9798 40.2177 33.0793 17.7336 41.3765 18.9195 36.2041 52.5892 10.6044 39.6524 53.4314 18.2523 44.3116 53.7955 25.9535 39.9994 52.7745 9.73549 48.0914 53.8815 16.9236 53.6009 53.2898 26.8721 49.8693 52.6952 9.12603 55.8675 52.7181 15.9783 60.8706 50.8542 23.2428 59.2083 51.1997 15.2006 70.9348 38.4909 -38.0814 66.6122 37.6368 -31.4745 63.2943 41.295 -12.9337 55.4359 50.6592 -29.8093 42.9681 46.5354 -18.6612 31.1764 47.8255 -30.266 55.8423 44.7033 36.2897 31.2217 48.0605 46.511 42.7776 47.7899 45.6636 56.4673 46.2574 32.8524 66.1703 44.2955 12.3579 67.2602 43.2175 -19.149 38.1518 50.4005 -23.6628 48.8825 49.2194 21.1045 32.7401 51.4785 32.4268 38.9651 51.46 35.2465 50.0413 50.7771 17.9201 63.7837 48.4371 30.018 60.597 49.2453 -20.4236 57.6424 48.1257 -7.11345 60.5511 48.2081 -5.54756 57.4675 50.6459 -6.2067 51.4293 52.475 -5.95461 43.3855 53.166 -4.66971 35.7333 52.2177 -5.70251 32.445 51.1085 -8.3205 17.8723 43.3717 -2.69678 11.3425 36.4653 -27.2981 42.8866 48.0687 -27.8897 55.043 46.5161 -16.4436 32.2248 49.3054 -18.5848 62.3861 45.599 13.6265 28.0639 49.9986 41.3922 43.4352 49.4685 32.3868 32.7171 49.8711 40.4699 56.3449 48.0345 28.9733 65.0389 46.3945 11.0523 65.6624 45.6909 -37.9272 11.78 6.99728 -50.2675 18.389 7.36354 75.8256 18.3928 2.93945 64.2756 11.6576 2.65993 82.8128 29.1368 2.93945 85.8726 42.1384 2.93945 84.9147 55.2091 3.25752 79.936 66.2007 3.25752 72.9207 75.6569 3.11665 -13.2799 78.2816 6.78078 -42.4217 91.5301 9.02211 -66.2519 42.375 7.59116 -67.9758 58.5114 6.99802 8.76422 81.5601 20.2429 8.65004 83.1534 13.7124 6.16626 86.3527 3.3376 10.3479 87.4003 13.9949 7.91973 84.7475 8.18356 19.5238 87.0994 20.6484 13.8638 85.0248 17.2846 35.1961 83.043 23.5111 26.055 84.941 22.3278 44.4291 87.1742 18.6599 55.1672 83.7325 13.2216 53.3737 85.5572 12.3674 -18.7264 10.108 26.6814 -28.5504 10.1785 15.7995 -28.6467 14.412 33.9793 -40.9463 14.6426 19.2219 68.6182 14.2022 14.0757 -36.9819 23.7436 38.5844 48.5084 72.1529 33.9029 -14.7042 76.6096 19.7209 -49.515 83.8778 20.7678 -60.3339 76.3635 19.0618 -54.5522 64.8765 32.9243 -60.8158 55.9957 28.5728 -50.6442 23.4975 21.2438 -45.1383 35.1824 39.0803 -57.747 33.5446 21.51 -27.5531 73.6877 22.8942 26.6207 76.9559 31.9144 -39.393 77.9086 22.2647 -65.5928 51.6658 17.2594 -44.8336 71.3336 32.1213 -65.569 63.5509 16.5565 25.3055 83.1594 23.781 12.1192 83.2358 18.075 25.9631 10.0257 30.0393 30.5288 14.0969 38.2233 18.4628 39.992 53.2994 17.691 48.9863 53.8221 16.1429 57.6002 52.3171 32.2615 71.41 37.9727 51.4408 62.676 41.4618 57.6406 48.9151 43.8433 52.9177 35.0586 44.5773 36.217 23.1483 43.9056 -31.7681 36.6178 45.7769 -37.83 51.5724 43.6927 -25.9576 36.5644 47.2776 -31.2662 49.6491 45.6583 26.7542 27.5116 48.1161 23.2102 67.8126 43.5534 -9.81152 64.5785 42.5347 -5.73514 54.6841 51.8166 -6.34459 47.5345 53.0926 -5.18279 39.3551 52.8687 -13.0679 23.5531 45.6457 -5.21985 14.0791 40.2548 -0.679352 10.0168 31.8299 -28.752 49.271 47.2864 -23.8534 36.6519 48.7626 -24.6964 59.5316 45.8889 -7.15942 29.3978 49.7079 38.1551 37.5127 49.7814 23.9612 29.5453 49.9126 42.2701 49.9123 48.8776 35.8278 61.6884 47.1419 20.5055 66.243 45.9037 -8.95663 63.2617 45.5834 -31.1142 10.1703 6.38486 -44.1714 14.6552 7.27827 70.6407 14.3913 2.92833 79.9353 23.413 2.93945 84.5803 35.3544 2.93945 85.9631 48.8595 3.25752 82.8254 61.0226 3.25826 76.7546 71.3433 3.2553 -19.2017 77.8115 7.33611 -48.5489 92.2656 9.06511 -60.1596 84.4057 8.28143 -55.757 23.043 7.73055 -29.2013 79.6561 8.08569 -37.1064 88.1752 8.91461 -68.0046 51.5783 7.15372 -66.9147 65.618 7.07735 57.0756 10.1525 2.28551 6.64003 83.0734 8.64102 7.67061 86.759 8.63805 14.3983 87.2706 17.8748 26.21 86.9437 22.1654 62.3057 92.5874 2.9313 1.3848 69.2606 38.5873 1.56273 65.4519 43.0262 1.32251 64.1537 45.6605 4.95551 9.99831 32.3904 4.63076 11.3477 37.0599 4.48174 13.922 40.9628 4.08211 17.3859 43.9419 3.02928 21.4474 45.8963 3.07525 28.2293 49.9356 3.11009 31.6361 51.3265 3.03002 35.4574 52.4675 2.61333 39.4033 53.3009 2.11362 43.4389 53.8266 1.75772 47.519 53.7873 1.63762 51.3863 53.3032 1.70287 54.8295 52.4802 1.76736 58.0161 51.0099 1.52196 61.5001 48.3586 1.93642 72.8387 33.8763 3.64763 75.9142 30.548 5.31806 78.4269 26.9639 58.5778 87.5953 2.23361 59.1501 85.8263 2.11721 61.5583 84.2063 2.51758 64.9644 82.1214 2.892 69.0133 79.1475 3.00989 32.7991 89.7151 -30.4233 18.3501 89.4171 -27.9721 8.67525 89.5668 -20.9938 2.39314 90.3705 -9.85685 41.3633 90.1718 -28.7054 -31.106 11.4775 -32.9686 -16.1893 11.413 -41.8242 -37.8441 11.7199 -17.9362 51.1145 17.827 -43.7764 65.4167 18.372 -34.6672 55.5386 11.4663 -30.2365 -22.7101 18.3816 -48.1723 -41.2258 18.6322 -37.22 -49.9064 18.1281 -19.4546 62.0944 11.4196 -20.5393 59.314 28.4606 -46.5397 70.9277 29.0352 -36.8544 -33.1991 29.873 -50.7109 -49.3615 28.878 -39.0246 73.4812 41.7559 -37.3453 64.6226 41.5905 -46.5931 72.9066 55.0971 -37.0309 63.9264 55.2231 -45.5736 67.308 66.4328 -36.116 55.8026 66.7664 -44.1694 43.9561 74.6649 -39.815 57.8297 75.238 -34.1393 15.5401 73.1894 -42.5115 -12.2174 73.8819 -36.4385 15.3978 78.7998 -35.5147 -2.0421 78.412 -29.475 -24.7876 76.5792 -19.7267 -12.534 78.2897 -17.6678 4.34457 81.1227 -24.1642 -55.8163 87.2424 -22.0756 -43.7036 88.3494 -22.3158 -54.1303 74.7924 -34.6324 -44.4888 77.8752 -33.6648 -65.5053 72.5896 -18.5049 -61.9613 65.7536 -32.9553 -43.4634 60.448 -47.4894 -65.1954 57.0723 -29.5143 -59.2654 27.9119 -20.2361 -49.2087 49.1998 -47.3723 -58.9689 43.7199 -35.5858 -66.3446 42.1948 -19.4391 15.5861 70.0443 -46.0785 -33.1287 69.3852 -41.4713 -34.4892 80.0254 -21.5618 48.699 81.1865 -30.8689 34.2382 80.5703 -34.2498 16.5759 81.1153 -31.895 0.727875 81.1872 -12.4148 -68.018 58.2133 -17.8183 14.7802 11.3848 -44.0174 16.9221 17.4452 -50.8066 -13.0864 43.3447 -58.8481 10.4495 43.9097 -61.0858 -9.32663 36.6667 -59.0505 -14.22 51.903 -58.0496 9.45597 51.998 -60.0277 24.246 37.0634 -60.5519 11.3896 35.7436 -60.2776 26.5918 44.6467 -61.0071 25.4626 54.4929 -59.5273 9.00666 58.9948 -57.2808 21.3366 60.5555 -57.2059 -11.1972 57.2725 -56.9708 -22.2438 53.1256 -56.0203 -20.3457 43.0689 -57.3067 -12.1122 35.0371 -58.1689 -14.9222 59.3774 -55.2218 12.2904 31.7184 -59.1973 27.7581 35.2002 -59.4961 33.8971 44.4969 -59.5273 32.7486 55.5991 -57.9969 24.5692 62.5262 -55.8246 9.69026 62.3164 -55.2589 6.31009 84.6215 -9.59067 9.94086 84.9232 -20.0693 19.0219 85.0345 -27.4843 34.7653 85.0426 -29.4209 44.1941 85.119 -26.7866 50.8728 90.6708 -23.6459 25.0482 89.5646 -29.954 12.9607 89.423 -24.9078 5.25504 89.8204 -16.202 3.24726 88.5844 -2.72431 56.928 89.7848 -10.5352 -24.3405 11.4359 -38.3603 -12.0514 9.99387 -37.4698 -25.119 9.92937 -30.186 -35.4745 11.6324 -25.6774 -30.9667 10.1577 -16.9998 61 14.303 -32.6913 42.9826 11.5093 -37.4209 46.9722 14.2133 -40.7944 -19.5197 14.3549 -45.3897 -36.488 14.4595 -35.3605 -33.1887 18.5722 -44.2309 -44.1233 14.4447 -18.6976 -46.6619 18.3928 -28.2843 73.0378 18.3468 -22.5011 68.5692 23.4107 -36.0025 54.8395 22.7093 -45.7182 -26.8814 23.6917 -50.1401 -45.535 23.6628 -38.5063 -41.3718 29.3444 -46.7703 79.1575 29.1894 -23.6481 76.6804 23.4678 -23.1566 72.5633 35.1268 -37.3883 62.517 34.8109 -46.6606 81.5568 42.114 -24.311 80.6278 35.3877 -23.9899 65.2083 48.5511 -46.1149 73.84 48.5629 -37.3 80.6871 55.3477 -24.807 81.674 48.8988 -24.6283 60.7961 61.4452 -45.0316 70.7794 61.119 -36.7907 75.5475 66.5218 -24.6246 78.6126 61.265 -24.804 62.9885 71.049 -35.1951 66.8647 75.4648 -24.4251 71.4756 71.2009 -24.4489 -6.85692 76.1307 -33.2993 15.3904 76.124 -38.9186 -20.6749 74.9933 -28.8188 -18.659 77.1776 -18.9697 -8.319 78.3549 -24.2702 1.96458 81.2562 -18.3514 -55.843 81.314 -28.5504 -49.6254 89.3466 -22.4648 -44.4451 82.6048 -28.9686 -48.6808 77.2324 -34.5316 -64.3131 69.6573 -25.8984 -61.7107 81.899 -20.9783 -58.7835 70.7123 -34.1097 -58.4469 60.3879 -39.1736 -50.5077 68.7809 -40.6817 -54.183 45.9931 -42.2824 -63.8549 52.5711 -32.0063 -63.9335 60.729 -31.1655 -54.957 22.8131 -19.9766 -55.152 28.2115 -29.5499 -11.2032 39.4137 -59.029 -53.076 34.2815 -38.5249 -39.7533 37.3377 -50.1979 -63.1283 33.463 -20.1464 -14.2141 47.7244 -58.4915 -30.0695 77.3155 -20.5683 -21.5757 71.2928 -39.3886 -34.2579 73.9026 -30.84 39.2161 77.6454 -37.0836 52.7939 78.4766 -32.8685 29.7051 73.7336 -42.0511 25.218 79.3136 -35.8083 57.9394 81.7173 -23.2211 62.3879 78.9177 -24.2442 -40.3947 73.317 -36.5831 -38.6256 84.6334 -22.1512 -63.1328 42.5522 -27.8513 -68.0395 51.255 -18.387 -66.6864 57.5891 -24.6884 -46.719 55.3544 -48.0974 -67.0838 65.1042 -17.911 46.0958 83.2499 -28.6417 50.9529 87.3143 -20.6038 25.2513 81.0708 -33.3601 17.9216 83.2039 -29.0153 34.0372 87.1164 -29.0287 5.17719 83.0067 -10.4967 38.7965 10.0502 -33.6129 49.3922 10.0272 -27.3241 14.187 9.93604 -39.5629 27.7425 11.4278 -42.1534 55.0359 10.0176 -19.0023 15.6372 13.9546 -47.8631 32.7953 17.7996 -48.8099 18.8513 36.2745 -60.5645 10.861 39.7903 -60.8997 18.3879 44.3219 -61.3282 25.5709 40.1514 -60.9249 9.98461 48.0417 -60.7803 17.172 53.0256 -60.1664 26.7053 49.7018 -60.6231 9.02446 55.628 -58.8755 15.9709 59.969 -57.3289 23.2776 58.2326 -58.209 44.1377 66.4765 -47.442 32.9162 70.0487 -45.5996 -39.1943 64.8054 -45.7138 55.5401 55.5242 -49.7715 51.248 61.6595 -48.7462 56.0065 41.9561 -51.2803 57.0734 48.8091 -50.5693 46.5132 29.225 -51.505 52.5663 35.3329 -51.6029 17.5056 21.4015 -53.1414 35.7529 23.258 -51.4249 -24.8654 30.3579 -52.8774 -37.595 44.6801 -51.7631 -32.3879 37.056 -52.6379 -36.3175 56.5451 -50.6094 -38.0947 50.8613 -51.419 -25.0582 65.9138 -47.2878 -13.0315 55.2283 -57.5699 -29.5994 42.7331 -54.0504 -17.7196 32.1054 -55.3997 -31.0452 54.9518 -52.1567 14.4814 25.6447 -55.9766 35.6595 31.6265 -55.6473 45.0786 43.2372 -55.4835 44.2682 56.1306 -54.0718 32.613 65.3459 -51.8098 12.2638 66.6664 -50.3239 -16.8788 38.5536 -57.7812 -22.2779 48.1633 -56.692 20.9614 32.7638 -59.3975 31.7892 39.2914 -59.6303 34.2463 50.1711 -58.9927 17.7651 63.1379 -55.4049 29.3959 59.9275 -56.7944 -19.9928 57.0804 -55.4805 -7.23875 60.3598 -55.204 -5.65804 57.5512 -57.0761 -6.0065 51.3551 -59.049 -5.22208 43.4715 -59.8809 -3.96387 36.0409 -59.508 -5.15608 32.8988 -58.5686 -13.5854 23.9342 -52.6112 -9.06415 18.1577 -50.5723 -3.25877 11.387 -43.9714 -26.2193 42.6871 -55.6006 -28.5919 54.4558 -53.8865 -15.0875 33.3422 -56.7928 -18.825 61.9909 -52.8915 13.3618 27.7844 -57.7174 39.8055 43.952 -57.5439 31.8122 33.1212 -57.6826 38.9151 56.1492 -56.0878 28.5307 64.3375 -53.8731 10.8825 65.2576 -52.8604 -38.7872 11.7814 -10.3899 -51.3804 18.2081 -11.1306 75.9308 18.2734 -10.619 64.3713 11.5264 -10.1319 82.6956 29.1294 -10.748 85.6139 42.137 -11.5317 84.7924 55.3455 -12.4133 79.6343 66.3979 -12.9219 71.6684 75.6332 -12.7061 -25.2621 79.1542 -11.2952 -14.3624 78.3676 -10.5812 -55.4174 91.1379 -15.1558 -43.1913 92.0224 -14.9719 -65.5402 74.7902 -11.1558 -61.0434 28.0454 -11.3123 -32.6111 84.6875 -12.5304 -67.2833 42.4839 -10.9141 -68.8802 58.6841 -10.4374 0.543259 81.1205 -6.22162 9.52418 81.0708 -28.7966 8.37571 83.1824 -21.1125 5.53085 86.6678 -9.24443 6.35532 84.3783 -3.72153 9.91936 86.9399 -19.9543 7.46301 84.8157 -15.1358 19.1716 86.9829 -27.1848 13.7244 84.9789 -24.2465 35.0315 83.0667 -31.2656 26.1633 85.0641 -29.3275 42.8321 87.2394 -26.5835 54.4673 83.6613 -21.5529 52.1903 85.3592 -20.4029 -19.1772 9.97014 -34.5627 -29.0093 10.0524 -23.9684 -28.9966 14.3787 -41.6404 -41.4341 14.4313 -27.1351 68.2653 14.2141 -21.6559 -37.1724 23.751 -45.8917 49.1935 70.9503 -42.3484 -14.5648 76.6133 -27.0075 -49.8916 83.6109 -28.9872 -61.1227 76.1114 -27.2671 -55.0601 65.0337 -40.5186 -61.3029 55.8348 -36.2984 -51.2017 23.1727 -29.0783 -45.8464 35.4359 -46.3143 -58.6945 33.6906 -29.4149 -27.3062 73.8878 -30.3291 27.1279 76.7275 -38.8845 -39.6428 78.0687 -29.8339 -66.1326 51.3373 -25.8257 -45.1368 71.2869 -39.6934 -65.8464 63.4174 -25.0094 25.8474 83.1357 -30.877 12.1451 83.2039 -25.5855 25.4849 9.93826 -37.9992 30.078 14.1043 -45.7664 18.448 40.0625 -61.2347 17.9876 48.7616 -61.0605 16.2348 56.7727 -58.8674 -32.2767 62.0154 -49.2051 -13.9368 67.8282 -45.9206 -24.8684 37.0434 -54.8511 -31.525 48.8313 -53.174 26.4258 27.5071 -55.6637 23.2554 67.017 -50.8845 -10.1563 64.4547 -50.0444 -5.75739 54.7064 -58.2557 -5.8419 47.5145 -59.5984 -4.37907 39.5768 -59.8409 -5.9761 14.2111 -47.5917 -0.926239 9.96272 -39.5747 -28.5177 48.5533 -54.7769 -21.6936 37.4949 -56.2842 -25.4638 59.1765 -53.191 -6.8028 30.1029 -57.2111 37.0326 38.1125 -57.7227 23.7499 29.4563 -57.6722 40.6137 50.1599 -57.0286 34.858 61.1842 -54.92 20.4387 65.7863 -53.1414 -9.18353 63.1068 -52.8225 -31.7926 10.1666 -9.9777 -45.2866 14.5017 -10.8326 70.7816 14.2259 -10.5137 79.9368 23.3648 -10.642 84.3683 35.367 -11.0661 85.8037 48.9262 -12.0255 82.7112 61.2146 -12.6921 76.0168 71.4278 -13.3949 -20.2604 77.9924 -11.2248 -49.3845 92.9811 -15.3182 -60.8729 85.6046 -14.2238 -56.4851 22.8762 -11.2211 -64.3531 34.2467 -11.1677 -29.1309 81.0871 -11.445 -37.3177 89.3021 -14.5323 -69.0093 51.6317 -10.622 -67.6547 66.1837 -10.4878 5.71547 83.0356 -4.42811 57.0919 10.0917 -9.5929 6.03725 83.0742 -16.133 5.45968 86.1214 -3.26036 7.12048 86.8962 -15.0149 13.8867 86.9385 -24.0596 25.9809 87.0964 -28.959 -11.6043 122.781 8.68477 -11.2981 122.692 9.69681 -10.977 122.366 10.6888 -10.6656 121.82 11.586 -10.3765 121.078 12.3445 -10.1237 120.175 12.9302 -9.91827 119.156 13.3142 -9.77222 118.067 13.4803 -9.68768 116.96 13.4188 -9.67062 115.887 13.1341 -9.72327 114.899 12.6358 -9.85822 114.021 11.8907 -10.7227 112.914 8.71887 -11.1023 127.944 8.41562 -10.4921 127.767 10.4464 -9.85971 127.122 12.423 -9.24655 126.037 14.2114 -8.68082 124.561 15.7276 -8.18628 122.764 16.8946 -7.78964 120.733 17.6635 -7.49306 118.563 17.9719 -7.3344 116.363 17.8451 -7.30846 114.233 17.2735 -7.41818 112.273 16.2733 -7.69992 110.534 14.786 -8.2775 109.033 12.4727 -9.35776 108.08 8.5424 -9.95609 132.998 7.96262 -9.04932 132.737 10.981 -8.11142 131.781 13.9103 -7.20317 130.173 16.5602 -6.3661 127.988 18.8075 -5.64024 125.328 20.5468 -5.05821 122.318 21.6961 -4.64821 119.099 22.2025 -4.42282 115.824 22.0238 -4.39761 112.65 21.1845 -4.56294 109.746 19.6875 -4.97073 107.211 17.3891 -7.42485 103.383 8.21767 -8.20483 137.879 7.33685 -7.0141 137.537 11.2983 -5.78555 136.284 15.1374 -4.59557 134.176 18.611 -3.49826 131.313 21.5559 -2.54626 127.827 23.8351 -1.78407 123.883 25.3417 -1.24654 119.664 26.006 -0.958862 115.367 25.7954 -0.932175 111.202 24.7018 -1.15683 107.411 22.6977 -1.71957 104.094 19.6809 -4.90993 99.0215 7.7476 -5.87453 142.516 6.54797 -4.41762 142.098 11.3954 -2.91623 140.566 16.0879 -1.46082 137.989 20.3341 -0.119568 134.489 23.9337 1.04373 130.229 26.72 1.97571 125.407 28.5617 2.63261 120.249 29.3728 2.98405 114.998 29.1163 3.01297 109.897 27.8025 2.72233 105.248 25.381 2.00388 101.315 21.4907 -1.90344 95.1527 7.08847 -2.99854 146.84 5.6071 -1.29695 146.353 11.2694 0.45578 144.564 16.7478 2.15439 141.556 21.7035 3.72029 137.47 25.9059 5.07858 132.497 29.1585 6.16626 126.869 31.3079 6.93364 120.848 32.2555 7.3429 114.718 31.9552 7.37701 108.764 30.4219 7.02557 103.335 27.5927 6.15958 98.8146 22.9217 1.31064 91.5316 5.92221 0.38089 150.789 4.52833 2.30194 150.239 10.9231 4.28081 148.22 17.1066 6.19814 144.825 22.7007 7.96496 140.213 27.4444 9.49823 134.6 31.1152 10.7268 128.246 33.5419 11.592 121.45 34.611 12.0547 114.531 34.2722 12.0932 107.81 32.5417 11.6995 101.628 29.4492 10.7461 96.4739 24.1724 4.21408 154.305 3.32648 6.32714 153.7 10.3604 8.50323 151.481 17.1593 10.6111 147.749 23.3102 12.5537 142.677 28.5254 14.2397 136.505 32.5617 15.5905 129.519 35.2301 16.5418 122.048 36.4053 17.0504 114.439 36.0331 17.0919 107.05 34.1306 16.6589 100.258 30.74 15.7233 94.7279 25.791 8.4454 157.338 2.02082 10.7201 156.687 9.59079 13.0608 154.299 16.9057 15.3288 150.283 23.5229 17.4189 144.827 29.1348 19.2332 138.186 33.4774 20.6856 130.67 36.3481 21.7103 122.631 37.6123 22.2575 114.445 37.2119 22.3019 106.495 35.1648 21.8259 99.2209 31.4888 20.825 93.3985 26.5962 13.0133 159.842 0.628418 15.4163 159.154 8.62471 17.8875 156.633 16.3489 20.283 152.392 23.3369 22.4903 146.631 29.2623 24.4054 139.618 33.8481 25.9394 131.682 36.879 27.0211 123.193 38.2151 27.5987 114.549 37.7917 27.6461 106.153 35.6297 27.1561 98.4202 31.8069 26.2026 92.3353 26.7949 17.8512 161.781 -0.829224 20.3468 161.067 7.47549 22.9136 158.449 15.497 25.4011 154.045 22.7534 27.6929 148.063 28.9072 29.6814 140.78 33.6686 31.2747 132.539 36.8168 32.3972 123.724 38.2032 33.0378 114.732 37.7776 33.1394 106.004 35.5511 32.5863 97.9694 31.5919 31.965 91.3737 26.2299 28.0317 162.761 5.43213 30.6652 160.074 13.6627 33.218 155.556 21.1096 35.5698 149.416 27.4236 37.6109 141.943 32.3103 39.2458 133.487 35.5408 40.3779 124.44 36.8931 41.0778 115.182 36.3645 41.3685 106.251 34.3441 40.5714 98.0124 30.0964 39.483 90.8428 24.5869 25.47 163.494 -3.09354 33.2647 163.97 -5.38011 35.8181 163.241 3.11665 38.442 160.564 11.3176 40.9852 156.062 18.737 45.5605 150.164 24.1539 46.9596 143.512 28.5313 48.7731 136.143 30.9839 48.1273 125.112 34.1698 49.5294 116.289 34.2469 49.9179 107.113 32.426 48.6893 98.8206 27.8254 47.2243 91.628 22.178 38.4532 163.455 -6.88224 40.9503 162.742 1.42916 43.5171 160.123 9.45065 47.7967 155.173 17.3906 53.1913 129.392 30.4605 57.4434 120.187 30.353 57.7555 108.881 29.1971 56.501 100.349 24.8901 54.4406 93.4897 18.651 43.5401 162.322 -8.34137 45.9453 161.636 -0.335434 50.4154 158.124 9.95186 48.4521 160.589 -9.73451 50.7305 159.939 -2.15119 54.3182 157.614 6.23138 63.8033 119.565 25.3861 63.9101 110.06 24.7226 62.901 102.219 20.9027 60.7679 96.0876 14.7059 53.1171 158.28 -11.0416 55.2347 157.675 -3.99215 58.19 155.872 2.80748 67.2969 119.573 21.0355 67.7537 111.25 20.0049 67.3733 103.92 17.1459 65.043 98.1407 11.5222 57.4671 155.429 -12.245 59.394 154.879 -5.83163 62.1915 152.982 0.103493 69.6977 119.848 16.5973 70.8076 112.269 15.649 70.4413 106.039 12.8968 68.5447 100.725 8.19913 61.4382 152.077 -13.326 63.1457 151.59 -7.6422 65.78 149.427 -2.04368 72.9933 113.56 10.1899 72.6093 109.123 7.23009 71.4208 102.692 -5.93692 66.1158 146.314 -14.556 67.6306 145.656 -8.87371 68.937 144.641 -4.73136 71.1249 140.238 -3.87204 72.9303 135.432 -3.25369 73.955 129.872 0.956131 73.8222 124.051 6.88754 69.9913 140.169 -15.5436 71.876 138.749 -9.69077 -11.3759 117.634 8.77818 63.3644 132.244 19.7795 58.7861 144.777 19.4836 67.0122 129.764 16.8798 70.6155 138.855 5.83472 63.4756 148.383 9.49515 62.8195 133.184 17.464 65.3848 131.323 15.0306 58.8061 141.77 16.8434 60.1659 137.06 18.4575 67.3103 131.311 12.1873 59.8997 144.627 13.2097 68.6945 133.697 9.63008 62.6779 144.573 10.0134 68.5944 137.783 7.94185 66.1373 141.972 8.0323 63.5846 133.449 17.7798 66.1373 131.523 15.497 59.6002 142.393 17.3936 68.0977 131.472 12.4801 69.5345 133.885 9.64862 63.3399 145.241 10.1906 69.4233 138.273 7.76169 66.8358 142.631 7.99524 70.3049 128.194 12.73 72.5233 132.983 6.70811 70.8876 139.701 3.88477 57.3232 138.168 24.4749 62.3546 131.157 22.7541 67.3926 146.279 4.41341 62.6852 151.575 8.16354 58.5355 152.152 14.7897 56.0087 147.327 21.699 67.4163 128.203 18.5732 61.7689 138.738 16.9517 60.1192 142.066 15.9826 64.1066 135.62 16.4201 65.946 133.39 14.7222 67.2903 132.939 12.8657 68.2793 135.009 11.4955 67.7633 138.355 10.7993 65.6517 141.685 10.9157 62.861 143.967 11.7343 60.6115 144.197 13.6175 60.9733 137.35 18.8824 60.8999 145.33 13.6701 65.4233 132.097 14.9091 64.194 132.052 16.3667 63.0381 133.984 17.1452 60.5626 137.576 18.0038 59.2072 139.485 18.0623 59.179 141.815 16.5439 61.4122 134.887 18.1943 67.2154 132.019 12.4453 66.4087 131.047 13.613 59.0411 143.572 15.1678 60.1096 144.464 13.3409 68.5151 134.306 10.3248 68.0821 132.189 10.829 61.149 144.974 11.4258 62.7831 144.363 10.5976 68.2882 138.059 8.96576 68.9548 135.624 8.61655 64.3898 143.534 8.86493 66.015 141.892 9.0614 67.5801 139.948 7.72906 62.5229 143.343 13.2497 61.0674 143.946 13.8533 64.8184 141.126 13.1519 66.8854 138.187 12.9695 67.3889 133.651 13.1986 66.7994 134.635 14.1328 65.5909 137.242 14.9847 63.4504 140.109 15.2998 61.4471 142.587 14.915 69.5049 129.705 12.5735 72.1177 136.32 4.77299 71.5801 133.393 8.20432 59.2932 134.201 23.8217 59.9546 137.579 21.2023 65.0801 149.359 5.97188 67.3192 144.395 6.27661 56.9459 150.409 18.5398 60.5959 148.729 14.5628 56.1303 142.947 23.7928 65.2135 129.283 20.9902 68.9562 127.783 15.7988 69.2988 142.988 3.69571 60.547 152.61 11.1863 71.7477 130.025 9.56706 72.9533 131.626 4.33482 71.3592 125.34 12.6099 70.8958 140.288 0.80043 60.4142 128.485 25.3476 53.3566 137.368 28.099 60.1785 154.454 5.65604 66.8521 148.152 1.54631 50.4599 149.321 23.457 54.4777 155.19 14.0957 66.8083 125.61 19.6379 60.7657 140.445 16.6648 62.9418 137.1 16.8738 65.1157 134.361 15.6497 66.6044 132.832 13.8036 67.9094 133.728 12.0538 68.246 136.622 11.0736 66.8721 140.078 10.7355 64.2593 143.015 11.2634 61.6205 144.401 12.4393 60.0361 143.345 14.9402 62.2167 135.13 18.5205 60.0235 144.253 15.7061 59.9835 139.927 18.519 64.9258 132.28 16.7923 67.1776 131.236 14.0179 68.9044 132.335 10.9928 69.7696 135.952 8.50682 68.3794 140.573 7.55853 64.9874 144.212 8.9287 61.9957 145.611 11.7513 64.3364 132.866 16.125 59.6128 139.75 17.5893 61.7458 135.583 17.8214 66.3694 131.791 13.6738 59.3318 143.457 15.0788 67.9657 132.894 11.3154 61.3218 144.772 11.7684 68.6738 136.094 9.51442 64.4194 143.374 9.69681 67.3615 140.039 8.78485 61.7844 144.005 13.1407 63.6091 142.365 13.2305 65.9438 139.693 13.0347 67.4912 136.673 12.9257 66.9492 133.714 13.8169 66.3464 135.861 14.5969 64.5685 138.672 15.2167 62.3546 141.447 15.1878 60.8028 143.341 14.6881 70.7571 131.099 10.3129 71.4393 136.084 6.66586 61.5272 134.531 20.6551 65.2209 146.715 7.63861 59.5052 147.331 17.3142 58.8328 141.204 20.8056 65.3699 130.706 18.6303 68.3045 129.387 14.7556 69.1838 141.704 5.63008 61.9527 149.098 11.8158 72.6026 127.566 8.47568 72.3965 136.097 1.70497 56.5247 132.614 27.6949 63.6929 151.685 3.08774 52.022 153.009 18.9305 51.1249 144.226 26.8356 63.9865 126.508 22.5154 69.2202 125.238 16.535 69.0541 144.317 0.692924 57.2187 155.661 9.56113 67.741 135.282 12.8723 67.7907 134.283 12.7419 71.6609 136.111 -15.9358 72.3201 105.969 -15.2641 74.0417 117.157 -16.1597 75.2065 106.525 -16.2769 79.8634 107.308 -17.6552 91.3867 109.457 -21.1013 88.3001 106.164 -20.0804 79.2991 114.295 -17.6596 83.595 107.064 -18.7273 84.1132 113.461 -18.9875 85.3967 106.488 -19.2404 74.3568 135.883 -16.7173 78.9611 134.305 -18.0244 82.9529 133.126 -19.1618 84.9244 134.248 -19.7638 86.99 136.683 -20.4237 90.4947 139.433 -21.5114 93.7133 139.447 -22.4507 94.9967 133.968 -22.6969 95.4994 138.023 -22.9393 92.0955 130.536 -21.7701 88.3638 126.832 -20.5942 85.6599 124.96 -19.7608 81.4537 123.062 -18.4885 74.8654 115.813 -16.3999 75.0456 119.162 -16.437 77.3477 106.901 -16.9108 90.4702 107.067 -20.7351 76.8324 114.944 -16.9597 81.866 106.977 -18.232 81.8267 113.709 -18.3173 87.5994 113.172 -20.0641 72.8517 136.463 -16.4526 76.6211 135.168 -17.3616 81.0749 133.56 -18.6235 84.1259 133.478 -19.5125 85.7941 135.222 -20.0404 95.5972 136.005 -22.9201 93.7963 132.209 -22.3054 90.1255 128.604 -21.1495 87.0197 125.694 -20.1745 83.7714 124.169 -19.1907 77.8207 121.529 -17.3927 90.9181 111.196 -21.0087 72.5032 108.223 -2.09484 75.2258 128.38 -2.75545 73.0089 134.723 -11.6266 74.987 120.808 6.20024 75.9205 117.527 -9.42607 74.9633 116.553 -9.73895 78.1707 127.11 -4.45851 76.4373 109.876 3.38505 75.8359 108.157 -4.45555 81.7666 127.621 -5.91393 76.6804 114.045 7.19746 76.6345 120.205 6.07716 82.3917 119.936 3.28125 80.7256 108.785 -7.12913 83.5075 117.685 2.46864 82.9974 115.277 1.76725 92.4261 111.042 -14.8022 90.3783 110.634 -9.15768 95.4037 129.402 -7.5814 96.0984 136.789 -17.4832 82.3405 119.579 -9.26593 80.8413 115.369 -9.65369 85.2625 124.587 -1.81087 84.8272 129.21 -7.48057 85.7451 117.806 -3.52579 86.8232 121.414 -9.52765 85.9097 118.886 0.325172 87.199 131.776 -9.16064 88.7516 134.416 -11.1099 90.1003 121.341 -5.78863 94.2515 126.991 -9.62626 89.9564 123.624 -10.2795 92.7753 126.838 -11.8772 90.8128 122.536 -2.9371 84.8317 108.856 -9.63812 86.0135 114.746 -2.76731 86.5792 108.162 -11.0609 90.7371 125.097 -2.53673 73.043 106.875 -10.3143 75.0849 116.366 -9.04127 75.9716 116.037 -9.92357 74.6763 117.226 -13.3023 76.6107 127.495 -3.81347 75.8715 107.338 -10.9986 74.2945 131.787 -6.83849 77.6673 130.92 -7.97213 79.9509 127.383 -5.12654 76.4239 117.364 7.49699 79.6098 120.36 4.88643 79.5468 114.305 5.90663 78.3479 108.471 -5.80049 80.1169 108.117 -13.6233 81.3351 130.611 -9.06203 83.483 116.149 2.62879 83.0011 114.026 3.50368 91.761 108.672 -14.126 92.1266 109.889 -18.0081 93.8845 131.645 -7.45462 96.1799 134.037 -11.4887 81.9698 117.706 -6.57603 78.9833 118.659 -9.33636 78.2737 115.773 -9.7916 81.6235 116.026 -5.37269 79.8693 114.493 -14.8934 83.5372 128.01 -6.78511 83.5372 116.896 -3.09725 86.2686 119.313 -6.65833 84.7701 120.477 -9.37344 85.7155 117.814 -1.09836 82.8336 116.065 -0.2435 84.0376 118.31 1.24899 82.4806 122.05 -11.5955 87.1182 124.405 -12.0018 88.0999 133.229 -10.2009 92.2897 123.818 -7.20253 93.4241 126.82 -10.8934 91.5661 125.3 -11.0513 89.9394 122.25 -7.90022 90.4806 121.459 -4.05592 93.4426 125.358 -4.55564 95.0537 127.861 -8.4207 86.6067 133.598 -11.5288 88.5707 135.852 -12.9256 89.8207 126.465 -12.6372 92.9117 128.817 -13.9117 95.0404 130.344 -13.2941 82.9299 109.011 -8.36213 85.6702 113.376 -2.09262 83.9642 114.927 -0.734322 83.2265 115.122 -10.3417 85.751 115.129 -7.31301 84.1511 107.994 -14.6242 84.6693 113.83 -16.0203 88.6597 113.95 -5.64331 88.16 112.314 -5.20661 87.6284 114.616 -8.44739 91.1709 112.257 -10.1186 89.261 107.896 -12.7825 84.4929 131.425 -10.2884 88.4714 122.412 -9.79086 88.4424 120.148 -1.065 85.9995 121.323 0.560211 86.1099 130.434 -8.26055 87.8345 118.872 -4.42515 91.1968 133.419 -9.01013 88.8191 128.275 -4.56676 81.5976 122.873 0.828606 76.9644 122.205 2.94316 81.4612 110.902 -0.296883 85.7392 110.723 -3.63627 75.9894 134.176 -12.4407 80.1251 132.842 -13.5803 83.9442 132.485 -14.6398 85.946 134.022 -15.3694 88.0213 136.327 -16.4059 91.3103 138.582 -16.933 94.3976 138.399 -17.1755 95.3962 132.764 -17.8798 92.8436 130.018 -17.5358 89.2928 126.974 -16.3569 86.4413 124.91 -15.6051 82.4754 123.01 -14.5108 91.896 112.486 -14.9156 82.8751 115.658 -0.544518 86.2805 115.188 -4.50003 76.1644 116.572 -8.83145 75.4185 115.882 -13.8516 76.0488 119.438 -12.6624 75.6543 131.457 -7.41829 79.4986 117.656 6.72963 79.0322 110.008 1.65974 78.0128 107.635 -12.0211 79.5268 130.758 -8.47779 82.1877 117.111 4.66623 91.3177 107.267 -17.6789 94.3523 135.804 -11.3701 79.199 116.397 -7.74822 77.416 115.064 -14.3959 84.1318 118.571 -6.36101 83.3881 117.034 -0.32283 85.0712 123.225 -11.8706 91.807 124.332 -9.03386 92.9703 124.047 -5.59067 87.5542 134.782 -12.3095 91.394 127.808 -13.2948 94.0891 129.464 -13.8324 83.6906 111.07 -2.07482 83.6929 113.909 0.096817 83.6402 115.586 -6.22978 82.2292 108.145 -14.0185 82.2626 114.108 -15.3812 85.9475 107.439 -15.3597 88.2578 113.456 -17.1125 88.2163 114.084 -11.2463 88.9763 106.666 -16.7455 83.1168 130.614 -9.81607 88.5233 125.332 -12.2287 88.5596 122.718 -0.990116 88.1236 120.568 -7.14322 91.5424 136.545 -12.2591 90.1959 130.708 -6.46555 83.1835 123.375 -0.566017 79.5957 122.783 1.99635 74.3672 117.295 7.88031 87.5631 110.072 -6.37584 74.1744 134.769 -11.9588 77.8467 133.564 -12.9456 82.0565 132.388 -14.1586 85.1416 133.114 -14.9897 86.8728 135.108 -15.8513 96.088 134.721 -17.6366 94.3716 131.254 -17.9443 90.9752 128.478 -16.8885 87.8886 125.817 -15.9581 84.6456 124.017 -15.1551 78.798 121.528 -13.6567 91.6357 111.58 -17.9377 84.2971 115.519 -2.50114 83.7426 120.625 1.77541 88.5833 114.451 -6.97195 88.0828 118.976 -2.26166 92.4098 128.085 -4.46593 90.9233 113.198 -10.8133 95.8359 131.912 -12.44 88.8584 109.104 -9.27186 75.6269 121.857 3.65715 78.5266 120.452 -11.3783 85.7325 132.479 -10.7807 87.2109 126.227 -3.03349 82.3865 115.792 -3.39975 85.5323 114.683 -10.7629 88.5351 113.906 -14.361 85.1809 114.135 -13.5766 82.7372 114.618 -13.0324 80.3171 114.815 -12.4815 77.8096 115.265 -12.0804 75.7054 115.895 -11.7089 74.7512 116.96 -11.2522 75.744 118.732 -10.8711 69.843 141.836 -9.30819 67.9679 143.189 -15.0231 72.8213 119.941 10.9157 71.6506 104.986 0.684029 69.456 100.727 -14.47 73.995 114.29 6.9995 73.1142 110.85 3.56299 72.9748 136.288 -10.6843 71.3295 137.732 -15.8765 71.3963 104.177 -15.1099 74.1581 133.103 -5.27631 75.2109 128.825 -1.40012 75.073 122.123 6.21136 74.2901 118.616 8.83824 74.0083 114.133 7.99301 73.4597 110.347 4.91832 72.8198 106.93 -0.967873 82.4554 113.29 2.18171 79.572 111.521 3.2642 80.1607 112.304 4.14649 -10.1429 113.254 10.7089 72.7842 105.382 -7.25814 -5.83078 104.99 14.0223 -2.85619 101.143 15.3198 0.690811 97.9167 16.3207 4.67302 94.8688 16.9057 66.3361 95.2358 0.153168 -11.892 122.645 7.67271 -12.1529 122.274 6.67995 -12.3643 121.685 5.78059 -12.534 120.909 5.0184 -12.626 119.978 4.42898 -12.646 118.938 4.04047 -12.5956 117.84 3.87142 -12.4777 116.734 3.92851 -12.2953 115.674 4.20803 -12.0595 114.707 4.70033 -11.7659 113.862 5.43361 -11.6777 127.672 6.3856 -12.1989 126.934 4.40896 -12.6304 125.765 2.6199 -12.9514 124.219 1.10294 -13.1465 122.369 -0.071487 -13.2072 120.301 -0.848503 -13.1242 118.113 -1.18808 -12.8996 115.91 -1.07389 -12.5437 113.798 -0.511894 -12.0803 111.876 0.468269 -11.5131 110.201 1.90664 -10.7279 108.684 4.35558 -10.8109 132.596 4.94501 -11.5843 131.502 2.01563 -12.2226 129.769 -0.634972 -12.6979 127.479 -2.88298 -12.987 124.738 -4.62311 -13.0768 121.674 -5.77454 -12.9633 118.431 -6.28242 -12.6504 115.16 -6.12376 -12.1492 112.018 -5.30077 -11.4627 109.168 -3.83942 -10.636 106.694 -1.7434 -9.32736 137.352 3.37615 -10.3401 135.919 -0.462959 -11.1772 133.648 -3.93729 -11.8 130.646 -6.88298 -12.1796 127.054 -9.1636 -12.2968 123.039 -10.6717 -12.1477 118.789 -11.3375 -11.7385 114.502 -11.1299 -11.0883 110.379 -10.0578 -10.1881 106.649 -8.12857 -9.11383 103.415 -5.39493 -7.24765 141.871 1.70126 -8.48584 140.119 -2.99197 -9.509 137.344 -7.23812 -10.2704 133.674 -10.8392 -10.7339 129.283 -13.627 -10.8777 124.375 -15.4702 -10.6953 119.179 -16.2843 -10.1948 113.94 -16.03 -9.38 108.916 -14.6924 -8.24042 104.41 -12.2576 -6.81169 100.55 -8.6587 -4.60298 146.087 -0.054435 -6.04802 144.042 -5.53284 -7.24321 140.802 -10.4893 -8.13144 136.519 -14.6932 -8.67267 131.393 -17.9473 -8.84024 125.664 -20.0997 -8.62744 119.599 -21.0494 -8.04318 113.482 -20.7529 -7.08603 107.625 -19.1759 -5.77963 102.353 -16.3577 -4.12698 97.8226 -12.2769 -1.43115 149.939 -1.86574 -3.0623 147.631 -8.04924 -4.41095 143.974 -13.6441 -5.41411 139.139 -18.3892 -6.02504 133.353 -22.0622 -6.21411 126.886 -24.4919 -5.97388 120.04 -25.564 -5.31401 113.136 -25.2289 -4.25377 106.509 -23.4776 -2.81467 100.514 -20.3577 -0.857285 95.3878 -15.9247 2.22112 153.371 -3.70596 0.427597 150.832 -10.5049 -1.05525 146.812 -16.6565 -2.15849 141.496 -21.8739 -2.82948 135.134 -25.9124 -3.03783 128.024 -28.5838 -2.77313 120.497 -29.7627 -2.04877 112.906 -29.3942 -0.897324 105.606 -27.4954 0.658188 98.9955 -24.1115 2.66969 93.7269 -19.7623 6.30045 156.332 -5.54841 4.37052 153.602 -12.8633 2.77497 149.275 -19.4821 1.58868 143.556 -25.0954 0.866531 136.711 -29.4409 0.642624 129.061 -32.3147 0.926575 120.963 -33.5833 1.70657 112.796 -33.1866 2.9455 104.941 -31.144 4.64336 97.9398 -27.491 6.69341 92.8958 -23.465 10.7483 158.78 -7.36639 8.71009 155.896 -15.0906 7.02557 151.328 -22.08 5.77182 145.289 -28.0077 5.00963 138.061 -32.5957 4.77312 129.983 -35.6311 5.07339 121.431 -36.9701 5.89712 112.807 -36.5512 7.20499 104.513 -34.3944 9.05486 97.2925 -30.556 11.2406 92.5807 -26.9734 15.4979 160.678 -9.13321 13.3818 157.684 -17.1547 11.6321 152.94 -24.4125 10.3309 146.669 -30.5671 9.53901 139.163 -35.3323 9.29359 130.775 -38.4834 9.60574 121.895 -39.8743 10.4606 112.939 -39.4398 11.8189 104.326 -37.2 14.0588 96.9514 -33.3467 16.6434 92.4725 -29.9718 23.0545 162.362 -11.6177 20.8829 159.289 -19.8483 19.0871 154.421 -27.2967 17.7525 147.986 -33.6129 16.9392 140.284 -38.5019 16.6871 131.675 -41.736 17.0074 122.563 -43.1632 17.8853 113.373 -42.7169 19.2791 104.535 -40.4185 21.2106 97.0107 -36.2628 23.42 92.7149 -32.4103 30.8573 162.843 -13.8754 28.6938 159.781 -22.0763 26.9055 154.931 -29.4973 27.9242 148.749 -36.2635 26.8335 141.896 -40.4148 27.1308 134.403 -43.1558 24.8332 123.19 -45.306 25.7073 114.033 -44.8611 27.096 105.227 -42.5709 28.977 97.7766 -38.3173 31.01 93.1798 -33.7501 36.0984 162.352 -15.1936 33.9816 159.358 -23.2144 33.3826 154.015 -31.9877 31.2043 127.797 -45.1888 41.2721 161.261 -16.3458 39.5527 157.252 -27.2589 34.1114 118.081 -46.7154 35.274 106.958 -44.7195 36.8836 99.3018 -39.4702 38.9366 94.263 -33.7738 46.3034 159.583 -17.3163 44.8502 156.854 -26.2038 42.5748 117.521 -46.6924 42.9789 108.591 -45.2964 44.501 100.951 -40.6187 47.291 94.8665 -33.4268 51.1197 157.345 -18.0904 49.9772 155.213 -25.3275 48.2059 117.708 -45.7612 48.7168 109.961 -44.0908 50.3568 102.509 -40.027 53.4827 96.7468 -32.9174 55.6498 154.578 -18.6568 54.8409 152.392 -25.0769 52.7864 118.209 -43.2581 53.6228 111.351 -41.2941 55.2413 104.656 -38.0407 58.7364 99.47 -31.8202 59.8286 151.323 -19.0083 59.0656 148.888 -25.0487 58.6371 112.647 -37.2162 60.0213 108.358 -34.3455 66.7364 101.215 -23.2055 64.3461 145.393 -20.1264 63.2939 144.171 -24.2324 64.6093 139.563 -25.8976 66.0209 134.24 -27.224 64.8265 128.137 -31.0498 61.4092 121.344 -36.0211 68.4454 138.292 -21.5291 45.453 130.809 -41.5454 41.6524 143.401 -39.21 50.101 128.433 -40.9145 59.0129 137.957 -33.7931 50.9314 147.376 -33.4765 46.2433 131.854 -39.2708 49.7303 130.061 -38.4737 43.1271 140.511 -36.8678 43.4601 135.718 -38.774 52.9147 130.138 -37.0872 45.9668 143.509 -34.5197 55.443 132.636 -35.7653 50.0284 143.557 -33.3201 56.2208 136.784 -34.4582 54.0432 141.001 -33.4001 46.726 132.091 -39.9847 50.1181 130.245 -39.3182 43.4927 141.099 -37.7857 53.4219 130.291 -37.7879 56.1362 132.807 -36.2509 50.4828 144.208 -33.8546 57.0422 137.29 -34.817 54.643 141.653 -33.7723 55.0842 126.961 -39.0439 60.0643 131.807 -35.2485 60.3282 138.873 -32.42 37.8104 136.599 -42.3736 42.95 129.62 -43.6504 57.0126 145.449 -31.2322 50.941 150.632 -32.0693 43.8723 150.975 -35.442 38.0876 145.889 -39.6926 49.5108 126.802 -42.685 45.605 137.439 -38.4211 44.6923 140.828 -36.8618 47.893 134.316 -39.1277 50.3776 132.134 -38.6198 52.5225 131.75 -37.7278 54.0743 133.869 -37.1666 53.9713 137.248 -36.4482 52.0865 140.596 -35.554 49.2647 142.875 -34.8407 46.3531 143.052 -35.2278 43.9086 135.978 -39.5785 46.5533 144.179 -35.4761 49.8356 130.846 -38.4441 47.9983 130.76 -39.0142 46.6052 132.656 -39.1566 44.0339 136.249 -38.6168 42.8387 138.17 -38.0111 43.6017 140.564 -36.8188 44.6634 133.535 -39.1929 52.6931 130.851 -37.3023 51.3763 129.845 -37.8198 44.2029 142.382 -35.6615 46.0758 143.337 -34.7362 54.9106 133.214 -36.2776 54.299 131.078 -36.3859 47.9753 143.917 -33.7041 49.8059 143.321 -33.8591 55.4037 137.025 -35.1736 56.1837 134.599 -35.1328 52.1021 142.547 -33.2281 53.387 140.878 -34.1972 55.4482 138.973 -33.8331 48.1733 142.19 -35.9091 46.6141 142.785 -35.6607 50.1892 139.952 -36.9649 52.0658 136.997 -37.7961 52.4194 132.447 -38.0845 51.4089 133.398 -38.5931 49.903 135.983 -38.7555 47.893 138.861 -37.994 46.3798 141.377 -36.6995 54.5637 128.486 -38.5583 60.8235 135.305 -33.5811 58.5718 132.382 -36.0552 39.8159 132.627 -42.8845 41.7955 136.119 -41.0087 54.1663 148.483 -31.4153 55.9539 143.477 -32.6654 40.5373 149.092 -37.6693 45.7748 147.539 -36.2109 37.1201 141.421 -41.3319 46.3145 127.804 -43.6823 52.3171 126.477 -40.9857 59.1168 142.133 -31.5495 47.4993 151.562 -33.5084 58.2159 128.907 -37.3334 61.9319 130.28 -33.5996 55.9843 124.214 -39.8068 61.9357 139.512 -29.8517 40.0547 127.159 -44.8752 32.5262 135.693 -43.2641 50.1396 153.648 -28.7343 58.0699 147.457 -28.6001 32.4395 147.874 -38.275 40.7865 154.09 -32.8062 48.5485 123.891 -44.2502 44.8917 139.171 -37.7145 46.6541 135.791 -38.9245 49.1683 133.076 -38.9875 51.4356 131.609 -38.169 53.4767 132.569 -37.389 54.253 135.498 -36.8633 53.2321 138.983 -35.9892 50.709 141.926 -35.1558 47.8345 143.294 -34.7866 45.1675 142.152 -35.9951 45.1713 133.754 -39.9113 44.7331 143.025 -36.6728 43.2421 138.583 -38.8326 48.3979 130.967 -39.812 51.8085 130.009 -38.6079 54.898 131.214 -36.9842 56.9414 134.926 -35.5317 56.2052 139.595 -34.146 52.5633 143.214 -33.6329 48.5055 144.528 -34.4611 48.2504 131.567 -38.9341 43.4311 138.451 -37.8428 45.1446 134.246 -39.058 51.3088 130.573 -37.8872 44.498 142.267 -35.7379 53.9312 131.767 -36.7632 47.939 143.698 -34.0771 55.4586 135.033 -35.7586 51.6817 142.351 -33.9384 54.6942 139.021 -34.6087 47.6009 142.867 -35.4487 49.1112 141.201 -36.4341 51.2183 138.511 -37.4098 52.6196 135.479 -38.0192 51.7129 132.488 -38.381 50.7646 134.609 -38.7822 48.8984 137.414 -38.4633 47.013 140.215 -37.3683 45.949 142.148 -36.1946 56.8747 130.003 -37.3653 59.271 135.122 -34.8148 43.4222 133.063 -41.3875 53.4219 145.768 -32.7803 43.3933 146.037 -37.8806 41.0259 139.775 -40.1938 47.7811 129.312 -41.5937 52.3542 128.12 -39.7631 57.9468 140.752 -33.0391 48.3905 148.009 -34.6435 59.466 126.101 -36.8574 62.769 134.918 -31.1499 35.337 130.917 -44.7544 54.5184 150.949 -28.3414 36.1436 151.734 -35.4628 31.2473 142.63 -41.2578 44.4825 124.75 -45.068 52.223 123.767 -42.08 60.3461 143.735 -29.0309 45.5294 154.723 -30.4826 52.8762 134.088 -38.0496 52.9993 133.095 -37.9288 65.4323 107.528 -26.9171 67.9487 126.833 -28.5074 70.5081 134.319 -20.2732 62.6749 119.616 -35.7438 72.6589 117.278 -23.098 72.2444 116.442 -22.3254 71.3889 125.795 -28.3703 65.5901 109.029 -33.5959 69.3603 107.637 -26.6398 75.0515 126.757 -29.2103 63.5342 113.12 -36.9642 64.2148 119.206 -36.4696 70.5985 118.958 -37.1681 74.9121 108.319 -27.0453 71.9998 116.742 -36.9872 71.9612 114.391 -36.0381 88.8094 110.578 -26.9527 84.1169 110.131 -30.6072 87.2695 128.749 -35.4465 93.0867 136.547 -27.8016 77.576 118.913 -26.6205 76.2215 114.981 -25.3972 75.678 123.817 -34.645 78.3012 128.686 -29.8368 77.0845 117.097 -33.174 81.2906 120.822 -28.8656 75.1464 118.021 -36.546 81.172 131.293 -29.8079 83.4949 133.994 -29.1154 81.9364 120.685 -33.7567 87.4282 126.444 -33.002 84.2007 123.162 -29.9962 87.3956 126.405 -30.3062 80.9881 121.747 -36.5927 79.7217 108.446 -27.144 76.8458 113.737 -33.7746 81.9683 107.792 -26.8548 80.6767 124.289 -36.9998 70.1714 106.645 -20.1493 72.022 116.241 -22.9037 72.8888 115.884 -22.6383 73.3892 117.141 -19.0068 69.7533 125.895 -28.1175 72.9185 107.101 -21.1147 69.1965 130.484 -24.8144 72.6997 129.897 -25.4795 73.1742 126.294 -28.81 63.1531 116.358 -37.3542 67.3688 119.359 -37.0517 66.7935 113.286 -37.5877 72.197 107.977 -26.8719 77.8994 107.939 -21.2215 76.3201 129.88 -26.4826 71.9026 115.225 -37.0598 71.0463 113.066 -37.4483 87.9791 108.369 -27.0824 90.3568 109.787 -24.1197 85.8919 131.003 -34.834 89.9668 133.538 -32.7744 75.3807 117.261 -28.6335 74.2589 118.273 -24.8974 74.5081 115.555 -23.9173 74.7186 115.201 -29.2771 78.273 114.414 -20.2702 76.9377 127.337 -29.5447 74.9877 116.19 -32.3036 79.228 118.61 -30.8741 79.7455 119.59 -27.752 75.7618 117.015 -35.1966 72.8947 115.268 -34.2906 73.0867 117.445 -36.2917 78.8617 122.15 -25.111 82.7305 124.079 -27.0743 82.4725 132.777 -29.4795 84.5114 123.193 -33.8509 87.4141 126.338 -31.4821 85.952 124.849 -30.2847 82.9247 121.687 -31.9314 81.3232 120.724 -35.4257 84.0399 124.603 -36.7655 87.4445 127.25 -34.4856 81.9223 133.222 -27.574 84.3016 135.509 -27.551 85.3181 126.104 -28.0604 88.5803 128.469 -28.7521 90.0231 129.941 -30.4819 77.43 108.57 -27.2025 76.3149 112.625 -34.143 74.121 114.113 -34.4307 78.5236 114.752 -26.0741 79.2235 114.861 -29.7308 81.84 107.809 -22.5419 82.8432 113.477 -21.7471 80.6945 113.198 -32.7484 80.1006 111.667 -32.8137 81.4167 114.445 -29.7768 85.2891 111.653 -30.1957 85.1586 107.567 -26.8363 79.5016 131.024 -27.3879 82.7149 121.901 -29.5647 78.0128 119.311 -36.7914 75.0649 120.445 -36.8974 79.7863 129.926 -29.9221 79.3229 118.187 -33.5803 84.4402 132.877 -32.1553 80.111 127.576 -34.3959 71.2569 121.989 -34.7844 66.2834 120.958 -33.9154 71.8315 110.129 -33.2852 77.2358 110.04 -32.7655 73.4782 133.884 -21.131 77.6228 132.464 -22.2276 81.3655 132.277 -23.4746 83.426 133.82 -24.0033 85.7036 136.141 -24.3458 88.7308 138.375 -25.7679 91.4667 138.163 -27.2159 92.7583 132.552 -26.9171 90.4562 129.827 -25.7152 86.8669 126.78 -24.6669 84.0844 124.721 -23.6771 80.1888 122.834 -22.3988 88.4224 111.98 -26.642 73.0971 114.872 -34.0422 78.0365 114.257 -32.4652 72.6559 116.366 -23.6348 74.0565 115.738 -18.8756 74.3546 119.371 -20.3332 70.6786 130.252 -24.9797 66.3234 116.559 -38.424 68.7427 109.182 -33.5877 75.2695 107.415 -21.4172 74.5162 129.923 -26.0103 69.7229 116.044 -38.0771 89.5331 107.124 -23.792 88.3401 135.32 -31.9677 74.1388 115.95 -26.0645 75.9612 114.948 -19.4391 77.1416 118.114 -30.0044 73.3922 116.231 -34.5642 80.9955 123.121 -26.1556 85.0815 123.793 -32.0715 84.2148 123.344 -35.5836 83.1264 134.427 -27.4776 86.9811 127.454 -28.4118 89.522 129.098 -29.4795 74.6652 110.346 -32.9938 73.4634 113.087 -34.946 76.8228 114.888 -29.5521 79.8915 107.956 -22.0252 80.6122 114.073 -21.0487 83.7573 107.262 -22.8645 86.4999 113.195 -22.8837 83.3651 113.698 -27.6845 87.0649 106.513 -23.293 78.1729 130.027 -26.8719 84.0191 124.97 -27.6585 78.0395 121.874 -37.0279 80.9955 119.953 -31.531 86.4391 136.135 -29.7404 82.2626 130.071 -33.6418 73.3188 122.63 -34.5204 68.9993 121.598 -34.5597 61.1201 116.288 -36.4563 80.2549 109.485 -31.4116 71.6743 134.356 -20.764 75.3384 133.298 -21.6337 79.5527 132.054 -22.774 82.5547 132.906 -23.8513 84.4528 134.914 -24.1434 93.1861 134.488 -27.5777 91.9487 131.059 -26.2461 88.5515 128.283 -25.1888 85.4827 125.624 -24.1983 82.3397 123.833 -23.052 76.6708 121.456 -21.1288 89.869 111.457 -23.9848 75.2791 114.471 -33.131 72.5418 119.712 -36.6595 81.3907 113.876 -31.5584 78.3679 118.196 -35.5399 83.0864 127.336 -36.4037 85.4308 112.541 -29.518 90.2145 131.46 -31.6971 82.9166 108.627 -29.6277 64.7835 120.521 -33.7531 75.2428 120.861 -23.2937 80.7976 132.083 -27.6852 77.9572 125.484 -34.7339 74.1796 115.013 -31.4161 80.9021 114.638 -26.7177 85.1483 113.312 -25.263 82.0676 114.019 -24.0982 79.6802 114.358 -23.3746 77.3173 114.669 -22.6413 75.2124 115.161 -21.7041 73.588 115.837 -21.0027 72.7523 116.861 -20.956 73.4137 118.581 -21.8902 66.4762 141.604 -20.8641 58.3546 118.743 -38.2809 63.6573 103.164 -29.6181 61.2017 113.464 -35.2759 62.603 110.079 -31.8602 69.9438 135.891 -21.1621 68.2393 131.67 -26.2038 67.4378 127.136 -29.5202 62.8091 120.687 -35.9907 60.5767 117.653 -37.3935 60.7761 113.247 -36.1998 62.0921 109.556 -33.1525 65.2417 105.935 -28.1842 71.3073 112.394 -36.0092 68.3164 110.617 -35.2945 68.3445 111.331 -36.3747 -11.3552 113.133 6.63324 68.4684 104.805 -22.5375 -9.45044 104.401 1.95409 -7.56053 100.492 -0.627556 -5.0686 97.2087 -3.46945 -1.8849 93.9531 -6.38548 56.808 93.3547 -23.3279 61.9223 96.6682 -23.3508 59.4081 140.566 19.6623 60.4639 137.464 20.042 61.8763 134.831 19.5882 63.4845 132.857 18.7674 59.1931 143.585 18.4382 65.1653 131.503 17.6961 59.7648 145.792 16.5098 66.574 130.654 16.1776 60.7479 147.03 14.1165 67.7426 130.322 14.3856 61.9742 147.354 11.7839 68.7983 130.581 12.5261 63.4081 146.812 9.84286 69.823 131.736 10.6896 65.1046 145.464 8.28365 70.6207 133.636 8.99838 67.079 143.51 7.13741 70.6489 135.976 7.7083 68.7916 141.109 6.6273 70.0306 138.529 6.87865 46.0899 131.451 -40.7647 44.2964 133.408 -40.6498 42.8521 136.048 -40.2939 42.1344 139.179 -39.5132 48.0895 130.139 -40.7032 42.5725 142.25 -38.4974 50.1107 129.339 -40.116 44.0636 144.531 -37.2763 52.0814 129.065 -39.1855 46.164 145.859 -35.8431 53.992 129.384 -38.172 48.4484 146.268 -34.5523 55.8478 130.62 -37.1918 50.7075 145.792 -33.6656 57.2832 132.639 -36.2405 52.9926 144.492 -33.2066 58.0113 135.002 -35.2811 55.2984 142.565 -33.2185 57.9772 137.569 -34.3714 57.0771 140.172 -33.5929 1.38182 68.9774 -45.9569 1.47894 65.0285 -50.2728 1.09637 63.909 -52.87 4.59888 9.97681 -40.0908 4.56625 11.4122 -44.5415 4.27933 14.0176 -48.351 3.6239 17.5846 -51.2515 2.5518 21.6054 -53.3934 2.81797 25.9316 -56.0077 3.01964 28.3271 -57.5284 3.3214 31.8267 -58.9081 3.45486 35.6754 -59.9047 3.14198 39.6169 -60.4303 2.63558 43.6332 -60.5215 2.15143 47.625 -60.2798 1.8074 51.4352 -59.6459 1.64281 54.9177 -58.6553 1.54494 58.1214 -57.1999 1.24614 61.2169 -55.2299 2.20258 72.8765 -41.2252 4.0999 75.8378 -37.4454 6.18702 78.5203 -33.435 56.4936 87.4619 -10.08 57.7629 85.6098 -10.3506 59.9983 84.0135 -10.7406 63.4852 82.0057 -11.5406 67.5801 79.1089 -12.265 -10.1652 108.262 6.21582 -11.0734 112.965 7.57632 -0.481384 91.8178 -0.502998 -8.62003 103.705 4.73889 -6.45135 99.499 2.95057 -3.73181 95.6969 0.985786 -60.1092 28.2359 7.92776 -8.84988 108.395 10.4182 -10.438 113.006 9.67531 2.73864 92.5778 10.975 -6.7205 103.892 10.9765 -4.01207 99.6658 11.3213 -0.806137 95.8341 11.3643 64.3527 94.8043 -12.5052 60.0369 91.4033 -11.0824 -11.539 10.151 19.9241 -5.49863 10.1436 21.8177 -15.9268 10.1577 16.38 -19.33 10.1651 11.6357 -22.5381 10.1681 4.40154 32.719 10.1303 18.5309 40.266 10.1244 13.6679 14.2263 10.1377 23.0462 22.7994 10.1333 21.7028 2.70157 10.137 23.1159 44.4157 10.1281 7.56966 6.82094 10.137 23.6438 46.5807 10.1555 0.804138 -22.7316 10.1651 -8.79883 46.5392 10.1481 -8.35619 -6.5737 10.1422 -30.0845 -12.5993 10.151 -28.2717 -18.4966 10.1644 -25.6115 -21.6988 10.1659 -20.5282 -21.6462 10.1607 -14.2928 40.6619 10.1362 -21.951 32.9614 10.1496 -27.1618 22.9625 10.1599 -31.832 13.8408 10.1637 -33.647 2.11658 10.1488 -32.443 44.7679 10.1347 -15.5147 6.04318 10.1488 -32.526 12.5907 10.1733 -3.80531 59.1887 91.8044 8.95242 -37.1383 88.9529 -2.97714 -31.8022 10.0858 -1.97102 -25.1531 10.1622 -2.2068 -48.967 94.3801 -3.43312 -42.7435 92.7505 -3.24479 -45.2458 14.541 -1.9814 -38.8006 11.688 -1.94433 -51.5643 18.2037 -2.1067 -56.8395 22.9229 -2.04294 -61.3273 28.167 -2.00068 -64.683 34.1592 -1.92802 -67.7244 42.676 -1.88947 -69.2985 52.0358 -1.98363 -69.0782 59.0674 -1.98585 -68.0128 66.587 -1.96361 -66.3149 75.4782 -2.11857 -61.6254 86.6775 -2.9586 -55.4464 92.4777 -3.38715 -32.8632 83.5116 -1.95249 -29.1664 80.3716 -1.67964 -25.0219 78.6923 -1.82199 -19.731 77.9019 -1.94433 -13.8211 78.3245 -1.89985 0.599609 81.0967 -1.11393 5.68803 83.0274 -0.72765 6.50954 84.4391 -0.967133 5.72511 86.2104 -0.331726 3.73808 88.5303 1.10886 0.442429 91.5093 2.82008 -2.82133 95.1602 4.04714 -5.66766 99.1208 5.2742 -8.03503 103.465 6.34038 -9.79816 108.128 7.22415 -10.9333 112.931 8.02786 -26.7479 60.7542 43.6698 -20.1774 63.8423 42.5992 -8.42801 27.4619 48.2347 14.9477 25.7121 48.3904 3.09452 25.896 48.4757 42.6645 36.5214 48.0598 47.7344 49.638 47.1827 40.5551 62.2549 45.2372 -20.4769 63.1994 -50.3046 -27.628 60.1306 -51.1217 -8.33606 28.1588 -55.7549 41.6947 37.0493 -55.6696 46.1069 49.7648 -54.9594 39.661 61.5616 -52.9449 -28.2701 61.5994 42.6785 -21.096 64.5792 41.7131 -10.6093 65.5757 41.2676 1.58052 66.8139 41.2357 -20.6037 30.6107 47.064 -27.9498 36.4747 46.6355 -32.0076 43.3195 45.7562 -33.3289 50.1288 44.8568 -9.84192 26.1273 47.153 -32.1367 56.4888 43.8329 40.1118 30.266 46.5139 29.9349 25.9004 46.5236 16.4046 23.9305 47.0581 3.12344 24.0639 47.2805 46.8217 35.817 46.5762 50.7757 42.2756 46.3478 52.0569 49.3051 45.7651 50.1277 56.399 44.7582 45.0638 62.5551 43.5645 13.7088 68.7742 41.1082 26.4851 69.2584 41.2994 37.1171 66.9377 42.3456 1.53827 66.2289 -48.7276 -11.1349 65.489 -48.6957 -21.7418 64.0098 -49.2903 -29.2399 60.7943 -50.2557 -33.7448 49.2984 -52.3954 -32.2894 43.1438 -53.1362 -27.8334 36.8602 -53.862 -20.3917 31.2343 -54.2831 -10.0503 26.5855 -54.5085 -32.8298 55.3737 -51.4331 2.729 24.1781 -54.8289 15.8893 23.9164 -54.731 29.5034 26.0458 -54.0829 39.6795 30.5618 -53.8806 46.253 36.21 -53.7901 50.0128 42.5536 -53.5439 51.139 49.2547 -52.9597 49.321 55.8341 -52.0848 44.6241 61.6202 -51.0127 37.1431 65.7944 -49.8316 26.732 68.0261 -48.7847 13.6339 67.8667 -48.6371 + + + + + + + + + + -0.192109 -0.934569 0.299458 -0.06315 -0.993623 0.093407 -0.038767 -0.993005 0.111528 -0.11695 -0.921313 0.370816 -0.085264 -0.993927 0.06957 -0.25821 -0.942076 0.214058 -0.305238 -0.944237 0.123473 -0.103012 -0.993873 0.04007 -0.109849 -0.993698 0.02232 -0.319871 -0.945464 0.061492 0.322015 -0.653105 0.68539 0.238016 -0.809438 0.536805 0.39559 -0.829362 0.394547 0.547107 -0.665777 0.50736 0.149283 -0.925897 0.34703 0.227375 -0.943129 0.242504 -0.182106 -0.7902 0.585167 -0.310544 -0.820667 0.479654 -0.418246 -0.841388 0.342252 -0.407245 -0.671943 0.618582 -0.544891 -0.711903 0.443045 -0.234371 -0.618101 0.750347 -0.474249 -0.857348 0.200104 -0.472515 -0.875412 0.101901 -0.601129 -0.750567 0.274396 -0.593419 -0.791427 0.146617 0.282256 -0.953514 0.105559 0.497204 -0.845385 0.195227 0.680184 -0.678639 0.277127 0.475425 -0.378716 0.794069 0.394699 -0.508097 0.765539 0.651796 -0.507567 0.563506 0.728714 -0.35445 0.585953 -0.280085 -0.456993 0.844222 -0.472084 -0.52749 0.706322 -0.629949 -0.5896 0.505505 -0.525528 -0.402813 0.749375 -0.688269 -0.483465 0.540877 -0.345696 -0.333643 0.877027 0.797494 -0.502759 0.333521 0.868857 -0.332163 0.36709 0.779236 -0.208323 0.591094 0.556733 -0.232343 0.797537 0.611419 -0.086952 0.786515 0.805975 -0.07802 0.586786 0.901017 -0.198547 0.385677 0.912954 -0.073233 0.401437 0.587309 0.31693 0.74473 0.626298 0.112282 0.771455 0.807598 0.10215 0.580819 0.767563 0.296279 0.568389 0.905959 0.097128 0.412074 0.868972 0.273148 0.412646 0.369046 0.664292 0.650016 0.498279 0.502362 0.706648 0.692864 0.459155 0.555982 0.584348 0.597963 0.548615 0.813067 0.415121 0.408163 0.751114 0.515121 0.41289 0.19627 0.766932 0.610977 0.270011 0.7156 0.644213 0.477417 0.672112 0.565984 0.38089 0.730939 0.56626 0.665617 0.613839 0.424448 0.5601 0.712938 0.42191 -0.142237 0.892596 0.427833 -0.115435 0.801937 0.586149 -0.145778 0.823148 0.548795 -0.183731 0.901347 0.392196 -0.170598 0.892172 0.418242 -0.198923 0.94046 0.275618 -0.083913 0.784617 0.614276 -0.104776 0.836925 0.537195 -0.07128 0.762805 0.642687 -0.083732 0.95816 0.273711 -0.152017 0.963903 0.218593 -0.043758 0.995476 0.084341 0.11433 0.983142 0.142691 -0.188565 0.971095 0.146345 -0.153667 0.986837 0.050398 -0.277878 0.955105 0.102752 -0.278528 0.959779 0.035299 -0.266228 0.943946 0.195163 -0.494465 0.642119 0.585822 -0.123678 0.744163 0.656449 -0.094312 0.919596 0.381378 -0.521981 0.776809 0.352284 0.287464 0.72515 0.625717 0.35104 0.866307 0.355363 -0.085399 0.659129 0.747166 0.224013 0.689809 0.688464 -0.41145 0.564912 0.715251 -0.896437 0.304297 0.322186 -0.755967 0.475931 0.449448 -0.804069 0.52634 0.276477 -0.929837 0.307416 0.202235 -0.651421 0.428251 0.626301 -0.812838 0.261118 0.520685 -0.700828 0.14352 0.698743 -0.528973 0.340042 0.777534 -0.323564 0.505566 0.799819 -0.384671 0.217738 0.897005 -0.26768 0.410295 0.871783 -0.51729 -0.021456 0.855541 -0.703157 -0.1848 0.686599 -0.802326 -0.033833 0.595927 -0.877917 -0.14451 0.456484 -0.806047 -0.267053 0.528176 -0.89323 0.116397 0.434273 -0.92976 -0.00252 0.368157 -0.693473 -0.636086 0.338364 -0.705373 -0.68381 0.186692 -0.75587 -0.532488 0.380943 -0.796546 -0.566484 0.211211 -0.077417 -0.240522 0.967551 -0.089798 -0.134723 0.986806 -0.168487 -0.121841 0.978145 -0.138523 -0.221426 0.965289 -0.113525 -0.038943 0.992772 -0.195995 -0.017488 0.980449 -0.602195 -0.290799 0.743503 -0.742439 -0.374894 0.555193 -0.432918 -0.200289 0.878901 -0.818103 -0.413906 0.399236 -0.879805 -0.419705 0.22314 -0.8832 -0.285146 0.372357 -0.940384 -0.263381 0.215195 -0.205308 0.092751 0.974293 -0.12459 0.080228 0.988959 -0.122228 0.178941 0.976238 -0.196017 0.189929 0.962031 -0.04789 0.778827 0.625407 -0.065661 0.712179 0.698921 -0.086279 0.666075 0.740878 -0.054107 0.736647 0.674109 0.32735 0.918436 0.222077 0.038245 0.947019 0.318892 -0.067436 0.912058 0.404479 0.299059 0.868082 0.396229 0.020777 0.864061 0.502958 0.601008 0.74983 0.276665 0.10013 0.787789 0.607752 0.137884 0.80072 0.582954 0.293157 0.782715 0.549014 0.251535 0.793724 0.553834 0.033793 0.760625 0.648311 0.012829 0.792843 0.609291 -0.001462 0.805911 0.592035 0.470195 0.782277 0.408607 0.406592 0.824118 0.394351 -0.228092 0.919665 0.319673 -0.149194 0.877198 0.45636 0.221981 0.775644 0.590848 0.477153 0.718896 0.505483 0.642223 0.702693 0.306223 -0.941954 -0.151996 0.299365 -0.977272 -0.097629 0.18817 -0.969667 0.027366 0.242894 -0.984274 0.065087 0.16422 -0.081923 0.660823 0.746057 -0.143863 0.635643 0.75846 -0.950758 0.179022 0.253002 -0.969441 0.180582 0.166057 0.433741 0.791171 0.431182 0.286611 0.730746 0.619568 0.635928 0.49935 0.588427 0.410194 0.41588 0.811655 -0.030936 0.832088 0.553781 -0.063268 0.738092 0.671727 -0.236437 0.785277 0.572222 -0.098454 0.365739 0.925495 -0.356861 0.365039 0.859882 0.116456 0.704283 0.700303 0.160354 0.369389 0.915335 -0.380395 0.81813 0.431235 -0.491132 0.823545 0.283836 -0.59916 0.341103 0.724332 -0.798743 0.301719 0.520552 0.047573 -0.992573 0.111966 0.069354 -0.994739 0.075398 0.015592 -0.990695 0.135202 0.028503 -0.991144 0.129693 0.0864 -0.911356 0.402449 0.046371 -0.905885 0.420977 -0.018844 -0.991895 0.125654 -0.057065 -0.909815 0.411073 0.087743 -0.99576 0.027619 0.126144 -0.779499 0.613571 0.067151 -0.760559 0.645787 0.153713 -0.607983 0.778928 0.075394 -0.57677 0.81342 -0.085238 -0.760064 0.644234 -0.102578 -0.566247 0.817827 0.045094 -0.227711 0.972684 0.047131 -0.133922 0.98987 0.005657 -0.158915 0.987276 0.006376 -0.238835 0.971039 0.058631 -0.040878 0.997442 0.002975 -0.056704 0.998387 0.127635 -0.116289 0.98498 0.152279 -0.014755 0.988227 0.100619 -0.20516 0.973543 0.059288 0.068169 0.995911 -0.006745 0.055506 0.998436 0.05032 0.180626 0.982264 -0.021925 0.163036 0.986376 0.163736 0.099069 0.981517 0.156175 0.220652 0.962768 0.020684 0.317842 0.947918 -0.050294 0.316731 0.947181 -0.025411 0.533931 0.845146 -0.086911 0.5228 0.848014 0.127716 0.356862 0.925385 0.071441 0.516034 0.853584 -0.061054 0.766638 0.63917 0.078289 0.741306 0.666586 0.208508 0.671416 0.711144 0.313289 0.499706 0.807554 0.378689 0.310587 0.871855 0.400342 0.118619 0.908656 0.381543 -0.070384 0.921668 0.331083 -0.22771 0.915714 0.260306 -0.364971 0.893889 0.178111 -0.473128 0.862802 0.071351 -0.485088 0.87155 -0.127917 -0.411323 0.902469 -0.217134 -0.272275 0.9374 -0.28612 -0.114565 0.95132 -0.297833 0.014133 0.954513 -0.259212 0.153056 0.953616 -0.214461 0.319798 0.922895 -0.151901 0.528641 0.835144 -0.103669 0.295387 0.949736 -0.165776 0.313209 0.935104 -0.083675 0.492895 0.866056 -0.119834 0.470121 0.874429 -0.087588 0.774585 0.626376 -0.256922 -0.123444 0.958516 -0.282852 0.013185 0.959073 -0.378724 -0.276752 0.883163 -0.438423 -0.070607 0.895991 -0.437651 -0.063548 0.896897 -0.390678 -0.27619 0.878117 -0.251518 -0.431278 0.866451 -0.276371 -0.456203 0.845871 -0.19905 -0.303218 0.9319 -0.274611 0.135247 0.951996 -0.249887 0.293965 0.922573 -0.442099 0.099565 0.891423 -0.416837 0.295755 0.859521 -0.412837 0.32408 0.851198 -0.438351 0.113033 0.891668 0.156401 -0.497394 0.85331 0.061408 -0.535686 0.842181 0.119454 -0.452018 0.883974 0.032667 -0.468626 0.882793 0.050048 -0.559259 0.827481 0.150699 -0.524664 0.837865 0.208739 -0.361482 0.908713 0.238743 -0.413555 0.878621 0.232419 -0.391651 0.890276 -0.125806 -0.451337 0.883441 -0.128663 -0.465603 0.875591 -0.150994 -0.530967 0.833832 0.284031 -0.235212 0.929517 0.269401 -0.199777 0.942079 0.293517 -0.238502 0.925724 0.286186 -0.032306 0.957629 0.310905 -0.056264 0.948774 0.312743 -0.062252 0.947795 0.322676 0.120164 0.938851 0.286685 0.125421 0.94978 0.312932 0.123775 0.941676 0.279716 0.294166 0.913907 0.303905 0.313656 0.89959 0.309104 0.311381 0.898608 0.037576 0.808415 0.587412 0.169817 0.698638 0.69503 -0.000992 0.780213 0.625514 0.138259 0.681294 0.718834 0.161529 0.715447 0.679738 0.018778 0.826522 0.562592 -0.09996 0.801388 0.589733 -0.098648 0.85295 0.512587 -0.076807 0.814801 0.574631 0.262922 0.511395 0.818137 0.242579 0.49202 0.836105 0.262895 0.521513 0.811733 -0.185749 0.495789 0.848346 -0.322481 0.52883 0.785076 -0.160242 0.722224 0.672841 -0.146317 0.772841 0.617501 -0.312096 0.577251 0.754571 -0.076559 0.797941 0.597853 -0.071594 0.840171 0.537576 -0.107376 0.806238 0.581766 -0.112987 0.848782 0.51653 -0.287568 -0.01818 0.957588 -0.246849 -0.15606 0.956405 -0.173556 -0.290795 0.940913 -0.283237 0.22681 0.931844 -0.297529 0.100463 0.949412 0.014537 -0.330354 0.943745 0.072188 -0.329168 0.941508 0.150177 -0.268878 0.951394 -0.091484 -0.341365 0.935468 0.211928 -0.141481 0.96699 0.233591 -0.009434 0.972289 0.24083 0.120366 0.963075 0.233787 0.260424 0.936762 0.102888 0.613185 0.78321 -0.030399 0.694019 0.719314 -0.098708 0.675427 0.730791 0.204918 0.428836 0.879834 -0.132475 0.557408 0.819602 -0.232943 0.388015 0.89173 -0.075386 0.634728 0.769049 -0.09685 0.652599 0.751489 -0.092397 0.509504 0.855493 -0.081276 0.316551 0.945087 -0.068265 0.172012 0.982727 -0.054553 0.065325 0.996372 -0.043341 -0.055449 0.99752 -0.033383 -0.160096 0.986537 -0.028874 -0.24536 0.969002 -0.033304 -0.336054 0.941254 -0.042357 -0.467717 0.882863 -0.046567 -0.556118 0.829798 -0.037674 -0.519487 0.853647 -0.022566 -0.457423 0.888963 -0.012961 -0.556886 0.830488 -0.007732 -0.753873 0.656974 -0.003792 -0.90729 0.420489 -0.001149 -0.991208 0.132304 0.512335 -0.857386 0.049017 0.70555 -0.704425 0.077354 0.297092 -0.954566 0.023258 0.84286 -0.528889 0.09931 0.930258 -0.348816 0.113782 0.968103 -0.21837 0.122848 0.986591 -0.093131 0.134031 0.985676 0.081564 0.147617 0.95281 0.259757 0.157095 0.894834 0.417704 0.157465 0.844113 0.514896 0.149516 0.774064 0.618654 0.134508 0.673761 0.729252 0.119321 0.59429 0.795832 0.116061 0.5205 0.84585 0.116695 0.525074 0.841884 0.124616 0.765546 0.621669 0.16573 0.097097 -0.995263 0.004896 -0.565407 0.809464 0.158374 -0.611313 0.789337 0.056957 -0.920895 0.236324 0.310006 -0.979363 0.144989 0.140806 -0.738247 -0.362498 0.568846 -0.830423 -0.418752 0.367485 -0.844491 -0.498578 0.195588 -0.637358 -0.672695 0.37584 -0.668066 -0.709833 0.223216 -0.553902 -0.635855 0.537476 -0.346188 -0.291036 0.891881 -0.564224 -0.330618 0.756534 -0.436173 -0.617389 0.654663 -0.266348 -0.628612 0.730688 -0.097978 -0.251576 0.962865 -0.086895 -0.643915 0.760146 0.176816 -0.222898 0.958672 0.120695 -0.699248 0.704617 0.465192 -0.190422 0.864486 0.373032 -0.681742 0.629345 0.749171 -0.141411 0.647105 0.57208 -0.682024 0.455597 0.984143 0.023025 0.175875 0.738366 -0.656556 0.154109 -0.095635 0.76965 0.631263 -0.315057 -0.948903 0.017974 -0.110306 -0.993886 0.004918 -0.457702 -0.888528 0.032039 -0.589111 -0.807168 0.037792 0.510058 -0.858624 -0.051043 0.70623 -0.703125 -0.082786 0.294439 -0.955391 -0.023102 0.843862 -0.525198 -0.109834 0.928966 -0.346434 -0.130403 0.964683 -0.219414 -0.145751 0.981881 -0.104853 -0.157847 0.98501 0.058597 -0.162241 0.95819 0.238399 -0.158234 0.897823 0.414043 -0.149942 0.829346 0.538002 -0.150797 0.747675 0.644543 -0.159833 0.659153 0.734437 -0.161615 0.265044 0.963485 0.038059 0.039034 0.999086 0.017437 0.018622 0.997848 -0.062875 0.244836 0.962544 -0.116463 -0.130658 0.991351 0.012349 -0.138096 0.990164 -0.022449 -0.273293 0.96189 0.008822 -0.274255 0.961657 0.000421 -0.053579 0.998129 0.029453 -0.515915 0.855204 0.049583 0.344116 0.89883 -0.271457 -0.055876 0.956544 -0.286182 0.365283 0.930753 0.01632 -0.828131 0.557888 0.054409 -0.952772 0.299578 0.049783 -0.711727 -0.701459 0.037422 -0.905755 -0.418034 -0.069676 -0.8121 -0.578723 -0.074656 -0.818385 -0.573492 0.036778 -0.910268 -0.412077 0.040054 0.709552 0.701423 0.067393 0.515618 0.854187 0.067105 0.52626 0.835416 -0.158524 0.711562 0.67733 -0.186822 0.587221 0.793907 -0.157743 0.504751 0.849895 -0.151344 0.655685 0.754174 0.036026 0.627882 0.742251 -0.234154 -0.995755 -0.076042 0.051857 -0.966252 -0.253074 0.048064 -0.995208 0.084624 0.048994 -0.98245 0.180559 0.046801 0.500696 0.849415 -0.166726 0.699452 0.674292 -0.236847 -0.644888 0.764208 0.010314 -0.658085 0.75262 0.022063 -0.996997 0.052783 0.056672 -0.999004 0.031144 0.031952 0.095211 -0.995451 -0.003478 -0.828476 -0.551185 0.099113 -0.83354 -0.552229 0.015914 -0.680841 -0.722996 0.117184 -0.70438 -0.709823 0.000289 0.942473 0.130036 -0.307954 0.760792 -0.603232 -0.239387 -0.191598 -0.926128 -0.324926 -0.11404 -0.910397 -0.397707 -0.034523 -0.992382 -0.118262 -0.056307 -0.993628 -0.097639 -0.08229 -0.99447 -0.065257 -0.263919 -0.93806 -0.224478 -0.301453 -0.945273 -0.124839 -0.10268 -0.994176 -0.032728 -0.109842 -0.993816 -0.016268 -0.306215 -0.95011 -0.059356 0.319117 -0.647606 -0.691933 0.534285 -0.666968 -0.519319 0.385251 -0.83007 -0.403195 0.239592 -0.805165 -0.542499 0.228594 -0.939199 -0.256224 0.158278 -0.918607 -0.362089 -0.178484 -0.75672 -0.628902 -0.309497 -0.797477 -0.51792 -0.420841 -0.831771 -0.362009 -0.538657 -0.700909 -0.467519 -0.394197 -0.64598 -0.653696 -0.222745 -0.580396 -0.783278 -0.463953 -0.858375 -0.218951 -0.461429 -0.880375 -0.109649 -0.599801 -0.782405 -0.167575 -0.59309 -0.744341 -0.306921 0.280118 -0.952342 -0.120743 0.489162 -0.845976 -0.212238 0.674722 -0.67782 -0.292079 0.467443 -0.364911 -0.805194 0.712309 -0.345361 -0.611018 0.641575 -0.494023 -0.586791 0.39121 -0.489528 -0.779305 -0.257887 -0.431057 -0.864687 -0.450347 -0.520374 -0.725533 -0.610796 -0.588414 -0.529809 -0.665056 -0.488467 -0.56489 -0.505193 -0.408993 -0.759938 -0.312897 -0.314982 -0.896037 0.796286 -0.495922 -0.346396 0.865739 -0.328626 -0.377493 0.760432 -0.204661 -0.616326 0.545204 -0.224716 -0.807623 0.593644 -0.079984 -0.800743 0.783915 -0.086134 -0.614865 0.896384 -0.199742 -0.395726 0.906271 -0.095045 -0.411874 0.551478 0.253954 -0.794594 0.749758 0.226635 -0.62169 0.783116 0.056593 -0.619295 0.5969 0.085909 -0.797703 0.90526 0.04554 -0.42241 0.880719 0.218398 -0.420282 0.336343 0.599609 -0.726183 0.572035 0.582293 -0.577677 0.679985 0.408785 -0.6087 0.461982 0.425407 -0.778204 0.822759 0.398489 -0.405308 0.73865 0.550111 -0.389581 0.158279 0.713924 -0.6821 0.37644 0.723509 -0.578643 0.467127 0.676077 -0.569835 0.228363 0.685665 -0.691168 0.648361 0.657528 -0.383777 0.564637 0.73282 -0.379684 -0.132948 0.895471 -0.424801 -0.16783 0.911023 -0.376656 -0.12755 0.841928 -0.524298 -0.095044 0.810733 -0.577649 -0.191234 0.937857 -0.289574 -0.161097 0.88789 -0.430929 -0.099619 0.831047 -0.547207 -0.068866 0.782563 -0.618751 -0.042804 0.75673 -0.652324 -0.106611 0.95728 -0.268792 0.061832 0.967519 -0.24512 -0.090989 0.984179 -0.152028 -0.171442 0.958937 -0.225938 -0.170146 0.982001 -0.081999 -0.195635 0.967138 -0.16239 -0.282706 0.95847 -0.037576 -0.282545 0.952356 -0.114834 -0.262642 0.936921 -0.230646 -0.457702 0.605028 -0.651498 -0.494691 0.715297 -0.493589 -0.076223 0.822259 -0.563986 -0.087936 0.702019 -0.706709 0.319664 0.765998 -0.557729 0.294833 0.694844 -0.655946 0.224172 0.682804 -0.695361 -0.063717 0.649517 -0.757673 -0.387084 0.558006 -0.734027 -0.896043 0.261582 -0.358722 -0.944002 0.274393 -0.183216 -0.810194 0.488173 -0.324457 -0.742944 0.435424 -0.508371 -0.645648 0.412332 -0.642745 -0.811086 0.243382 -0.531887 -0.699157 0.136155 -0.701885 -0.530892 0.331786 -0.77979 -0.30426 0.511436 -0.803654 -0.248492 0.408629 -0.878222 -0.387347 0.198969 -0.900208 -0.511763 -0.033699 -0.858465 -0.688173 -0.178311 -0.703294 -0.790784 -0.260454 -0.553917 -0.872048 -0.112083 -0.476413 -0.794394 -0.013341 -0.607256 -0.920109 0.042291 -0.389372 -0.884532 0.127633 -0.44868 -0.676964 -0.636735 -0.369174 -0.702442 -0.678564 -0.214769 -0.78028 -0.57775 -0.239514 -0.733839 -0.540713 -0.41123 -0.092147 -0.181509 -0.979062 -0.144369 -0.166467 -0.975421 -0.159435 -0.079334 -0.984015 -0.094565 -0.065989 -0.993329 -0.168501 -0.000101 -0.985701 -0.104493 0.01153 -0.994459 -0.726284 -0.369697 -0.579514 -0.588438 -0.292192 -0.753899 -0.407291 -0.20071 -0.890971 -0.869486 -0.42871 -0.245363 -0.799739 -0.41079 -0.4378 -0.938755 -0.260153 -0.225963 -0.869609 -0.274794 -0.410206 -0.170534 0.079532 -0.982137 -0.161151 0.169743 -0.972223 -0.090409 0.181448 -0.979236 -0.10396 0.092065 -0.990311 -0.061474 0.779505 -0.623373 -0.054952 0.743789 -0.666152 -0.103099 0.66864 -0.736404 -0.089248 0.714186 -0.694242 0.313646 0.879357 -0.358269 0.027421 0.941997 -0.334499 -0.080622 0.891857 -0.445073 0.022338 0.831019 -0.555795 0.289168 0.850636 -0.43909 0.556005 0.699289 -0.449281 0.050624 0.773712 -0.631511 0.231632 0.808083 -0.541616 0.288863 0.771715 -0.566581 0.103245 0.744807 -0.659244 0.031939 0.724546 -0.688486 0.003268 0.749951 -0.661485 -0.026171 0.792703 -0.609046 0.482137 0.794981 -0.36817 0.398207 0.851469 -0.34122 -0.221077 0.901734 -0.371484 -0.143622 0.850839 -0.505417 0.234374 0.743588 -0.626216 0.46128 0.703836 -0.540218 0.562017 0.649813 -0.511741 -0.977474 -0.09123 -0.19032 -0.936551 -0.12725 -0.326619 -0.984003 0.070682 -0.163533 -0.961337 0.050417 -0.270718 -0.12138 0.620783 -0.774529 -0.05521 0.647511 -0.760053 -0.944461 0.162933 -0.285388 -0.972855 0.171501 -0.15537 0.237565 0.800499 -0.55024 0.395586 0.847721 -0.353385 0.35269 0.570432 -0.741766 0.568049 0.652016 -0.502191 -0.054488 0.806873 -0.588206 -0.221404 0.774347 -0.592762 -0.082141 0.728443 -0.680164 -0.34248 0.449493 -0.825023 -0.1184 0.432945 -0.893611 0.102358 0.477975 -0.872389 0.062161 0.735187 -0.675008 -0.351621 0.822971 -0.446186 -0.453177 0.839825 -0.298872 -0.753559 0.408132 -0.515341 -0.56556 0.457673 -0.686059 0.070662 -0.994095 -0.082354 0.053046 -0.991548 -0.1184 0.013209 -0.990078 -0.139895 0.042006 -0.899343 -0.435221 0.096965 -0.90473 -0.414802 0.032991 -0.99044 -0.133938 -0.056118 -0.897897 -0.436614 -0.016738 -0.990736 -0.134764 0.086464 -0.995644 -0.034877 0.061043 -0.750045 -0.658564 0.137198 -0.774505 -0.61751 0.069229 -0.578014 -0.813085 0.165722 -0.607498 -0.776841 -0.08926 -0.735213 -0.671934 -0.114239 -0.544747 -0.830783 0.019911 -0.230638 -0.972836 -0.030593 -0.214954 -0.976145 -0.045955 -0.097756 -0.994149 0.002659 -0.095509 -0.995425 -0.052141 0.011297 -0.998576 0.002127 0.01818 -0.999832 0.120697 0.01473 -0.99258 0.113372 -0.110702 -0.987366 0.096736 -0.223211 -0.969958 -0.055442 0.119889 -0.991238 -0.003618 0.136061 -0.990694 -0.057352 0.236947 -0.969828 -0.01353 0.263616 -0.964533 0.087309 0.294367 -0.951696 0.113304 0.153076 -0.981697 -0.061332 0.359879 -0.930981 -0.028754 0.371752 -0.927887 -0.069217 0.479884 -0.874597 -0.04309 0.485197 -0.873342 0.017067 0.479437 -0.87741 0.052641 0.398131 -0.915817 -0.034654 0.760876 -0.647972 0.07156 0.732098 -0.67743 0.191934 0.634425 -0.748777 0.303753 0.458556 -0.835141 0.384402 0.282027 -0.879031 0.419845 0.110042 -0.9009 0.406427 -0.062856 -0.911518 0.353955 -0.220425 -0.908916 0.281504 -0.354287 -0.89176 0.067511 -0.500136 -0.863311 0.193668 -0.469971 -0.861174 -0.14958 -0.414815 -0.897527 -0.228363 -0.298833 -0.926579 -0.288297 -0.161724 -0.943785 -0.298702 -0.022525 -0.954081 -0.190826 0.301532 -0.934165 -0.246409 0.126265 -0.960906 -0.15017 0.520238 -0.840715 -0.129702 0.309072 -0.942153 -0.066417 0.305119 -0.949995 -0.055085 0.462192 -0.885067 -0.090042 0.449004 -0.888981 -0.071733 0.766958 -0.637675 -0.283007 -0.028509 -0.958694 -0.281863 -0.191917 -0.940065 -0.351312 -0.084797 -0.932411 -0.309888 -0.241843 -0.919501 -0.329877 -0.256795 -0.908426 -0.371873 -0.083592 -0.924512 -0.244245 -0.370528 -0.896133 -0.261882 -0.399787 -0.878401 -0.239012 -0.350966 -0.905371 -0.228514 0.26963 -0.935457 -0.253264 0.114721 -0.960571 -0.387754 0.261515 -0.883887 -0.38213 0.068912 -0.921536 -0.395833 0.087229 -0.914171 -0.400411 0.295266 -0.867461 0.059717 -0.537384 -0.841221 0.170799 -0.490618 -0.854471 0.023673 -0.491984 -0.870282 0.138029 -0.482666 -0.864859 0.172547 -0.546798 -0.819292 0.048051 -0.585369 -0.809342 0.24535 -0.391127 -0.88703 0.271557 -0.425603 -0.863203 0.253362 -0.383231 -0.888224 -0.16392 -0.464478 -0.870282 -0.156074 -0.43633 -0.886147 -0.174103 -0.495914 -0.85074 0.311338 -0.234144 -0.921002 0.314452 -0.22765 -0.921573 0.331844 -0.253055 -0.908759 0.334948 -0.047443 -0.941041 0.358791 -0.06942 -0.930833 0.352034 -0.064094 -0.93379 0.370008 0.120956 -0.921121 0.325861 0.13785 -0.935314 0.365501 0.126808 -0.922133 0.293842 0.331419 -0.896559 0.345775 0.339247 -0.874843 0.349666 0.318511 -0.88107 0.181191 0.722006 -0.667741 0.050427 0.826013 -0.561391 0.124911 0.682336 -0.720288 -8.3e-005 0.771418 -0.636329 0.029371 0.862647 -0.504953 0.172441 0.753171 -0.634821 -0.088449 0.796983 -0.597491 -0.084759 0.878493 -0.470177 -0.056365 0.816918 -0.573992 0.28721 0.527283 -0.799677 0.229314 0.522426 -0.821271 0.28443 0.557632 -0.779838 -0.184783 0.47937 -0.857939 -0.159072 0.705689 -0.690434 -0.306838 0.513915 -0.801088 -0.313651 0.56677 -0.761837 -0.157757 0.765176 -0.624195 -0.073978 0.778021 -0.623867 -0.070331 0.835642 -0.544753 -0.087799 0.795672 -0.599331 -0.090591 0.859197 -0.503561 -0.232887 -0.144487 -0.961711 -0.244705 -0.029472 -0.96915 -0.189644 -0.261806 -0.946305 -0.251478 0.075314 -0.964928 -0.245154 0.195506 -0.949567 0.069738 -0.345456 -0.93584 -0.006898 -0.32309 -0.946343 0.169707 -0.300933 -0.938424 -0.116208 -0.315517 -0.941778 0.239122 -0.166926 -0.956533 0.255866 -0.011563 -0.966643 0.242809 0.152646 -0.957989 0.202267 0.315072 -0.927264 -0.032641 0.607102 -0.793953 0.060458 0.564272 -0.823372 -0.076278 0.598808 -0.797252 0.144831 0.45396 -0.879173 -0.202967 0.364176 -0.908945 -0.116061 0.523868 -0.843856 -0.061288 0.585836 -0.808109 -0.069247 0.590821 -0.803825 -0.06147 0.471147 -0.87991 -0.062087 0.339494 -0.938557 -0.069753 0.213116 -0.974534 -0.075711 0.106988 -0.991373 -0.074759 0.010224 -0.997149 -0.065915 -0.084862 -0.99421 -0.056359 -0.195476 -0.979088 -0.058264 -0.312594 -0.948098 -0.069962 -0.465689 -0.882179 -0.071195 -0.557949 -0.826815 -0.045754 -0.47841 -0.876944 -0.060646 -0.52652 -0.847997 -0.029989 -0.553187 -0.832517 -0.018388 -0.737572 -0.675018 -0.009087 -0.897441 -0.441041 -0.00158 -0.989993 -0.141109 -0.308322 -0.951065 -0.020322 -0.110713 -0.99381 -0.009215 -0.455221 -0.889796 -0.032191 -0.596471 -0.800898 -0.052761 -0.511407 0.823202 -0.246578 -0.952243 0.291325 -0.09145 -0.828387 0.538442 -0.154449 -0.712918 -0.697663 -0.070811 -0.964192 -0.256036 -0.069136 -0.99426 -0.077609 -0.073642 -0.993521 0.085088 -0.075342 -0.980403 0.180699 -0.07847 -0.618484 0.785248 -0.029371 -0.985065 0.143698 -0.094851 -0.540296 0.826158 -0.159823 -0.899944 0.302263 -0.314224 -0.858864 -0.489238 -0.15165 -0.711588 -0.680949 -0.173063 -0.767866 -0.270651 -0.580629 -0.848883 -0.383401 -0.36387 -0.671939 -0.656576 -0.342645 -0.602072 -0.614193 -0.510173 -0.382168 -0.137855 -0.913752 -0.607476 -0.181274 -0.773377 -0.492091 -0.563373 -0.66367 -0.327921 -0.53701 -0.777231 -0.13782 -0.132667 -0.981532 -0.138241 -0.548212 -0.824835 0.069946 -0.573914 -0.815923 0.11889 -0.117351 -0.985948 0.269629 -0.627654 -0.730309 0.418909 -0.085153 -0.904027 0.751138 0.018205 -0.659894 0.495888 -0.698066 -0.516526 -0.95931 0.034968 0.280182 -0.952229 0.032635 0.303636 -0.93144 0.167086 0.323268 -0.946666 0.171861 0.272557 -0.944846 0.025037 0.326557 -0.91551 0.150958 0.372899 -0.937578 0.012119 0.347564 -0.899986 0.12397 0.417919 -0.930687 -0.005661 0.365772 -0.885622 0.08696 0.456193 -0.924746 -0.02703 0.379623 -0.873384 0.042333 0.485189 -0.919713 -0.051956 0.389139 -0.863691 -0.010116 0.503919 -0.915891 -0.078133 0.39375 -0.857075 -0.064545 0.511132 -0.913924 -0.104134 0.392301 -0.854193 -0.116994 0.506623 -0.913686 -0.130204 0.385001 -0.854276 -0.170718 0.490986 -0.915221 -0.154787 0.372036 -0.856986 -0.224754 0.463745 -0.918574 -0.175545 0.354127 -0.862661 -0.271395 0.426803 -0.924357 -0.190998 0.330279 -0.874699 -0.302741 0.378484 -0.93489 -0.202027 0.291831 -0.900162 -0.32556 0.289342 -0.890596 -0.319641 0.323525 -0.930807 -0.199874 0.306022 -0.896 0.289458 0.336747 -0.918721 0.296141 0.261252 -0.872107 0.26593 0.410745 -0.848724 0.226438 0.477905 -0.827137 0.172709 0.534805 -0.80861 0.10747 0.578446 -0.794368 0.032855 0.606547 -0.785336 -0.046853 0.617294 -0.781515 -0.12666 0.610894 -0.781913 -0.208771 0.58739 -0.785856 -0.293485 0.544332 -0.793937 -0.361184 0.489091 -0.811021 -0.403504 0.423592 -0.835242 -0.430573 0.342022 -0.847345 0.403795 0.3449 -0.876998 0.412515 0.246384 -0.816114 0.373023 0.441375 -0.785473 0.321444 0.528872 -0.757102 0.251755 0.60284 -0.732492 0.167285 0.659903 -0.71285 0.071993 0.697612 -0.699448 -0.030237 0.714044 -0.693366 -0.135002 0.707826 -0.694705 -0.244186 0.676579 -0.700161 -0.36004 0.616559 -0.706167 -0.453566 0.543697 -0.723583 -0.510419 0.464651 -0.757493 -0.546167 0.357639 -0.786239 0.510828 0.347683 -0.822283 0.521471 0.227858 -0.748188 0.473296 0.464978 -0.710816 0.41044 0.571208 -0.676265 0.32557 0.66081 -0.646313 0.222825 0.729815 -0.622397 0.107069 0.775344 -0.605751 -0.016281 0.795488 -0.597541 -0.142104 0.789146 -0.599072 -0.273389 0.752576 -0.605625 -0.422009 0.67463 -0.607323 -0.542234 0.580639 -0.62045 -0.60942 0.493609 -0.663091 -0.648882 0.373178 -0.713977 0.609147 0.34522 -0.755821 0.6215 0.206088 -0.669772 0.565403 0.481378 -0.626414 0.492206 0.604433 -0.58635 0.393512 0.708055 -0.551603 0.274208 0.787746 -0.523909 0.140003 0.84019 -0.504656 -0.002861 0.863316 -0.494725 -0.148092 0.856339 -0.496885 -0.296649 0.81554 -0.511217 -0.470298 0.719359 -0.523448 -0.603062 0.601929 -0.54514 -0.6692 0.504969 -0.589688 -0.712391 0.380483 -0.632092 0.697412 0.337752 -0.679083 0.71125 0.181575 -0.582478 0.648166 0.490511 -0.533908 0.565768 0.62837 -0.489063 0.454778 0.744308 -0.450216 0.320826 0.833293 -0.419311 0.170384 0.891711 -0.397828 0.010371 0.917402 -0.386738 -0.152189 0.909545 -0.388906 -0.314579 0.865905 -0.416834 -0.497637 0.760662 -0.460989 -0.625959 0.629018 -0.542107 0.774681 0.32556 -0.593506 0.78981 0.15476 -0.487909 0.720672 0.492521 -0.434921 0.630341 0.64305 -0.3861 0.508756 0.769476 -0.343913 0.362223 0.866325 -0.310381 0.197869 0.929791 -0.287052 0.023243 0.957633 -0.274984 -0.154056 0.949026 -0.274153 -0.330443 0.903132 -0.301736 -0.514601 0.802584 -0.360883 -0.638403 0.679857 -0.445437 0.840329 0.308923 -0.50045 0.856542 0.126038 -0.387543 0.782319 0.487634 -0.331043 0.685354 0.648614 -0.279115 0.554987 0.783636 -0.234323 0.398047 0.886934 -0.198766 0.222238 0.954517 -0.174032 0.035606 0.984096 -0.161146 -0.153806 0.974872 -0.161623 -0.341915 0.925728 -0.183322 -0.527132 0.829774 -0.220903 -0.657095 0.720714 -0.343523 0.893833 0.288192 -0.401399 0.910874 0.095845 -0.282773 0.832684 0.476106 -0.223681 0.730476 0.645269 -0.169508 0.593188 0.787016 -0.122852 0.428085 0.895349 -0.085869 0.24334 0.966133 -0.060478 0.047525 0.997037 -0.048298 -0.151042 0.987347 -0.051169 -0.346801 0.936542 -0.071334 -0.536879 0.840638 -0.087789 -0.68823 0.720162 -0.21986 0.940431 0.259327 -0.28005 0.958152 0.059303 -0.156918 0.876718 0.454689 -0.095926 0.770248 0.630489 -0.040164 0.627316 0.777728 0.007734 0.455603 0.890149 0.046891 0.262808 0.963708 0.076503 0.059129 0.995315 0.087975 -0.141662 0.985998 0.082632 -0.346525 0.934394 0.066735 -0.543112 0.837004 0.044893 -0.70688 0.705907 -0.074449 0.972485 0.220751 -0.13589 0.990587 0.016451 -0.0105 0.907325 0.420298 0.052421 0.798072 0.600278 0.112271 0.651463 0.750327 0.17284 0.475296 0.862682 0.224622 0.286559 0.931359 0.237263 0.088989 0.967361 0.218281 -0.113 0.969322 0.208533 -0.342413 0.916116 0.208343 -0.548433 0.809824 0.177566 -0.726111 0.664254 0.072457 0.981536 0.17702 0.011184 0.999581 -0.026697 0.13045 0.91774 0.375149 0.17379 0.810665 0.559124 0.202259 0.677497 0.70717 0.281823 0.466274 0.838549 0.389486 0.279956 0.877454 0.38011 0.146887 0.913204 0.357385 -0.040932 0.93306 0.345941 -0.321259 0.881543 0.34413 -0.559385 0.754098 0.331752 -0.740685 0.584232 0.196145 0.971318 0.134422 0.140044 0.988072 -0.064045 0.22226 0.915547 0.335221 0.215212 0.826522 0.520139 0.485045 0.203691 0.850436 0.549186 0.085396 0.831326 0.51886 -0.274121 0.809717 0.494351 -0.559544 0.665228 0.486216 -0.716967 0.499552 0.288962 0.953069 0.090338 0.249176 0.963756 -0.09532 0.279421 0.910567 0.304618 0.388152 0.921065 0.031265 0.355698 0.926134 -0.125519 0.404067 0.903782 0.141097 0.68549 -0.217008 0.69499 0.702569 0.095581 0.705167 0.629523 -0.529053 0.569037 0.593718 -0.693079 0.408828 0.496683 0.867503 -0.027267 0.458279 0.875316 -0.154276 0.528047 0.848543 0.03378 0.806768 -0.152023 0.570977 0.808457 0.086821 0.582116 0.751952 -0.463847 0.468417 0.679141 -0.659907 0.321388 0.597185 0.799146 -0.068811 0.555473 0.811556 -0.181181 0.641605 0.76683 -0.017718 0.890943 -0.106367 0.441483 0.8665 0.068021 0.494522 0.874776 -0.373384 0.30879 0.812876 -0.546789 0.200637 0.713003 0.692155 -0.112017 0.675208 0.706006 -0.213658 0.760001 0.64795 -0.050575 0.881663 0.086627 0.463859 0.915057 -0.143088 0.377089 0.91943 -0.337729 0.201463 0.893271 -0.433495 0.118948 0.740476 -0.66906 0.063675 0.859379 -0.511092 0.015908 0.647012 -0.745143 -0.161672 0.622061 -0.770384 0.139818 0.519697 -0.840964 -0.150645 0.82048 0.555122 -0.136569 0.782459 0.574043 -0.241314 0.857424 0.511442 -0.057009 0.806681 0.536729 -0.247364 0.862468 0.496193 -0.099707 0.878972 0.473396 -0.057475 0.818208 0.516312 -0.252897 -0.95504 -0.087036 0.283414 0.458007 0.336509 0.822795 0.548647 0.436829 0.712858 0.498793 0.508214 0.702085 0.40895 0.438856 0.800103 0.458788 0.419381 0.783347 0.488579 0.295919 0.820806 0.338496 0.547557 0.765246 0.40128 0.540787 0.739273 0.447903 0.573978 0.685516 0.572577 0.090453 0.814846 0.659971 0.242585 0.711049 0.600793 0.356629 0.715446 0.507798 0.222804 0.832165 0.525407 0.175386 0.832579 0.592642 0.076696 0.801806 0.696495 -0.160757 0.699323 0.747071 -0.060562 0.66198 0.716368 0.089686 0.691935 0.643654 -0.044528 0.76402 0.679875 -0.004061 0.733317 0.751902 -0.071444 0.655392 0.836517 -0.293072 0.462977 0.828132 -0.230473 0.510959 0.762807 -0.199352 0.61513 0.753672 -0.259258 0.603957 0.803598 -0.130297 0.580735 0.857252 -0.175255 0.484153 0.916775 -0.199713 0.345889 0.913851 -0.163134 0.371839 0.958882 -0.051876 0.279022 0.954667 -0.015331 0.297282 0.878559 0.023718 0.477045 0.887732 -0.142315 0.437811 0.881622 0.374121 0.287709 0.786275 0.361357 0.501191 0.845764 0.203036 0.493417 0.938392 0.191581 0.287606 0.964699 0.141352 0.222208 0.919874 0.344658 0.187198 0.735833 0.601185 0.31165 0.66518 0.53777 0.518014 0.724119 0.464664 0.509645 0.811286 0.503396 0.297333 0.847399 0.503007 0.169996 0.757311 0.630422 0.170435 0.55095 0.766953 0.328993 0.550236 0.662384 0.508417 0.604139 0.603421 0.520479 0.650213 0.6874 0.32358 0.647232 0.739853 0.183595 0.52066 0.823219 0.226328 0.232539 0.84106 0.48841 0.333081 0.772484 0.540672 0.4542 0.75815 0.467879 0.390892 0.846896 0.360515 0.372475 0.869089 0.325495 0.285053 0.827495 0.483733 0.339781 0.673393 0.656575 0.238562 0.704887 0.668 0.320797 0.691569 0.647164 0.829927 0.324203 0.453996 0.78816 0.413058 0.456275 0.818961 0.437724 0.37108 0.868606 0.367447 0.332424 0.594766 0.761672 -0.257117 0.732865 0.586033 -0.345649 0.753901 0.533838 0.38295 0.862991 0.204761 0.461865 0.867214 0.193679 0.458725 0.940858 -0.000486 0.3388 0.908483 -0.022324 0.417326 0.966409 -0.169051 -0.193584 0.923393 -0.383468 0.01723 0.951149 0.102662 0.291162 0.867316 0.198019 0.456675 0.856872 0.261318 0.444391 0.920131 0.262219 0.290862 0.845974 0.375555 -0.378531 0.934245 0.115443 -0.337429 0.724297 0.540152 0.42852 0.705159 0.593618 0.387773 0.719293 0.595991 0.356949 0.405662 0.913937 -0.012545 0.486535 0.862055 -0.141935 0.71787 0.605721 0.343167 0.730039 0.584407 0.354276 0.725686 0.562032 0.396862 0.693853 0.591752 0.410363 0.217331 0.868422 0.445659 0.312452 0.932842 0.179389 0.629841 0.545507 0.552922 0.214362 0.527633 0.821981 0.173015 0.7023 0.690536 0.57713 0.459556 0.675077 0.602476 0.389152 0.696838 0.688167 0.493994 0.531411 0.689409 0.382203 0.615335 0.751692 0.33439 0.568456 0.797599 0.361585 0.482797 0.671211 0.364963 0.645196 0.411128 0.319273 0.853838 0.313319 0.402291 0.860228 0.718031 0.380064 0.58308 0.802641 0.402836 0.439876 0.786668 0.41629 0.455912 0.7261 0.396288 0.561903 0.493842 0.121551 0.861014 0.469657 0.240907 0.849345 0.710366 0.36318 0.602894 0.767343 0.380847 0.515888 0.773688 0.31236 0.551215 0.718919 0.257235 0.645744 0.615801 -0.251493 0.746687 0.530844 -0.044491 0.846301 0.775459 0.113009 0.621203 0.81328 0.246247 0.527199 0.846491 0.212923 0.487972 0.849483 0.012404 0.52747 0.842402 -0.47405 0.256193 0.735809 -0.426295 0.526173 0.762121 0.060604 0.644592 0.762121 0.060604 0.644592 0.670388 0.105094 0.734531 0.670388 0.105094 0.734531 0.53593 0.35712 0.765013 0.53593 0.35712 0.765013 0.519593 0.470857 0.712963 0.519593 0.470857 0.712963 0.592721 0.147272 0.791829 0.592721 0.147272 0.791829 0.539402 0.227876 0.810628 0.539402 0.227876 0.810628 0.838046 -0.041961 0.543984 0.838046 -0.041961 0.543984 0.805134 0.024108 0.592603 0.805134 0.024108 0.592603 0.458987 0.56981 0.681651 0.458987 0.56981 0.681651 0.36131 0.737053 0.571146 0.36131 0.737053 0.571146 0.930114 -0.106536 0.351481 0.930114 -0.106536 0.351481 0.880661 -0.11099 0.460561 0.880661 -0.11099 0.460561 0.320732 0.857422 0.402441 0.320732 0.857422 0.402441 0.44726 0.859353 0.247932 0.44726 0.859353 0.247932 0.95182 0.231775 0.200795 0.95182 0.231775 0.200795 0.964167 0.021103 0.264456 0.964167 0.021103 0.264456 0.579093 0.8006 0.153919 0.579093 0.8006 0.153919 0.697437 0.705567 0.12553 0.697437 0.705567 0.12553 0.814036 0.566095 0.129927 0.814036 0.566095 0.129927 0.890074 0.43096 0.148464 0.890074 0.43096 0.148464 0.029208 0.881474 -0.471328 0.029208 0.881474 -0.471328 0.096449 0.728365 -0.678368 0.096449 0.728365 -0.678368 0.4685 0.04873 -0.882118 0.4685 0.04873 -0.882118 0.638087 -0.253445 -0.727056 0.638087 -0.253445 -0.727056 0.178322 0.511529 -0.840559 0.178322 0.511529 -0.840559 0.316697 0.307225 -0.897394 0.316697 0.307225 -0.897394 -0.229597 0.97301 0.023188 -0.229597 0.97301 0.023188 -0.099111 0.961282 -0.257125 -0.099111 0.961282 -0.257125 0.690989 -0.552351 -0.466307 0.690989 -0.552351 -0.466307 0.614728 -0.774975 -0.146708 0.614728 -0.774975 -0.146708 -0.213285 0.674612 0.706689 -0.213285 0.674612 0.706689 -0.277125 0.880387 0.384865 -0.277125 0.880387 0.384865 0.522099 -0.831492 0.189823 0.522099 -0.831492 0.189823 0.41303 -0.701304 0.581016 0.41303 -0.701304 0.581016 0.016451 0.304495 0.952372 0.016451 0.304495 0.952372 -0.102423 0.482133 0.87009 -0.102423 0.482133 0.87009 0.321342 -0.449506 0.833477 0.321342 -0.449506 0.833477 0.240502 -0.251619 0.937468 0.240502 -0.251619 0.937468 0.177609 -0.048219 0.982919 0.177609 -0.048219 0.982919 0.113264 0.143803 0.983103 0.113264 0.143803 0.983103 0.856752 0.237426 0.457827 0.923385 0.210649 0.320917 0.807841 0.342573 0.479622 0.926355 0.306361 0.219111 0.893024 0.401372 0.203491 0.707489 0.350542 0.613661 0.690028 0.404138 0.600445 0.701459 0.296818 0.647962 0.79174 0.518629 0.322757 0.756722 0.567339 0.324806 0.829456 0.472735 0.297531 0.598529 0.538416 0.593188 0.611969 0.432342 0.662249 0.636119 0.597396 0.488334 0.661695 0.3349 0.670821 0.723255 0.374582 0.580165 0.790325 0.34767 0.504491 0.811959 0.371822 0.449969 0.863778 0.442517 0.24097 0.701135 0.600411 0.384599 0.932766 0.160597 0.322732 0.970845 0.170441 0.168552 0.883636 0.175716 0.433947 0.958137 0.275993 0.076165 0.918477 0.391142 0.058382 0.596042 0.268924 0.756581 0.631692 0.23949 0.737299 0.526233 0.296752 0.79688 0.713347 0.696389 0.078601 0.607873 0.785114 0.118686 0.815341 0.574919 0.068466 0.317442 0.747572 0.583409 0.328784 0.607429 0.72314 0.382484 0.824581 0.416859 0.421264 0.422347 0.802596 0.694449 0.183029 0.695875 0.790988 0.142639 0.594973 0.851498 0.154648 0.501034 0.88206 0.467139 0.061249 0.494106 0.834447 0.244044 0.898388 0.239427 0.368203 0.928433 0.290662 0.231361 0.927907 0.362185 0.088373 0.90613 0.422899 -0.009252 0.502343 -0.531378 -0.68212 0.481433 0.034979 -0.875785 0.821621 0.007587 -0.569984 0.601173 0.059321 -0.796914 0.288385 0.93379 -0.211824 0.988457 0.045901 -0.144378 0.606647 0.786641 -0.114787 0.631147 0.75431 -0.180748 0.972584 0.01879 -0.231792 0.50542 0.85821 -0.089584 0.979429 0.125423 -0.158074 0.681238 -0.704485 -0.199036 0.649817 -0.670326 -0.358331 0.486326 -0.865845 -0.117473 0.446328 -0.866561 -0.223303 0.749936 -0.639396 -0.169616 0.164446 0.814374 0.556554 0.230868 0.7458 0.624886 0.513037 0.656869 0.552553 0.434017 0.729299 0.528916 0.753221 0.48407 0.445347 0.753221 0.48407 0.445347 0.124146 -0.973254 0.193296 0.136691 -0.979344 0.149 0.136691 -0.979344 0.149 0.184839 -0.973906 0.131688 0.16227 -0.986484 -0.022769 0.212195 -0.968006 0.133929 0.212195 -0.968006 0.133929 0.404326 0.749489 0.524201 0.579587 0.654669 0.485269 0.579587 0.654669 0.485269 0.267339 0.835446 0.480167 0.245983 0.889628 0.38478 0.267339 0.835446 0.480167 0.316456 0.757992 0.570354 0.349573 0.870764 0.345787 0.299173 0.736411 0.60679 0.210334 0.763548 0.610536 0.173912 0.765408 0.619601 0.197207 0.7873 0.584182 0.208134 0.150701 0.966421 0.45413 0.145812 0.878922 0.34138 0.606573 0.718004 0.193961 0.656473 0.728987 0.702212 0.014831 0.711813 0.629702 0.408791 0.660579 0.464374 -0.299888 0.833321 0.195845 -0.470873 0.860188 0.247334 -0.957018 0.151467 0.40013 -0.846054 0.352263 0.156142 -0.842984 0.51478 0.487382 -0.796965 0.356799 0.24234 -0.955279 0.169453 0.220077 -0.968074 0.119991 0.144759 -0.978459 0.147185 0.183204 -0.982603 -0.03045 0.067622 -0.997704 0.003667 0.333609 0.885237 0.324131 0.26257 0.786829 0.558531 0.249027 0.818022 0.518484 0.310909 0.905688 0.288211 0.981618 -0.064667 0.179569 0.953472 -0.110057 0.280676 0.829047 -0.397145 0.393645 0.92859 0.156172 0.336647 0.777747 -0.421784 0.466056 0.769156 -0.579058 0.270354 0.995933 0.044395 0.078399 0.452986 -0.772336 0.445309 0.25562 -0.911562 0.322045 0.985612 -0.013881 -0.168452 0.7241 -0.689125 0.028032 0.669094 -0.721471 -0.178308 0.959852 -0.03757 -0.277979 0.142983 -0.970854 0.192352 0.080246 -0.996775 0.00032 0.399717 0.880195 0.255896 0.376418 0.74386 0.552252 0.932941 0.251988 0.257146 0.923519 0.376658 0.072404 0.341071 0.563945 0.752088 0.901143 0.06264 0.428972 0.473307 -0.704975 -0.528197 0.53861 0.034196 -0.841861 0.284747 -0.650038 -0.704536 0.28859 -0.717857 -0.633559 0.66476 -0.69131 -0.283167 0.687122 0.601648 -0.407288 0.19454 0.943367 -0.268726 0.142669 0.967481 -0.20887 0.158097 0.977372 -0.140534 0.267227 0.956959 -0.113221 0.206618 0.964826 -0.16254 0.111176 0.975912 -0.187714 0.29006 0.951394 -0.103509 0.197728 0.977642 -0.071559 0.133329 0.730763 0.669484 -0.021072 0.776457 0.629818 -0.048861 0.692427 0.719831 -0.267381 0.736738 0.621067 0.502201 -0.841758 -0.198082 0.347489 -0.823244 -0.44891 0.323269 -0.832159 -0.450565 0.365532 -0.909977 -0.195774 0.278989 -0.744812 -0.606152 0.310543 -0.724294 -0.615598 0.470573 -0.845704 0.251686 0.639991 -0.751749 0.159014 0.847528 -0.526779 -0.064814 0.931762 0.360605 -0.042234 0.731131 -0.37377 0.57074 0.545828 -0.440059 0.713036 0.28654 -0.807827 -0.515083 0.336227 -0.798398 -0.499512 0.390344 -0.778946 -0.490791 0.394888 -0.900382 -0.182694 0.453746 -0.877199 -0.156959 0.356802 -0.910855 -0.207449 -0.344161 0.695104 0.631176 -0.149439 0.640429 0.753338 -0.149043 0.665502 0.731364 -0.349826 0.693839 0.629452 -0.136209 0.702366 0.698663 -0.323407 0.705435 0.63069 0.682989 -0.682468 -0.260315 0.59895 -0.703991 -0.381648 0.629914 -0.656157 -0.415531 0.77097 -0.571238 -0.281588 0.426971 -0.693708 -0.580055 0.470882 -0.685627 -0.555145 0.547183 -0.735019 -0.400422 0.403878 -0.692278 -0.598025 0.639219 -0.729933 -0.242067 0.756317 -0.646196 0.102054 0.818345 -0.573567 0.036491 0.814869 -0.159464 0.557279 0.753505 -0.300809 0.584589 0.916322 -0.395282 -0.064085 -0.552229 0.717565 0.424433 -0.549898 0.723485 0.417351 -0.689114 0.695621 0.20306 -0.692124 0.693865 0.198787 -0.449937 0.772191 0.44864 -0.582332 0.776773 0.23982 0.4591 -0.736156 -0.497294 0.428557 -0.75507 -0.496193 0.470093 -0.756298 -0.455001 0.604445 -0.773438 -0.190894 0.573109 -0.784752 -0.236031 0.620477 -0.767507 -0.161065 -0.154659 0.830449 0.535196 -0.208047 0.933434 0.292262 0.839948 -0.488026 -0.237313 0.649751 -0.668884 -0.361136 0.686328 -0.685198 -0.243841 0.870409 -0.456272 -0.184943 0.113928 -0.971144 0.209524 0.420169 -0.778433 0.466369 0.36716 -0.763202 0.531711 -0.02591 -0.968892 0.246125 0.735247 0.502746 0.454597 0.760736 -0.231899 0.60622 0.709739 -0.164748 0.68493 0.677088 0.518341 0.522374 0.150157 0.985896 -0.073902 0.110758 0.979195 -0.170028 0.14924 0.977328 -0.150193 0.102024 0.980668 -0.166976 0.092901 0.976521 -0.194362 0.035026 -0.981694 0.187218 -0.094184 -0.972517 0.212932 -0.040179 -0.998571 0.035247 -0.134425 -0.988935 0.062742 0.104938 0.981244 -0.161707 0.151335 0.986059 -0.069173 0.069929 0.986197 -0.150086 0.095076 0.992657 -0.074781 -0.031932 -0.959846 0.278703 0.3959 -0.771292 0.498369 0.753955 -0.269659 0.599029 0.811465 0.345679 0.471202 0.245701 0.963498 -0.106314 0.226774 0.963215 -0.144187 -0.201856 -0.975954 0.082263 -0.144695 -0.963786 0.22401 0.238399 0.953876 -0.182445 0.263237 0.957272 -0.119739 0.137189 0.954008 0.266548 0.004047 0.860303 0.509766 -0.324412 0.82325 0.46585 -0.221133 0.946632 0.234497 0.552688 -0.819889 -0.14939 0.435697 -0.752668 -0.493618 0.365249 -0.701895 -0.611504 0.358271 0.298744 0.88453 0.369064 0.261778 0.891776 0.680582 -0.368671 0.633159 0.35026 0.27383 0.895732 -0.101362 0.652868 0.750659 -0.31403 0.712829 0.627104 0.528306 -0.819128 -0.223433 0.448996 -0.780542 -0.434921 0.341896 0.423686 0.838807 0.504935 0.340193 0.79329 0.181522 0.411952 0.892942 0.181522 0.411952 0.892942 0.465736 -0.606641 0.644264 -0.0363 0.939717 0.340021 0.06455 0.996125 -0.059741 -0.0363 0.939717 0.340021 0.286421 0.951044 -0.116095 0.288616 0.950349 -0.116354 0.275757 0.953921 -0.118292 0.150003 0.985457 -0.079833 -0.160278 0.98687 0.019962 -0.557805 0.804225 0.205125 -0.528811 0.837981 0.134713 -0.689987 0.699784 0.184985 -0.704052 0.684413 0.189445 -0.639015 0.750411 0.168948 -0.301208 0.951297 0.065638 0.321965 0.939617 -0.116016 0.978366 -0.179418 -0.103002 0.950511 -0.146462 -0.274005 0.864752 0.428163 -0.262451 0.86448 -0.440579 -0.242001 0.720676 -0.665351 -0.194768 0.631835 -0.756962 -0.166709 0.640249 -0.749264 -0.169365 0.627443 -0.760901 -0.165364 0.541996 -0.828837 -0.138816 0.434754 -0.894291 -0.105989 0.396475 -0.913174 -0.094449 0.3782 -0.921198 -0.091428 0.733887 0.635327 -0.240355 0.720343 0.687761 -0.089944 0.744559 0.62451 -0.235838 0.345736 0.9286 0.13479 0.993133 0.093733 0.070012 0.356159 0.925036 0.132136 0.187307 0.978163 -0.09007 0.502357 0.858922 0.099456 0.251333 0.962401 -0.103033 0.65335 -0.735934 0.17758 0.65112 0.755621 0.071276 0.96166 -0.25776 -0.093651 0.209729 0.846026 0.490157 0.369985 -0.806261 -0.461579 -0.486759 0.759504 0.431532 0.951681 0.185976 -0.24437 0.902737 0.332183 -0.273352 0.941165 0.315326 -0.121568 0.951681 0.185976 -0.24437 0.956675 0.290442 0.020395 0.999368 -0.03479 -0.007251 0.964422 0.229761 0.130768 0.952504 0.13236 0.274258 0.999368 -0.03479 -0.007251 0.940577 -0.003262 0.339566 0.985356 -0.047323 -0.163812 0.973149 -0.138935 0.183517 0.98634 -0.163979 0.015638 0.985356 -0.047323 -0.163812 0.800077 -0.569905 -0.187309 0.874318 -0.431977 -0.221278 0.945305 -0.32607 -0.008707 0.031586 -0.183913 0.982435 0.031586 -0.183913 0.982435 -0.030751 -0.950601 0.30889 -0.030751 -0.950601 0.30889 0.985137 -0.170059 0.024169 -0.138803 -0.672288 0.727161 -0.138803 -0.672288 0.727161 0.909257 -0.407951 -0.082632 0.909257 -0.407951 -0.082632 0.975975 0.172973 -0.132486 0.975975 0.172973 -0.132486 0.980139 0.18814 -0.062699 0.980139 0.18814 -0.062699 0.977763 -0.075286 0.195733 0.977763 -0.075286 0.195733 0.989301 -0.108793 0.097195 0.989301 -0.108793 0.097195 0.977445 0.124096 -0.170885 0.977445 0.124096 -0.170885 0.998153 0.056019 0.023506 0.998153 0.056019 0.023506 0.796335 -0.523715 0.302611 0.474101 -0.734714 0.485204 -0.961031 0.165053 0.221757 -0.966015 0.031778 0.256527 -0.974186 0.146597 0.171671 -0.972365 0.022683 0.232362 -0.984794 0.118521 0.127015 -0.97678 0.011602 0.213931 -0.992779 0.080892 0.088578 -0.980405 -0.006081 0.1969 -0.997692 0.034776 0.058321 -0.983084 -0.030932 0.180525 -0.999084 -0.01652 0.039467 -0.983546 -0.055798 0.171824 -0.996955 -0.071034 0.03217 -0.982323 -0.081459 0.168542 -0.991355 -0.12588 0.037019 -0.979425 -0.107879 0.170556 -0.982538 -0.178319 0.053122 -0.975168 -0.132497 0.177459 -0.97118 -0.224992 0.078667 -0.9699 -0.153567 0.188972 -0.957807 -0.263848 0.113978 -0.963903 -0.170188 0.204763 -0.939615 -0.29636 0.171153 -0.955655 -0.183417 0.230396 -0.916192 -0.318352 0.243403 -0.943673 -0.194814 0.26745 -0.940074 0.285894 0.18581 -0.959445 0.258862 0.111609 -0.975323 0.216319 0.04416 -0.986978 0.160325 -0.013014 -0.993968 0.093475 -0.057363 -0.996059 0.018754 -0.086686 -0.993227 -0.06055 -0.099163 -0.985628 -0.140582 -0.09367 -0.972899 -0.220345 -0.070116 -0.955697 -0.29262 -0.031897 -0.933885 -0.356815 0.023271 -0.904554 -0.412768 0.106793 -0.874187 -0.443341 0.198105 -0.904883 0.399162 0.14784 -0.930066 0.363832 0.051015 -0.950616 0.308169 -0.036885 -0.965592 0.235032 -0.111317 -0.974471 0.147814 -0.168987 -0.976979 0.05078 -0.207202 -0.973161 -0.05162 -0.224262 -0.963025 -0.155851 -0.219756 -0.94516 -0.263631 -0.192798 -0.918341 -0.367435 -0.147108 -0.884469 -0.46033 -0.076225 -0.846414 -0.531736 0.028979 -0.81683 -0.561478 0.132408 -0.856198 0.505244 0.107954 -0.886734 0.462178 -0.009715 -0.911564 0.394322 -0.116455 -0.92955 0.305236 -0.206801 -0.940103 0.199203 -0.276631 -0.942966 0.081326 -0.322801 -0.938215 -0.042948 -0.343377 -0.925514 -0.170798 -0.338011 -0.90304 -0.303133 -0.304351 -0.869126 -0.43109 -0.242446 -0.825613 -0.542663 -0.154533 -0.78679 -0.615366 -0.04782 -0.763783 -0.641746 0.069265 -0.795208 0.602633 0.06691 -0.830597 0.552504 -0.069627 -0.85928 0.473551 -0.193358 -0.879991 0.369951 -0.297914 -0.892055 0.246859 -0.378547 -0.895219 0.110198 -0.431786 -0.889617 -0.03377 -0.455457 -0.87547 -0.181874 -0.447743 -0.852671 -0.3311 -0.404135 -0.819795 -0.473097 -0.322669 -0.773161 -0.597383 -0.21297 -0.732323 -0.672114 -0.109388 -0.703802 -0.710148 0.018793 -0.723285 0.690084 0.025367 -0.762965 0.633675 -0.127835 -0.79508 0.544841 -0.266451 -0.818228 0.428382 -0.383395 -0.831653 0.290204 -0.47343 -0.835118 0.137002 -0.532737 -0.828804 -0.024239 -0.559013 -0.813771 -0.188224 -0.549862 -0.79107 -0.350428 -0.501406 -0.757687 -0.507139 -0.410755 -0.712161 -0.640658 -0.287028 -0.672656 -0.725938 0.143347 -0.641851 0.766661 -0.016075 -0.68527 0.704796 -0.183489 -0.720395 0.607414 -0.334782 -0.745674 0.479891 -0.46225 -0.760327 0.328783 -0.560182 -0.764125 0.161453 -0.624537 -0.757252 -0.014499 -0.652962 -0.740618 -0.191819 -0.643964 -0.713493 -0.368156 -0.596145 -0.67319 -0.539525 -0.505696 -0.633594 -0.66652 -0.392824 -0.552217 0.831757 -0.056883 -0.598779 0.765354 -0.236001 -0.636491 0.660838 -0.397708 -0.663675 0.524103 -0.533716 -0.679467 0.362301 -0.638015 -0.683616 0.18334 -0.706439 -0.676308 -0.004709 -0.736604 -0.658096 -0.193709 -0.72759 -0.624976 -0.385418 -0.678866 -0.57331 -0.567527 -0.590956 -0.539712 -0.669892 -0.509859 -0.455829 0.884817 -0.096532 -0.504906 0.814845 -0.284776 -0.544771 0.704701 -0.454557 -0.573584 0.560728 -0.597148 -0.59041 0.390539 -0.706325 -0.594941 0.202476 -0.777849 -0.58738 0.005005 -0.809296 -0.568315 -0.193377 -0.799765 -0.531724 -0.399254 -0.746904 -0.472063 -0.588647 -0.65624 -0.438252 -0.663694 -0.606173 -0.336649 0.931055 -0.140727 -0.387856 0.858178 -0.336301 -0.429627 0.743452 -0.512543 -0.459974 0.593597 -0.660353 -0.477869 0.416607 -0.773356 -0.482921 0.221168 -0.847273 -0.475295 0.016124 -0.879678 -0.455543 -0.189817 -0.869741 -0.417917 -0.406061 -0.812687 -0.353552 -0.60422 -0.714086 -0.307968 -0.666598 -0.678825 -0.193714 0.962913 -0.187815 -0.246267 0.8884 -0.387424 -0.288613 0.77069 -0.568101 -0.317008 0.616998 -0.720292 -0.324374 0.435579 -0.839674 -0.320365 0.248902 -0.91401 -0.326185 0.041175 -0.944409 -0.317893 -0.181748 -0.930544 -0.279515 -0.404386 -0.870829 -0.213288 -0.614544 -0.759503 -0.156721 -0.682515 -0.713871 -0.046463 0.971992 -0.230375 -0.103325 0.898972 -0.425645 -0.164362 0.783516 -0.59924 -0.218293 0.643744 -0.733446 -0.220032 0.426957 -0.877094 -0.163378 0.257767 -0.952294 -0.189104 0.091231 -0.97771 -0.196106 -0.137994 -0.970824 -0.15848 -0.395997 -0.904473 -0.068774 -0.626707 -0.776214 0.011498 -0.702817 -0.711278 0.080842 0.962059 -0.260588 -0.004368 0.897342 -0.441313 -0.108637 0.80053 -0.589364 -0.077282 0.160772 -0.983961 -0.047366 -0.005136 -0.998864 -0.055321 -0.376835 -0.924627 0.024205 -0.64051 -0.767568 0.122657 -0.746286 -0.654227 0.182989 0.944565 -0.272601 0.060296 0.892968 -0.446064 0.298773 0.913904 -0.274797 0.253313 0.891687 -0.375137 0.114854 -0.338324 -0.933994 0.102232 0.013353 -0.994671 0.151765 -0.614693 -0.774028 0.247572 -0.789545 -0.561539 0.422501 0.861523 -0.281553 0.416333 0.839555 -0.34902 0.37199 -0.274879 -0.886603 0.353485 0.017625 -0.935274 0.378321 -0.507369 -0.774242 0.386435 -0.730111 -0.563565 0.530382 0.793788 -0.297652 0.540498 0.759214 -0.362568 0.588887 -0.200332 -0.782994 0.56861 0.014756 -0.822475 0.582449 -0.344028 -0.736476 0.575726 -0.569224 -0.586961 0.65241 0.687716 -0.318445 0.658927 0.642592 -0.391012 0.527988 0.032741 -0.848621 0.572271 -0.222348 -0.789346 0.647447 -0.270239 -0.712589 0.71954 -0.352064 -0.598592 0.761452 -0.51329 -0.395884 0.588683 -0.724004 -0.359542 0.425419 -0.825843 -0.370137 0.75829 0.548346 -0.35258 0.752446 0.495489 -0.433954 0.762878 0.455469 -0.458873 0.774527 0.480972 -0.410821 -0.059483 0.299655 -0.952191 -0.090596 0.399221 -0.912368 0.036545 0.471124 -0.881309 0.07364 0.399264 -0.913874 -0.030114 0.266255 -0.963432 -0.038844 0.381241 -0.923659 -0.13284 0.509742 -0.85001 -0.066453 0.503298 -0.861554 0.001768 0.538105 -0.842876 0.050754 0.065758 -0.996544 -0.019181 0.193572 -0.980899 0.117727 0.320417 -0.939933 0.173089 0.209675 -0.962329 0.073986 0.047418 -0.996131 -0.002861 0.154045 -0.98806 0.22268 -0.189591 -0.956279 0.142047 -0.070696 -0.987332 0.235945 0.061061 -0.969846 0.284019 -0.085242 -0.955022 0.284187 -0.119522 -0.95129 0.18495 -0.046926 -0.981627 0.469944 -0.314762 -0.824668 0.324898 -0.286474 -0.901318 0.327435 -0.220891 -0.918691 0.436096 -0.251459 -0.864054 0.473624 -0.209127 -0.855538 0.371679 -0.174482 -0.911817 0.593781 -0.220328 -0.773873 0.64569 -0.038921 -0.762607 0.659388 -0.074842 -0.748068 0.577338 -0.188497 -0.794449 0.520053 -0.164818 -0.838081 0.486574 -0.003404 -0.873633 0.583694 0.350278 -0.732535 0.633952 0.167061 -0.755112 0.445809 0.172583 -0.878333 0.388775 0.329865 -0.860258 0.670839 0.324639 -0.666772 0.692093 0.11947 -0.711852 0.445222 0.577844 -0.684013 0.517686 0.479897 -0.708308 0.330597 0.433029 -0.838565 0.275479 0.50654 -0.817024 0.53871 0.612813 -0.578145 0.616696 0.484403 -0.620516 0.278003 0.744964 -0.606418 0.365453 0.664551 -0.651779 0.221829 0.57283 -0.789087 0.182217 0.632878 -0.752504 0.306851 0.80584 -0.506422 0.437533 0.722967 -0.534681 -0.077112 0.816166 -0.572649 0.125172 0.825515 -0.550324 0.121846 0.731498 -0.670868 -0.019603 0.743964 -0.667932 -0.030227 0.802231 -0.596248 0.128031 0.849287 -0.512171 -0.166759 0.672289 -0.721262 -0.074919 0.639876 -0.764817 -0.086363 0.65898 -0.747185 0.419268 0.406688 -0.811677 0.45283 0.31045 -0.835802 0.550354 0.354523 -0.755926 0.488995 0.426269 -0.761038 0.798505 0.589542 -0.121777 0.629664 0.764854 -0.136094 0.428097 0.516657 -0.741484 0.481992 0.162651 -0.860946 0.476625 0.173666 -0.861782 0.541781 -0.051837 -0.83892 0.610962 -0.026965 -0.7912 0.77405 -0.395398 -0.494477 0.920958 -0.172543 -0.349378 0.643893 0.078074 -0.761122 0.480736 0.233816 -0.845117 0.483133 0.167149 -0.859444 0.616661 0.240115 -0.749715 0.967736 0.117908 -0.222674 0.913198 0.379905 -0.147451 0.390578 0.591083 -0.705741 0.382839 0.535126 -0.753044 0.414139 0.577573 -0.70349 0.47634 0.860797 -0.179246 0.340392 0.907818 -0.24495 0.421549 0.584377 -0.693397 0.405414 0.540989 -0.736865 0.431518 0.576007 -0.694268 0.364935 0.56563 -0.739517 0.160295 0.921034 -0.354968 -0.063838 0.850342 -0.522343 0.231853 0.516573 -0.824255 -0.234963 0.674542 -0.699847 -0.263787 0.488611 -0.831671 0.143761 0.349005 -0.926028 0.121957 0.430188 -0.894463 0.244238 0.368175 -0.897104 0.286839 0.465666 -0.837185 0.431825 0.308888 -0.847417 0.349106 0.306214 -0.88564 0.242828 0.317447 -0.916658 -0.193183 0.358321 -0.913393 -0.108882 0.280328 -0.953709 0.308743 0.342271 -0.887428 0.400235 0.380025 -0.833902 0.437071 0.358464 -0.824907 0.306876 0.362809 -0.879885 -0.062544 0.201463 -0.977497 -0.04802 0.0781 -0.995788 0.266858 0.326827 -0.906626 0.350138 0.278047 -0.894479 0.354862 0.347322 -0.868009 0.255429 0.219947 -0.941477 -0.006971 -0.087812 -0.996113 0.120653 -0.291438 -0.94895 0.318338 0.07641 -0.944893 0.448609 0.180967 -0.875215 0.399034 0.212972 -0.89186 0.432397 -0.02109 -0.901437 0.342686 -0.457883 -0.820311 0.578434 -0.49519 -0.648229 0.296419 -0.000702 -0.955058 0.296419 -0.000702 -0.955058 0.172523 0.052896 -0.983584 0.172523 0.052896 -0.983584 0.039158 0.322577 -0.945733 0.039158 0.322577 -0.945733 0.047516 0.433082 -0.900101 0.047516 0.433082 -0.900101 0.073663 0.121903 -0.989805 0.073663 0.121903 -0.989805 0.020637 0.212144 -0.977021 0.020637 0.212144 -0.977021 0.424054 -0.091556 -0.900997 0.424054 -0.091556 -0.900997 0.357272 -0.03225 -0.933444 0.357272 -0.03225 -0.933444 0.012525 0.534209 -0.84526 0.012525 0.534209 -0.84526 -0.011494 0.7071 -0.707021 -0.011494 0.7071 -0.707021 0.597526 -0.131026 -0.791072 0.597526 -0.131026 -0.791072 0.505826 -0.146625 -0.850083 0.505826 -0.146625 -0.850083 0.043082 0.835064 -0.548463 0.043082 0.835064 -0.548463 0.232892 0.841802 -0.486962 0.232892 0.841802 -0.486962 0.692441 0.211038 -0.689919 0.692441 0.211038 -0.689919 0.670034 -0.002279 -0.742327 0.670034 -0.002279 -0.742327 0.395537 0.785831 -0.475416 0.395537 0.785831 -0.475416 0.511415 0.69064 -0.511342 0.511415 0.69064 -0.511342 0.608864 0.549501 -0.572131 0.608864 0.549501 -0.572131 0.665886 0.412472 -0.621662 0.665886 0.412472 -0.621662 0.267718 0.900516 0.342634 0.267718 0.900516 0.342634 0.434491 0.763425 0.477912 0.434491 0.763425 0.477912 0.869912 0.076138 0.487294 0.869912 0.076138 0.487294 0.932155 -0.229683 0.279881 0.932155 -0.229683 0.279881 0.602872 0.538559 0.588642 0.602872 0.538559 0.588642 0.752279 0.323048 0.574209 0.752279 0.323048 0.574209 -0.213672 0.974192 0.072768 -0.213672 0.974192 0.072768 0.039021 0.973056 0.227243 0.039021 0.973056 0.227243 0.840289 -0.540248 0.045233 0.840289 -0.540248 0.045233 0.606818 -0.775669 -0.17352 0.606818 -0.775669 -0.17352 -0.573632 0.648601 -0.500262 -0.573632 0.648601 -0.500262 -0.459052 0.865899 -0.198721 -0.459052 0.865899 -0.198721 0.348772 -0.845309 -0.404736 0.348772 -0.845309 -0.404736 0.044107 -0.731158 -0.680781 0.044107 -0.731158 -0.680781 -0.526631 0.262875 -0.808429 -0.526631 0.262875 -0.808429 -0.572583 0.444835 -0.688673 -0.572583 0.444835 -0.688673 -0.171813 -0.489749 -0.854767 -0.171813 -0.489749 -0.854767 -0.298216 -0.294897 -0.907801 -0.298216 -0.294897 -0.907801 -0.378075 -0.092709 -0.921121 -0.378075 -0.092709 -0.921121 -0.44719 0.096281 -0.889242 -0.44719 0.096281 -0.889242 0.612429 0.206829 -0.762989 0.464886 0.248405 -0.849809 0.407407 0.351958 -0.842701 0.648197 0.357749 -0.672202 0.671753 0.259933 -0.693674 0.260779 0.444292 -0.857088 0.266283 0.359019 -0.894538 0.239549 0.282383 -0.928911 0.456076 0.54318 -0.704947 0.484975 0.494828 -0.721072 0.523431 0.452679 -0.721874 0.154432 0.395601 -0.905345 0.17883 0.504716 -0.84456 0.266157 0.567731 -0.779001 0.193307 0.300033 -0.934138 0.427534 0.439385 -0.790035 0.307666 0.464115 -0.830626 0.465664 0.419078 -0.779442 0.586011 0.418412 -0.693919 0.376686 0.574397 -0.726757 0.72401 0.167928 -0.669036 0.615211 0.144276 -0.775048 0.538442 0.194451 -0.81992 0.755996 0.352652 -0.551458 0.765047 0.251817 -0.592698 0.104303 0.251884 -0.96212 0.084593 0.265317 -0.960443 0.005837 0.281933 -0.959416 0.438714 0.77153 -0.460728 0.549094 0.684577 -0.479427 0.639111 0.567102 -0.51955 -0.119349 0.571474 -0.811895 -0.055497 0.717664 -0.694175 0.087893 0.80095 -0.592244 -0.082255 0.383999 -0.919662 0.371981 0.25099 -0.893663 0.168173 0.254214 -0.952414 0.515832 0.244885 -0.820943 0.711746 0.448691 -0.540457 0.274747 0.816832 -0.507247 0.645705 0.281916 -0.70964 0.539281 0.220414 -0.812769 0.769022 0.394085 -0.503292 0.726749 0.338639 -0.597628 0.910687 0.132665 0.391214 0.999599 0.019627 0.020427 0.95412 0.024299 0.298438 0.445708 0.894704 -0.029136 0.965917 0.00636 -0.258774 0.63813 0.749781 -0.174984 0.564478 0.808758 -0.165152 0.955888 0.074409 -0.28415 0.833027 -0.550995 -0.049699 0.747769 -0.638876 -0.180774 0.496269 -0.862279 -0.100952 -0.207933 0.848115 -0.487303 0.067624 0.763984 -0.641681 0.12728 0.626188 -0.769213 -0.218784 0.728379 -0.649305 0.477035 0.407812 -0.778542 0.477035 0.407812 -0.778542 0.017333 -0.981177 -0.192329 0.100697 -0.980826 -0.166857 0.066985 -0.985016 -0.158922 0.066985 -0.985016 -0.158922 0.113176 -0.977596 -0.177477 0.113176 -0.977596 -0.177477 0.260639 0.584649 -0.768279 0.260639 0.584649 -0.768279 0.016554 0.67435 -0.738226 -0.106362 0.750404 -0.652366 -0.106362 0.750404 -0.652366 -0.052394 0.836039 -0.546163 0.073173 0.824552 -0.561034 -0.11046 0.686583 -0.718611 -0.155032 0.743111 -0.650962 -0.209657 0.806439 -0.552901 -0.277141 0.74834 -0.602644 -0.254322 0.755762 -0.603444 -0.358109 0.092557 -0.929081 -0.250923 0.673348 -0.695442 -0.112663 0.603179 -0.789609 -0.09202 0.089713 -0.991708 0.154625 0.382352 -0.910988 0.205405 -0.026468 -0.978319 -0.072607 -0.353019 -0.932795 -0.315135 -0.516218 -0.796372 0.137801 -0.96591 -0.219155 -0.147037 -0.862058 -0.485012 0.15353 -0.866566 -0.474859 0.229098 -0.817711 -0.528075 0.125194 -0.964684 -0.231758 0.055128 -0.985656 -0.159509 0.133227 -0.975043 -0.1776 0.08158 0.845691 -0.5274 0.078804 0.875247 -0.477213 -0.135909 0.78308 -0.606889 -0.14307 0.731129 -0.667069 0.652262 -0.134271 -0.746006 0.728452 -0.084587 -0.679855 0.489926 -0.423017 -0.762253 0.604152 0.140091 -0.784458 0.789901 0.036981 -0.612119 0.511155 -0.597093 -0.618224 0.41548 -0.442463 -0.794735 0.053874 -0.927755 -0.369281 0.152238 -0.796477 -0.58519 0.917433 -0.01634 -0.397554 0.60325 -0.699086 -0.383887 0.029478 -0.980033 -0.196639 0.188278 0.863211 -0.468421 0.734878 0.361526 -0.573806 0.645074 0.228829 -0.729052 0.011092 0.714503 -0.699544 0.528285 0.032629 -0.84844 -0.123905 0.526586 -0.841044 0.709036 -0.679127 0.189881 0.54884 -0.680148 0.485977 0.696633 -0.536154 0.476698 0.937025 0.142119 0.319041 0.883729 -0.390989 0.257199 0.771856 0.621298 -0.135006 0.80244 -0.582305 -0.130427 0.360455 0.931906 0.040288 0.246781 0.968966 0.014261 0.199409 0.979909 0.003657 0.20259 0.97835 0.042279 0.297397 0.954751 0.002279 0.296878 0.953346 -0.054732 -0.448272 0.750301 -0.485901 -0.299256 0.711329 -0.635969 -0.449932 0.662013 -0.599417 -0.604373 0.702658 -0.375506 0.543677 -0.837776 -0.05046 0.41825 -0.908309 0.006481 0.525642 -0.828016 0.195167 0.513327 -0.837473 0.187441 0.632445 -0.690176 0.351668 0.562937 -0.723503 0.399556 0.270888 -0.860723 -0.431018 0.466072 -0.760826 -0.451575 0.785817 -0.470274 -0.401664 0.806986 0.379916 -0.452147 0.311722 -0.406116 -0.859011 0.08011 -0.476468 -0.875534 0.492226 -0.783275 0.379728 0.564196 -0.75938 0.324076 0.615425 -0.747397 0.250297 0.467281 -0.880804 -0.076373 0.423525 -0.905139 -0.036738 0.388235 -0.921287 -0.022439 -0.638353 0.671458 -0.376365 -0.642083 0.670375 -0.371923 -0.527289 0.635121 -0.564436 -0.53912 0.609156 -0.581618 -0.499354 0.673213 -0.545371 -0.620665 0.681581 -0.387585 0.724403 -0.679107 -0.118553 0.808578 -0.568186 -0.152862 0.76273 -0.645516 0.039393 0.719046 -0.694329 0.029644 0.704086 -0.666952 0.243799 0.68063 -0.673335 0.288725 0.675478 -0.668555 0.311069 0.688796 -0.721756 0.068031 0.678689 -0.726051 -0.110594 0.590821 -0.659388 -0.464906 0.324614 -0.335183 -0.884465 0.389368 -0.193616 -0.900503 0.677507 -0.584788 -0.446103 0.811911 -0.403641 -0.421752 -0.702864 0.705439 -0.091315 -0.699069 0.693346 0.174852 -0.698884 0.694843 0.169571 -0.697074 0.711711 -0.08692 -0.629707 0.772938 0.077689 -0.630257 0.757744 -0.169115 0.665495 -0.718329 0.202779 0.637554 -0.7383 0.220087 0.650398 -0.741869 0.163133 0.619906 -0.781037 -0.075482 0.62189 -0.772088 -0.130895 0.619404 -0.767547 -0.164959 -0.428525 0.808484 -0.403384 -0.344282 0.922494 -0.174568 0.841854 -0.487833 -0.230867 0.838993 -0.458769 -0.292613 0.718357 -0.682624 -0.134116 0.750372 -0.66081 -0.016469 -0.004385 -0.980634 -0.195802 0.11327 -0.803082 -0.585003 0.033162 -0.790045 -0.612151 -0.142029 -0.978203 -0.151482 0.398848 0.500353 -0.768484 0.284867 0.522124 -0.803889 0.240759 -0.182234 -0.953324 0.326055 -0.256882 -0.90978 0.106126 0.992625 0.058596 0.101925 0.991712 -0.078227 0.185058 0.981762 0.043548 0.161241 0.98316 0.086007 0.203627 0.976108 0.075821 -0.181266 -0.979622 -0.086502 -0.058418 -0.989239 -0.134139 0.18691 0.981774 0.034418 0.16088 0.98655 0.028917 -0.164751 -0.970502 -0.176023 0.075477 -0.797038 -0.599194 0.41959 0.332341 -0.844685 0.322606 -0.288805 -0.901397 0.338129 0.937695 -0.079978 0.299596 0.953203 -0.040569 -0.230271 -0.970692 -0.068787 0.273756 0.960659 -0.046809 -0.093554 0.935084 -0.341855 -0.357811 0.927392 -0.109158 -0.580229 0.784645 -0.218327 -0.370232 0.823908 -0.429073 0.555442 -0.82035 -0.136052 0.648256 -0.730721 0.214037 0.665073 -0.670138 0.329534 -0.177345 0.255741 -0.950339 0.237945 -0.404121 -0.883215 -0.171659 0.218398 -0.960643 -0.191232 0.22974 -0.95428 -0.611039 0.688951 -0.389844 -0.497376 0.621066 -0.605717 0.578572 -0.812132 -0.075471 0.636769 -0.760919 0.124606 -0.168096 0.382717 -0.908445 -0.01579 0.29859 -0.954251 -0.354497 0.372019 -0.857866 -0.354497 0.372019 -0.857866 0.030753 -0.642052 -0.766044 -0.28865 0.899627 -0.327645 -0.28865 0.899627 -0.327645 -0.590748 0.801531 0.092551 0.882451 -0.187177 -0.431561 0.631213 0.690214 -0.3538 0.716773 0.651128 -0.249539 0.810085 0.079366 -0.580916 0.218435 0.918014 -0.330963 0.140919 0.983259 -0.115515 0.178425 0.905077 -0.386006 0.364259 0.817074 -0.446884 0.299785 0.939825 -0.163886 0.464631 -0.750462 -0.470027 0.536199 0.720631 -0.439525 0.864301 -0.265631 -0.427112 -0.127859 0.902899 -0.410396 0.648779 -0.746777 0.14632 -0.65206 0.746179 -0.134292 0.932257 0.179954 -0.313868 0.932257 0.179954 -0.313868 0.85443 0.301563 -0.423095 0.797829 0.26596 -0.541049 0.873116 -0.177098 -0.454207 0.873116 -0.177098 -0.454207 0.649289 0.072699 -0.757059 0.753442 0.191783 -0.628923 0.6043 -0.0704 -0.793641 0.921298 -0.001363 -0.388856 0.921298 -0.001363 -0.388856 0.805464 -0.09727 -0.584608 0.710857 -0.181827 -0.679427 0.859553 -0.250977 -0.445172 -0.504833 -0.252405 -0.825491 -0.504833 -0.252405 -0.825491 -0.176988 -0.95937 -0.219738 -0.176988 -0.95937 -0.219738 0.838581 -0.043777 -0.543014 -0.50884 -0.695521 -0.507279 -0.50884 -0.695521 -0.507279 0.843621 -0.371969 -0.387224 0.843621 -0.371969 -0.387224 0.897769 0.154532 -0.41247 0.897769 0.154532 -0.41247 0.883068 0.157461 -0.442037 0.883068 0.157461 -0.442037 0.71598 -0.20424 -0.667576 0.71598 -0.20424 -0.667576 0.84052 -0.139279 -0.523572 0.84052 -0.139279 -0.523572 0.889164 0.201883 -0.410647 0.889164 0.201883 -0.410647 0.844759 0.094819 -0.526679 0.844759 0.094819 -0.526679 0.516769 -0.546521 -0.658988 0.137687 -0.761356 -0.633545 -0.073521 0.769689 -0.634171 -0.902895 -0.325759 0.280467 -0.936415 -0.200727 0.287811 -0.858832 -0.448083 0.248252 -0.80054 -0.564124 0.202238 -0.740856 -0.649577 0.170825 -0.640499 -0.727822 0.245023 -0.852262 -0.443442 0.277505 -0.785146 -0.561254 0.261802 -0.709343 -0.657204 0.254784 0.578683 -0.759785 0.2964 -0.000115 -0.99999 -0.004589 -0.00051 -0.999977 -0.006811 -3.4e-005 -0.999995 -0.003095 -0.0006 -0.999998 -0.001658 0.001309 -0.999998 0.001288 -0.003465 -0.999976 -0.006061 -0.004195 -0.999979 -0.004981 -0.000633 -0.99997 -0.007748 -0.001948 -0.999974 -0.00693 -6e-006 -0.999971 -0.007673 -0.00264 -0.99998 -0.005704 -6.6e-005 -0.999967 -0.008151 -0.00142 -0.999996 -0.002481 0.003645 -0.999993 4.6e-005 -0.002686 -0.999991 0.003221 0.002724 -0.999944 0.010221 0.004946 -0.999932 0.010546 0.006765 -0.99992 0.010688 0.004595 -0.999966 0.006817 0.001146 -0.999997 0.002298 -0.004822 -0.999982 0.003527 -0.003588 -0.999964 0.00771 -0.00298 -0.999888 0.014663 -0.001243 -0.999863 0.016531 0.001848 -0.999933 0.011451 -0.004415 -0.999984 0.003674 0.001118 -0.999907 0.013595 0.001334 -0.999999 -0.000699 -0.00033 -1 -0.000292 + + + + + + + + + + 0.245158 0.423975 0.25011 0.468112 0.150442 0.543685 0.148569 0.498875 0.302841 0.416173 0.345064 0.636086 0.339502 0.673242 0.260986 0.672117 0.283208 0.642063 0.331126 0.714598 0.241009 0.71553 0.233372 0.762934 0.302959 0.373132 0.224027 0.289653 0.23558 0.359702 0.143764 0.429085 0.134156 0.320572 0.298228 0.319321 0.288073 0.263566 0.326898 0.757163 0.328393 0.797118 0.23841 0.805793 0.60087 0.640918 0.866606 0.398924 0.510699 0.676291 0.517366 0.634965 0.871384 0.397619 0.505796 0.719121 0.878048 0.397558 0.87416 0.398826 0.86606 0.397625 0.86057 0.399008 0.501279 0.762876 0.856321 0.39906 0.497144 0.804816 0.862375 0.397683 0.860024 0.397676 0.853776 0.399148 0.494669 0.842655 0.936097 0.40457 0.495808 0.877438 0.932361 0.401286 0.944998 0.401429 0.333511 0.830512 0.255441 0.838224 0.335539 0.859065 0.275714 0.857682 0.13703 0.645509 0.099669 0.709478 0.072436 0.710311 0.114209 0.64461 0.217381 0.600094 0.193334 0.589335 0.083907 0.774978 0.093256 0.834193 0.067488 0.842396 0.056643 0.778851 0.948825 0.405179 0.543475 0.557405 0.5578 0.533271 0.685834 0.551732 0.928618 0.398828 0.939922 0.398832 0.318062 0.571086 0.304302 0.551225 0.870712 0.401462 0.862287 0.401557 0.855482 0.401642 0.85836 0.405349 0.85103 0.405417 0.86725 0.404976 0.851008 0.401767 0.84805 0.401779 0.618068 0.949096 0.595914 0.442419 0.701364 0.36472 0.704143 0.312403 0.595493 0.387203 0.757075 0.288915 0.749567 0.262372 0.79867 0.019963 0.720188 0.090411 0.342229 0.232442 0.353643 0.285267 0.846214 0.405443 0.84246 0.405195 0.945825 0.3988 0.51556 0.94314 0.529717 0.959537 0.951482 0.401365 0.955814 0.405156 0.355112 0.336459 0.416748 0.23909 0.409212 0.301844 0.412385 0.174765 0.722678 0.141004 0.371257 0.129527 0.316583 0.183819 0.278107 0.146712 0.815355 0.094326 0.586596 0.164171 0.31201 0.090946 0.272238 0.213152 0.591566 0.221736 0.775513 0.183818 0.258385 0.177707 0.714664 0.225413 0.594393 0.311859 0.803506 0.201004 0.853165 0.100422 0.240207 0.064107 0.220228 0.127313 0.134162 0.116701 0.137886 0.045291 0.20962 0.176711 0.132836 0.176022 0.393776 0.367451 0.346805 0.380154 0.21424 0.228892 0.133514 0.241035 0.127886 0.880246 0.194162 0.909528 0.176891 0.924466 0.105635 0.892789 0.298575 0.918513 0.289302 0.932026 0.41004 0.927663 0.412647 0.940987 0.152917 0.714025 0.188039 0.660899 0.251002 0.622891 0.148083 0.821618 0.139091 0.770988 0.529124 0.59406 0.624566 0.605374 0.943792 0.414167 0.33386 0.602351 0.939709 0.408955 0.951716 0.40979 0.95394 0.414936 0.863781 0.409841 0.854643 0.410095 0.847079 0.410021 0.50373 0.914675 0.043999 0.560029 0.039161 0.51728 0.035514 0.442488 0.02836 0.327681 0.57657 0.399149 0.579657 0.45714 0.483058 0.467543 0.484696 0.402538 0.027211 0.11532 0.026409 0.041836 0.027231 0.176259 0.027041 0.244825 0.496033 0.232082 0.498386 0.171519 0.545104 0.178866 0.55478 0.242428 0.486973 0.320445 0.572701 0.32584 0.253473 0.42034 0.198325 0.471074 0.201641 0.514357 0.257191 0.464291 0.304409 0.414784 0.305266 0.371658 0.230885 0.286168 0.167912 0.306331 0.188981 0.401339 0.242536 0.354324 0.300813 0.31779 0.290984 0.262458 0.644363 0.422582 0.643061 0.366324 0.70337 0.314326 0.703499 0.366966 0.745969 0.26707 0.75382 0.293297 0.343946 0.231017 0.355397 0.284532 0.356783 0.335152 0.414764 0.29281 0.419941 0.236001 0.413771 0.173263 0.370421 0.125545 0.313385 0.086563 0.282902 0.142155 0.319456 0.18046 0.261679 0.175104 0.275739 0.211488 0.247515 0.05956 0.175872 0.043369 0.166908 0.113803 0.230266 0.122298 0.162066 0.173298 0.220575 0.173418 0.399643 0.347472 0.348371 0.378515 0.850892 0.415208 0.23283 0.882474 0.174218 0.860862 0.318561 0.890705 0.412205 0.900441 0.414872 0.864697 0.414169 0.832004 0.413463 0.796679 0.414763 0.757 0.418623 0.715141 0.424042 0.67374 0.797949 0.022112 0.816816 0.093012 0.720595 0.147032 0.715991 0.092651 0.636546 0.210325 0.627672 0.148444 0.772502 0.189202 0.711355 0.231084 0.641706 0.289174 0.223314 0.226619 0.162858 0.235961 0.139391 0.505963 0.140772 0.546375 0.105327 0.324975 0.131454 0.436403 0.855305 0.0942 0.800674 0.205793 0.103269 0.042003 0.100779 0.11305 0.099208 0.173793 0.099637 0.242841 0.428561 0.633258 0.429426 0.594048 0.429051 0.559095 0.429259 0.535162 0.35272 0.639241 0.294558 0.645659 0.274212 0.673847 0.348213 0.675519 0.253789 0.714174 0.339072 0.715472 0.241562 0.759109 0.241492 0.801977 0.330569 0.796358 0.332348 0.756954 0.843668 0.414845 0.519216 0.636196 0.513483 0.677706 0.858319 0.415536 0.509018 0.719971 0.595108 0.724198 0.959154 0.409842 0.961426 0.415077 0.955396 0.420505 0.503982 0.762367 0.946551 0.419988 0.498249 0.80295 0.581926 0.813498 0.948394 0.426244 0.956245 0.426562 0.493564 0.840197 0.962774 0.420748 0.49337 0.874734 0.5689 0.884732 0.963626 0.426902 0.947821 0.439136 0.254385 0.836095 0.333265 0.830744 0.334347 0.859927 0.274272 0.857068 0.111374 0.707428 0.160452 0.654158 0.126019 0.649524 0.074711 0.707898 0.232092 0.611555 0.203545 0.598866 0.085639 0.828171 0.086444 0.767612 0.053832 0.770468 0.05904 0.833261 0.5406 0.554531 0.653253 0.57169 0.949156 0.432796 0.552741 0.532581 0.956416 0.432776 0.955188 0.438695 0.321928 0.578317 0.3053 0.558373 0.963377 0.433055 0.962074 0.438861 0.939469 0.450342 0.944673 0.445101 0.952905 0.444195 0.949616 0.449137 0.959891 0.444199 0.95721 0.449055 0.928445 0.45763 0.933041 0.454385 0.647892 0.957038 0.945196 0.453364 0.513713 0.938992 0.528694 0.953445 0.940767 0.456994 0.954246 0.453493 0.191556 0.905473 0.119561 0.876603 0.09609 0.886393 0.173642 0.917872 0.296111 0.916924 0.285563 0.930752 0.407594 0.925155 0.699705 0.808301 0.767751 0.813767 0.770203 0.857847 0.710393 0.859091 0.67046 0.86001 0.652167 0.800156 0.732575 0.902022 0.706983 0.910753 0.776574 0.894725 0.709069 0.706824 0.772884 0.721001 0.769128 0.766819 0.69961 0.756109 0.650715 0.739559 0.665169 0.685443 0.747389 0.629544 0.781976 0.645207 0.777571 0.679447 0.726035 0.663915 0.69251 0.641696 0.7256 0.608173 0.800842 0.598447 0.800844 0.613722 0.782354 0.62203 0.77064 0.606739 0.761516 0.586356 0.801211 0.57812 0.833474 0.606525 0.843418 0.585771 0.884582 0.608278 0.861681 0.62927 0.826927 0.645008 0.821482 0.621769 0.901508 0.709495 0.841154 0.721344 0.835351 0.679466 0.88519 0.664947 0.920582 0.64464 0.946246 0.692573 0.905321 0.811872 0.840491 0.814502 0.842749 0.767471 0.908491 0.759591 0.957769 0.748636 0.953229 0.808266 0.87648 0.901039 0.832824 0.894364 0.83647 0.858222 0.893987 0.860506 0.934495 0.863509 0.904941 0.908789 0.811165 0.93926 0.808557 0.928096 0.833115 0.918674 0.850764 0.928355 0.866017 0.939324 0.815782 0.955298 0.781351 0.919619 0.767445 0.930389 0.756778 0.947206 0.874321 0.260529 0.87457 0.258357 0.870642 0.262514 0.870232 0.260129 0.875205 0.262091 0.87418 0.274349 0.878088 0.275377 0.879128 0.284194 0.875282 0.284248 0.876451 0.268146 0.87176 0.26763 0.879196 0.270887 0.875496 0.265391 0.893101 0.28442 0.892287 0.271326 0.879947 0.284131 0.862255 0.219399 0.877309 0.242158 0.869772 0.241647 0.855575 0.218438 0.862432 0.239621 0.84944 0.210845 0.867315 0.244511 0.849901 0.240235 0.863194 0.266321 0.876212 0.265675 0.880423 0.283451 0.866718 0.283089 0.870498 0.254293 0.863904 0.253791 0.870234 0.270504 0.864805 0.270607 0.879852 0.25405 0.878645 0.27023 0.884908 0.221559 0.894641 0.243235 0.885819 0.242521 0.87478 0.219802 0.853855 0.205189 0.868038 0.204565 0.870975 0.210424 0.856654 0.209577 0.882303 0.208527 0.885027 0.21281 0.869343 0.207181 0.855354 0.205901 0.879862 0.246326 0.872817 0.221463 0.859409 0.2185 0.885826 0.225344 0.891813 0.248223 0.886742 0.266822 0.897889 0.269881 0.890434 0.283337 0.902191 0.283202 0.887267 0.269985 0.888486 0.253806 0.897003 0.253871 0.897865 0.269734 0.890567 0.21382 0.890889 0.214313 0.887336 0.211472 0.940502 0.247339 0.935827 0.245027 0.948386 0.259727 0.952135 0.261243 0.929477 0.246937 0.935892 0.257903 0.955141 0.271935 0.951237 0.271687 0.951697 0.282445 0.956107 0.282705 0.939971 0.271031 0.941535 0.28252 0.963745 0.266939 0.955791 0.248173 0.96377 0.246708 0.971434 0.266214 0.948554 0.235961 0.955224 0.234835 0.896396 0.245174 0.886107 0.251776 0.887306 0.25714 0.901578 0.253513 0.893935 0.234459 0.893306 0.241625 0.88488 0.259333 0.895682 0.256287 0.898524 0.274248 0.887363 0.275119 0.885952 0.26722 0.897217 0.265981 0.888292 0.284017 0.899782 0.283788 0.893557 0.224473 0.903384 0.244263 0.904117 0.226402 0.909834 0.245212 0.898452 0.232315 0.90536 0.242289 0.914901 0.24109 0.908475 0.23147 0.912117 0.251402 0.92111 0.249824 0.905103 0.223634 0.894105 0.223477 0.891627 0.223783 0.892209 0.224715 0.894785 0.217728 0.904032 0.218825 0.905292 0.26092 0.916745 0.259188 0.925679 0.257542 0.919312 0.270264 0.927598 0.269904 0.909165 0.270372 0.922229 0.248254 0.923018 0.231732 0.931448 0.236491 0.927474 0.250713 0.939132 0.243721 0.931475 0.252998 0.941395 0.236759 0.941774 0.24318 0.951181 0.24757 0.953028 0.242625 0.943442 0.249961 0.949719 0.251412 0.932269 0.241398 0.935522 0.24909 0.930136 0.234395 0.929446 0.228394 0.942151 0.230847 0.942787 0.227016 0.929372 0.224433 0.954848 0.237908 0.922857 0.256527 0.927955 0.258098 0.929776 0.270263 0.925166 0.269641 0.93313 0.259066 0.935431 0.270899 0.938091 0.256867 0.945703 0.257403 0.953024 0.257866 0.948714 0.269472 0.957575 0.269677 0.940805 0.269454 0.944953 0.253898 0.950208 0.269278 0.961307 0.253711 0.957956 0.256418 0.964661 0.269455 0.96896 0.268209 0.902892 0.249987 0.897745 0.228849 0.908596 0.231834 0.912735 0.252197 0.897122 0.224227 0.89485 0.22181 0.90624 0.226903 0.908607 0.228742 0.903082 0.242361 0.906809 0.256103 0.917237 0.255133 0.919494 0.264606 0.908311 0.265315 0.907454 0.269025 0.916487 0.269043 0.911531 0.283044 0.919593 0.2829 0.909419 0.273405 0.911476 0.28336 0.920571 0.273041 0.922157 0.283218 0.922114 0.255039 0.920062 0.238863 0.921052 0.234472 0.923775 0.23538 0.929369 0.253983 0.934895 0.263753 0.927988 0.282737 0.92516 0.269608 0.937386 0.272947 0.938515 0.283177 0.906903 0.269654 0.905634 0.25451 0.912156 0.254648 0.915624 0.269303 0.934262 0.269581 0.931993 0.256855 0.928513 0.24901 0.928512 0.223212 0.917128 0.220406 0.916725 0.220767 0.9041 0.217973 0.914088 0.228391 0.916363 0.246441 0.918617 0.23227 0.923487 0.240784 0.938248 0.22777 0.892821 0.216321 0.844542 0.206031 0.874322 0.212263 0.870581 0.286403 0.864795 0.285932 0.877377 0.285736 0.887924 0.285532 0.898823 0.285311 0.908672 0.285115 0.917425 0.284957 0.921216 0.269224 0.922914 0.284906 0.926665 0.284912 0.930758 0.284928 0.936388 0.28496 0.952837 0.284936 0.967867 0.284724 0.971593 0.266723 0.976556 0.284338 0.976161 0.284497 0.973686 0.284223 0.968029 0.284169 0.960033 0.284154 0.950775 0.284138 0.942494 0.284121 0.936182 0.284123 0.929809 0.284158 0.920968 0.284223 0.910111 0.284292 0.952943 0.272204 0.950019 0.262148 0.953976 0.282879 0.900909 0.229617 0.889642 0.217102 0.912068 0.234085 0.913562 0.243735 0.925227 0.239763 0.92311 0.245509 0.916786 0.225007 0.940372 0.24984 0.963568 0.250138 0.888081 0.264217 0.918118 0.254988 0.844126 0.209259 0.844951 0.221286 0.886769 0.216308 0.872985 0.215718 0.879346 0.309871 0.875833 0.306046 0.875654 0.308144 0.879007 0.306407 0.876295 0.294136 0.878977 0.293033 0.879812 0.300399 0.876175 0.301094 0.880254 0.30345 0.882198 0.297454 0.893175 0.297687 0.865817 0.349629 0.859181 0.350621 0.872916 0.327332 0.880252 0.326495 0.865713 0.330422 0.852822 0.359205 0.869257 0.322943 0.877097 0.301439 0.864055 0.301093 0.852819 0.327816 0.866118 0.317194 0.872679 0.31623 0.865658 0.301152 0.871305 0.301562 0.879516 0.300927 0.881998 0.315802 0.888262 0.347411 0.878301 0.348969 0.888479 0.326114 0.897047 0.325511 0.857019 0.363938 0.860381 0.359999 0.874655 0.358691 0.872015 0.364197 0.888629 0.3558 0.886097 0.359632 0.872907 0.361011 0.858128 0.36229 0.881706 0.320824 0.862423 0.349295 0.875903 0.346079 0.888714 0.341972 0.893556 0.318638 0.898554 0.296744 0.887564 0.300041 0.888147 0.300674 0.898715 0.300283 0.89883 0.31539 0.89048 0.315686 0.894383 0.353795 0.894065 0.354129 0.890921 0.356254 0.942171 0.318343 0.9529 0.304272 0.949521 0.305533 0.937705 0.320863 0.937122 0.30759 0.931259 0.318903 0.955735 0.293528 0.951772 0.293299 0.940544 0.294181 0.964624 0.302435 0.972337 0.302695 0.965634 0.321964 0.957594 0.320997 0.957663 0.333351 0.950951 0.332759 0.897685 0.323309 0.904388 0.314564 0.887892 0.312338 0.888936 0.316243 0.699423 0.809253 0.710111 0.860044 0.769921 0.8588 0.767468 0.81472 0.651885 0.801109 0.669688 0.860514 0.732293 0.902975 0.706453 0.911484 0.776292 0.895678 0.708787 0.707777 0.699329 0.757062 0.768846 0.767772 0.772602 0.721954 0.664887 0.686395 0.650433 0.740512 0.747107 0.630497 0.725753 0.664868 0.777288 0.6804 0.781693 0.64616 0.725318 0.609127 0.692228 0.642648 0.80056 0.5994 0.770358 0.607692 0.782072 0.622983 0.800562 0.614675 0.800928 0.579073 0.761234 0.587309 0.833192 0.607478 0.861399 0.630223 0.8843 0.609231 0.843136 0.586725 0.8212 0.622722 0.826645 0.645961 0.901226 0.710448 0.884907 0.6659 0.835069 0.680418 0.840872 0.722297 0.945964 0.693526 0.920299 0.645594 0.905039 0.812825 0.908209 0.760544 0.842467 0.768423 0.840209 0.815454 0.952947 0.809219 0.957487 0.749588 0.876198 0.901993 0.893705 0.861459 0.836187 0.859175 0.832541 0.895317 0.904659 0.909742 0.934213 0.864462 0.810883 0.940213 0.850482 0.929308 0.832833 0.919627 0.808275 0.929049 0.815494 0.955807 0.865735 0.940277 0.767163 0.931342 0.781069 0.920572 0.878641 0.308129 0.757688 0.947696 0.89571 0.326063 0.896265 0.333541 0.887647 0.308911 0.896958 0.311973 0.898883 0.293285 0.897963 0.301935 0.887703 0.301029 0.887878 0.29293 0.905567 0.324686 0.896731 0.344468 0.906991 0.342485 0.911791 0.324251 0.900908 0.335596 0.911043 0.336295 0.917143 0.326675 0.907054 0.325968 0.923285 0.31808 0.915184 0.316034 0.908088 0.344187 0.897103 0.344536 0.894607 0.344154 0.895142 0.343144 0.898106 0.350443 0.90726 0.349181 0.907871 0.308374 0.918398 0.309598 0.927049 0.310818 0.928305 0.298442 0.920004 0.298182 0.909927 0.298243 0.924036 0.321254 0.929162 0.318872 0.933826 0.332572 0.925629 0.337191 0.941158 0.32555 0.933051 0.316658 0.943727 0.330971 0.955075 0.325269 0.952983 0.320359 0.943791 0.324629 0.951332 0.316568 0.945126 0.31796 0.937248 0.318798 0.934373 0.326359 0.932584 0.333273 0.932192 0.3393 0.932318 0.343421 0.945607 0.340893 0.944776 0.336887 0.957129 0.33006 0.924262 0.313255 0.925922 0.300164 0.930502 0.299579 0.929283 0.311724 0.936126 0.298969 0.93441 0.310774 0.939442 0.311396 0.947027 0.310849 0.954323 0.310334 0.958291 0.298597 0.94944 0.298819 0.941532 0.298832 0.946483 0.315703 0.950981 0.300512 0.962811 0.314479 0.969751 0.300159 0.965388 0.298807 0.959326 0.311738 0.904541 0.316598 0.900452 0.33816 0.911146 0.334819 0.914268 0.314088 0.900043 0.343367 0.910827 0.338483 0.909045 0.340214 0.897918 0.345703 0.907714 0.311836 0.905082 0.324826 0.918749 0.311513 0.909052 0.30192 0.920236 0.301846 0.91718 0.297035 0.908155 0.297332 0.909931 0.29344 0.92041 0.293444 0.923496 0.310879 0.922253 0.327378 0.925923 0.331262 0.923469 0.332076 0.930583 0.312153 0.934974 0.302503 0.925817 0.29614 0.93758 0.293425 0.907706 0.300101 0.916398 0.300537 0.913653 0.315103 0.907277 0.314776 0.934984 0.298714 0.933344 0.311407 0.930312 0.318902 0.931529 0.345055 0.919853 0.347075 0.920283 0.347817 0.907379 0.350402 0.918259 0.323025 0.916863 0.340467 0.921166 0.335346 0.925584 0.327014 0.941044 0.340685 0.896265 0.352186 0.847118 0.363087 0.877923 0.355511 0.921992 0.300554 0.972463 0.301867 0.950828 0.303658 0.953466 0.293583 0.892951 0.350759 0.90326 0.337983 0.915596 0.322974 0.91417 0.333036 0.927312 0.326701 0.92504 0.320904 0.919699 0.342662 0.941871 0.316003 0.965254 0.318221 0.889956 0.306147 0.919598 0.314755 0.845891 0.359181 0.847322 0.346695 0.890112 0.35133 0.87636 0.352039 0.950166 0.457401 0.877438 0.456074 0.890333 0.455013 0.891902 0.457826 0.881771 0.45805 0.893433 0.460126 0.885457 0.459788 0.90216 0.458193 0.902038 0.46051 0.902093 0.455956 0.869348 0.456995 0.875073 0.458463 0.870949 0.459563 0.865831 0.459946 0.88002 0.459819 0.876379 0.459992 0.890696 0.462723 0.889158 0.462546 0.893089 0.46287 0.842115 0.409869 0.837426 0.409453 0.838646 0.414482 0.833434 0.414204 0.847163 0.42056 0.840709 0.41957 0.839445 0.430603 0.83503 0.428579 0.852464 0.422383 0.843659 0.433436 0.835601 0.419062 0.830596 0.418889 0.831257 0.427506 0.827802 0.427141 0.876435 0.450731 0.866399 0.449489 0.869211 0.447456 0.878828 0.448367 0.861778 0.461251 0.86329 0.45579 0.869445 0.454182 0.919848 0.462088 0.9244 0.459418 0.936505 0.460001 0.932799 0.462552 0.914853 0.457033 0.912969 0.45878 0.983064 0.742705 0.970242 0.681277 0.978343 0.807461 0.961861 0.871181 0.925 0.920764 0.93957 0.629718 0.896636 0.591965 0.87816 0.953598 0.820182 0.969676 0.849136 0.56846 0.801508 0.561342 0.753635 0.961316 0.693916 0.922274 0.756457 0.570463 0.715065 0.59271 0.62759 0.729278 0.628526 0.797321 0.647916 0.672373 0.648988 0.865355 0.678001 0.627321 0.970524 0.680324 0.983346 0.741752 0.978626 0.806509 0.962143 0.870229 0.925282 0.919811 0.896919 0.591012 0.939853 0.628765 0.878442 0.952645 0.819304 0.969461 0.80179 0.560389 0.849419 0.567507 0.753465 0.960832 0.694447 0.921544 0.715348 0.591757 0.756739 0.569509 0.628808 0.796368 0.627873 0.728326 0.648199 0.671421 0.648584 0.866073 0.678283 0.626368 0.411737 0.936637 0.212659 0.665019 0.175067 0.711347 0.264355 0.628942 0.154113 0.763611 0.154483 0.81452 0.911051 0.461039 0.528987 0.594894 0.945951 0.460521 0.339791 0.607004 0.94197 0.46307 0.896594 0.462992 0.902819 0.462828 0.939147 0.46498 0.588358 0.917245 0.930869 0.464578 0.500784 0.908814 0.937502 0.466649 0.178893 0.855096 0.23388 0.878659 0.317203 0.888741 0.409219 0.897533 0.412456 0.865776 0.413517 0.832907 0.415303 0.797177 0.41903 0.758087 0.424284 0.717135 0.429773 0.675932 0.433166 0.635493 0.431719 0.596003 0.42845 0.560105 0.426262 0.535529 0.166927 0.932027 0.089131 0.90146 0.412839 0.954955 0.280654 0.94225 0.092604 0.643694 0.172265 0.583534 0.034269 0.783775 0.048602 0.713913 0.288973 0.53753 0.047197 0.849027 0.9297 0.466322 0.910929 0.462701 0.429574 0.516361 0.573602 0.514995 0.911763 0.464455 0.904647 0.46452 0.91245 0.466086 0.906026 0.466148 0.920833 0.464349 0.682918 0.980037 0.544365 0.975068 0.92089 0.466118 0.274953 0.94136 0.412382 0.948959 0.078614 0.893197 0.159929 0.926191 0.045546 0.712112 0.029763 0.775258 0.174568 0.589926 0.093871 0.647648 0.286715 0.542233 0.039682 0.837587 0.568016 0.514851 0.425296 0.517534 0.89967 0.464526 0.715649 0.536695 0.89649 0.46445 0.90127 0.466162 0.89793 0.466107 0.92457 0.397524 0.934172 0.397517 0.90196 0.397532 0.543555 0.96576 0.912366 0.397543 0.914428 0.398827 0.902477 0.39881 0.887934 0.397535 0.886084 0.398748 0.939158 0.397548 0.916553 0.401268 0.903345 0.401161 0.918892 0.404595 0.904419 0.40426 0.88377 0.401252 0.880927 0.404722 0.905294 0.428912 0.905488 0.424961 0.912357 0.424967 0.91334 0.429138 0.905906 0.421495 0.911087 0.422154 0.904076 0.437412 0.90478 0.43319 0.913199 0.433998 0.911884 0.43877 0.90321 0.444063 0.903361 0.441071 0.909872 0.442542 0.908067 0.444769 0.902496 0.453271 0.918142 0.453706 0.928783 0.450398 0.93573 0.445715 0.939896 0.439756 0.941415 0.433124 0.940295 0.426582 0.937084 0.420446 0.931618 0.414911 0.921769 0.409549 0.905101 0.407893 0.876573 0.40992 0.866307 0.415598 0.859425 0.421874 0.854503 0.429219 0.846009 0.439206 0.853866 0.435555 0.855666 0.44134 0.849189 0.44441 0.859693 0.44628 0.853635 0.449316 0.859396 0.453185 0.889827 0.45174 0.862926 0.421743 0.859205 0.428005 0.869662 0.416377 0.857993 0.434235 0.859086 0.440054 0.916008 0.412068 0.903601 0.410265 0.918257 0.418305 0.91053 0.415402 0.913091 0.413541 0.921836 0.416936 0.92534 0.416062 0.879532 0.412275 0.931494 0.42114 0.923547 0.422692 0.927682 0.421785 0.926515 0.428111 0.931209 0.427509 0.93512 0.42705 0.936295 0.433481 0.92732 0.434037 0.932331 0.433786 0.925669 0.439922 0.930432 0.440034 0.934525 0.439972 0.912845 0.451737 0.922595 0.449614 0.907361 0.448978 0.915126 0.447877 0.918684 0.448912 0.909842 0.450414 0.901128 0.451294 0.929882 0.445604 0.921412 0.444811 0.925747 0.445329 0.862632 0.44473 0.90791 0.418325 0.914417 0.420366 0.918293 0.424021 0.92059 0.42877 0.920879 0.434155 0.919487 0.439514 0.911345 0.446349 0.90499 0.446728 0.916084 0.443813 0.891421 0.410387 0.891335 0.407994 0.8923 0.404278 0.892667 0.401108 0.892803 0.398753 0.893101 0.397518 0.953337 0.401538 0.958091 0.405199 0.9475 0.399036 0.96186 0.409791 0.964499 0.415028 0.96612 0.420717 0.967305 0.426924 0.967388 0.433074 0.966427 0.438883 0.96451 0.444202 0.961861 0.44894 0.958944 0.453645 0.955428 0.457592 0.951844 0.460785 0.948132 0.463506 0.945008 0.465414 0.9428 0.466896 0.940897 0.39766 0.894646 0.464377 0.893748 0.464327 0.895819 0.465909 0.894732 0.465707 0.898046 0.468336 0.895591 0.467749 0.894211 0.467377 0.894053 0.470321 0.892528 0.469525 0.89702 0.472125 0.906461 0.46806 0.901761 0.468217 0.901883 0.471147 0.906501 0.470456 0.912592 0.467918 0.912253 0.470089 0.920682 0.467923 0.920674 0.470154 0.9293 0.468129 0.929876 0.470181 0.93702 0.468441 0.938213 0.470896 0.942275 0.468514 0.942757 0.470744 0.890006 0.4495 0.852976 0.399065 0.859393 0.397599 0.847065 0.401675 0.84127 0.405026 0.953466 0.401386 0.958188 0.405089 0.947588 0.398916 0.961862 0.409747 0.964391 0.415022 0.965926 0.420729 0.967068 0.426923 0.967242 0.433135 0.966314 0.439008 0.964406 0.444378 0.961584 0.44912 0.958267 0.453722 0.954279 0.457569 0.865611 0.460368 0.870463 0.459645 0.869977 0.459728 0.865391 0.460791 0.875883 0.460032 0.875386 0.460071 0.889107 0.462568 0.889055 0.46259 0.836433 0.409343 0.829542 0.419704 0.832578 0.41403 0.832317 0.414141 0.82924 0.419624 0.86181 0.461905 0.861843 0.46256 0.95053 0.46075 0.946775 0.4634 0.943577 0.465237 0.941527 0.466697 0.893773 0.464335 0.893798 0.464342 0.894526 0.465626 0.894385 0.465571 0.940912 0.397604 0.893807 0.467247 0.893563 0.467166 0.891985 0.469369 0.891535 0.469419 0.940364 0.468392 0.940762 0.470517 0.866236 0.398834 0.873711 0.398813 0.877506 0.397514 0.870971 0.397493 0.865522 0.397455 0.860032 0.398872 0.856026 0.399014 0.861954 0.397568 0.860159 0.397664 0.853853 0.399094 0.935431 0.404681 0.948546 0.405179 0.944496 0.401457 0.931632 0.401375 0.939488 0.398861 0.927974 0.398901 0.870657 0.401504 0.861966 0.401526 0.855096 0.4016 0.850751 0.405417 0.858121 0.405363 0.867731 0.405188 0.850561 0.401575 0.848094 0.401586 0.842791 0.404957 0.845766 0.405198 0.9455 0.398818 0.951158 0.401375 0.955535 0.405156 0.94295 0.41441 0.9536 0.414936 0.951437 0.40979 0.938847 0.409148 0.863906 0.410047 0.854469 0.410101 0.8468 0.410021 0.843291 0.414792 0.850618 0.415218 0.858112 0.415702 0.958875 0.409842 0.961147 0.415077 0.9551 0.420509 0.945887 0.42022 0.947818 0.426423 0.955942 0.426574 0.962495 0.420748 0.963347 0.426902 0.947179 0.438896 0.955415 0.438781 0.95627 0.432802 0.948355 0.432791 0.963455 0.433109 0.96255 0.43901 0.93973 0.449457 0.950281 0.449152 0.953464 0.44429 0.944309 0.444589 0.960647 0.444424 0.957836 0.449233 0.928866 0.456683 0.941589 0.457208 0.946319 0.453375 0.933669 0.453285 0.954103 0.453514 0.949874 0.457416 0.877353 0.455968 0.882269 0.458025 0.892317 0.457757 0.890577 0.455047 0.886684 0.460112 0.89423 0.460211 0.902677 0.460467 0.90267 0.458019 0.902808 0.455334 0.869597 0.456984 0.865825 0.458435 0.871446 0.458982 0.8752 0.458466 0.877063 0.46 0.880928 0.46006 0.889224 0.462652 0.890358 0.462714 0.892541 0.462593 0.841603 0.409572 0.838159 0.409243 0.834209 0.413908 0.837981 0.414182 0.839885 0.419736 0.846514 0.420792 0.834481 0.428371 0.838869 0.430451 0.84343 0.433385 0.852102 0.422532 0.830666 0.418987 0.834732 0.419195 0.827717 0.426976 0.830662 0.427303 0.875777 0.450429 0.878346 0.448288 0.868619 0.446935 0.865577 0.448677 0.860982 0.459109 0.863516 0.455972 0.868771 0.453598 0.919955 0.462087 0.933215 0.46265 0.936971 0.460171 0.92452 0.45941 0.915797 0.455832 0.913434 0.458571 0.911682 0.460937 0.945768 0.460575 0.941689 0.463136 0.897291 0.462545 0.903757 0.462585 0.930828 0.464538 0.938505 0.464915 0.929084 0.466249 0.936418 0.466469 0.911714 0.462545 0.904992 0.464496 0.91226 0.464434 0.906001 0.466171 0.912549 0.466198 0.920438 0.466178 0.920682 0.464371 0.899694 0.464496 0.896238 0.464476 0.897673 0.46607 0.901142 0.46612 0.933851 0.397545 0.924135 0.397565 0.901567 0.397461 0.902111 0.398787 0.913998 0.398826 0.911927 0.397463 0.885568 0.398789 0.887707 0.397486 0.939027 0.397536 0.902897 0.401138 0.916139 0.401275 0.904075 0.404332 0.918631 0.404656 0.883077 0.401373 0.880245 0.404983 0.905419 0.428922 0.912942 0.429219 0.912006 0.425106 0.905474 0.425025 0.910791 0.422281 0.905844 0.421559 0.904305 0.436885 0.911907 0.438227 0.913047 0.433844 0.905052 0.432984 0.903203 0.443238 0.908124 0.443775 0.909903 0.441649 0.903445 0.440313 0.90285 0.452456 0.918742 0.45246 0.929033 0.449192 0.935553 0.444785 0.939489 0.439171 0.940895 0.433027 0.939916 0.426757 0.936762 0.420698 0.931211 0.415109 0.90461 0.407951 0.921344 0.40965 0.876099 0.410269 0.865754 0.416146 0.858856 0.422274 0.85408 0.42925 0.845714 0.439016 0.8487 0.443676 0.855252 0.440105 0.853622 0.434905 0.852614 0.447663 0.858958 0.44511 0.858176 0.451853 0.889824 0.45148 0.858947 0.427844 0.863033 0.422095 0.869857 0.416948 0.858451 0.439034 0.857612 0.433475 0.903128 0.410252 0.915613 0.4122 0.910336 0.415321 0.91773 0.418674 0.921258 0.417307 0.91279 0.413538 0.924944 0.416332 0.879341 0.412694 0.930972 0.4215 0.922517 0.423241 0.926792 0.422268 0.92506 0.428584 0.929895 0.42793 0.93442 0.427304 0.935453 0.433435 0.925801 0.434263 0.930838 0.433902 0.924243 0.439743 0.929152 0.439726 0.933786 0.439455 0.922618 0.448568 0.913071 0.450609 0.91472 0.447235 0.9073 0.44856 0.909883 0.449686 0.918464 0.448158 0.90106 0.450464 0.929479 0.444749 0.920523 0.44435 0.924927 0.444695 0.861743 0.443993 0.907779 0.418347 0.914012 0.420577 0.917709 0.42432 0.919641 0.429082 0.919962 0.434273 0.918588 0.43924 0.904848 0.446138 0.911088 0.445577 0.915514 0.4432 0.890897 0.408138 0.891059 0.410492 0.89188 0.404459 0.892481 0.401195 0.892744 0.398811 0.892774 0.397499 0.852987 0.39915 0.859402 0.397672 0.847027 0.401638 0.84144 0.40503 0.836758 0.409301 0.826856 0.427241 0.893304 0.464316 0.894343 0.465793 0.894093 0.464377 0.895401 0.465971 0.893628 0.467665 0.890751 0.471053 0.897653 0.467915 0.895086 0.467874 0.893376 0.47055 0.896513 0.470318 0.906138 0.467954 0.901291 0.467913 0.900442 0.470186 0.905385 0.470181 0.912382 0.468058 0.911527 0.470316 0.918635 0.470453 0.91977 0.468076 0.926488 0.470872 0.927835 0.468189 0.935282 0.468257 0.935209 0.471328 0.877915 0.500707 0.878197 0.500625 0.878935 0.505269 0.878376 0.50543 0.87849 0.500327 0.879515 0.504678 0.878776 0.499827 0.880077 0.503685 0.879041 0.499148 0.880596 0.502336 0.879273 0.498323 0.88105 0.500691 0.879461 0.49739 0.881414 0.498833 0.879595 0.496393 0.881685 0.496848 0.879673 0.495381 0.881831 0.494834 0.879688 0.4944 0.881855 0.492886 0.879641 0.493495 0.881754 0.491093 0.879517 0.492692 0.881496 0.489502 0.879256 0.49199 0.880966 0.488128 0.878724 0.491679 0.879976 0.487255 0.880441 0.487544 0.878985 0.491764 0.880259 0.509816 0.879427 0.510054 0.881118 0.508941 0.881951 0.507469 0.882719 0.50547 0.883385 0.503037 0.883918 0.500283 0.884295 0.497337 0.884501 0.494341 0.884524 0.491438 0.884373 0.488781 0.883999 0.486461 0.88321 0.484429 0.882394 0.483424 0.882124 0.514208 0.881033 0.51452 0.883251 0.513061 0.884343 0.511133 0.885349 0.508513 0.886222 0.505324 0.886921 0.501715 0.887414 0.497854 0.887677 0.493924 0.887702 0.490113 0.887496 0.486645 0.88698 0.48361 0.885938 0.48091 0.884878 0.479558 0.884506 0.51838 0.88317 0.518762 0.885883 0.516979 0.887217 0.514621 0.888447 0.511419 0.889514 0.507521 0.890369 0.503109 0.890971 0.49839 0.891293 0.493586 0.89132 0.488919 0.891054 0.484665 0.890395 0.481066 0.88919 0.477958 0.887817 0.476052 0.887367 0.522273 0.885807 0.522719 0.888975 0.520637 0.890533 0.517885 0.891968 0.514147 0.893214 0.509596 0.894212 0.504446 0.894915 0.498938 0.895291 0.493329 0.895322 0.487882 0.895 0.482915 0.894205 0.478779 0.892842 0.475169 0.891068 0.473073 0.890668 0.525829 0.888906 0.526332 0.892483 0.523982 0.894241 0.520876 0.895861 0.516656 0.897267 0.51152 0.898394 0.505707 0.899187 0.499489 0.899612 0.493158 0.899646 0.487009 0.899286 0.481354 0.898411 0.476638 0.894359 0.528996 0.892421 0.529549 0.896354 0.526965 0.898288 0.52355 0.900069 0.518911 0.901615 0.513263 0.902854 0.506872 0.903726 0.500036 0.904193 0.493075 0.904231 0.486314 0.903834 0.4801 0.902975 0.47504 0.898388 0.531728 0.896302 0.532323 0.900534 0.529543 0.902614 0.525869 0.904531 0.520877 0.906194 0.514801 0.907527 0.507925 0.908466 0.50057 0.908967 0.493081 0.909009 0.485806 0.908572 0.479151 0.907654 0.473824 0.902694 0.533986 0.900491 0.534614 0.90496 0.531679 0.907157 0.527799 0.909181 0.522528 0.910937 0.516111 0.912345 0.50885 0.913336 0.501084 0.913866 0.493175 0.913909 0.485494 0.91346 0.478418 0.912585 0.472851 0.907215 0.535736 0.904927 0.536388 0.909569 0.53334 0.91185 0.529311 0.913952 0.523838 0.915776 0.517175 0.917237 0.509635 0.918266 0.50157 0.918854 0.493342 0.918947 0.485357 0.91844 0.478006 0.91787 0.471971 0.914263 0.537286 0.911914 0.537955 0.916678 0.534827 0.919019 0.530693 0.921175 0.525076 0.923047 0.518239 0.924546 0.510502 0.925585 0.502224 0.926227 0.493754 0.926493 0.485583 0.925762 0.478045 0.924764 0.471485 0.921403 0.537724 0.919062 0.538392 0.92381 0.535275 0.926142 0.531156 0.930338 0.525761 0.93162 0.519674 0.933283 0.512932 0.932692 0.502839 0.933977 0.494768 0.934333 0.486371 0.933206 0.478784 0.931863 0.472204 0.92611 0.537268 0.92382 0.53792 0.928464 0.534872 0.932388 0.530343 0.937335 0.506755 0.941235 0.498334 0.941521 0.487989 0.940371 0.480184 0.938481 0.473907 0.930691 0.536256 0.928485 0.536884 0.934789 0.533043 0.935078 0.534703 0.932989 0.535298 0.938368 0.532576 0.947164 0.489068 0.947066 0.497764 0.946239 0.481893 0.944283 0.476284 0.939209 0.532632 0.937267 0.533185 0.941919 0.530982 0.950689 0.490156 0.950271 0.497772 0.95034 0.48345 0.948203 0.478162 0.943023 0.530074 0.941256 0.530577 0.945589 0.528338 0.95349 0.491089 0.952472 0.498024 0.953154 0.485389 0.951415 0.480527 0.946464 0.527065 0.944898 0.52751 0.948879 0.525086 0.955336 0.498108 0.955494 0.49227 0.955142 0.488211 0.954263 0.484425 0.949389 0.475505 0.954052 0.482326 0.94757 0.475109 0.945693 0.473082 0.943613 0.471998 0.950577 0.521636 0.949187 0.522238 0.951775 0.520708 0.950886 0.519379 0.952605 0.518141 0.95447 0.515316 0.952742 0.516616 0.878125 0.495997 0.943537 0.514246 0.944979 0.511457 0.945299 0.511731 0.944004 0.514141 0.946866 0.510467 0.945612 0.512005 0.946775 0.509925 0.944125 0.524447 0.943125 0.523168 0.943363 0.52176 0.944265 0.522893 0.943213 0.51865 0.9436 0.520352 0.942839 0.519741 0.942465 0.520831 0.942508 0.517563 0.943036 0.516979 0.944472 0.514036 0.943564 0.516394 0.946664 0.509365 0.948503 0.507957 0.948316 0.508687 0.949207 0.508705 0.948096 0.509397 0.949608 0.50791 0.950009 0.507096 0.951195 0.506751 0.950679 0.507606 0.951005 0.508659 0.950161 0.508443 0.951647 0.507843 0.952323 0.510866 0.951744 0.509448 0.952587 0.5089 0.953318 0.510638 0.952296 0.507042 0.953444 0.508317 0.954198 0.510416 0.954069 0.512878 0.953344 0.512779 0.95222 0.51488 0.952538 0.512757 0.952777 0.515115 0.953314 0.515413 0.952001 0.51802 0.951641 0.517475 0.949848 0.518868 0.951263 0.516984 0.950071 0.519673 0.950291 0.520481 0.948367 0.522605 0.94826 0.52146 0.946642 0.521256 0.948152 0.520315 0.946704 0.522693 0.946766 0.524131 0.94537 0.524785 0.945389 0.52319 0.944404 0.521338 0.945409 0.521595 0.948517 0.508521 0.947425 0.509189 0.946164 0.510225 0.943731 0.513771 0.942852 0.515989 0.942484 0.51808 0.944874 0.511783 0.950283 0.508511 0.949456 0.508269 0.942699 0.51973 0.943487 0.520694 0.951552 0.510694 0.95099 0.509314 0.944633 0.521012 0.946034 0.520645 0.951461 0.514432 0.951791 0.512457 0.947604 0.519694 0.949207 0.518265 0.95053 0.516413 0.954352 0.507334 0.955064 0.51004 0.953029 0.50566 0.954691 0.513093 0.953563 0.516187 0.942931 0.511155 0.945738 0.50837 0.941124 0.514785 0.948237 0.525023 0.946042 0.527051 0.950358 0.522206 0.940778 0.525984 0.939919 0.523165 0.942236 0.527579 0.940031 0.519157 0.94836 0.506655 0.95038 0.505668 0.951792 0.505283 0.952106 0.519194 0.94408 0.527997 0.955136 0.505085 0.955458 0.508799 0.953996 0.503048 0.954947 0.51289 0.953571 0.516724 0.940392 0.509704 0.943959 0.505926 0.937487 0.514053 0.946965 0.527152 0.943743 0.529685 0.949863 0.52392 0.936263 0.528363 0.934831 0.524989 0.938515 0.530358 0.93544 0.520327 0.947235 0.504116 0.949823 0.503295 0.952034 0.502955 0.951882 0.52041 0.941028 0.53079 0.956255 0.501869 0.956376 0.507194 0.955436 0.512282 0.95378 0.516679 0.954272 0.512902 0.953969 0.514386 0.955477 0.513065 0.955509 0.511632 0.956562 0.510151 0.957541 0.50583 0.957528 0.506237 0.957401 0.500104 0.957323 0.498901 0.956684 0.496896 0.956413 0.492938 0.956425 0.492794 0.955922 0.48933 0.955605 0.489791 0.952251 0.480529 0.95403 0.483685 0.955302 0.484788 0.955335 0.486204 0.955539 0.486154 0.954877 0.485325 0.956687 0.508947 0.956754 0.495687 0.955045 0.487387 0.877848 0.505182 0.877652 0.500582 0.87737 0.504506 0.877412 0.500243 0.876974 0.503437 0.877218 0.499703 0.87668 0.502023 0.877063 0.498994 0.876501 0.50033 0.876979 0.498142 0.876446 0.498438 0.87696 0.497191 0.876522 0.496436 0.877006 0.496186 0.876728 0.49442 0.877115 0.495174 0.877054 0.492488 0.877281 0.494204 0.877479 0.49073 0.877498 0.49332 0.877999 0.489197 0.877767 0.492546 0.878719 0.487808 0.878144 0.491879 0.879235 0.487423 0.878402 0.491725 0.878643 0.509686 0.877934 0.508686 0.877348 0.507101 0.876912 0.505005 0.876647 0.502497 0.876565 0.499694 0.876669 0.496727 0.876956 0.493734 0.877416 0.490859 0.878045 0.488251 0.878803 0.485988 0.879891 0.48389 0.880652 0.483253 0.880004 0.514038 0.879075 0.512727 0.878307 0.510649 0.877736 0.507903 0.877388 0.504616 0.87728 0.500942 0.877417 0.497054 0.877793 0.493132 0.878389 0.48936 0.879214 0.485947 0.880199 0.482989 0.881623 0.480314 0.882641 0.479405 0.881911 0.518172 0.880775 0.516569 0.879836 0.51403 0.879138 0.510673 0.878713 0.506655 0.878582 0.502165 0.878749 0.497412 0.879208 0.492618 0.879955 0.488021 0.881001 0.483899 0.88231 0.480367 0.883909 0.47731 0.885135 0.475926 0.884336 0.52203 0.883011 0.520159 0.881915 0.517195 0.8811 0.513276 0.880604 0.508586 0.88045 0.503344 0.880646 0.497795 0.881181 0.492199 0.882059 0.48684 0.883257 0.482017 0.884772 0.477872 0.886828 0.474331 0.888116 0.472377 0.887245 0.525554 0.885749 0.523442 0.884512 0.520096 0.883592 0.515673 0.883032 0.510379 0.882858 0.504462 0.883079 0.498199 0.883683 0.491882 0.884656 0.485819 0.885976 0.480334 0.887771 0.475644 0.888962 0.472096 0.890594 0.528694 0.888949 0.526372 0.887589 0.522693 0.886578 0.51783 0.885962 0.512009 0.885771 0.505504 0.886014 0.498617 0.886678 0.491672 0.887734 0.484992 0.889161 0.478945 0.891005 0.474124 0.894335 0.531403 0.892565 0.528905 0.891102 0.524947 0.890014 0.519714 0.889351 0.513452 0.889146 0.506453 0.889407 0.499043 0.890122 0.491571 0.891258 0.484384 0.892815 0.477978 0.894695 0.473363 0.898413 0.533643 0.896544 0.531004 0.894999 0.526825 0.89385 0.5213 0.893151 0.514687 0.892934 0.507295 0.893209 0.499472 0.893965 0.491581 0.895164 0.483992 0.89686 0.477387 0.898865 0.473076 0.902769 0.53538 0.900829 0.53264 0.899224 0.5283 0.898031 0.522562 0.897305 0.515695 0.897079 0.50802 0.897366 0.499895 0.89815 0.491701 0.899396 0.483821 0.901449 0.477074 0.903819 0.472976 0.909699 0.53692 0.907707 0.534109 0.906061 0.529655 0.904836 0.523767 0.904091 0.516721 0.90386 0.508844 0.904153 0.500507 0.904958 0.492099 0.906237 0.484012 0.908008 0.477129 0.910034 0.473198 0.916854 0.53736 0.91487 0.534559 0.91323 0.530122 0.914164 0.524465 0.913164 0.518196 0.913437 0.51134 0.91133 0.50108 0.912131 0.492703 0.913405 0.484646 0.91513 0.47783 0.916994 0.473623 0.92166 0.536911 0.919719 0.534172 0.91917 0.529284 0.917172 0.505296 0.919838 0.496406 0.920904 0.486229 0.92238 0.479225 0.924263 0.474614 0.926405 0.535913 0.924828 0.532245 0.931019 0.534378 0.929686 0.53188 0.92797 0.487724 0.927599 0.495894 0.929366 0.480734 0.931925 0.475167 0.935435 0.53233 0.934387 0.530379 0.933232 0.488977 0.932764 0.496065 0.934736 0.482159 0.937602 0.476887 0.93959 0.529799 0.938848 0.527798 0.937731 0.490249 0.936964 0.496523 0.939215 0.484123 0.942421 0.479379 0.943421 0.526821 0.942722 0.524593 0.94207 0.497013 0.942329 0.491435 0.943599 0.487511 0.946933 0.482758 0.949756 0.480976 0.945342 0.476815 0.940652 0.473783 0.947564 0.521395 0.9466 0.520277 0.951324 0.514898 0.949518 0.517928 0.928377 0.510114 0.926885 0.51291 0.927854 0.512845 0.929178 0.51043 0.92998 0.510746 0.931406 0.509225 0.930823 0.508639 0.92835 0.521984 0.930534 0.523359 0.930891 0.521821 0.928964 0.520607 0.929579 0.519229 0.928441 0.517467 0.927597 0.51852 0.926179 0.516255 0.926753 0.519573 0.927195 0.51571 0.928211 0.515165 0.928823 0.512781 0.932374 0.506682 0.930239 0.508053 0.932657 0.507439 0.93294 0.508196 0.934517 0.507536 0.93451 0.506707 0.936567 0.505592 0.934502 0.505878 0.936317 0.506456 0.936067 0.50732 0.937546 0.507578 0.93807 0.506748 0.938901 0.508422 0.940036 0.50988 0.941088 0.509726 0.939772 0.507879 0.940713 0.507314 0.938594 0.505926 0.942911 0.511998 0.942269 0.509491 0.941755 0.511888 0.940774 0.511818 0.940867 0.513981 0.941724 0.514237 0.941696 0.517149 0.942674 0.514592 0.940898 0.516619 0.940099 0.51609 0.938667 0.517973 0.939267 0.518807 0.937547 0.521739 0.939868 0.519641 0.937153 0.52057 0.936759 0.519402 0.934851 0.520311 0.935057 0.52176 0.932933 0.523788 0.935263 0.523209 0.932985 0.522196 0.933038 0.520604 0.931248 0.520284 0.932573 0.508007 0.934161 0.507367 0.930964 0.509008 0.927841 0.514787 0.928411 0.512543 0.928106 0.516928 0.929515 0.510546 0.935671 0.507169 0.937081 0.507438 0.929093 0.51864 0.93071 0.519671 0.938351 0.508298 0.9394 0.509723 0.932552 0.520045 0.934434 0.519715 0.940079 0.511519 0.940113 0.513519 0.936336 0.518792 0.938116 0.517377 0.939405 0.515521 0.943638 0.508965 0.941943 0.506311 0.939071 0.504531 0.94388 0.51543 0.944335 0.512165 0.927944 0.506963 0.925069 0.509715 0.923231 0.513349 0.935271 0.526189 0.938229 0.524222 0.940839 0.521447 0.923484 0.521848 0.925731 0.524779 0.928789 0.526502 0.922597 0.517761 0.93396 0.504385 0.931029 0.505302 0.936534 0.504088 0.942769 0.518413 0.932116 0.527039 0.945351 0.507568 0.943089 0.503744 0.939896 0.502018 0.945354 0.516015 0.946118 0.511811 0.925289 0.504712 0.920962 0.50815 0.918385 0.51252 0.934537 0.528948 0.938552 0.526478 0.941809 0.523283 0.918305 0.523665 0.921702 0.527196 0.925959 0.529352 0.917212 0.518867 0.933078 0.501722 0.929349 0.502508 0.936447 0.501609 0.943896 0.519878 0.930309 0.529931 0.948005 0.505607 0.944871 0.499392 0.947806 0.516062 0.9491 0.511191 0.953215 0.511264 0.952698 0.512701 0.951135 0.50884 0.950868 0.504414 0.946032 0.497811 0.946155 0.49879 0.9504 0.504692 0.944108 0.496015 0.944681 0.492183 0.945966 0.489086 0.945497 0.488606 0.944291 0.491984 0.951345 0.48426 0.948386 0.485293 0.952907 0.485943 0.952013 0.507755 0.944606 0.494766 0.94856 0.486751 0.889967 0.448966 0.879572 0.4873 0.878531 0.491695 0.881189 0.483034 0.883359 0.479059 0.88597 0.475436 0.826451 0.427416 0.889758 0.472115 0.881748 0.482959 0.884054 0.478968 0.886811 0.475429 0.942835 0.472365 0.877975 0.397658 0.883515 0.397651 0.873951 0.397664 0.870831 0.397671 0.867889 0.397674 0.918562 0.397639 0.925482 0.397634 0.901603 0.397646 0.909465 0.397642 0.891034 0.397645 0.929288 0.397637 0.894812 0.397645 0.931273 0.397662 0.86549 0.397668 0.931235 0.397655 0.882529 0.39765 0.877003 0.397658 0.871595 0.397671 0.868659 0.397671 0.868707 0.397667 0.925845 0.397644 0.918784 0.397657 0.909614 0.397666 0.901249 0.39767 0.890498 0.397656 0.92961 0.397643 0.894099 0.397656 0.867711 0.397671 0.900103 0.397679 0.595916 0.679782 0.593633 0.724091 0.587548 0.772055 0.579229 0.819401 0.570764 0.860428 0.56898 0.893979 0.055194 0.327681 0.056512 0.244825 0.056323 0.176259 0.056343 0.11532 0.057144 0.041836 0.468306 0.320445 0.459246 0.232082 0.470583 0.402538 0.456894 0.171519 0.044392 0.51728 0.04804 0.442488 0.039555 0.560029 0.472222 0.467543 0.655545 0.572596 0.685594 0.967391 0.590033 0.92387 0.595756 0.680499 0.590769 0.76975 0.682275 0.551691 0.647404 0.965201 0.571758 0.851938 0.600135 0.64164 0.623018 0.605621 0.617347 0.944413 0.720327 0.535205 + + + + + + + + + + + + + + + 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 4 4 4 5 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 4 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 4 4 4 5 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 4 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 +

89 0 23 243 1 26 90 2 28 6 3 29 91 4 30 243 1 26 89 0 23 5 5 31 92 6 33 244 7 35 91 4 30 5 5 31 299 8 36 244 7 35 92 6 33 218 9 37 7 10 39 95 11 41 93 12 42 8 13 57 93 12 42 95 11 41 94 14 61 9 15 62 96 16 65 245 17 66 89 0 23 6 3 29 89 0 23 245 17 66 97 18 67 5 5 31 97 18 67 245 17 66 98 19 68 11 20 69 98 19 68 245 17 66 96 16 65 10 21 70 97 18 67 246 22 71 92 6 33 5 5 31 92 6 33 246 22 71 300 23 72 218 9 37 300 23 72 246 22 71 99 24 84 219 25 85 99 24 84 246 22 71 97 18 67 11 20 69 12 26 86 247 27 89 93 12 42 9 15 62 93 12 42 247 27 89 100 28 90 8 13 57 13 29 135 102 30 137 101 31 138 14 32 139 101 31 138 102 30 137 7 10 39 8 13 57 103 33 140 248 34 141 98 19 68 10 21 70 98 19 68 248 34 141 104 35 142 11 20 69 104 35 142 248 34 141 105 36 200 16 37 246 105 36 200 248 34 141 103 33 140 15 38 249 100 28 90 107 39 252 101 31 138 8 13 57 101 31 138 107 39 252 106 40 253 14 32 139 108 41 254 109 42 256 13 29 135 14 32 139 18 43 259 109 42 256 108 41 254 17 44 260 106 40 253 111 45 262 108 41 254 14 32 139 108 41 254 111 45 262 110 46 265 17 44 260 20 47 266 112 48 283 113 49 285 19 50 286 113 49 285 112 48 283 18 43 259 17 44 260 110 46 265 115 51 289 113 49 285 17 44 260 113 49 285 115 51 289 114 52 290 19 50 286 22 53 291 116 54 292 117 55 293 21 56 294 117 55 293 116 54 292 20 47 266 19 50 286 114 52 290 119 57 295 117 55 293 19 50 286 117 55 293 119 57 295 118 58 296 21 56 294 23 59 297 249 60 298 120 61 300 24 62 303 120 61 300 249 60 298 22 53 291 21 56 294 118 58 296 122 63 304 120 61 300 21 56 294 120 61 300 122 63 304 121 64 884 24 62 303 26 65 885 339 66 886 340 67 887 123 68 888 123 68 888 340 67 887 341 69 889 28 70 890 341 69 889 340 67 887 124 71 891 27 72 892 124 71 891 340 67 887 339 66 886 25 73 893 125 74 894 250 75 895 307 76 896 29 77 897 307 76 896 250 75 895 126 78 898 227 79 899 126 78 898 250 75 895 123 68 888 28 70 890 123 68 888 250 75 895 125 74 894 26 65 885 126 78 898 127 80 900 45 81 901 227 79 899 126 78 898 28 70 890 30 82 902 127 80 900 128 83 0 251 84 1 308 85 2 31 86 3 308 85 74 251 84 75 129 87 76 228 88 77 129 87 76 251 84 75 130 89 78 33 90 79 130 89 4 251 84 1 128 83 0 32 91 12 131 92 13 252 93 14 309 94 15 34 95 16 309 94 15 252 93 14 128 83 0 31 86 3 128 83 0 252 93 14 132 96 17 32 91 12 132 96 17 252 93 14 131 92 13 35 97 18 133 98 82 253 99 83 132 96 17 35 97 18 132 96 17 253 99 83 134 100 91 32 91 12 134 100 91 253 99 83 156 101 92 36 102 93 156 101 92 253 99 83 133 98 82 38 103 94 135 104 96 254 105 97 136 106 98 39 107 101 136 106 98 254 105 97 137 108 102 37 109 105 137 108 102 254 105 97 133 98 82 35 97 18 133 98 82 254 105 97 135 104 96 38 103 94 104 35 142 255 110 903 99 24 84 11 20 69 99 24 84 255 110 903 310 111 904 219 25 85 310 111 904 255 110 903 138 112 905 1978 113 906 138 112 905 255 110 903 104 35 142 16 37 246 204 114 5 285 115 6 139 116 7 59 117 8 139 116 7 285 115 6 203 118 9 57 119 10 105 36 200 256 120 907 140 121 908 16 37 246 140 121 908 256 120 907 135 104 909 39 107 910 135 104 909 256 120 907 141 122 911 38 103 912 141 122 911 256 120 907 105 36 200 15 38 249 138 112 905 257 123 913 142 124 914 1978 113 906 142 124 914 257 123 913 154 125 915 229 126 916 154 125 915 257 123 913 140 121 908 39 107 910 140 121 908 257 123 913 138 112 905 16 37 246 143 127 11 284 128 19 202 129 20 60 130 21 203 118 9 284 128 19 143 127 11 57 119 10 144 131 917 56 132 918 2065 133 919 2066 134 920 311 135 921 258 136 922 125 74 894 29 77 897 125 74 894 258 136 922 145 137 923 26 65 885 145 137 80 258 136 81 146 138 95 40 139 99 146 138 95 258 136 81 311 135 100 41 140 103 43 141 924 147 142 925 148 143 926 42 144 927 148 143 926 147 142 925 23 59 297 24 62 303 149 145 928 259 146 929 124 71 891 25 73 893 124 71 891 259 146 929 150 147 976 27 72 892 150 147 976 259 146 929 147 142 925 43 141 924 147 142 925 259 146 929 149 145 928 23 59 297 121 64 884 152 148 978 148 143 926 24 62 303 148 143 926 152 148 978 151 149 980 42 144 927 231 150 981 30 82 902 28 70 890 341 69 889 231 150 981 341 69 889 27 72 892 44 151 982 153 152 104 260 153 106 129 87 76 33 90 79 129 87 76 260 153 106 312 154 107 228 88 77 312 154 107 260 153 106 146 138 95 41 140 103 146 138 95 260 153 106 153 152 104 40 139 99 154 125 110 261 155 111 313 156 112 229 126 113 313 156 112 261 155 111 155 157 114 230 158 115 155 157 114 261 155 111 136 106 98 37 109 105 136 106 98 261 155 111 154 125 110 39 107 101 153 152 104 262 159 108 181 160 109 40 139 99 181 160 116 262 159 117 134 100 91 36 102 93 134 100 91 262 159 117 130 89 4 32 91 12 130 89 78 262 159 108 153 152 104 33 90 79 137 108 102 263 161 118 155 157 114 37 109 105 155 157 114 263 161 118 314 162 119 230 158 115 314 162 119 263 161 118 131 92 13 34 95 16 131 92 13 263 161 118 137 108 102 35 97 18 151 149 980 241 163 983 157 164 985 42 144 927 157 164 985 241 163 983 242 165 987 83 166 1012 159 167 1013 264 168 1016 160 169 1017 44 151 982 160 169 1017 264 168 1016 239 170 1018 81 171 1019 239 170 1018 264 168 1016 238 172 1020 82 173 1023 238 172 1020 264 168 1016 159 167 1013 43 141 924 82 173 1023 238 172 1020 157 164 985 83 166 1012 157 164 985 238 172 1020 43 141 924 42 144 927 160 169 1017 265 174 1036 231 150 981 44 151 982 231 150 981 265 174 1036 232 175 1038 30 82 902 232 175 1038 265 174 1036 237 176 1039 80 177 1040 237 176 1039 265 174 1036 160 169 1017 81 171 1019 94 14 61 163 178 1041 164 179 1042 9 15 62 165 180 1043 266 181 1045 166 182 1046 46 183 1047 166 182 1046 266 181 1045 163 178 1041 94 14 61 90 2 28 288 184 1048 207 185 1049 6 3 29 164 179 1042 167 186 1050 12 26 86 9 15 62 166 182 1046 267 187 1051 168 188 1052 46 183 1047 168 188 1052 267 187 1051 169 189 1053 47 190 1054 169 189 1053 267 187 1051 95 11 41 7 10 39 95 11 41 267 187 1051 166 182 1046 94 14 61 207 185 1049 287 191 1055 96 16 65 6 3 29 96 16 65 287 191 1055 206 192 1056 10 21 70 170 193 22 268 194 2246 171 195 24 63 196 25 171 195 24 268 194 2246 172 197 2247 58 198 27 172 197 1057 268 194 1058 173 199 1059 64 200 1060 173 199 1059 268 194 1058 170 193 1061 62 201 1062 172 197 2247 269 202 2248 174 203 32 58 198 27 174 203 32 269 202 2248 175 204 2249 61 205 34 175 204 1063 269 202 1064 176 206 1065 65 207 1066 176 206 1065 269 202 1064 172 197 1057 64 200 1060 175 204 2249 270 208 2250 177 209 38 61 205 34 177 209 38 270 208 2250 178 210 2251 66 211 40 178 210 1067 270 208 1068 179 212 1069 67 213 1070 179 212 1069 270 208 1068 175 204 1063 65 207 1066 180 214 1071 271 215 1072 149 145 928 25 73 893 149 145 928 271 215 1072 249 60 298 23 59 297 249 60 298 271 215 1072 48 216 1073 22 53 291 150 147 976 159 167 1013 44 151 982 27 72 892 159 167 1013 150 147 976 43 141 924 48 216 1073 272 217 1074 116 54 292 22 53 291 116 54 292 272 217 1074 49 218 1075 20 47 266 49 218 1075 273 219 1076 112 48 283 20 47 266 112 48 283 273 219 1076 50 220 1077 18 43 259 50 220 1077 274 221 1078 109 42 256 18 43 259 109 42 256 274 221 1078 51 222 1079 13 29 135 169 189 1053 275 223 1080 52 224 1081 47 190 1054 51 222 1079 275 223 1080 102 30 137 13 29 135 102 30 137 275 223 1080 169 189 1053 7 10 39 206 192 1056 286 225 1082 103 33 140 10 21 70 103 33 140 286 225 1082 53 226 1083 15 38 249 53 226 1083 276 227 1084 141 122 911 15 38 249 141 122 911 276 227 1084 54 228 1085 38 103 912 156 101 1086 277 229 1087 55 230 1088 36 102 1089 54 228 1085 277 229 1087 156 101 1086 38 103 912 55 230 1088 182 231 1090 181 160 1091 36 102 1089 181 160 1091 182 231 1090 56 132 918 40 139 1092 202 129 20 283 232 43 183 233 44 60 130 21 201 234 45 68 235 46 183 233 44 283 232 43 56 132 918 144 131 917 145 137 923 40 139 1092 144 131 917 321 236 1093 339 66 886 26 65 885 145 137 923 276 227 1084 2069 237 1094 2070 238 1095 54 228 1085 290 239 47 208 240 48 184 241 49 278 242 50 210 243 51 290 239 47 278 242 50 185 244 52 2068 245 1096 2069 237 1094 276 227 1084 53 226 1083 277 229 1087 2071 246 1097 2073 247 1098 55 230 1088 289 248 53 209 249 54 186 250 55 279 251 56 208 240 48 289 248 53 279 251 56 184 241 49 2070 238 1095 2071 246 1097 277 229 1087 54 228 1085 275 223 1080 2075 252 1099 2076 253 1100 52 224 1081 294 254 2265 212 255 58 2053 256 59 280 257 60 214 258 1101 294 254 1102 280 257 1103 187 259 1104 2074 260 1105 2075 252 1099 275 223 1080 51 222 1079 286 225 1082 2072 261 1106 2068 245 1096 53 226 1083 292 262 63 210 243 51 185 244 52 2052 263 64 274 221 1078 2078 264 1107 2074 260 1105 51 222 1079 293 265 1108 214 258 1101 187 259 1104 2055 266 1109 213 267 1110 293 265 1108 2055 266 1109 188 268 1111 2079 269 1112 2078 264 1107 274 221 1078 50 220 1077 273 219 1076 2080 270 1113 2079 269 1112 50 220 1077 295 271 1114 213 267 1110 188 268 1111 2056 272 1115 215 273 1116 295 271 1114 2056 272 1115 189 274 1117 2081 275 1118 2080 270 1113 273 219 1076 49 218 1075 271 215 1072 2084 276 1119 2085 277 1120 48 216 1073 297 278 1121 216 279 1122 190 280 1123 281 281 1124 217 282 87 297 278 73 281 281 2271 191 283 88 2083 284 1125 2084 276 1119 271 215 1072 180 214 1071 272 217 1074 2082 285 1126 2081 275 1118 49 218 1075 296 286 1127 215 273 1116 189 274 1117 2057 287 1128 216 279 1122 296 286 1127 2057 287 1128 190 280 1123 2085 277 1120 2082 285 1126 272 217 1074 48 216 1073 182 231 1090 2064 288 1129 2065 133 919 56 132 918 291 289 120 211 290 121 2051 291 122 2050 292 123 209 249 54 291 289 120 2050 292 123 186 250 55 2073 247 1098 2064 288 1129 182 231 1090 55 230 1088 211 290 121 298 293 124 282 294 125 2051 291 122 298 293 124 323 295 126 322 296 127 282 294 125 70 297 128 192 298 129 139 116 7 57 119 10 59 117 8 139 116 7 192 298 129 71 299 130 69 300 131 193 301 132 143 127 11 60 130 21 70 297 128 57 119 10 143 127 11 193 301 132 73 302 133 194 303 134 170 193 22 63 196 25 62 201 1062 170 193 1061 194 303 1130 74 304 1131 59 117 8 71 299 130 205 305 136 204 114 5 62 201 1062 74 304 1131 195 306 1132 173 199 1059 64 200 1060 173 199 1059 195 306 1132 75 307 1133 64 200 1060 75 307 1133 196 308 1134 176 206 1065 65 207 1066 176 206 1065 196 308 1134 76 309 1135 77 310 1136 197 311 1137 178 210 1067 67 213 1070 66 211 40 178 210 2251 197 311 2267 78 312 143 65 207 1066 76 309 1135 198 313 1138 179 212 1069 77 310 1136 67 213 1070 179 212 1069 198 313 1138 72 314 201 199 315 202 183 233 44 68 235 46 69 300 131 60 130 21 183 233 44 199 315 202 200 316 203 72 314 201 68 235 46 201 234 45 338 317 204 200 316 203 201 234 45 337 318 205 338 317 204 337 318 205 66 211 40 78 312 143 283 232 43 336 319 206 337 318 205 201 234 45 177 209 38 336 319 206 335 320 207 61 205 34 284 128 19 334 321 208 335 320 207 202 129 20 174 203 32 334 321 208 333 322 209 58 198 27 285 115 6 332 323 210 333 322 209 203 118 9 171 195 24 332 323 210 331 324 232 63 196 25 331 324 232 204 114 5 205 305 136 330 325 233 331 324 232 330 325 233 73 302 133 63 196 25 329 326 234 292 262 63 2052 263 64 2054 327 235 2076 253 1100 2077 328 1139 328 329 1140 52 224 1081 52 224 1081 328 329 1140 327 330 1141 47 190 1054 287 191 1055 326 331 1142 327 330 1141 206 192 1056 168 188 1052 326 331 1142 325 332 1143 46 183 1047 288 184 1048 324 333 1144 325 332 1143 207 185 1049 193 301 132 289 248 53 208 240 48 70 297 128 209 249 54 289 248 53 193 301 132 69 300 131 210 243 51 292 262 63 205 305 136 71 299 130 208 240 48 290 239 47 192 298 129 70 297 128 192 298 129 290 239 47 210 243 51 71 299 130 199 315 202 291 289 120 209 249 54 69 300 131 211 290 121 291 289 120 199 315 202 72 314 201 292 262 63 329 326 234 330 325 233 205 305 136 2053 256 59 212 255 58 329 326 234 2054 327 235 195 306 1132 293 265 1108 213 267 1110 75 307 1133 214 258 1101 293 265 1108 195 306 1132 74 304 1131 212 255 58 294 254 2265 194 303 134 73 302 133 194 303 1130 294 254 1102 214 258 1101 74 304 1131 213 267 1110 295 271 1114 196 308 1134 75 307 1133 196 308 1134 295 271 1114 215 273 1116 76 309 1135 215 273 1116 296 286 1127 198 313 1138 76 309 1135 198 313 1138 296 286 1127 216 279 1122 77 310 1136 323 295 126 217 282 87 191 283 88 322 296 127 217 282 87 323 295 126 338 317 204 78 312 143 216 279 1122 297 278 1121 197 311 1137 77 310 1136 197 311 2267 297 278 73 217 282 87 78 312 143 200 316 203 298 293 124 211 290 121 72 314 201 247 27 89 301 334 1145 220 335 1146 100 28 90 221 336 1147 301 334 1145 247 27 89 12 26 86 107 39 252 302 337 1148 222 338 1149 106 40 253 220 335 1146 302 337 1148 107 39 252 100 28 90 111 45 262 303 339 1150 223 340 1151 110 46 265 222 338 1149 303 339 1150 111 45 262 106 40 253 115 51 289 304 341 1152 224 342 1153 114 52 290 223 340 1151 304 341 1152 115 51 289 110 46 265 119 57 295 305 343 1154 225 344 1155 118 58 296 224 342 1153 305 343 1154 119 57 295 114 52 290 122 63 304 306 345 1156 226 346 1157 121 64 884 225 344 1155 306 345 1156 122 63 304 118 58 296 152 148 978 346 347 1158 345 348 1159 151 149 980 152 148 978 121 64 884 226 346 1157 346 347 1158 241 163 983 344 349 1160 343 350 1161 242 165 987 241 163 983 151 149 980 345 348 1159 344 349 1160 167 186 1050 315 351 1162 221 336 1147 12 26 86 232 175 1038 316 352 1163 127 80 900 30 82 902 127 80 900 316 352 1163 162 353 1164 45 81 901 162 353 1164 316 352 1163 235 354 1165 79 355 1166 235 354 1165 316 352 1163 232 175 1038 80 177 1040 234 356 1167 317 357 1168 235 354 1165 80 177 1040 235 354 1165 317 357 1168 233 358 1169 79 355 1166 233 358 1169 317 357 1168 87 359 1170 3 360 1171 87 359 1170 317 357 1168 234 356 1167 2 361 1172 236 362 1173 318 363 1174 237 176 1039 81 171 1019 237 176 1039 318 363 1174 234 356 1167 80 177 1040 234 356 1167 318 363 1174 86 364 1175 2 361 1172 86 364 1175 318 363 1174 236 362 1173 1 365 1176 239 170 1018 319 366 1177 236 362 1173 81 171 1019 236 362 1173 319 366 1177 85 367 1178 1 365 1176 85 367 1178 319 366 1177 161 368 1179 0 369 1180 161 368 1179 319 366 1177 239 170 1018 82 173 1023 0 369 1180 161 368 1179 240 370 1181 4 371 1182 240 370 1181 161 368 1179 82 173 1023 83 166 1012 242 165 987 158 372 1183 240 370 1181 83 166 1012 240 370 1181 158 372 1183 84 373 1184 4 371 1182 343 350 1161 342 374 1185 158 372 1183 242 165 987 158 372 1183 342 374 1185 88 375 1186 84 373 1184 144 131 917 2066 134 920 2067 376 1187 321 236 1093 339 66 886 321 236 1093 180 214 1071 25 73 893 2067 376 1187 2083 284 1125 180 214 1071 321 236 1093 46 183 1047 325 332 1143 324 333 1144 165 180 1043 207 185 1049 325 332 1143 326 331 1142 287 191 1055 47 190 1054 327 330 1141 326 331 1142 168 188 1052 206 192 1056 327 330 1141 328 329 1140 286 225 1082 286 225 1082 328 329 1140 2077 328 1139 2072 261 1106 73 302 133 330 325 233 329 326 234 212 255 58 204 114 5 331 324 232 332 323 210 285 115 6 58 198 27 333 322 209 332 323 210 171 195 24 203 118 9 333 322 209 334 321 208 284 128 19 61 205 34 335 320 207 334 321 208 174 203 32 202 129 20 335 320 207 336 319 206 283 232 43 66 211 40 337 318 205 336 319 206 177 209 38 200 316 203 338 317 204 323 295 126 298 293 124 299 8 36 218 9 37 2022 377 1188 2017 378 1189 218 9 37 300 23 72 2021 379 1190 2022 377 1188 300 23 72 219 25 85 2023 380 1191 2021 379 1190 220 335 1146 301 334 1145 674 381 1192 592 382 1193 301 334 1145 221 336 1147 593 383 1194 674 381 1192 222 338 1149 302 337 1148 675 384 1195 594 385 1196 302 337 1148 220 335 1146 592 382 1193 675 384 1195 223 340 1151 303 339 1150 676 386 1197 595 387 1198 303 339 1150 222 338 1149 594 385 1196 676 386 1197 224 342 1153 304 341 1152 677 388 1199 596 389 1200 304 341 1152 223 340 1151 595 387 1198 677 388 1199 225 344 1155 305 343 1154 678 390 1201 597 391 1202 305 343 1154 224 342 1153 596 389 1200 678 390 1201 226 346 1157 306 345 1156 679 392 1203 598 393 1204 306 345 1156 225 344 1155 597 391 1202 679 392 1203 2036 394 1205 2037 395 1206 680 396 1207 599 397 1208 2037 395 1206 2038 398 1209 600 399 1210 680 396 1207 2038 398 1209 2039 400 1211 608 401 1212 600 399 1210 31 86 3 308 85 2 2019 402 144 2033 403 2261 602 404 148 681 405 149 2019 402 2264 2020 406 2259 34 95 16 309 94 15 2032 407 2262 2031 408 2252 309 94 15 31 86 3 2033 403 2261 2032 407 2262 219 25 85 310 111 904 2024 409 1213 2023 380 1191 684 410 1214 604 411 1215 2025 412 1216 2026 413 1217 2034 414 2258 2035 415 2260 685 416 158 605 417 159 2035 415 1218 2036 394 1205 599 397 1208 685 416 1219 345 348 1159 346 347 1158 1971 418 1220 1970 419 1221 346 347 1158 226 346 1157 598 393 1204 1971 418 1220 2020 406 2259 2016 420 2257 686 421 161 602 404 148 2016 420 2257 2034 414 2258 605 417 159 686 421 161 229 126 113 313 156 112 2028 422 2255 2027 423 2256 313 156 112 230 158 115 2029 424 2254 2028 422 2255 230 158 115 314 162 119 2030 425 2253 2029 424 2254 314 162 119 34 95 16 2031 408 2252 2030 425 2253 343 350 1161 344 349 1160 1969 426 1222 1968 427 1223 344 349 1160 345 348 1159 1970 419 1221 1969 426 1222 2039 400 1211 2040 428 1224 689 429 1225 608 401 1212 2040 428 1224 2041 430 1226 612 431 1227 689 429 1225 221 336 1147 315 351 1162 690 432 1228 593 383 1194 2041 430 1226 2042 433 1229 692 434 1230 612 431 1227 2042 433 1229 2043 435 1231 434 436 1232 692 434 1230 88 375 1186 342 374 1185 1967 437 1233 435 438 1234 342 374 1185 343 350 1161 1968 427 1223 1967 437 1233 436 439 1235 353 440 1236 437 441 1237 622 442 1238 438 443 1239 352 444 1240 436 439 1235 622 442 1238 439 445 1241 352 444 1240 438 443 1239 623 446 1242 440 447 1243 354 448 1244 439 445 1241 623 446 1242 355 449 1245 356 450 1246 441 451 1247 443 452 1248 441 451 1247 357 453 1249 442 454 1250 443 452 1248 444 455 1251 353 440 1236 436 439 1235 624 456 1252 436 439 1235 352 444 1240 445 457 1253 624 456 1252 445 457 1253 359 458 1254 446 459 1255 624 456 1252 446 459 1255 358 460 1256 444 455 1251 624 456 1252 445 457 1253 352 444 1240 439 445 1241 625 461 1257 439 445 1241 354 448 1244 447 462 1258 625 461 1257 447 462 1258 360 463 1259 448 464 1260 625 461 1257 448 464 1260 359 458 1254 445 457 1253 625 461 1257 361 465 1261 357 453 1249 441 451 1247 626 466 1262 441 451 1247 356 450 1246 449 467 1263 626 466 1262 362 468 1264 363 469 1265 450 470 1266 451 471 1267 450 470 1266 356 450 1246 355 449 1245 451 471 1267 452 472 1268 358 460 1256 446 459 1255 627 473 1269 446 459 1255 359 458 1254 453 474 1270 627 473 1269 453 474 1270 365 475 1271 454 476 1272 627 473 1269 454 476 1272 364 477 1273 452 472 1268 627 473 1269 449 467 1263 356 450 1246 450 470 1266 456 478 1274 450 470 1266 363 469 1265 455 479 1275 456 478 1274 457 480 1276 363 469 1265 362 468 1264 458 481 1277 367 482 1278 366 483 1279 457 480 1276 458 481 1277 455 479 1275 363 469 1265 457 480 1276 460 484 1280 457 480 1276 366 483 1279 459 485 1281 460 484 1280 369 486 1282 368 487 1283 462 488 1284 461 489 1285 462 488 1284 366 483 1279 367 482 1278 461 489 1285 459 485 1281 366 483 1279 462 488 1284 464 490 1286 462 488 1284 368 487 1283 463 491 1287 464 490 1286 371 492 1288 370 493 1289 466 494 1290 465 495 1291 466 494 1290 368 487 1283 369 486 1282 465 495 1291 463 491 1287 368 487 1283 466 494 1290 468 496 1292 466 494 1290 370 493 1289 467 497 1293 468 496 1292 372 498 1294 373 499 1295 469 500 1296 628 501 1297 469 500 1296 370 493 1289 371 492 1288 628 501 1297 467 497 1293 370 493 1289 469 500 1296 471 502 1298 469 500 1296 373 499 1295 470 503 1299 471 502 1298 375 504 1300 472 505 1301 1965 506 1302 1964 507 1303 472 505 1301 377 508 1304 1966 509 1305 1965 506 1302 1966 509 1305 376 510 1306 473 511 1307 1965 506 1302 473 511 1307 374 512 1308 1964 507 1303 1965 506 1302 474 513 1309 378 514 1310 475 515 1311 629 516 1312 475 515 1311 379 517 1313 476 518 1314 629 516 1312 476 518 1314 377 508 1304 472 505 1301 629 516 1312 472 505 1301 375 504 1300 474 513 1309 629 516 1312 476 518 1314 379 517 1313 399 519 1315 477 520 1316 476 518 1314 477 520 1316 380 521 1317 377 508 1304 478 522 162 381 523 163 479 524 164 630 525 165 479 524 174 382 526 175 480 527 176 630 525 177 480 527 176 384 528 178 481 529 179 630 525 177 481 529 166 383 530 167 478 522 162 630 525 165 482 531 168 385 532 169 483 533 170 631 534 171 483 533 170 381 523 163 478 522 162 631 534 171 478 522 162 383 530 167 484 535 172 631 534 171 484 535 172 386 536 173 482 531 168 631 534 171 485 537 180 386 536 173 484 535 172 632 538 181 484 535 172 383 530 167 486 539 182 632 538 181 486 539 182 387 540 183 511 541 184 632 538 181 511 541 184 390 542 185 485 537 180 632 538 181 487 543 186 391 544 187 488 545 188 633 546 189 488 545 188 388 547 190 489 548 191 633 546 189 489 548 191 386 536 173 485 537 180 633 546 189 485 537 180 390 542 185 487 543 186 633 546 189 453 474 1270 359 458 1254 448 464 1260 634 549 1318 448 464 1260 360 463 1259 490 550 1319 634 549 1318 490 550 1319 389 551 1320 491 552 1321 634 549 1318 491 552 1321 365 475 1271 453 474 1270 634 549 1318 575 553 236 405 554 237 492 555 238 659 556 239 492 555 238 403 557 240 574 558 241 659 556 239 454 476 1272 365 475 1271 493 559 1322 635 560 1323 493 559 1322 391 544 1324 487 543 1325 635 560 1323 487 543 1325 390 542 1326 494 561 1327 635 560 1323 494 561 1327 364 477 1273 454 476 1272 635 560 1323 491 552 1321 389 551 1320 495 562 1328 636 563 1329 495 562 1328 392 564 1330 508 565 1331 636 563 1329 508 565 1331 391 544 1324 493 559 1322 636 563 1329 493 559 1322 365 475 1271 491 552 1321 636 563 1329 496 566 242 406 567 243 573 568 244 658 569 245 574 558 241 403 557 240 496 566 242 658 569 245 651 570 1332 2087 571 1333 2088 572 1334 552 573 1335 497 574 1336 378 514 1310 474 513 1309 637 575 1337 474 513 1309 375 504 1300 498 576 1338 637 575 1337 498 576 211 394 577 212 499 578 213 637 575 214 499 578 213 395 579 215 497 574 216 637 575 214 397 580 1339 396 581 1340 501 582 1341 500 583 1342 501 582 1341 373 499 1295 372 498 1294 500 583 1342 502 584 1343 374 512 1308 473 511 1307 638 585 1344 473 511 1307 376 510 1306 503 586 1345 638 585 1344 503 586 1345 397 580 1339 500 583 1342 638 585 1344 500 583 1342 372 498 1294 502 584 1343 638 585 1344 470 503 1299 373 499 1295 501 582 1341 505 587 1346 501 582 1341 396 581 1340 504 588 1347 505 587 1346 609 589 1348 1966 509 1305 377 508 1304 380 521 1317 609 589 1348 398 590 1349 376 510 1306 1966 509 1305 506 591 217 384 528 178 480 527 176 639 592 218 480 527 176 382 526 175 507 593 219 639 592 218 507 593 219 395 579 215 499 578 213 639 592 218 499 578 213 394 577 212 506 591 217 639 592 218 508 565 192 392 564 193 509 594 194 640 595 195 509 594 194 400 596 196 510 597 197 640 595 195 510 597 197 388 547 190 488 545 188 640 595 195 488 545 188 391 544 187 508 565 192 640 595 195 506 591 217 394 577 212 538 598 226 641 599 227 538 598 198 387 540 183 486 539 182 641 599 199 486 539 182 383 530 167 481 529 166 641 599 199 481 529 179 384 528 178 506 591 217 641 599 227 489 548 191 388 547 190 510 597 197 642 600 220 510 597 197 400 596 196 512 601 221 642 600 220 512 601 221 385 532 169 482 531 168 642 600 220 482 531 168 386 536 173 489 548 191 642 600 220 504 588 1347 396 581 1340 513 602 1350 620 603 1351 513 602 1350 429 604 1352 621 605 1353 620 603 1351 515 606 1354 398 590 1349 516 607 1355 643 608 1356 516 607 1355 427 609 1357 618 610 1358 643 608 1356 618 610 1358 428 611 1359 617 612 1360 643 608 1356 617 612 1360 397 580 1339 515 606 1354 643 608 1356 428 611 1359 429 604 1352 513 602 1350 617 612 1360 513 602 1350 396 581 1340 397 580 1339 617 612 1360 516 607 1355 398 590 1349 609 589 1348 644 613 1361 609 589 1348 380 521 1317 610 614 1362 644 613 1361 610 614 1362 426 615 1363 616 616 1364 644 613 1361 616 616 1364 427 609 1357 516 607 1355 644 613 1361 442 454 1250 357 453 1249 520 617 1365 519 618 1366 521 619 1367 401 620 1368 522 621 1369 645 622 1370 522 621 1369 442 454 1250 519 618 1366 645 622 1370 437 441 1237 353 440 1236 579 623 1371 661 624 1372 520 617 1365 357 453 1249 361 465 1261 523 625 1373 522 621 1369 401 620 1368 524 626 1374 646 627 1375 524 626 1374 402 628 1376 525 629 1377 646 627 1375 525 629 1377 355 449 1245 443 452 1248 646 627 1375 443 452 1248 442 454 1250 522 621 1369 646 627 1375 579 623 1371 353 440 1236 444 455 1251 660 630 1378 444 455 1251 358 460 1256 578 631 1379 660 630 1378 526 632 2273 409 633 247 527 634 248 647 635 2268 527 634 248 404 636 250 528 637 251 647 635 2268 528 637 1380 410 638 1381 529 639 1382 647 635 1383 529 639 1382 408 640 1384 526 632 1385 647 635 1383 528 637 251 404 636 250 530 641 255 648 642 2269 530 641 255 407 643 257 531 644 258 648 642 2269 531 644 1386 411 645 1387 532 646 1388 648 642 1389 532 646 1388 410 638 1381 528 637 1380 648 642 1389 531 644 258 407 643 257 533 647 261 649 648 2272 533 647 261 412 649 263 534 650 264 649 648 2272 534 650 1390 413 651 1391 535 652 1392 649 648 1393 535 652 1392 411 645 1387 531 644 1386 649 648 1393 393 653 1394 374 512 1308 502 584 1343 537 654 1395 502 584 1343 372 498 1294 628 501 1297 537 654 1395 628 501 1297 371 492 1288 536 655 1396 537 654 1395 503 586 1345 376 510 1306 398 590 1349 515 606 1354 515 606 1354 397 580 1339 503 586 1345 536 655 1396 371 492 1288 465 495 1291 540 656 1397 465 495 1291 369 486 1282 539 657 1398 540 656 1397 539 657 1398 369 486 1282 461 489 1285 542 658 1399 461 489 1285 367 482 1278 541 659 1400 542 658 1399 541 659 1400 367 482 1278 458 481 1277 544 660 1401 458 481 1277 362 468 1264 543 661 1402 544 660 1401 525 629 1377 402 628 1376 545 662 1403 546 663 1404 543 661 1402 362 468 1264 451 471 1267 546 663 1404 451 471 1267 355 449 1245 525 629 1377 546 663 1404 578 631 1379 358 460 1256 452 472 1268 577 664 1405 452 472 1268 364 477 1273 547 665 1406 577 664 1405 547 665 1406 364 477 1273 494 561 1327 549 666 1407 494 561 1327 390 542 1326 548 667 1408 549 666 1407 511 541 1409 387 540 1410 550 668 1411 551 669 1412 548 667 1408 390 542 1326 511 541 1409 551 669 1412 550 668 1411 387 540 1410 538 598 1413 650 670 1414 538 598 1413 394 577 1415 552 573 1335 650 670 1414 573 568 244 406 567 243 553 671 267 657 672 268 572 673 269 657 672 268 553 671 267 414 674 270 552 573 1335 394 577 1415 498 576 1338 651 570 1332 651 570 1332 498 576 1338 375 504 1300 1964 507 1303 1945 675 1416 549 666 1407 548 667 1408 2091 676 1417 2092 677 1418 580 678 271 663 679 272 652 680 273 554 681 274 663 679 272 582 682 275 555 683 276 652 680 273 2093 684 1419 547 665 1406 549 666 1407 2092 677 1418 551 669 1412 550 668 1411 2095 685 1420 2090 686 1421 581 687 277 662 688 278 653 689 279 556 690 280 662 688 278 580 678 271 554 681 274 653 689 279 2091 676 1417 548 667 1408 551 669 1412 2090 686 1421 546 663 1404 545 662 1403 2097 691 1422 2098 692 1423 584 693 281 667 694 282 654 695 2270 557 696 284 667 694 1424 586 697 1425 558 698 1426 654 695 1427 2099 699 1428 543 661 1402 546 663 1404 2098 692 1423 577 664 1405 547 665 1406 2093 684 1419 2094 700 1429 582 682 275 665 701 287 2060 702 288 555 683 276 544 660 1401 543 661 1402 2099 699 1428 2100 703 1430 586 697 1425 666 704 1431 2061 705 1432 558 698 1426 666 704 1431 585 706 1433 559 707 1434 2061 705 1432 2101 708 1435 541 659 1400 544 660 1401 2100 703 1430 542 658 1399 541 659 1400 2101 708 1435 2102 709 1436 585 706 1433 668 710 1437 2062 711 1438 559 707 1434 668 710 1437 587 712 1439 560 713 1440 2062 711 1438 2103 714 1441 539 657 1398 542 658 1399 2102 709 1436 537 654 1395 536 655 1396 2105 715 1442 2106 716 1443 588 717 1444 670 718 1445 655 719 1446 561 720 1447 670 718 2275 589 721 301 562 722 302 655 719 299 2107 723 1448 393 653 1394 537 654 1395 2106 716 1443 540 656 1397 539 657 1398 2103 714 1441 2104 724 1449 587 712 1439 669 725 1450 2063 726 1451 560 713 1440 669 725 1450 588 717 1444 561 720 1447 2063 726 1451 2105 715 1442 536 655 1396 540 656 1397 2104 724 1449 650 670 1414 552 573 1335 2088 572 1334 2089 727 1452 583 728 305 664 729 306 2059 730 307 2058 731 308 664 729 306 581 687 277 556 690 280 2059 730 307 2095 685 1420 550 668 1411 650 670 1414 2089 727 1452 671 732 309 583 728 305 2058 731 308 656 733 310 1947 734 311 671 732 309 656 733 310 1946 735 970 563 736 971 416 737 972 403 557 240 492 555 238 563 736 971 492 555 238 405 554 237 417 738 973 564 739 974 415 740 975 406 567 243 496 566 242 564 739 974 496 566 242 403 557 240 416 737 972 565 741 2274 419 742 977 409 633 247 526 632 2273 565 741 1453 526 632 1385 408 640 1384 420 743 1454 576 744 979 417 738 973 405 554 237 575 553 236 566 745 1455 420 743 1454 408 640 1384 529 639 1382 566 745 1455 529 639 1382 410 638 1381 421 746 1456 567 747 1457 421 746 1456 410 638 1381 532 646 1388 567 747 1457 532 646 1388 411 645 1387 422 748 1458 568 749 1459 423 750 1460 413 651 1391 534 650 1390 568 749 984 534 650 264 412 649 263 424 751 986 569 752 1461 422 748 1458 411 645 1387 535 652 1392 569 752 1461 535 652 1392 413 651 1391 423 750 1460 570 753 988 418 754 989 414 674 270 553 671 267 570 753 988 553 671 267 406 567 243 415 740 975 414 674 270 418 754 989 571 755 990 572 673 269 572 673 269 571 755 990 1963 756 991 1962 757 992 424 751 986 412 649 263 1962 757 992 1963 756 991 657 672 268 572 673 269 1962 757 992 1961 758 993 533 647 261 407 643 257 1960 759 994 1961 758 993 658 569 245 573 568 244 1960 759 994 1959 760 995 530 641 255 404 636 250 1958 761 996 1959 760 995 659 556 239 574 558 241 1958 761 996 1957 762 997 527 634 248 409 633 247 1956 763 998 1957 762 997 576 744 979 575 553 236 1956 763 998 1955 764 999 409 633 247 419 742 977 1955 764 999 1956 763 998 2060 702 288 665 701 287 1954 765 1000 1953 766 1001 2097 691 1422 545 662 1403 1952 767 1462 2096 768 1463 545 662 1403 402 628 1376 1951 769 1464 1952 767 1462 660 630 1378 578 631 1379 1951 769 1464 1950 770 1465 524 626 1374 401 620 1368 1949 771 1466 1950 770 1465 661 624 1372 579 623 1371 1949 771 1466 1948 772 1467 564 739 974 416 737 972 580 678 271 662 688 278 581 687 277 415 740 975 564 739 974 662 688 278 582 682 275 417 738 973 576 744 979 665 701 287 580 678 271 416 737 972 563 736 971 663 679 272 563 736 971 417 738 973 582 682 275 663 679 272 570 753 988 415 740 975 581 687 277 664 729 306 583 728 305 418 754 989 570 753 988 664 729 306 665 701 287 576 744 979 1955 764 999 1954 765 1000 1954 765 1000 584 693 281 557 696 284 1953 766 1001 566 745 1455 421 746 1456 585 706 1433 666 704 1431 586 697 1425 420 743 1454 566 745 1455 666 704 1431 584 693 281 419 742 977 565 741 2274 667 694 282 565 741 1453 420 743 1454 586 697 1425 667 694 1424 585 706 1433 421 746 1456 567 747 1457 668 710 1437 567 747 1457 422 748 1458 587 712 1439 668 710 1437 587 712 1439 422 748 1458 569 752 1461 669 725 1450 569 752 1461 423 750 1460 588 717 1444 669 725 1450 589 721 301 1947 734 311 1946 735 970 562 722 302 589 721 301 424 751 986 1963 756 991 1947 734 311 588 717 1444 423 750 1460 568 749 1459 670 718 1445 568 749 984 424 751 986 589 721 301 670 718 2275 571 755 990 418 754 989 583 728 305 671 732 309 590 773 1468 354 448 1244 440 447 1243 672 774 1469 447 462 1258 354 448 1244 590 773 1468 673 775 1470 591 776 1471 360 463 1259 447 462 1258 673 775 1470 626 466 1262 449 467 1263 592 382 1193 674 381 1192 593 383 1194 361 465 1261 626 466 1262 674 381 1192 456 478 1274 455 479 1275 594 385 1196 675 384 1195 592 382 1193 449 467 1263 456 478 1274 675 384 1195 460 484 1280 459 485 1281 595 387 1198 676 386 1197 594 385 1196 455 479 1275 460 484 1280 676 386 1197 464 490 1286 463 491 1287 596 389 1200 677 388 1199 595 387 1198 459 485 1281 464 490 1286 677 388 1199 468 496 1292 467 497 1293 597 391 1202 678 390 1201 596 389 1200 463 491 1287 468 496 1292 678 390 1201 471 502 1298 470 503 1299 598 393 1204 679 392 1203 597 391 1202 467 497 1293 471 502 1298 679 392 1203 475 515 1311 378 514 1310 599 397 1208 680 396 1207 600 399 1210 379 517 1313 475 515 1311 680 396 1207 399 519 1315 379 517 1313 600 399 1210 608 401 1212 479 524 164 381 523 163 601 777 222 681 405 223 602 404 148 382 526 175 479 524 174 681 405 149 483 533 170 385 532 169 603 778 224 682 779 225 601 777 222 381 523 163 483 533 170 682 779 225 490 550 1319 360 463 1259 591 776 1471 683 780 1472 604 411 1215 389 551 1320 490 550 1319 683 780 1472 495 562 1328 389 551 1320 604 411 1215 684 410 1214 606 781 1473 392 564 1330 495 562 1328 684 410 1214 497 574 216 395 579 215 605 417 159 685 416 158 599 397 1208 378 514 1310 497 574 1336 685 416 1219 505 587 1346 504 588 1347 1970 419 1221 1971 418 1220 505 587 1346 1971 418 1220 598 393 1204 470 503 1299 507 593 219 382 526 175 602 404 148 686 421 161 605 417 159 395 579 215 507 593 219 686 421 161 509 594 194 392 564 193 606 781 228 687 782 229 607 783 230 400 596 196 509 594 194 687 782 229 512 601 221 400 596 196 607 783 230 688 784 231 603 778 224 385 532 169 512 601 221 688 784 231 620 603 1351 621 605 1353 1968 427 1223 1969 426 1222 620 603 1351 1969 426 1222 1970 419 1221 504 588 1347 518 785 1474 399 519 1315 608 401 1212 689 429 1225 612 431 1227 425 786 1475 518 785 1474 689 429 1225 523 625 1373 361 465 1261 593 383 1194 690 432 1228 610 614 1362 380 521 1317 477 520 1316 691 787 1476 477 520 1316 399 519 1315 518 785 1474 691 787 1476 518 785 1474 425 786 1475 614 788 1477 691 787 1476 614 788 1477 426 615 1363 610 614 1362 691 787 1476 611 789 1478 425 786 1475 612 431 1227 692 434 1230 434 436 1232 350 790 1479 611 789 1478 692 434 1230 613 791 1480 426 615 1363 614 788 1477 693 792 1481 614 788 1477 425 786 1475 611 789 1478 693 792 1481 611 789 1478 350 790 1479 433 793 1482 693 792 1481 433 793 1482 349 794 1483 613 791 1480 693 792 1481 615 795 1484 427 609 1357 616 616 1364 694 796 1485 616 616 1364 426 615 1363 613 791 1480 694 796 1485 613 791 1480 349 794 1483 432 797 1486 694 796 1485 432 797 1486 348 798 1487 615 795 1484 694 796 1485 618 610 1358 427 609 1357 615 795 1484 695 799 1488 615 795 1484 348 798 1487 431 800 1489 695 799 1488 431 800 1489 347 801 1490 517 802 1491 695 799 1488 517 802 1491 428 611 1359 618 610 1358 695 799 1488 347 801 1490 351 803 1492 619 804 1493 517 802 1491 619 804 1493 429 604 1352 428 611 1359 517 802 1491 621 605 1353 429 604 1352 619 804 1493 514 805 1494 619 804 1493 351 803 1492 430 806 1495 514 805 1494 1968 427 1223 621 605 1353 514 805 1494 1967 437 1233 514 805 1494 430 806 1495 435 438 1234 1967 437 1233 696 807 1496 697 808 1497 710 809 1498 709 810 1499 697 808 1497 698 811 1500 711 812 1501 710 809 1498 698 811 1500 699 813 1502 712 814 1503 711 812 1501 699 813 1502 700 815 1504 713 816 1505 712 814 1503 700 815 1504 701 817 1506 714 818 1507 713 816 1505 701 817 1506 702 819 1508 715 820 1509 714 818 1507 702 819 1508 703 821 1510 716 822 1511 715 820 1509 703 821 1510 704 823 1512 717 824 1513 716 822 1511 704 823 1512 705 825 1514 718 826 1515 717 824 1513 705 825 1514 706 827 1516 719 828 1517 718 826 1515 706 827 1516 707 829 1518 720 830 1519 719 828 1517 707 829 1518 1331 831 1520 721 832 1521 720 830 1519 708 833 1522 722 834 1523 1979 835 1524 1980 836 1525 709 810 1499 710 809 1498 724 837 1526 723 838 1527 710 809 1498 711 812 1501 725 839 1528 724 837 1526 711 812 1501 712 814 1503 726 840 1529 725 839 1528 712 814 1503 713 816 1505 727 841 1530 726 840 1529 713 816 1505 714 818 1507 728 842 1531 727 841 1530 714 818 1507 715 820 1509 729 843 1532 728 842 1531 715 820 1509 716 822 1511 730 844 1533 729 843 1532 716 822 1511 717 824 1513 731 845 1534 730 844 1533 717 824 1513 718 826 1515 732 846 1535 731 845 1534 718 826 1515 719 828 1517 733 847 1536 732 846 1535 719 828 1517 720 830 1519 734 848 1537 733 847 1536 1333 849 1538 721 832 1521 1979 835 1524 1982 850 1539 723 838 1527 724 837 1526 737 851 1540 736 852 1541 724 837 1526 725 839 1528 738 853 1542 737 851 1540 725 839 1528 726 840 1529 739 854 1543 738 853 1542 726 840 1529 727 841 1530 740 855 1544 739 854 1543 727 841 1530 728 842 1531 741 856 1545 740 855 1544 728 842 1531 729 843 1532 742 857 1546 741 856 1545 729 843 1532 730 844 1533 743 858 1547 742 857 1546 730 844 1533 731 845 1534 744 859 1548 743 858 1547 731 845 1534 732 846 1535 745 860 1549 744 859 1548 732 846 1535 733 847 1536 746 861 1550 745 860 1549 733 847 1536 734 848 1537 747 862 1551 746 861 1550 1334 863 1552 1333 849 1538 1982 850 1539 1983 864 1553 736 852 1541 737 851 1540 750 865 1554 749 866 1555 737 851 1540 738 853 1542 751 867 1556 750 865 1554 738 853 1542 739 854 1543 752 868 1557 751 867 1556 739 854 1543 740 855 1544 753 869 1558 752 868 1557 740 855 1544 741 856 1545 754 870 1559 753 869 1558 741 856 1545 742 857 1546 755 871 1560 754 870 1559 742 857 1546 743 858 1547 756 872 1561 755 871 1560 743 858 1547 744 859 1548 757 873 1562 756 872 1561 744 859 1548 745 860 1549 758 874 1563 757 873 1562 745 860 1549 746 861 1550 759 875 1564 758 874 1563 746 861 1550 747 862 1551 760 876 1565 759 875 1564 1335 877 1566 1334 863 1552 1983 864 1553 1984 878 1567 749 866 1555 750 865 1554 763 879 1568 762 880 1569 750 865 1554 751 867 1556 764 881 1570 763 879 1568 751 867 1556 752 868 1557 765 882 1571 764 881 1570 752 868 1557 753 869 1558 766 883 1572 765 882 1571 753 869 1558 754 870 1559 767 884 1573 766 883 1572 754 870 1559 755 871 1560 768 885 1574 767 884 1573 755 871 1560 756 872 1561 769 886 1575 768 885 1574 756 872 1561 757 873 1562 770 887 1576 769 886 1575 757 873 1562 758 874 1563 771 888 1577 770 887 1576 758 874 1563 759 875 1564 772 889 1578 771 888 1577 759 875 1564 760 876 1565 773 890 1579 772 889 1578 1336 891 1580 1335 877 1566 1984 878 1567 1981 892 1581 762 880 1569 763 879 1568 776 893 1582 775 894 1583 763 879 1568 764 881 1570 777 895 1584 776 893 1582 764 881 1570 765 882 1571 778 896 1585 777 895 1584 765 882 1571 766 883 1572 779 897 1586 778 896 1585 766 883 1572 767 884 1573 780 898 1587 779 897 1586 767 884 1573 768 885 1574 781 899 1588 780 898 1587 768 885 1574 769 886 1575 782 900 1589 781 899 1588 769 886 1575 770 887 1576 783 901 1590 782 900 1589 770 887 1576 771 888 1577 784 902 1591 783 901 1590 771 888 1577 772 889 1578 785 903 1592 784 902 1591 772 889 1578 773 890 1579 786 904 1593 785 903 1592 2 361 1172 1336 891 1580 1981 892 1581 87 359 1170 775 894 1583 776 893 1582 788 905 1594 787 906 1595 776 893 1582 777 895 1584 789 907 1596 788 905 1594 777 895 1584 778 896 1585 790 908 1597 789 907 1596 778 896 1585 779 897 1586 791 909 1598 790 908 1597 779 897 1586 780 898 1587 792 910 1599 791 909 1598 780 898 1587 781 899 1588 793 911 1600 792 910 1599 781 899 1588 782 900 1589 794 912 1601 793 911 1600 782 900 1589 783 901 1590 795 913 1602 794 912 1601 783 901 1590 784 902 1591 796 914 1603 795 913 1602 784 902 1591 785 903 1592 797 915 1604 796 914 1603 785 903 1592 786 904 1593 798 916 1605 797 915 1604 787 906 1595 788 905 1594 800 917 1606 799 918 1607 788 905 1594 789 907 1596 801 919 1608 800 917 1606 789 907 1596 790 908 1597 802 920 1609 801 919 1608 790 908 1597 791 909 1598 803 921 1610 802 920 1609 791 909 1598 792 910 1599 804 922 1611 803 921 1610 792 910 1599 793 911 1600 805 923 1612 804 922 1611 793 911 1600 794 912 1601 806 924 1613 805 923 1612 794 912 1601 795 913 1602 807 925 1614 806 924 1613 795 913 1602 796 914 1603 808 926 1615 807 925 1614 796 914 1603 797 915 1604 809 927 1616 808 926 1615 797 915 1604 798 916 1605 810 928 1617 809 927 1616 799 918 1607 800 917 1606 812 929 1618 811 930 1619 800 917 1606 801 919 1608 813 931 1620 812 929 1618 801 919 1608 802 920 1609 814 932 1621 813 931 1620 802 920 1609 803 921 1610 815 933 1622 814 932 1621 803 921 1610 804 922 1611 816 934 1623 815 933 1622 804 922 1611 805 923 1612 817 935 1624 816 934 1623 805 923 1612 806 924 1613 818 936 1625 817 935 1624 806 924 1613 807 925 1614 819 937 1626 818 936 1625 807 925 1614 808 926 1615 820 938 1627 819 937 1626 808 926 1615 809 927 1616 821 939 1628 820 938 1627 809 927 1616 810 928 1617 822 940 1629 821 939 1628 811 930 1619 812 929 1618 824 941 1630 823 942 1631 812 929 1618 813 931 1620 825 943 1632 824 941 1630 813 931 1620 814 932 1621 826 944 1633 825 943 1632 814 932 1621 815 933 1622 827 945 1634 826 944 1633 815 933 1622 816 934 1623 828 946 1635 827 945 1634 816 934 1623 817 935 1624 829 947 1636 828 946 1635 817 935 1624 818 936 1625 830 948 1637 829 947 1636 818 936 1625 819 937 1626 831 949 1638 830 948 1637 819 937 1626 820 938 1627 832 950 1639 831 949 1638 820 938 1627 821 939 1628 833 951 1640 832 950 1639 821 939 1628 822 940 1629 834 952 1641 833 951 1640 823 942 1631 824 941 1630 835 953 1642 846 954 1643 824 941 1630 825 943 1632 836 955 1644 835 953 1642 825 943 1632 826 944 1633 837 956 1645 836 955 1644 826 944 1633 827 945 1634 838 957 1646 837 956 1645 827 945 1634 828 946 1635 839 958 1647 838 957 1646 828 946 1635 829 947 1636 840 959 1648 839 958 1647 829 947 1636 830 948 1637 841 960 1649 840 959 1648 830 948 1637 831 949 1638 842 961 1650 841 960 1649 831 949 1638 832 950 1639 843 962 1651 842 961 1650 832 950 1639 833 951 1640 844 963 1652 843 962 1651 833 951 1640 834 952 1641 845 964 1653 844 963 1652 846 954 1643 835 953 1642 848 965 1654 847 966 1655 835 953 1642 836 955 1644 849 967 1656 848 965 1654 836 955 1644 837 956 1645 850 968 1657 849 967 1656 837 956 1645 838 957 1646 851 969 1658 850 968 1657 838 957 1646 839 958 1647 852 970 1659 851 969 1658 839 958 1647 840 959 1648 853 971 1660 852 970 1659 840 959 1648 841 960 1649 854 972 1661 853 971 1660 841 960 1649 842 961 1650 855 973 1662 854 972 1661 842 961 1650 843 962 1651 856 974 1663 855 973 1662 843 962 1651 844 963 1652 857 975 1664 856 974 1663 844 963 1652 845 964 1653 858 976 1665 857 975 1664 847 966 1655 848 965 1654 860 977 1666 859 978 1667 848 965 1654 849 967 1656 861 979 1668 860 977 1666 849 967 1656 850 968 1657 862 980 1669 861 979 1668 853 971 1660 854 972 1661 863 981 1670 854 972 1661 855 973 1662 864 982 1671 863 981 1670 855 973 1662 856 974 1663 865 983 1672 864 982 1671 856 974 1663 857 975 1664 866 984 1673 865 983 1672 857 975 1664 858 976 1665 867 985 1674 866 984 1673 859 978 1667 860 977 1666 869 986 1675 868 987 1676 860 977 1666 861 979 1668 870 988 1677 869 986 1675 868 987 1676 869 986 1675 872 989 1678 871 990 1679 869 986 1675 870 988 1677 873 991 1680 872 989 1678 875 992 1681 874 993 1682 864 982 1671 865 983 1672 865 983 1672 866 984 1673 876 994 1683 875 992 1681 866 984 1673 867 985 1674 877 995 1684 876 994 1683 871 990 1679 872 989 1678 879 996 1685 878 997 1686 872 989 1678 873 991 1680 880 998 1687 879 996 1685 882 999 1688 881 1000 1689 874 993 1682 875 992 1681 875 992 1681 876 994 1683 883 1001 1690 882 999 1688 876 994 1683 877 995 1684 884 1002 1691 883 1001 1690 878 997 1686 879 996 1685 886 1003 1692 885 1004 1693 879 996 1685 880 998 1687 887 1005 1694 886 1003 1692 889 1006 1695 888 1007 1696 881 1000 1689 882 999 1688 882 999 1688 883 1001 1690 890 1008 1697 889 1006 1695 883 1001 1690 884 1002 1691 891 1009 1698 890 1008 1697 885 1004 1693 886 1003 1692 893 1010 1699 892 1011 1700 886 1003 1692 887 1005 1694 894 1012 1701 893 1010 1699 1313 1013 1702 888 1007 1696 889 1006 1695 895 1014 1703 889 1006 1695 890 1008 1697 896 1015 1704 895 1014 1703 890 1008 1697 891 1009 1698 1314 1016 1705 896 1015 1704 891 1009 1698 1337 1017 1706 897 1018 1707 1314 1016 1705 1985 1019 1708 1337 1017 1706 320 1020 1709 1986 1021 1710 892 1011 1700 893 1010 1699 899 1022 1711 898 1023 1712 893 1010 1699 894 1012 1701 900 1024 1713 899 1022 1711 1312 1025 1714 1311 1026 1715 906 1027 1716 905 1028 1717 697 808 1497 696 807 1496 907 1029 1718 698 811 1500 697 808 1497 907 1029 1718 699 813 1502 698 811 1500 907 1029 1718 700 815 1504 699 813 1502 907 1029 1718 701 817 1506 700 815 1504 907 1029 1718 702 819 1508 701 817 1506 907 1029 1718 703 821 1510 702 819 1508 907 1029 1718 704 823 1512 703 821 1510 907 1029 1718 705 825 1514 704 823 1512 907 1029 1718 706 827 1516 705 825 1514 907 1029 1718 707 829 1518 706 827 1516 907 1029 1718 707 829 1518 907 1029 1718 1331 831 1520 708 833 1522 1980 836 1525 907 1029 1718 941 1030 312 980 1031 313 1044 1032 314 1007 1033 315 1007 1033 315 1028 1034 316 956 1035 317 941 1030 312 942 1036 318 958 1037 319 1028 1034 316 1007 1033 315 1007 1033 315 1044 1032 314 981 1038 320 942 1036 318 943 1039 321 979 1040 322 1043 1041 323 1008 1042 324 1008 1042 324 1029 1043 325 955 1044 326 943 1039 321 941 1030 312 956 1035 317 1029 1043 325 1008 1042 324 1008 1042 324 1043 1041 323 980 1031 313 941 1030 312 944 1045 327 978 1046 328 1042 1047 329 1009 1048 330 1009 1048 330 1027 1049 331 953 1050 332 944 1045 327 943 1039 321 955 1044 326 1027 1049 331 1009 1048 330 1009 1048 330 1042 1047 329 979 1040 322 943 1039 321 945 1051 333 977 1052 334 1041 1053 335 1010 1054 336 1010 1054 336 1030 1055 337 960 1056 338 945 1051 333 944 1045 327 953 1050 332 1030 1055 337 1010 1054 336 1010 1054 336 1041 1053 335 978 1046 328 944 1045 327 1011 1057 339 1032 1058 340 964 1059 341 946 1060 342 945 1051 333 960 1056 338 1032 1058 340 1011 1057 339 1011 1057 339 946 1060 342 1066 1061 343 1067 1062 344 947 1063 345 976 1064 346 1040 1065 347 1012 1066 348 1012 1066 348 1034 1067 349 968 1068 350 947 1063 345 946 1060 342 964 1059 341 1034 1067 349 1012 1066 348 1012 1066 348 1040 1065 347 1066 1061 343 946 1060 342 948 1069 351 975 1070 352 1039 1071 353 1013 1072 354 1013 1072 354 1036 1073 355 971 1074 356 948 1069 351 947 1063 345 968 1068 350 1036 1073 355 1013 1072 354 1013 1072 354 1039 1071 353 976 1064 346 947 1063 345 949 1075 357 973 1076 358 1038 1077 359 1014 1078 360 1014 1078 360 1035 1079 361 967 1080 362 949 1075 357 948 1069 351 971 1074 356 1035 1079 361 1014 1078 360 1014 1078 360 1038 1077 359 975 1070 352 948 1069 351 950 1081 363 974 1082 364 1037 1083 365 1015 1084 366 1015 1084 366 1033 1085 367 963 1086 368 950 1081 363 949 1075 357 967 1080 362 1033 1085 367 1015 1084 366 1015 1084 366 1037 1083 365 973 1076 358 949 1075 357 942 1036 318 981 1038 320 1045 1087 369 1016 1088 370 1016 1088 370 1031 1089 371 958 1037 319 942 1036 318 950 1081 363 963 1086 368 1031 1089 371 1016 1088 370 1016 1088 370 1045 1087 369 974 1082 364 950 1081 363 1044 1032 314 1038 1077 359 973 1076 358 981 1038 320 986 1090 1719 1048 1091 1720 1907 1092 1721 1906 1093 1722 923 1094 1723 1017 1095 1724 1907 1092 1721 1908 1096 1725 990 1097 1726 1050 1098 1727 1911 1099 1728 1913 1100 1729 925 1101 1730 1018 1102 1731 1911 1099 1728 1909 1103 1732 909 1104 1733 1051 1105 1734 1905 1106 1735 1909 1103 1732 951 1107 1736 1019 1108 1737 1905 1106 1735 1906 1093 1722 908 1109 1738 1052 1110 1739 1910 1111 1740 1908 1096 1725 924 1112 1741 1020 1113 1742 1910 1111 1740 1912 1114 1743 910 1115 1744 1053 1116 1745 1914 1117 1746 1912 1114 1743 926 1118 1747 1021 1119 1748 1914 1117 1746 1916 1120 1749 927 1121 1750 1022 1122 1751 1918 1123 1752 1920 1124 1753 982 1125 1754 1046 1126 1755 1918 1123 1752 1916 1120 1749 984 1127 1756 1047 1128 1757 1922 1129 1758 1920 1124 1753 929 1130 1759 1023 1131 1760 1922 1129 1758 1924 1132 1761 911 1133 1762 1054 1134 1763 1923 1135 1764 1924 1132 1761 930 1136 1765 1024 1137 1766 1923 1135 1764 1921 1138 1767 988 1139 1768 1049 1140 1769 1919 1141 1770 1921 1138 1767 928 1142 1771 1025 1143 1772 1919 1141 1770 1917 1144 1773 912 1145 1774 1055 1146 1775 1915 1147 1776 1917 1144 1773 952 1148 1777 1026 1149 1778 1915 1147 1776 1913 1100 1729 953 1050 332 1027 1049 331 954 1150 969 914 1151 963 954 1152 969 1027 1049 331 955 1044 326 913 1153 967 956 1035 317 1028 1034 316 957 1154 968 916 1155 965 957 1156 968 1028 1034 316 958 1037 319 915 1157 962 955 1044 326 1029 1043 325 959 1158 966 913 1159 967 959 1160 966 1029 1043 325 956 1035 317 916 1161 965 960 1056 338 1030 1055 337 961 1162 964 917 1163 959 961 1164 964 1030 1055 337 953 1050 332 914 1165 963 958 1037 319 1031 1089 371 962 1166 961 915 1167 962 962 1168 961 1031 1089 371 963 1086 368 918 1169 958 964 1059 341 1032 1058 340 965 1170 960 919 1171 955 965 1172 960 1032 1058 340 960 1056 338 917 1173 959 963 1086 368 1033 1085 367 966 1174 957 918 1175 958 966 1176 957 1033 1085 367 967 1080 362 920 1177 954 968 1068 350 1034 1067 349 969 1178 956 921 1179 950 969 1180 956 1034 1067 349 964 1059 341 919 1181 955 967 1080 362 1035 1079 361 970 1182 953 920 1183 954 970 1184 953 1035 1079 361 971 1074 356 922 1185 952 971 1074 356 1036 1073 355 972 1186 951 922 1187 952 972 1188 951 1036 1073 355 968 1068 350 921 1189 950 914 1190 1779 954 1191 1780 1020 1113 1742 924 1112 1741 923 1094 1723 1020 1113 1742 954 1192 1780 913 1193 1781 916 1194 1782 957 1195 1783 1019 1108 1737 951 1107 1736 925 1101 1730 1019 1108 1737 957 1196 1783 915 1197 1784 923 1094 1723 913 1198 1781 959 1199 1785 1017 1095 1724 916 1200 1782 951 1107 1736 1017 1095 1724 959 1201 1785 917 1202 1786 961 1203 1787 1021 1119 1748 926 1118 1747 914 1204 1779 924 1112 1741 1021 1119 1748 961 1205 1787 925 1101 1730 915 1206 1784 962 1207 1788 1018 1102 1731 952 1148 1777 1018 1102 1731 962 1208 1788 918 1209 1789 919 1210 1790 965 1211 1791 1022 1122 1751 927 1121 1750 917 1212 1786 926 1118 1747 1022 1122 1751 965 1213 1791 952 1148 1777 918 1214 1789 966 1215 1792 1026 1149 1778 928 1142 1771 1026 1149 1778 966 1216 1792 920 1217 1793 921 1218 1794 969 1219 1795 1023 1131 1760 929 1130 1759 919 1220 1790 927 1121 1750 1023 1131 1760 969 1221 1795 928 1142 1771 920 1222 1793 970 1223 1796 1025 1143 1772 930 1136 1765 1025 1143 1772 970 1224 1796 922 1225 1797 930 1136 1765 922 1226 1797 972 1227 1798 1024 1137 1766 921 1228 1794 929 1130 1759 1024 1137 1766 972 1229 1798 984 1127 1756 1046 1126 1755 996 1230 1799 932 1231 1800 996 1230 1799 1046 1126 1755 982 1125 1754 931 1232 1801 911 1133 1762 1047 1128 1757 983 1233 1802 933 1234 1803 983 1233 1802 1047 1128 1757 984 1127 1756 932 1231 1800 908 1109 1738 1048 1091 1720 985 1235 1804 935 1236 1805 985 1235 1804 1048 1091 1720 986 1090 1719 934 1237 1806 912 1145 1774 1049 1140 1769 987 1238 1807 937 1239 1808 987 1238 1807 1049 1140 1769 988 1139 1768 936 1240 1809 909 1104 1733 1050 1098 1727 989 1241 1810 939 1242 1811 989 1241 1810 1050 1098 1727 990 1097 1726 938 1243 1812 986 1090 1719 1051 1105 1734 991 1244 1813 934 1237 1806 991 1244 1813 1051 1105 1734 909 1104 1733 939 1242 1811 910 1115 1744 1052 1110 1739 992 1245 1814 940 1246 1815 992 1245 1814 1052 1110 1739 908 1109 1738 935 1236 1805 982 1125 1754 1053 1116 1745 993 1247 1816 931 1232 1801 993 1247 1816 1053 1116 1745 910 1115 1744 940 1246 1815 988 1139 1768 1054 1134 1763 994 1248 1817 936 1240 1809 994 1248 1817 1054 1134 1763 911 1133 1762 933 1234 1803 990 1097 1726 1055 1146 1775 995 1249 1818 938 1243 1812 995 1249 1818 1055 1146 1775 912 1145 1774 937 1239 1808 996 1230 1799 1056 1250 1819 997 1251 1820 932 1231 1800 998 1252 1821 1056 1250 1819 996 1230 1799 931 1232 1801 983 1233 1802 1057 1253 1822 999 1254 1823 933 1234 1803 997 1251 1820 1057 1253 1822 983 1233 1802 932 1231 1800 985 1235 1804 1058 1255 1824 1000 1256 1825 935 1236 1805 1001 1257 1826 1058 1255 1824 985 1235 1804 934 1237 1806 987 1238 1807 1059 1258 1827 1002 1259 1828 937 1239 1808 1003 1260 1829 1059 1258 1827 987 1238 1807 936 1240 1809 989 1241 1810 1060 1261 1830 1004 1262 1831 939 1242 1811 1005 1263 1832 1060 1261 1830 989 1241 1810 938 1243 1812 991 1244 1813 1061 1264 1833 1001 1257 1826 934 1237 1806 1004 1262 1831 1061 1264 1833 991 1244 1813 939 1242 1811 992 1245 1814 1062 1265 1834 1006 1266 1835 940 1246 1815 1000 1256 1825 1062 1265 1834 992 1245 1814 935 1236 1805 993 1247 1816 1063 1267 1836 998 1252 1821 931 1232 1801 1006 1266 1835 1063 1267 1836 993 1247 1816 940 1246 1815 994 1248 1817 1064 1268 1837 1003 1260 1829 936 1240 1809 999 1254 1823 1064 1268 1837 994 1248 1817 933 1234 1803 995 1249 1818 1065 1269 1838 1005 1263 1832 938 1243 1812 1002 1259 1828 1065 1269 1838 995 1249 1818 937 1239 1808 973 1076 358 1037 1083 365 974 1082 364 1045 1087 369 981 1038 320 980 1031 313 1043 1041 323 1039 1071 353 975 1070 352 1044 1032 314 980 1031 313 975 1070 352 1038 1077 359 1043 1041 323 979 1040 322 976 1064 346 1039 1071 353 978 1046 328 1041 1053 335 977 1052 334 1067 1062 344 1066 1061 343 979 1040 322 1042 1047 329 1040 1065 347 976 1064 346 1011 1057 339 1067 1062 344 977 1052 334 945 1051 333 978 1046 328 1066 1061 343 1040 1065 347 1042 1047 329 997 1251 1820 1056 1250 1819 904 1270 1839 903 1271 1840 1056 1250 1819 998 1252 1821 1313 1013 1702 904 1270 1839 999 1254 1823 1057 1253 1822 902 1272 1841 901 1273 1842 1000 1256 1825 1058 1255 1824 863 981 1670 864 982 1671 1058 1255 1824 1001 1257 1826 853 971 1660 863 981 1670 1002 1259 1828 1059 1258 1827 887 1005 1694 880 998 1687 1059 1258 1827 1003 1260 1829 894 1012 1701 887 1005 1694 1004 1262 1831 1060 1261 1830 862 980 1669 851 969 1658 1060 1261 1830 1005 1263 1832 870 988 1677 862 980 1669 1001 1257 1826 1061 1264 1833 852 970 1659 853 971 1660 1061 1264 1833 1004 1262 1831 851 969 1658 852 970 1659 1006 1266 1835 1062 1265 1834 874 993 1682 881 1000 1689 1062 1265 1834 1000 1256 1825 864 982 1671 874 993 1682 1063 1267 1836 1006 1266 1835 881 1000 1689 888 1007 1696 1003 1260 1829 1064 1268 1837 900 1024 1713 894 1012 1701 1064 1268 1837 999 1254 1823 901 1273 1842 900 1024 1713 1005 1263 1832 1065 1269 1838 873 991 1680 870 988 1677 1065 1269 1838 1002 1259 1828 880 998 1687 873 991 1680 1057 1253 1822 997 1251 1820 903 1271 1840 902 1272 1841 870 988 1677 861 979 1668 862 980 1669 862 980 1669 850 968 1657 851 969 1658 1063 1267 1836 888 1007 1696 1313 1013 1702 998 1252 1821 1116 1274 372 1237 1275 373 1117 1276 374 1151 1277 375 1237 1275 373 1152 1278 376 1117 1276 374 1153 1279 377 1238 1280 378 1092 1281 379 1070 1282 380 1308 1283 381 1238 1280 378 1153 1279 377 1309 1284 382 1153 1279 377 1239 1285 383 1310 1286 384 1309 1284 382 1110 1287 385 1287 1288 386 1239 1285 383 1093 1289 387 1093 1289 387 1239 1285 383 1153 1279 377 1070 1282 380 1219 1290 388 1118 1291 389 1154 1292 390 1297 1293 391 1113 1294 392 1115 1295 393 1297 1293 391 1154 1292 390 1120 1296 394 1112 1297 395 1150 1298 396 1155 1299 397 1071 1300 398 1155 1299 397 1150 1301 396 1069 1302 399 1154 1292 390 1240 1303 400 1156 1304 401 1113 1305 392 1156 1306 401 1240 1303 400 1277 1307 402 1114 1308 403 1277 1307 402 1240 1303 400 1157 1309 404 1222 1310 405 1157 1309 404 1240 1303 400 1154 1292 390 1118 1291 389 1218 1311 406 1121 1312 407 1158 1313 408 1274 1314 409 1219 1290 388 1274 1314 409 1158 1313 408 1118 1291 389 1159 1315 410 1241 1316 411 1160 1317 412 1123 1318 413 1160 1317 412 1241 1316 411 1245 1319 414 1124 1320 415 1245 1319 414 1241 1316 411 1161 1321 416 1161 1321 416 1241 1316 411 1159 1315 410 1122 1322 417 1162 1323 418 1242 1324 419 1119 1325 420 1120 1296 394 1220 1326 421 1242 1324 419 1162 1323 418 1125 1327 422 1162 1323 418 1243 1328 423 1163 1329 424 1125 1327 422 1163 1329 424 1243 1328 423 1094 1330 425 1072 1331 426 1094 1330 425 1243 1328 423 1155 1299 397 1071 1300 398 1155 1299 397 1243 1328 423 1162 1323 418 1120 1296 394 1278 1332 427 1244 1333 428 1164 1334 429 1223 1335 430 1164 1334 429 1244 1333 428 1158 1313 408 1121 1312 407 1158 1313 408 1244 1333 428 1157 1309 404 1118 1291 389 1157 1309 404 1244 1333 428 1278 1332 427 1222 1310 405 1124 1320 415 1245 1319 414 1165 1336 431 1126 1337 432 1165 1336 431 1245 1319 414 1166 1338 433 1208 1339 434 1129 1340 435 1167 1341 436 1128 1342 437 1167 1341 436 1129 1340 435 1296 1343 438 1209 1344 439 1168 1345 440 1246 1346 441 1095 1347 442 1073 1348 443 1095 1347 442 1246 1346 441 1266 1349 444 1074 1350 445 1266 1349 444 1246 1346 441 1167 1341 436 1209 1344 439 1167 1341 436 1246 1346 441 1168 1345 440 1128 1342 437 1228 1351 446 1247 1352 447 1170 1353 448 1131 1354 449 1170 1353 448 1247 1352 447 1169 1355 450 1130 1356 451 1171 1357 452 1248 1358 453 1172 1359 454 1132 1360 455 1172 1359 454 1248 1358 453 1237 1275 373 1116 1274 372 1171 1357 452 1301 1361 456 1174 1362 457 1248 1358 453 1237 1275 373 1248 1358 453 1173 1363 458 1152 1278 376 1173 1363 458 1248 1358 453 1174 1362 457 1133 1364 459 1175 1365 460 1249 1366 461 1307 1367 462 1306 1368 463 1307 1367 462 1249 1366 461 1238 1280 378 1308 1283 381 1238 1280 378 1249 1366 461 1096 1369 464 1092 1281 379 1096 1369 464 1249 1366 461 1175 1365 460 1075 1370 465 1218 1311 406 1273 1371 466 1176 1372 467 1121 1312 407 1134 1373 468 1135 1374 469 1176 1372 467 1273 1371 466 1177 1375 470 1250 1376 471 1178 1377 472 1136 1378 473 1178 1377 472 1250 1376 471 1179 1379 474 1137 1380 475 1179 1379 474 1250 1376 471 1171 1357 452 1132 1360 455 1180 1381 476 1251 1382 477 1177 1375 470 1136 1378 473 1181 1383 478 1235 1384 479 1174 1362 457 1301 1361 456 1181 1383 478 1251 1382 477 1182 1385 480 1126 1337 432 1182 1385 480 1251 1382 477 1180 1381 476 1138 1386 481 1183 1387 482 1252 1388 483 1179 1379 474 1132 1360 455 1179 1379 474 1252 1388 483 1184 1389 484 1137 1380 475 1184 1389 484 1252 1388 483 1286 1390 485 1232 1391 486 1286 1390 485 1252 1388 483 1183 1387 482 1233 1392 487 1139 1393 488 1217 1394 489 1272 1395 490 1185 1396 491 1216 1397 492 1140 1398 493 1185 1396 491 1272 1395 490 1186 1399 494 1253 1400 495 1187 1401 496 1142 1402 497 1187 1401 496 1253 1400 495 1188 1403 498 1144 1404 499 1188 1403 498 1253 1400 495 1189 1405 500 1143 1406 501 1189 1405 500 1253 1400 495 1186 1399 494 1141 1407 502 1190 1408 503 1254 1409 504 1191 1410 505 1145 1411 506 1191 1410 505 1254 1409 504 1192 1412 507 1130 1356 451 1192 1412 507 1254 1409 504 1186 1399 494 1142 1402 497 1186 1399 494 1254 1409 504 1190 1408 503 1141 1407 502 1193 1413 508 1255 1414 509 1281 1415 510 1225 1416 511 1281 1415 510 1255 1414 509 1194 1417 512 1226 1418 513 1194 1417 512 1255 1414 509 1185 1396 491 1140 1398 493 1185 1396 491 1255 1414 509 1193 1413 508 1139 1393 488 1195 1419 514 1256 1420 515 1188 1403 498 1143 1406 501 1188 1403 498 1256 1420 515 1196 1421 516 1144 1404 499 1196 1421 516 1256 1420 515 1284 1422 517 1230 1423 518 1284 1422 517 1256 1420 515 1195 1419 514 1231 1424 519 1216 1397 492 1271 1425 520 1194 1417 512 1140 1398 493 1227 1426 521 1226 1418 513 1194 1417 512 1271 1425 520 1197 1427 522 1257 1428 523 1283 1429 524 1229 1430 525 1283 1429 524 1257 1428 523 1196 1421 516 1230 1423 518 1196 1421 516 1257 1428 523 1187 1401 496 1144 1404 499 1187 1401 496 1257 1428 523 1197 1427 522 1142 1402 497 1198 1431 526 1258 1432 527 1220 1326 421 1125 1327 422 1221 1433 528 1258 1432 527 1198 1431 526 1146 1434 529 1200 1435 530 1259 1436 531 1199 1437 532 1147 1438 533 1174 1362 457 1260 1439 534 1201 1440 535 1133 1364 459 1302 1441 536 1304 1442 537 1305 1443 538 1201 1440 535 1198 1431 526 1261 1444 539 1203 1445 540 1146 1434 529 1203 1445 540 1261 1444 539 1097 1446 541 1076 1447 542 1097 1446 541 1261 1444 539 1163 1329 424 1072 1331 426 1163 1329 424 1261 1444 539 1198 1431 526 1125 1327 422 1305 1443 538 1262 1448 543 1175 1365 460 1306 1368 463 1175 1365 460 1262 1448 543 1098 1449 544 1075 1370 465 1098 1449 544 1262 1448 543 1204 1450 545 1077 1451 546 1204 1450 545 1262 1448 543 1305 1443 538 1304 1442 537 1148 1452 547 1276 1453 548 1221 1433 528 1146 1434 529 1199 1437 532 1206 1454 549 1205 1455 550 1147 1438 533 1265 1456 551 1303 1457 552 1304 1442 537 1302 1441 536 1078 1458 553 1263 1459 554 1203 1445 540 1076 1447 542 1203 1445 540 1263 1459 554 1148 1452 547 1146 1434 529 1204 1450 545 1264 1460 555 1099 1461 556 1077 1451 546 1303 1457 552 1264 1460 555 1204 1450 545 1304 1442 537 1206 1454 549 1129 1340 435 1208 1339 434 1205 1455 550 1074 1350 445 1266 1349 444 1263 1459 554 1078 1458 553 1263 1459 554 1266 1349 444 1209 1344 439 1148 1452 547 1279 1462 557 1267 1463 558 1210 1464 559 1224 1465 560 1210 1464 559 1267 1463 558 1176 1372 467 1135 1374 469 1176 1372 467 1267 1463 558 1164 1334 429 1121 1312 407 1164 1334 429 1267 1463 558 1279 1462 557 1223 1335 430 1285 1466 561 1268 1467 562 1184 1389 484 1232 1391 486 1184 1389 484 1268 1467 562 1211 1468 563 1137 1380 475 1211 1468 563 1268 1467 562 1195 1419 514 1143 1406 501 1195 1419 514 1268 1467 562 1285 1466 561 1231 1424 519 1149 1469 564 1269 1470 565 1212 1471 566 1145 1411 506 1212 1471 566 1269 1470 565 1213 1472 567 1138 1386 481 1134 1373 468 1300 1473 568 1214 1474 569 1135 1374 469 1139 1393 488 1214 1474 569 1300 1473 568 1217 1394 489 1215 1475 570 1270 1476 571 1189 1405 500 1141 1407 502 1189 1405 500 1270 1476 571 1211 1468 563 1143 1406 501 1211 1468 563 1270 1476 571 1178 1377 472 1137 1380 475 1178 1377 472 1270 1476 571 1215 1475 570 1136 1378 473 1227 1426 521 1271 1425 520 1247 1352 447 1228 1351 446 1247 1352 447 1271 1425 520 1216 1397 492 1169 1355 450 1216 1397 492 1272 1395 490 1293 1477 572 1169 1355 450 1293 1477 572 1272 1395 490 1217 1394 489 1149 1469 564 1134 1373 468 1273 1371 466 1290 1478 573 1213 1472 567 1290 1478 573 1273 1371 466 1218 1311 406 1124 1320 415 1218 1311 406 1274 1314 409 1160 1317 412 1124 1320 415 1160 1317 412 1274 1314 409 1219 1290 388 1123 1318 413 1115 1479 393 1275 1480 574 1159 1315 410 1123 1318 413 1330 1481 575 1161 1321 416 1122 1322 417 1259 1436 531 1258 1432 527 1221 1433 528 1199 1437 532 1221 1433 528 1276 1453 548 1206 1454 549 1199 1437 532 1276 1453 548 1296 1343 438 1129 1340 435 1206 1454 549 1114 1482 403 1277 1307 402 1100 1483 576 1068 1484 577 1100 1483 576 1277 1307 402 1222 1310 405 1079 1485 578 1222 1310 405 1278 1332 427 1101 1486 579 1079 1485 578 1101 1486 579 1278 1332 427 1223 1335 430 1080 1487 580 1223 1335 430 1279 1462 557 1102 1488 581 1080 1487 580 1102 1488 581 1279 1462 557 1224 1465 560 1081 1489 582 1224 1465 560 1280 1490 583 1103 1491 584 1081 1489 582 1103 1491 584 1280 1490 583 1225 1416 511 1082 1492 585 1225 1416 511 1281 1415 510 1104 1493 586 1082 1492 585 1104 1493 586 1281 1415 510 1226 1418 513 1083 1494 587 1083 1494 587 1226 1418 513 1227 1426 521 1084 1495 588 1084 1495 588 1227 1426 521 1228 1351 446 1085 1496 589 1131 1354 449 1282 1497 590 1105 1498 591 1087 1499 592 1105 1498 591 1282 1497 590 1229 1430 525 1086 1500 593 1106 1501 594 1283 1429 524 1230 1423 518 1088 1502 595 1229 1430 525 1283 1429 524 1106 1501 594 1086 1500 593 1230 1423 518 1284 1422 517 1107 1503 596 1088 1502 595 1107 1503 596 1284 1422 517 1231 1424 519 1089 1504 597 1108 1505 598 1285 1466 561 1232 1391 486 1090 1506 599 1231 1424 519 1285 1466 561 1108 1505 598 1089 1504 597 1232 1391 486 1286 1390 485 1109 1507 600 1090 1506 599 1109 1507 600 1286 1390 485 1233 1392 487 1091 1508 601 1233 1392 487 1287 1288 386 1110 1287 385 1091 1508 601 1168 1345 440 1288 1509 602 1234 1510 603 1128 1342 437 1234 1510 603 1288 1509 602 1264 1460 555 1303 1457 552 1264 1460 555 1288 1509 602 1111 1511 604 1099 1461 556 1111 1511 604 1288 1509 602 1168 1345 440 1073 1348 443 1085 1496 589 1228 1351 446 1131 1354 449 1087 1499 592 1200 1435 530 1289 1512 605 1235 1384 479 1127 1513 606 1235 1384 479 1289 1512 605 1260 1439 534 1174 1362 457 1260 1439 534 1289 1512 605 1236 1514 607 1202 1515 608 1236 1514 607 1289 1512 605 1200 1435 530 1147 1438 533 1213 1472 567 1290 1478 573 1182 1385 480 1138 1386 481 1126 1337 432 1182 1385 480 1290 1478 573 1124 1320 415 1205 1455 550 1291 1516 609 1236 1514 607 1147 1438 533 1236 1514 607 1291 1516 609 1207 1517 610 1202 1515 608 1215 1475 570 1292 1518 611 1180 1381 476 1136 1378 473 1180 1381 476 1292 1518 611 1212 1471 566 1138 1386 481 1212 1471 566 1292 1518 611 1190 1408 503 1145 1411 506 1190 1408 503 1292 1518 611 1215 1475 570 1141 1407 502 1208 1339 434 1294 1519 612 1291 1516 609 1205 1455 550 1291 1516 609 1294 1519 612 1265 1456 551 1207 1517 610 1169 1355 450 1293 1477 572 1191 1410 505 1130 1356 451 1191 1410 505 1293 1477 572 1149 1469 564 1145 1411 506 1234 1510 603 1294 1519 612 1208 1339 434 1128 1342 437 1282 1497 590 1295 1520 613 1197 1427 522 1229 1430 525 1197 1427 522 1295 1520 613 1192 1412 507 1142 1402 497 1192 1412 507 1295 1520 613 1170 1353 448 1130 1356 451 1170 1353 448 1295 1520 613 1282 1497 590 1131 1354 449 1209 1344 439 1296 1343 438 1276 1453 548 1148 1452 547 1219 1290 388 1297 1293 391 1115 1521 393 1123 1318 413 1235 1384 479 1181 1383 478 1126 1337 432 1165 1336 431 1127 1513 606 1183 1387 482 1298 1522 614 1287 1288 386 1233 1392 487 1287 1288 386 1298 1522 614 1239 1285 383 1239 1285 383 1298 1522 614 1310 1286 384 1172 1359 454 1298 1522 614 1183 1387 482 1132 1360 455 1210 1464 559 1299 1523 615 1280 1490 583 1224 1465 560 1280 1490 583 1299 1523 615 1193 1413 508 1225 1416 511 1193 1413 508 1299 1523 615 1214 1474 569 1139 1393 488 1214 1474 569 1299 1523 615 1210 1464 559 1135 1374 469 1217 1394 489 1300 1473 568 1269 1470 565 1149 1469 564 1269 1470 565 1300 1473 568 1134 1373 468 1213 1472 567 1301 1361 456 1177 1375 470 1251 1382 477 1181 1383 478 1171 1357 452 1250 1376 471 1177 1375 470 1301 1361 456 1202 1515 608 1207 1517 610 1265 1456 551 1302 1441 536 1201 1440 535 1260 1439 534 1202 1515 608 1302 1441 536 1265 1456 551 1294 1519 612 1234 1510 603 1303 1457 552 1201 1440 535 1305 1443 538 1306 1368 463 1133 1364 459 1307 1367 462 1173 1363 458 1133 1364 459 1306 1368 463 1173 1363 458 1307 1367 462 1308 1283 381 1152 1278 376 1152 1278 376 1308 1283 381 1309 1284 382 1117 1276 374 1310 1286 384 1116 1274 372 1117 1276 374 1309 1284 382 1298 1522 614 1172 1359 454 1116 1274 372 1310 1286 384 1068 1524 1843 1319 1525 1844 1318 1526 1845 1114 1527 1846 902 1272 1841 1321 1528 1847 1318 1526 1845 906 1027 1716 902 1272 1841 906 1027 1716 1311 1026 1715 901 1273 1842 1311 1026 1715 899 1022 1711 900 1024 1713 901 1273 1842 898 1023 1712 899 1022 1711 1311 1026 1715 1312 1025 1714 1113 1529 1848 1322 1530 1849 1323 1531 1850 1115 1532 1851 1313 1013 1702 1324 1533 1852 1323 1531 1850 904 1270 1839 1316 1534 1853 1325 1535 1854 1326 1536 1855 1317 1537 1856 1315 1538 1857 1320 1539 1858 1332 1540 1859 897 1018 1707 903 1271 1840 1322 1530 1849 1321 1528 1847 902 1272 1841 895 1014 1703 1325 1535 1854 1324 1533 1852 1313 1013 1702 1159 1315 410 1275 1541 574 1316 1542 616 1122 1322 417 1120 1296 394 1119 1325 420 1317 1543 617 1112 1544 395 1314 1016 1705 1327 1545 1860 1326 1536 1855 896 1015 1704 1317 1546 617 1119 1325 420 1122 1322 417 1316 1547 616 906 1027 1716 1318 1526 1845 1319 1525 1844 905 1028 1717 1150 1548 1861 1332 1540 1859 1320 1539 1858 1069 1549 1862 1114 1550 1846 1318 1526 1845 1321 1528 1847 1156 1551 1863 1156 1552 1863 1321 1528 1847 1322 1530 1849 1113 1553 1848 904 1270 1839 1323 1531 1850 1322 1530 1849 903 1271 1840 1115 1554 1851 1323 1531 1850 1324 1533 1852 1275 1555 1864 1275 1556 1864 1324 1533 1852 1325 1535 1854 1316 1557 1853 896 1015 1704 1326 1536 1855 1325 1535 1854 895 1014 1703 1317 1558 1856 1326 1536 1855 1327 1545 1860 1112 1559 1865 1112 1560 1865 1327 1545 1860 1332 1540 1859 1150 1561 1861 1328 1562 618 1259 1436 531 1200 1435 530 1127 1513 606 1220 1326 421 1258 1432 527 1259 1436 531 1328 1562 618 1329 1563 619 1242 1324 419 1220 1326 421 1328 1562 618 1166 1338 433 1328 1562 618 1127 1513 606 1165 1336 431 1330 1481 575 1329 1563 619 1328 1562 618 1166 1338 433 1119 1325 420 1329 1563 619 1330 1481 575 1122 1322 417 1119 1325 420 1242 1324 419 1329 1563 619 1161 1321 416 1330 1481 575 1166 1338 433 1245 1319 414 1314 1016 1705 897 1018 1707 1332 1540 1859 1327 1545 1860 720 830 1519 721 832 1521 1333 849 1538 734 848 1537 734 848 1537 1333 849 1538 1334 863 1552 747 862 1551 747 862 1551 1334 863 1552 1335 877 1566 760 876 1565 760 876 1565 1335 877 1566 1336 891 1580 773 890 1579 773 890 1579 1336 891 1580 2 361 1172 786 904 1593 786 904 1593 2 361 1172 86 364 1175 798 916 1605 884 1002 1691 320 1020 1709 1337 1017 1706 891 1009 1698 696 807 1496 709 810 1499 1349 1564 1866 1338 1565 1867 1338 1565 1867 1349 1564 1866 1350 1566 1868 1339 1567 1869 1339 1567 1869 1350 1566 1868 1351 1568 1870 1340 1569 1871 1340 1569 1871 1351 1568 1870 1352 1570 1872 1341 1571 1873 1341 1571 1873 1352 1570 1872 1353 1572 1874 1342 1573 1875 1342 1573 1875 1353 1572 1874 1354 1574 1876 1343 1575 1877 1343 1575 1877 1354 1574 1876 1355 1576 1878 1344 1577 1879 1344 1577 1879 1355 1576 1878 1356 1578 1880 1345 1579 1881 1345 1579 1881 1356 1578 1880 1357 1580 1882 1346 1581 1883 1346 1581 1883 1357 1580 1882 1358 1582 1884 1347 1583 1885 1347 1583 1885 1358 1582 1884 1359 1584 1886 1348 1585 1887 1348 1585 1887 1359 1584 1886 1360 1586 1888 1897 1587 1889 1897 1587 1889 1360 1586 1888 1972 1588 1890 1973 1589 1891 709 810 1499 723 838 1527 1361 1590 1892 1349 1564 1866 1349 1564 1866 1361 1590 1892 1362 1591 1893 1350 1566 1868 1350 1566 1868 1362 1591 1893 1363 1592 1894 1351 1568 1870 1351 1568 1870 1363 1592 1894 1364 1593 1895 1352 1570 1872 1352 1570 1872 1364 1593 1895 1365 1594 1896 1353 1572 1874 1353 1572 1874 1365 1594 1896 1366 1595 1897 1354 1574 1876 1354 1574 1876 1366 1595 1897 1367 1596 1898 1355 1576 1878 1355 1576 1878 1367 1596 1898 1368 1597 1899 1356 1578 1880 1356 1578 1880 1368 1597 1899 1369 1598 1900 1357 1580 1882 1357 1580 1882 1369 1598 1900 1370 1599 1901 1358 1582 1884 1358 1582 1884 1370 1599 1901 1371 1600 1902 1359 1584 1886 1360 1586 1888 1899 1601 1903 1975 1602 1904 1972 1588 1890 723 838 1527 736 852 1541 1372 1603 1905 1361 1590 1892 1361 1590 1892 1372 1603 1905 1373 1604 1906 1362 1591 1893 1362 1591 1893 1373 1604 1906 1374 1605 1907 1363 1592 1894 1363 1592 1894 1374 1605 1907 1375 1606 1908 1364 1593 1895 1364 1593 1895 1375 1606 1908 1376 1607 1909 1365 1594 1896 1365 1594 1896 1376 1607 1909 1377 1608 1910 1366 1595 1897 1366 1595 1897 1377 1608 1910 1378 1609 1911 1367 1596 1898 1367 1596 1898 1378 1609 1911 1379 1610 1912 1368 1597 1899 1368 1597 1899 1379 1610 1912 1380 1611 1913 1369 1598 1900 1369 1598 1900 1380 1611 1913 1381 1612 1914 1370 1599 1901 1370 1599 1901 1381 1612 1914 1382 1613 1915 1371 1600 1902 1899 1601 1903 1900 1614 1916 1976 1615 1917 1975 1602 1904 736 852 1541 749 866 1555 1383 1616 1918 1372 1603 1905 1372 1603 1905 1383 1616 1918 1384 1617 1919 1373 1604 1906 1373 1604 1906 1384 1617 1919 1385 1618 1920 1374 1605 1907 1374 1605 1907 1385 1618 1920 1386 1619 1921 1375 1606 1908 1375 1606 1908 1386 1619 1921 1387 1620 1922 1376 1607 1909 1376 1607 1909 1387 1620 1922 1388 1621 1923 1377 1608 1910 1377 1608 1910 1388 1621 1923 1389 1622 1924 1378 1609 1911 1378 1609 1911 1389 1622 1924 1390 1623 1925 1379 1610 1912 1379 1610 1912 1390 1623 1925 1391 1624 1926 1380 1611 1913 1380 1611 1913 1391 1624 1926 1392 1625 1927 1381 1612 1914 1381 1612 1914 1392 1625 1927 1393 1626 1928 1382 1613 1915 1900 1614 1916 1901 1627 1929 1977 1628 1930 1976 1615 1917 749 866 1555 762 880 1569 1394 1629 1931 1383 1616 1918 1383 1616 1918 1394 1629 1931 1395 1630 1932 1384 1617 1919 1384 1617 1919 1395 1630 1932 1396 1631 1933 1385 1618 1920 1385 1618 1920 1396 1631 1933 1397 1632 1934 1386 1619 1921 1386 1619 1921 1397 1632 1934 1398 1633 1935 1387 1620 1922 1387 1620 1922 1398 1633 1935 1399 1634 1936 1388 1621 1923 1388 1621 1923 1399 1634 1936 1400 1635 1937 1389 1622 1924 1389 1622 1924 1400 1635 1937 1401 1636 1938 1390 1623 1925 1390 1623 1925 1401 1636 1938 1402 1637 1939 1391 1624 1926 1391 1624 1926 1402 1637 1939 1403 1638 1940 1392 1625 1927 1392 1625 1927 1403 1638 1940 1404 1639 1941 1393 1626 1928 1901 1627 1929 1902 1640 1942 1974 1641 1943 1977 1628 1930 762 880 1569 775 894 1583 1405 1642 1944 1394 1629 1931 1394 1629 1931 1405 1642 1944 1406 1643 1945 1395 1630 1932 1395 1630 1932 1406 1643 1945 1407 1644 1946 1396 1631 1933 1396 1631 1933 1407 1644 1946 1408 1645 1947 1397 1632 1934 1397 1632 1934 1408 1645 1947 1409 1646 1948 1398 1633 1935 1398 1633 1935 1409 1646 1948 1410 1647 1949 1399 1634 1936 1399 1634 1936 1410 1647 1949 1411 1648 1950 1400 1635 1937 1400 1635 1937 1411 1648 1950 1412 1649 1951 1401 1636 1938 1401 1636 1938 1412 1649 1951 1413 1650 1952 1402 1637 1939 1402 1637 1939 1413 1650 1952 1414 1651 1953 1403 1638 1940 1403 1638 1940 1414 1651 1953 1415 1652 1954 1404 1639 1941 2043 435 1231 2044 1653 1955 1974 1641 1943 434 436 1232 775 894 1583 787 906 1595 1416 1654 1956 1405 1642 1944 1405 1642 1944 1416 1654 1956 1417 1655 1957 1406 1643 1945 1406 1643 1945 1417 1655 1957 1418 1656 1958 1407 1644 1946 1407 1644 1946 1418 1656 1958 1419 1657 1959 1408 1645 1947 1408 1645 1947 1419 1657 1959 1420 1658 1960 1409 1646 1948 1409 1646 1948 1420 1658 1960 1421 1659 1961 1410 1647 1949 1410 1647 1949 1421 1659 1961 1422 1660 1962 1411 1648 1950 1411 1648 1950 1422 1660 1962 1423 1661 1963 1412 1649 1951 1412 1649 1951 1423 1661 1963 1424 1662 1964 1413 1650 1952 1413 1650 1952 1424 1662 1964 1425 1663 1965 1414 1651 1953 1414 1651 1953 1425 1663 1965 1426 1664 1966 1415 1652 1954 787 906 1595 799 918 1607 1427 1665 1967 1416 1654 1956 1416 1654 1956 1427 1665 1967 1428 1666 1968 1417 1655 1957 1417 1655 1957 1428 1666 1968 1429 1667 1969 1418 1656 1958 1418 1656 1958 1429 1667 1969 1430 1668 1970 1419 1657 1959 1419 1657 1959 1430 1668 1970 1431 1669 1971 1420 1658 1960 1420 1658 1960 1431 1669 1971 1432 1670 1972 1421 1659 1961 1421 1659 1961 1432 1670 1972 1433 1671 1973 1422 1660 1962 1422 1660 1962 1433 1671 1973 1434 1672 1974 1423 1661 1963 1423 1661 1963 1434 1672 1974 1435 1673 1975 1424 1662 1964 1424 1662 1964 1435 1673 1975 1436 1674 1976 1425 1663 1965 1425 1663 1965 1436 1674 1976 1437 1675 1977 1426 1664 1966 799 918 1607 811 930 1619 1438 1676 1978 1427 1665 1967 1427 1665 1967 1438 1676 1978 1439 1677 1979 1428 1666 1968 1428 1666 1968 1439 1677 1979 1440 1678 1980 1429 1667 1969 1429 1667 1969 1440 1678 1980 1441 1679 1981 1430 1668 1970 1430 1668 1970 1441 1679 1981 1442 1680 1982 1431 1669 1971 1431 1669 1971 1442 1680 1982 1443 1681 1983 1432 1670 1972 1432 1670 1972 1443 1681 1983 1444 1682 1984 1433 1671 1973 1433 1671 1973 1444 1682 1984 1445 1683 1985 1434 1672 1974 1434 1672 1974 1445 1683 1985 1446 1684 1986 1435 1673 1975 1435 1673 1975 1446 1684 1986 1447 1685 1987 1436 1674 1976 1436 1674 1976 1447 1685 1987 1448 1686 1988 1437 1675 1977 811 930 1619 823 942 1631 1449 1687 1989 1438 1676 1978 1438 1676 1978 1449 1687 1989 1450 1688 1990 1439 1677 1979 1439 1677 1979 1450 1688 1990 1451 1689 1991 1440 1678 1980 1440 1678 1980 1451 1689 1991 1452 1690 1992 1441 1679 1981 1441 1679 1981 1452 1690 1992 1453 1691 1993 1442 1680 1982 1442 1680 1982 1453 1691 1993 1454 1692 1994 1443 1681 1983 1443 1681 1983 1454 1692 1994 1455 1693 1995 1444 1682 1984 1444 1682 1984 1455 1693 1995 1456 1694 1996 1445 1683 1985 1445 1683 1985 1456 1694 1996 1457 1695 1997 1446 1684 1986 1446 1684 1986 1457 1695 1997 1458 1696 1998 1447 1685 1987 1447 1685 1987 1458 1696 1998 1459 1697 1999 1448 1686 1988 823 942 1631 846 954 1643 1460 1698 2000 1449 1687 1989 1449 1687 1989 1460 1698 2000 1461 1699 2001 1450 1688 1990 1450 1688 1990 1461 1699 2001 1462 1700 2002 1451 1689 1991 1451 1689 1991 1462 1700 2002 1463 1701 2003 1452 1690 1992 1452 1690 1992 1463 1701 2003 1464 1702 2004 1453 1691 1993 1453 1691 1993 1464 1702 2004 1465 1703 2005 1454 1692 1994 1454 1692 1994 1465 1703 2005 1466 1704 2006 1455 1693 1995 1455 1693 1995 1466 1704 2006 1467 1705 2007 1456 1694 1996 1456 1694 1996 1467 1705 2007 1468 1706 2008 1457 1695 1997 1457 1695 1997 1468 1706 2008 1469 1707 2009 1458 1696 1998 1458 1696 1998 1469 1707 2009 1470 1708 2010 1459 1697 1999 846 954 1643 847 966 1655 1471 1709 2011 1460 1698 2000 1460 1698 2000 1471 1709 2011 1472 1710 2012 1461 1699 2001 1461 1699 2001 1472 1710 2012 1473 1711 2013 1462 1700 2002 1462 1700 2002 1473 1711 2013 1474 1712 2014 1463 1701 2003 1463 1701 2003 1474 1712 2014 1475 1713 2015 1464 1702 2004 1464 1702 2004 1475 1713 2015 1476 1714 2016 1465 1703 2005 1465 1703 2005 1476 1714 2016 1477 1715 2017 1466 1704 2006 1466 1704 2006 1477 1715 2017 1478 1716 2018 1467 1705 2007 1467 1705 2007 1478 1716 2018 1479 1717 2019 1468 1706 2008 1468 1706 2008 1479 1717 2019 1480 1718 2020 1469 1707 2009 1469 1707 2009 1480 1718 2020 1481 1719 2021 1470 1708 2010 847 966 1655 859 978 1667 1482 1720 2022 1471 1709 2011 1471 1709 2011 1482 1720 2022 1483 1721 2023 1472 1710 2012 1472 1710 2012 1483 1721 2023 1484 1722 2024 1473 1711 2013 1476 1714 2016 1485 1723 2025 1477 1715 2017 1477 1715 2017 1485 1723 2025 1488 1724 2026 1478 1716 2018 1478 1716 2018 1488 1724 2026 1489 1725 2027 1479 1717 2019 1479 1717 2019 1489 1725 2027 1490 1726 2028 1480 1718 2020 1480 1718 2020 1490 1726 2028 1491 1727 2029 1481 1719 2021 859 978 1667 868 987 1676 1486 1728 2030 1482 1720 2022 1482 1720 2022 1486 1728 2030 1487 1729 2031 1483 1721 2023 868 987 1676 871 990 1679 1492 1730 2032 1486 1728 2030 1486 1728 2030 1492 1730 2032 1493 1731 2033 1487 1729 2031 1495 1732 2034 1489 1725 2027 1488 1724 2026 1494 1733 2035 1489 1725 2027 1495 1732 2034 1496 1734 2036 1490 1726 2028 1490 1726 2028 1496 1734 2036 1497 1735 2037 1491 1727 2029 871 990 1679 878 997 1686 1498 1736 2038 1492 1730 2032 1492 1730 2032 1498 1736 2038 1499 1737 2039 1493 1731 2033 1501 1738 2040 1495 1732 2034 1494 1733 2035 1500 1739 2041 1495 1732 2034 1501 1738 2040 1502 1740 2042 1496 1734 2036 1496 1734 2036 1502 1740 2042 1503 1741 2043 1497 1735 2037 878 997 1686 885 1004 1693 1504 1742 2044 1498 1736 2038 1498 1736 2038 1504 1742 2044 1505 1743 2045 1499 1737 2039 1507 1744 2046 1501 1738 2040 1500 1739 2041 1506 1745 2047 1501 1738 2040 1507 1744 2046 1508 1746 2048 1502 1740 2042 1502 1740 2042 1508 1746 2048 1509 1747 2049 1503 1741 2043 885 1004 1693 892 1011 1700 1510 1748 2050 1504 1742 2044 1504 1742 2044 1510 1748 2050 1511 1749 2051 1505 1743 2045 1882 1750 2052 1512 1751 2053 1507 1744 2046 1506 1745 2047 1507 1744 2046 1512 1751 2053 1513 1752 2054 1508 1746 2048 1508 1746 2048 1513 1752 2054 1883 1753 2055 1509 1747 2049 1509 1747 2049 1883 1753 2055 1514 1754 2056 1904 1755 2057 1904 1755 2057 1985 1019 1708 1986 1021 1710 1903 1756 2058 892 1011 1700 898 1023 1712 1515 1757 2059 1510 1748 2050 1510 1748 2050 1515 1757 2059 1516 1758 2060 1511 1749 2051 1312 1025 1714 905 1028 1717 1521 1759 2061 1881 1760 2062 1338 1565 1867 907 1029 1718 696 807 1496 1339 1567 1869 907 1029 1718 1338 1565 1867 1340 1569 1871 907 1029 1718 1339 1567 1869 1341 1571 1873 907 1029 1718 1340 1569 1871 1342 1573 1875 907 1029 1718 1341 1571 1873 1343 1575 1877 907 1029 1718 1342 1573 1875 1344 1577 1879 907 1029 1718 1343 1575 1877 1345 1579 1881 907 1029 1718 1344 1577 1879 1346 1581 1883 907 1029 1718 1345 1579 1881 1347 1583 1885 907 1029 1718 1346 1581 1883 1348 1585 1887 907 1029 1718 1347 1583 1885 1348 1585 1887 1897 1587 1889 907 1029 1718 1973 1589 1891 907 1029 1718 1897 1587 1889 1555 1761 692 1621 1762 693 1658 1763 694 1594 1764 695 1621 1762 693 1555 1761 692 1570 1765 696 1642 1766 697 1556 1767 698 1621 1762 693 1642 1766 697 1572 1768 699 1621 1762 693 1556 1767 698 1595 1769 700 1658 1763 694 1557 1770 701 1622 1771 702 1657 1772 703 1593 1773 704 1622 1771 702 1557 1770 701 1569 1774 705 1643 1775 706 1555 1761 692 1622 1771 702 1643 1775 706 1570 1765 696 1622 1771 702 1555 1761 692 1594 1764 695 1657 1772 703 1558 1776 707 1623 1777 708 1656 1778 709 1592 1779 710 1623 1777 708 1558 1776 707 1567 1780 711 1641 1781 712 1557 1770 701 1623 1777 708 1641 1781 712 1569 1774 705 1623 1777 708 1557 1770 701 1593 1773 704 1656 1778 709 1559 1782 713 1624 1783 714 1655 1784 715 1591 1785 716 1624 1783 714 1559 1782 713 1574 1786 717 1644 1787 718 1558 1776 707 1624 1783 714 1644 1787 718 1567 1780 711 1624 1783 714 1558 1776 707 1592 1779 710 1655 1784 715 1625 1788 719 1560 1789 720 1578 1790 721 1646 1791 722 1559 1782 713 1625 1788 719 1646 1791 722 1574 1786 717 1625 1788 719 1681 1792 723 1680 1793 724 1560 1789 720 1561 1794 725 1626 1795 726 1654 1796 727 1590 1797 728 1626 1795 726 1561 1794 725 1582 1798 729 1648 1799 730 1560 1789 720 1626 1795 726 1648 1799 730 1578 1790 721 1626 1795 726 1560 1789 720 1680 1793 724 1654 1796 727 1562 1800 731 1627 1801 732 1653 1802 733 1589 1803 734 1627 1801 732 1562 1800 731 1585 1804 735 1650 1805 736 1561 1794 725 1627 1801 732 1650 1805 736 1582 1798 729 1627 1801 732 1561 1794 725 1590 1797 728 1653 1802 733 1563 1806 737 1628 1807 738 1652 1808 739 1587 1809 740 1628 1807 738 1563 1806 737 1581 1810 741 1649 1811 742 1562 1800 731 1628 1807 738 1649 1811 742 1585 1804 735 1628 1807 738 1562 1800 731 1589 1803 734 1652 1808 739 1564 1812 743 1629 1813 744 1651 1814 745 1588 1815 746 1629 1813 744 1564 1812 743 1577 1816 747 1647 1817 748 1563 1806 737 1629 1813 744 1647 1817 748 1581 1810 741 1629 1813 744 1563 1806 737 1587 1809 740 1651 1814 745 1556 1767 698 1630 1818 749 1659 1819 750 1595 1769 700 1630 1818 749 1556 1767 698 1572 1768 699 1645 1820 752 1564 1812 743 1630 1818 749 1645 1820 752 1577 1816 747 1630 1818 749 1564 1812 743 1588 1815 746 1659 1819 750 1658 1763 694 1595 1769 700 1587 1809 740 1652 1808 739 1662 1821 2063 1600 1822 2064 1927 1823 2065 1926 1824 2066 1631 1825 2067 1537 1826 2068 1925 1827 2069 1926 1824 2066 1664 1828 2070 1604 1829 2071 1934 1830 2072 1932 1831 2073 1632 1832 2074 1539 1833 2075 1930 1834 2076 1932 1831 2073 1665 1835 2077 1523 1836 2078 1930 1834 2076 1928 1837 2079 1633 1838 2080 1565 1839 2081 1927 1823 2065 1928 1837 2079 1666 1840 2082 1522 1841 2083 1925 1827 2069 1929 1842 2084 1634 1843 2085 1538 1844 2086 1931 1845 2087 1929 1842 2084 1667 1846 2088 1524 1847 2089 1931 1845 2087 1933 1848 2090 1635 1849 2091 1540 1850 2092 1935 1851 2093 1933 1848 2090 1636 1852 2094 1541 1853 2095 1939 1854 2096 1937 1855 2097 1660 1856 2098 1596 1857 2099 1935 1851 2093 1937 1855 2097 1661 1858 2100 1598 1859 2101 1939 1854 2096 1941 1860 2102 1637 1861 2103 1543 1862 2104 1943 1863 2105 1941 1860 2102 1668 1864 2106 1525 1865 2107 1943 1863 2105 1944 1866 2108 1638 1867 2109 1544 1868 2110 1942 1869 2111 1944 1866 2108 1663 1870 2112 1602 1871 2113 1942 1869 2111 1940 1872 2114 1639 1873 2115 1542 1874 2116 1938 1875 2117 1940 1872 2114 1669 1876 2118 1526 1877 2119 1938 1875 2117 1936 1878 2120 1640 1879 2121 1566 1880 2122 1934 1830 2072 1936 1878 2120 1567 1780 711 1528 1881 944 1568 1882 949 1641 1781 712 1568 1883 949 1527 1884 947 1569 1774 705 1641 1781 712 1570 1765 696 1530 1885 946 1571 1886 948 1642 1766 697 1571 1887 948 1529 1888 942 1572 1768 699 1642 1766 697 1569 1774 705 1527 1889 947 1573 1890 945 1643 1775 706 1573 1891 945 1530 1892 946 1570 1765 696 1643 1775 706 1574 1786 717 1531 1893 940 1575 1894 943 1644 1787 718 1575 1895 943 1528 1896 944 1567 1780 711 1644 1787 718 1572 1768 699 1529 1897 942 1576 1898 941 1645 1820 752 1576 1899 941 1532 1900 938 1577 1816 747 1645 1820 752 1578 1790 721 1533 1901 936 1579 1902 939 1646 1791 722 1579 1903 939 1531 1904 940 1574 1786 717 1646 1791 722 1577 1816 747 1532 1905 938 1580 1906 937 1647 1817 748 1580 1907 937 1534 1908 934 1581 1810 741 1647 1817 748 1582 1798 729 1535 1909 931 1583 1910 935 1648 1799 730 1583 1911 935 1533 1912 936 1578 1790 721 1648 1799 730 1581 1810 741 1534 1913 934 1584 1914 933 1649 1811 742 1584 1915 933 1536 1916 932 1585 1804 735 1649 1811 742 1585 1804 735 1536 1917 932 1586 1918 930 1650 1805 736 1586 1919 930 1535 1920 931 1582 1798 729 1650 1805 736 1568 1921 2123 1528 1922 2124 1538 1844 2086 1634 1843 2085 1568 1923 2123 1634 1843 2085 1537 1826 2068 1527 1924 2125 1571 1925 2126 1530 1926 2127 1565 1839 2081 1633 1838 2080 1571 1927 2126 1633 1838 2080 1539 1833 2075 1529 1928 2128 1573 1929 2129 1527 1930 2125 1537 1826 2068 1631 1825 2067 1573 1931 2129 1631 1825 2067 1565 1839 2081 1530 1932 2127 1575 1933 2130 1531 1934 2131 1540 1850 2092 1635 1849 2091 1575 1935 2130 1635 1849 2091 1538 1844 2086 1528 1936 2124 1576 1937 2132 1529 1938 2128 1539 1833 2075 1632 1832 2074 1576 1939 2132 1632 1832 2074 1566 1880 2122 1532 1940 2133 1579 1941 2134 1533 1942 2135 1541 1853 2095 1636 1852 2094 1579 1943 2134 1636 1852 2094 1540 1850 2092 1531 1944 2131 1580 1945 2136 1532 1946 2133 1566 1880 2122 1640 1879 2121 1580 1947 2136 1640 1879 2121 1542 1874 2116 1534 1948 2137 1583 1949 2138 1535 1950 2139 1543 1862 2104 1637 1861 2103 1583 1951 2138 1637 1861 2103 1541 1853 2095 1533 1952 2135 1584 1953 2140 1534 1954 2137 1542 1874 2116 1639 1873 2115 1584 1955 2140 1639 1873 2115 1544 1868 2110 1536 1956 2141 1586 1957 2142 1536 1958 2141 1544 1868 2110 1638 1867 2109 1586 1959 2142 1638 1867 2109 1543 1862 2104 1535 1960 2139 1598 1859 2101 1546 1961 2143 1610 1962 2144 1660 1856 2098 1610 1962 2144 1545 1963 2145 1596 1857 2099 1660 1856 2098 1525 1865 2107 1547 1964 2146 1597 1965 2147 1661 1858 2100 1597 1965 2147 1546 1961 2143 1598 1859 2101 1661 1858 2100 1522 1841 2083 1549 1966 2148 1599 1967 2149 1662 1821 2063 1599 1967 2149 1548 1968 2150 1600 1822 2064 1662 1821 2063 1526 1877 2119 1551 1969 2151 1601 1970 2152 1663 1870 2112 1601 1970 2152 1550 1971 2153 1602 1871 2113 1663 1870 2112 1523 1836 2078 1553 1972 2154 1603 1973 2155 1664 1828 2070 1603 1973 2155 1552 1974 2156 1604 1829 2071 1664 1828 2070 1600 1822 2064 1548 1968 2150 1605 1975 2157 1665 1835 2077 1605 1975 2157 1553 1972 2154 1523 1836 2078 1665 1835 2077 1524 1847 2089 1554 1976 2158 1606 1977 2159 1666 1840 2082 1606 1977 2159 1549 1966 2148 1522 1841 2083 1666 1840 2082 1596 1857 2099 1545 1963 2145 1607 1978 2160 1667 1846 2088 1607 1978 2160 1554 1976 2158 1524 1847 2089 1667 1846 2088 1602 1871 2113 1550 1971 2153 1608 1979 2161 1668 1864 2106 1608 1979 2161 1547 1964 2146 1525 1865 2107 1668 1864 2106 1604 1829 2071 1552 1974 2156 1609 1980 2162 1669 1876 2118 1609 1980 2162 1551 1969 2151 1526 1877 2119 1669 1876 2118 1610 1962 2144 1546 1961 2143 1611 1981 2163 1670 1982 2164 1612 1983 2165 1545 1963 2145 1610 1962 2144 1670 1982 2164 1597 1965 2147 1547 1964 2146 1613 1984 2166 1671 1985 2167 1611 1981 2163 1546 1961 2143 1597 1965 2147 1671 1985 2167 1599 1967 2149 1549 1966 2148 1614 1986 2168 1672 1987 2169 1615 1988 2170 1548 1968 2150 1599 1967 2149 1672 1987 2169 1601 1970 2152 1551 1969 2151 1616 1989 2171 1673 1990 2172 1617 1991 2173 1550 1971 2153 1601 1970 2152 1673 1990 2172 1603 1973 2155 1553 1972 2154 1618 1992 2174 1674 1993 2175 1619 1994 2176 1552 1974 2156 1603 1973 2155 1674 1993 2175 1605 1975 2157 1548 1968 2150 1615 1988 2170 1675 1995 2177 1618 1992 2174 1553 1972 2154 1605 1975 2157 1675 1995 2177 1606 1977 2159 1554 1976 2158 1620 1996 2178 1676 1997 2179 1614 1986 2168 1549 1966 2148 1606 1977 2159 1676 1997 2179 1607 1978 2160 1545 1963 2145 1612 1983 2165 1677 1998 2180 1620 1996 2178 1554 1976 2158 1607 1978 2160 1677 1998 2180 1608 1979 2161 1550 1971 2153 1617 1991 2173 1678 1999 2181 1613 1984 2166 1547 1964 2146 1608 1979 2161 1678 1999 2181 1609 1980 2162 1552 1974 2156 1619 1994 2176 1679 2000 2182 1616 1989 2171 1551 1969 2151 1609 1980 2162 1679 2000 2182 1587 1809 740 1595 1769 700 1659 1819 750 1588 1815 746 1651 1814 745 1594 1764 695 1589 1803 734 1653 1802 733 1657 1772 703 1658 1763 694 1652 1808 739 1589 1803 734 1594 1764 695 1657 1772 703 1653 1802 733 1590 1797 728 1593 1773 704 1592 1779 710 1680 1793 724 1681 1792 723 1591 1785 716 1655 1784 715 1593 1773 704 1590 1797 728 1654 1796 727 1656 1778 709 1625 1788 719 1559 1782 713 1591 1785 716 1681 1792 723 1592 1779 710 1656 1778 709 1654 1796 727 1680 1793 724 1611 1981 2163 1519 2001 2183 1520 2002 2184 1670 1982 2164 1670 1982 2164 1520 2002 2184 1882 1750 2052 1612 1983 2165 1613 1984 2166 1517 2003 2185 1518 2004 2186 1671 1985 2167 1614 1986 2168 1488 1724 2026 1485 1723 2025 1672 1987 2169 1672 1987 2169 1485 1723 2025 1476 1714 2016 1615 1988 2170 1616 1989 2171 1499 1737 2039 1505 1743 2045 1673 1990 2172 1673 1990 2172 1505 1743 2045 1511 1749 2051 1617 1991 2173 1618 1992 2174 1474 1712 2014 1484 1722 2024 1674 1993 2175 1674 1993 2175 1484 1722 2024 1487 1729 2031 1619 1994 2176 1615 1988 2170 1476 1714 2016 1475 1713 2015 1675 1995 2177 1675 1995 2177 1475 1713 2015 1474 1712 2014 1618 1992 2174 1620 1996 2178 1500 1739 2041 1494 1733 2035 1676 1997 2179 1676 1997 2179 1494 1733 2035 1488 1724 2026 1614 1986 2168 1677 1998 2180 1506 1745 2047 1500 1739 2041 1620 1996 2178 1617 1991 2173 1511 1749 2051 1516 1758 2060 1678 1999 2181 1678 1999 2181 1516 1758 2060 1517 2003 2185 1613 1984 2166 1619 1994 2176 1487 1729 2031 1493 1731 2033 1679 2000 2182 1679 2000 2182 1493 1731 2033 1499 1737 2039 1616 1989 2171 1671 1985 2167 1518 2004 2186 1519 2001 2183 1611 1981 2163 1487 1729 2031 1484 1722 2024 1483 1721 2023 1484 1722 2024 1474 1712 2014 1473 1711 2013 1677 1998 2180 1612 1983 2165 1882 1750 2052 1506 1745 2047 1807 2005 620 1687 2006 621 1721 2007 622 1721 2007 622 1687 2006 621 1722 2008 623 1807 2005 620 1723 2009 624 1070 1282 380 1092 1281 379 1808 2010 625 1878 2011 626 1879 2012 627 1723 2009 624 1808 2010 625 1723 2009 624 1879 2012 627 1880 2013 628 1809 2014 629 1110 1287 385 1093 1289 387 1809 2014 629 1857 2015 630 1093 1289 387 1070 1282 380 1723 2009 624 1809 2014 629 1789 2016 631 1867 2017 632 1724 2018 633 1688 2019 634 1683 2020 635 1724 2018 633 1867 2017 632 1685 2021 636 1690 2022 637 1725 2023 638 1720 2024 639 1682 2025 640 1071 1300 398 1069 2026 399 1720 2027 639 1725 2023 638 1724 2018 633 1683 2028 635 1726 2029 641 1810 2030 642 1726 2031 641 1684 2032 643 1847 2033 644 1810 2030 642 1847 2033 644 1792 2034 645 1727 2035 646 1810 2030 642 1727 2035 646 1688 2019 634 1724 2018 633 1810 2030 642 1788 2036 647 1844 2037 648 1728 2038 649 1691 2039 650 1789 2016 631 1688 2019 634 1728 2038 649 1844 2037 648 1729 2040 651 1693 2041 652 1730 2042 653 1811 2043 654 1730 2042 653 1694 2044 655 1815 2045 656 1811 2043 654 1815 2045 656 1731 2046 657 1811 2043 654 1731 2046 657 1692 2047 658 1729 2040 651 1811 2043 654 1732 2048 659 1690 2022 637 1689 2049 660 1812 2050 661 1790 2051 662 1695 2052 663 1732 2048 659 1812 2050 661 1732 2048 659 1695 2052 663 1733 2053 664 1813 2054 665 1733 2053 664 1072 1331 426 1094 1330 425 1813 2054 665 1094 1330 425 1071 1300 398 1725 2023 638 1813 2054 665 1725 2023 638 1690 2022 637 1732 2048 659 1813 2054 665 1848 2055 666 1793 2056 667 1734 2057 668 1814 2058 669 1734 2057 668 1691 2039 650 1728 2038 649 1814 2058 669 1728 2038 649 1688 2019 634 1727 2035 646 1814 2058 669 1727 2035 646 1792 2034 645 1848 2055 666 1814 2058 669 1694 2044 655 1696 2059 670 1735 2060 671 1815 2045 656 1735 2060 671 1736 2061 672 1815 2045 656 1778 2062 673 1698 2063 674 1737 2064 675 1699 2065 676 1737 2064 675 1779 2066 677 1866 2067 678 1699 2065 676 1738 2068 679 1073 1348 443 1095 1347 442 1816 2069 680 1095 1347 442 1074 1350 445 1836 2070 681 1816 2069 680 1836 2070 681 1779 2066 677 1737 2064 675 1816 2069 680 1737 2064 675 1698 2063 674 1738 2068 679 1816 2069 680 1798 2071 682 1701 2072 683 1740 2073 684 1817 2074 685 1740 2073 684 1700 2075 686 1739 2076 687 1817 2074 685 1741 2077 688 1702 2078 689 1742 2079 690 1818 2080 691 1742 2079 690 1686 2081 751 1807 2005 620 1818 2080 691 1741 2077 688 1818 2080 691 1744 2082 753 1871 2083 754 1807 2005 620 1722 2008 623 1743 2084 755 1818 2080 691 1743 2084 755 1703 2085 756 1744 2082 753 1818 2080 691 1745 2086 757 1876 2087 758 1877 2088 759 1819 2089 760 1877 2088 759 1878 2011 626 1808 2010 625 1819 2089 760 1808 2010 625 1092 1281 379 1096 1369 464 1819 2089 760 1096 1369 464 1075 1370 465 1745 2086 757 1819 2089 760 1788 2036 647 1691 2039 650 1746 2090 761 1843 2091 762 1704 2092 763 1843 2091 762 1746 2090 761 1705 2093 764 1747 2094 765 1706 2095 766 1748 2096 767 1820 2097 768 1748 2096 767 1707 2098 769 1749 2099 770 1820 2097 768 1749 2099 770 1702 2078 689 1741 2077 688 1820 2097 768 1750 2100 771 1706 2095 766 1747 2094 765 1821 2101 772 1751 2102 773 1871 2083 754 1744 2082 753 1805 2103 774 1751 2102 773 1696 2059 670 1752 2104 775 1821 2101 772 1752 2104 775 1708 2105 776 1750 2100 771 1821 2101 772 1753 2106 777 1702 2078 689 1749 2099 770 1822 2107 778 1749 2099 770 1707 2098 769 1754 2108 779 1822 2107 778 1754 2108 779 1802 2109 780 1856 2110 781 1822 2107 778 1856 2110 781 1803 2111 782 1753 2106 777 1822 2107 778 1709 2112 783 1755 2113 784 1842 2114 785 1787 2115 786 1786 2116 787 1842 2114 785 1755 2113 784 1710 2117 788 1756 2118 789 1712 2119 790 1757 2120 791 1823 2121 792 1757 2120 791 1714 2122 793 1758 2123 794 1823 2121 792 1758 2123 794 1713 2124 795 1759 2125 796 1823 2121 792 1759 2125 796 1711 2126 797 1756 2118 789 1823 2121 792 1760 2127 798 1715 2128 799 1761 2129 800 1824 2130 801 1761 2129 800 1700 2075 686 1762 2131 802 1824 2130 801 1762 2131 802 1712 2119 790 1756 2118 789 1824 2130 801 1756 2118 789 1711 2126 797 1760 2127 798 1824 2130 801 1763 2132 803 1795 2133 804 1851 2134 805 1825 2135 806 1851 2134 805 1796 2136 807 1764 2137 808 1825 2135 806 1764 2137 808 1710 2117 788 1755 2113 784 1825 2135 806 1755 2113 784 1709 2112 783 1763 2132 803 1825 2135 806 1765 2138 809 1713 2124 795 1758 2123 794 1826 2139 810 1758 2123 794 1714 2122 793 1766 2140 811 1826 2139 810 1766 2140 811 1800 2141 812 1854 2142 813 1826 2139 810 1854 2142 813 1801 2143 814 1765 2138 809 1826 2139 810 1786 2116 787 1710 2117 788 1764 2137 808 1841 2144 815 1797 2145 816 1841 2144 815 1764 2137 808 1796 2136 807 1767 2146 817 1799 2147 818 1853 2148 819 1827 2149 820 1853 2148 819 1800 2141 812 1766 2140 811 1827 2149 820 1766 2140 811 1714 2122 793 1757 2120 791 1827 2149 820 1757 2120 791 1712 2119 790 1767 2146 817 1827 2149 820 1768 2150 821 1695 2052 663 1790 2051 662 1828 2151 822 1791 2152 823 1716 2153 824 1768 2150 821 1828 2151 822 1770 2154 825 1717 2155 826 1769 2156 827 1829 2157 828 1744 2082 753 1703 2085 756 1771 2158 829 1830 2159 830 1872 2160 831 1771 2158 829 1875 2161 832 1874 2162 833 1768 2150 821 1716 2153 824 1773 2163 834 1831 2164 835 1773 2163 834 1076 1447 542 1097 1446 541 1831 2164 835 1097 1446 541 1072 1331 426 1733 2053 664 1831 2164 835 1733 2053 664 1695 2052 663 1768 2150 821 1831 2164 835 1875 2161 832 1876 2087 758 1745 2086 757 1832 2165 836 1745 2086 757 1075 1370 465 1098 1449 544 1832 2165 836 1098 1449 544 1077 1451 546 1774 2166 837 1832 2165 836 1774 2166 837 1874 2162 833 1875 2161 832 1832 2165 836 1718 2167 838 1716 2153 824 1791 2152 823 1846 2168 839 1769 2156 827 1717 2155 826 1775 2169 840 1776 2170 841 1835 2171 842 1872 2160 831 1874 2162 833 1873 2172 843 1078 1458 553 1076 1447 542 1773 2163 834 1833 2173 844 1773 2163 834 1716 2153 824 1718 2167 838 1833 2173 844 1774 2166 837 1077 1451 546 1099 1461 556 1834 2174 845 1873 2172 843 1874 2162 833 1774 2166 837 1834 2174 845 1776 2170 841 1775 2169 840 1778 2062 673 1699 2065 676 1074 1350 445 1078 1458 553 1833 2173 844 1836 2070 681 1833 2173 844 1718 2167 838 1779 2066 677 1836 2070 681 1849 2175 846 1794 2176 847 1780 2177 848 1837 2178 849 1780 2177 848 1705 2093 764 1746 2090 761 1837 2178 849 1746 2090 761 1691 2039 650 1734 2057 668 1837 2178 849 1734 2057 668 1793 2056 667 1849 2175 846 1837 2178 849 1855 2179 850 1802 2109 780 1754 2108 779 1838 2180 851 1754 2108 779 1707 2098 769 1781 2181 852 1838 2180 851 1781 2181 852 1713 2124 795 1765 2138 809 1838 2180 851 1765 2138 809 1801 2143 814 1855 2179 850 1838 2180 851 1719 2182 853 1715 2128 799 1782 2183 854 1839 2184 855 1782 2183 854 1708 2105 776 1783 2185 856 1839 2184 855 1704 2092 763 1705 2093 764 1784 2186 857 1870 2187 858 1709 2112 783 1787 2115 786 1870 2187 858 1784 2186 857 1785 2188 859 1711 2126 797 1759 2125 796 1840 2189 860 1759 2125 796 1713 2124 795 1781 2181 852 1840 2189 860 1781 2181 852 1707 2098 769 1748 2096 767 1840 2189 860 1748 2096 767 1706 2095 766 1785 2188 859 1840 2189 860 1797 2145 816 1798 2071 682 1817 2074 685 1841 2144 815 1817 2074 685 1739 2076 687 1786 2116 787 1841 2144 815 1786 2116 787 1739 2076 687 1863 2190 861 1842 2114 785 1863 2190 861 1719 2182 853 1787 2115 786 1842 2114 785 1704 2092 763 1783 2185 856 1860 2191 862 1843 2091 762 1860 2191 862 1694 2044 655 1788 2036 647 1843 2091 762 1788 2036 647 1694 2044 655 1730 2042 653 1844 2037 648 1730 2042 653 1693 2041 652 1789 2016 631 1844 2037 648 1685 2192 636 1693 2041 652 1729 2040 651 1845 2193 863 1896 2194 864 1692 2047 658 1731 2046 657 1829 2157 828 1769 2156 827 1791 2152 823 1828 2151 822 1791 2152 823 1769 2156 827 1776 2170 841 1846 2168 839 1846 2168 839 1776 2170 841 1699 2065 676 1866 2067 678 1684 2195 643 1068 2196 577 1100 1483 576 1847 2033 644 1100 1483 576 1079 1485 578 1792 2034 645 1847 2033 644 1792 2034 645 1079 1485 578 1101 1486 579 1848 2055 666 1101 1486 579 1080 1487 580 1793 2056 667 1848 2055 666 1793 2056 667 1080 1487 580 1102 1488 581 1849 2175 846 1102 1488 581 1081 1489 582 1794 2176 847 1849 2175 846 1794 2176 847 1081 1489 582 1103 1491 584 1850 2197 865 1103 1491 584 1082 1492 585 1795 2133 804 1850 2197 865 1795 2133 804 1082 1492 585 1104 1493 586 1851 2134 805 1104 1493 586 1083 1494 587 1796 2136 807 1851 2134 805 1083 1494 587 1084 1495 588 1797 2145 816 1796 2136 807 1084 1495 588 1085 1496 589 1798 2071 682 1797 2145 816 1701 2072 683 1087 1499 592 1105 1498 591 1852 2198 866 1105 1498 591 1086 1500 593 1799 2147 818 1852 2198 866 1106 1501 594 1088 1502 595 1800 2141 812 1853 2148 819 1799 2147 818 1086 1500 593 1106 1501 594 1853 2148 819 1800 2141 812 1088 1502 595 1107 1503 596 1854 2142 813 1107 1503 596 1089 1504 597 1801 2143 814 1854 2142 813 1108 1505 598 1090 1506 599 1802 2109 780 1855 2179 850 1801 2143 814 1089 1504 597 1108 1505 598 1855 2179 850 1802 2109 780 1090 1506 599 1109 1507 600 1856 2110 781 1109 1507 600 1091 1508 601 1803 2111 782 1856 2110 781 1803 2111 782 1091 1508 601 1110 1287 385 1857 2015 630 1738 2068 679 1698 2063 674 1804 2199 867 1858 2200 868 1804 2199 867 1873 2172 843 1834 2174 845 1858 2200 868 1834 2174 845 1099 1461 556 1111 1511 604 1858 2200 868 1111 1511 604 1073 1348 443 1738 2068 679 1858 2200 868 1085 1496 589 1087 1499 592 1701 2072 683 1798 2071 682 1770 2154 825 1697 2201 869 1805 2103 774 1859 2202 870 1805 2103 774 1744 2082 753 1830 2159 830 1859 2202 870 1830 2159 830 1772 2203 871 1806 2204 872 1859 2202 870 1806 2204 872 1717 2155 826 1770 2154 825 1859 2202 870 1783 2185 856 1708 2105 776 1752 2104 775 1860 2191 862 1696 2059 670 1694 2044 655 1860 2191 862 1752 2104 775 1775 2169 840 1717 2155 826 1806 2204 872 1861 2205 873 1806 2204 872 1772 2203 871 1777 2206 874 1861 2205 873 1785 2188 859 1706 2095 766 1750 2100 771 1862 2207 875 1750 2100 771 1708 2105 776 1782 2183 854 1862 2207 875 1782 2183 854 1715 2128 799 1760 2127 798 1862 2207 875 1760 2127 798 1711 2126 797 1785 2188 859 1862 2207 875 1778 2062 673 1775 2169 840 1861 2205 873 1864 2208 876 1861 2205 873 1777 2206 874 1835 2171 842 1864 2208 876 1739 2076 687 1700 2075 686 1761 2129 800 1863 2190 861 1761 2129 800 1715 2128 799 1719 2182 853 1863 2190 861 1804 2199 867 1698 2063 674 1778 2062 673 1864 2208 876 1852 2198 866 1799 2147 818 1767 2146 817 1865 2209 877 1767 2146 817 1712 2119 790 1762 2131 802 1865 2209 877 1762 2131 802 1700 2075 686 1740 2073 684 1865 2209 877 1740 2073 684 1701 2072 683 1852 2198 866 1865 2209 877 1779 2066 677 1718 2167 838 1846 2168 839 1866 2067 678 1789 2016 631 1693 2041 652 1685 2210 636 1867 2017 632 1805 2103 774 1697 2201 869 1735 2060 671 1696 2059 670 1751 2102 773 1753 2106 777 1803 2111 782 1857 2015 630 1868 2211 878 1857 2015 630 1809 2014 629 1868 2211 878 1809 2014 629 1880 2013 628 1868 2211 878 1742 2079 690 1702 2078 689 1753 2106 777 1868 2211 878 1780 2177 848 1794 2176 847 1850 2197 865 1869 2212 879 1850 2197 865 1795 2133 804 1763 2132 803 1869 2212 879 1763 2132 803 1709 2112 783 1784 2186 857 1869 2212 879 1784 2186 857 1705 2093 764 1780 2177 848 1869 2212 879 1787 2115 786 1719 2182 853 1839 2184 855 1870 2187 858 1839 2184 855 1783 2185 856 1704 2092 763 1870 2187 858 1871 2083 754 1751 2102 773 1821 2101 772 1747 2094 765 1741 2077 688 1871 2083 754 1747 2094 765 1820 2097 768 1772 2203 871 1872 2160 831 1835 2171 842 1777 2206 874 1771 2158 829 1872 2160 831 1772 2203 871 1830 2159 830 1835 2171 842 1873 2172 843 1804 2199 867 1864 2208 876 1771 2158 829 1703 2085 756 1876 2087 758 1875 2161 832 1877 2088 759 1876 2087 758 1703 2085 756 1743 2084 755 1743 2084 755 1722 2008 623 1878 2011 626 1877 2088 759 1722 2008 623 1687 2006 621 1879 2012 627 1878 2011 626 1880 2013 628 1879 2012 627 1687 2006 621 1686 2081 751 1868 2211 878 1880 2013 628 1686 2081 751 1742 2079 690 1068 2213 1843 1684 2214 2187 1886 2215 2188 1319 1525 1844 1518 2004 2186 1521 1759 2061 1886 2215 2188 1887 2216 2189 1518 2004 2186 1517 2003 2185 1881 1760 2062 1521 1759 2061 1881 1760 2062 1517 2003 2185 1516 1758 2060 1515 1757 2059 898 1023 1712 1312 1025 1714 1881 1760 2062 1515 1757 2059 1683 2217 2190 1685 2218 2191 1889 2219 2192 1888 2220 2193 1882 1750 2052 1520 2002 2184 1889 2219 2192 1890 2221 2194 1884 2222 2195 1885 2223 2196 1892 2224 2197 1891 2225 2198 1315 1538 1857 1514 1754 2056 1898 2226 2199 1320 1539 1858 1519 2001 2183 1518 2004 2186 1887 2216 2189 1888 2220 2193 1512 1751 2053 1882 1750 2052 1890 2221 2194 1891 2225 2198 1729 2040 651 1692 2047 658 1884 2227 880 1845 2228 863 1690 2022 637 1682 2229 640 1885 2230 881 1689 2049 660 1883 1753 2055 1513 1752 2054 1892 2224 2197 1893 2231 2200 1885 2232 881 1884 2233 880 1692 2047 658 1689 2049 660 1521 1759 2061 905 1028 1717 1319 1525 1844 1886 2215 2188 1720 2234 2201 1069 2235 1862 1320 1539 1858 1898 2226 2199 1684 2236 2187 1726 2237 2202 1887 2216 2189 1886 2215 2188 1726 2238 2202 1683 2239 2190 1888 2220 2193 1887 2216 2189 1520 2002 2184 1519 2001 2183 1888 2220 2193 1889 2219 2192 1685 2240 2191 1845 2241 2203 1890 2221 2194 1889 2219 2192 1845 2242 2203 1884 2243 2195 1891 2225 2198 1890 2221 2194 1513 1752 2054 1512 1751 2053 1891 2225 2198 1892 2224 2197 1885 2244 2196 1682 2245 2204 1893 2231 2200 1892 2224 2197 1682 2246 2204 1720 2247 2201 1898 2226 2199 1893 2231 2200 1894 2248 882 1697 2201 869 1770 2154 825 1829 2157 828 1790 2051 662 1894 2248 882 1829 2157 828 1828 2151 822 1895 2249 883 1894 2248 882 1790 2051 662 1812 2050 661 1736 2061 672 1735 2060 671 1697 2201 869 1894 2248 882 1896 2194 864 1736 2061 672 1894 2248 882 1895 2249 883 1689 2049 660 1692 2047 658 1896 2194 864 1895 2249 883 1689 2049 660 1895 2249 883 1812 2050 661 1731 2046 657 1815 2045 656 1736 2061 672 1896 2194 864 1883 1753 2055 1893 2231 2200 1898 2226 2199 1514 1754 2056 1359 1584 1886 1371 1600 1902 1899 1601 1903 1360 1586 1888 1371 1600 1902 1382 1613 1915 1900 1614 1916 1899 1601 1903 1382 1613 1915 1393 1626 1928 1901 1627 1929 1900 1614 1916 1393 1626 1928 1404 1639 1941 1902 1640 1942 1901 1627 1929 1404 1639 1941 1415 1652 1954 350 790 1479 1902 1640 1942 1415 1652 1954 1426 1664 1966 433 793 1482 350 790 1479 1497 1735 2037 1903 1756 2058 430 806 1495 1503 1741 2043 1509 1747 2049 1904 1755 2057 1903 1756 2058 1051 1105 1734 986 1090 1719 1906 1093 1722 1905 1106 1735 1048 1091 1720 908 1109 1738 1908 1096 1725 1907 1092 1721 1017 1095 1724 951 1107 1736 1906 1093 1722 1907 1092 1721 1019 1108 1737 925 1101 1730 1909 1103 1732 1905 1106 1735 1020 1113 1742 923 1094 1723 1908 1096 1725 1910 1111 1740 1050 1098 1727 909 1104 1733 1909 1103 1732 1911 1099 1728 1052 1110 1739 910 1115 1744 1912 1114 1743 1910 1111 1740 1018 1102 1731 952 1148 1777 1913 1100 1729 1911 1099 1728 1021 1119 1748 924 1112 1741 1912 1114 1743 1914 1117 1746 1055 1146 1775 990 1097 1726 1913 1100 1729 1915 1147 1776 1053 1116 1745 982 1125 1754 1916 1120 1749 1914 1117 1746 1026 1149 1778 928 1142 1771 1917 1144 1773 1915 1147 1776 1022 1122 1751 926 1118 1747 1916 1120 1749 1918 1123 1752 1049 1140 1769 912 1145 1774 1917 1144 1773 1919 1141 1770 1046 1126 1755 984 1127 1756 1920 1124 1753 1918 1123 1752 1025 1143 1772 930 1136 1765 1921 1138 1767 1919 1141 1770 1023 1131 1760 927 1121 1750 1920 1124 1753 1922 1129 1758 1054 1134 1763 988 1139 1768 1921 1138 1767 1923 1135 1764 1047 1128 1757 911 1133 1762 1924 1132 1761 1922 1129 1758 1024 1137 1766 929 1130 1759 1924 1132 1761 1923 1135 1764 1522 1841 2083 1662 1821 2063 1926 1824 2066 1925 1827 2069 1600 1822 2064 1665 1835 2077 1928 1837 2079 1927 1823 2065 1565 1839 2081 1631 1825 2067 1926 1824 2066 1927 1823 2065 1537 1826 2068 1634 1843 2085 1929 1842 2084 1925 1827 2069 1539 1833 2075 1633 1838 2080 1928 1837 2079 1930 1834 2076 1524 1847 2089 1666 1840 2082 1929 1842 2084 1931 1845 2087 1523 1836 2078 1664 1828 2070 1932 1831 2073 1930 1834 2076 1538 1844 2086 1635 1849 2091 1933 1848 2090 1931 1845 2087 1566 1880 2122 1632 1832 2074 1932 1831 2073 1934 1830 2072 1596 1857 2099 1667 1846 2088 1933 1848 2090 1935 1851 2093 1604 1829 2071 1669 1876 2118 1936 1878 2120 1934 1830 2072 1540 1850 2092 1636 1852 2094 1937 1855 2097 1935 1851 2093 1542 1874 2116 1640 1879 2121 1936 1878 2120 1938 1875 2117 1598 1859 2101 1660 1856 2098 1937 1855 2097 1939 1854 2096 1526 1877 2119 1663 1870 2112 1940 1872 2114 1938 1875 2117 1541 1853 2095 1637 1861 2103 1941 1860 2102 1939 1854 2096 1544 1868 2110 1639 1873 2115 1940 1872 2114 1942 1869 2111 1525 1865 2107 1661 1858 2100 1941 1860 2102 1943 1863 2105 1602 1871 2113 1668 1864 2106 1944 1866 2108 1942 1869 2111 1543 1862 2104 1638 1867 2109 1944 1866 2108 1943 1863 2105 651 570 1332 1945 675 1416 2086 2250 2205 2087 571 1333 1964 507 1303 374 512 1308 393 653 1394 1945 675 1416 2086 2250 2205 1945 675 1416 393 653 1394 2107 723 1448 401 620 1368 521 619 1367 1948 772 1467 1949 771 1466 579 623 1371 660 630 1378 1950 770 1465 1949 771 1466 402 628 1376 524 626 1374 1950 770 1465 1951 769 1464 578 631 1379 577 664 1405 1952 767 1462 1951 769 1464 577 664 1405 2094 700 1429 2096 768 1463 1952 767 1462 419 742 977 584 693 281 1954 765 1000 1955 764 999 575 553 236 659 556 239 1957 762 997 1956 763 998 404 636 250 527 634 248 1957 762 997 1958 761 996 574 558 241 658 569 245 1959 760 995 1958 761 996 407 643 257 530 641 255 1959 760 995 1960 759 994 573 568 244 657 672 268 1961 758 993 1960 759 994 412 649 263 533 647 261 1961 758 993 1962 757 992 571 755 990 671 732 309 1947 734 311 1963 756 991 1470 1708 2010 1481 1719 2021 347 801 1490 431 800 1489 1459 1697 1999 1470 1708 2010 431 800 1489 348 798 1487 1448 1686 1988 1459 1697 1999 348 798 1487 432 797 1486 1437 1675 1977 1448 1686 1988 432 797 1486 349 794 1483 1491 1727 2029 351 803 1492 347 801 1490 1481 1719 2021 1497 1735 2037 430 806 1495 351 803 1492 1491 1727 2029 435 438 1234 430 806 1495 1903 1756 2058 1986 1021 1710 435 438 1234 1986 1021 1710 320 1020 1709 88 375 1186 433 793 1482 1426 1664 1966 1437 1675 1977 349 794 1483 2048 2251 2206 2049 2252 2207 1973 1589 1891 1972 1588 1890 1902 1640 1942 350 790 1479 434 436 1232 1974 1641 1943 2047 2253 2208 2048 2251 2206 1972 1588 1890 1975 1602 1904 2046 2254 2209 2047 2253 2208 1975 1602 1904 1976 1615 1917 2045 2255 2210 2046 2254 2209 1976 1615 1917 1977 1628 1930 2044 1653 1955 2045 2255 2210 1977 1628 1930 1974 1641 1943 606 781 1473 684 410 1214 2026 413 1217 2027 423 2211 310 111 904 1978 113 906 2025 412 1216 2024 409 1213 867 985 1674 858 976 1665 4 371 1182 84 373 1184 858 976 1665 845 964 1653 0 369 1180 4 371 1182 721 832 1521 1331 831 1520 1980 836 1525 1979 835 1524 774 2256 2212 3 360 1171 87 359 1170 1981 892 1581 722 834 1523 735 2257 2213 1982 850 1539 1979 835 1524 735 2257 2213 748 2258 2214 1983 864 1553 1982 850 1539 748 2258 2214 761 2259 2215 1984 878 1567 1983 864 1553 761 2259 2215 774 2256 2212 1981 892 1581 1984 878 1567 810 928 1617 798 916 1605 86 364 1175 1 365 1176 1 365 1176 85 367 1178 822 940 1629 810 928 1617 834 952 1641 822 940 1629 85 367 1178 0 369 1180 845 964 1653 834 952 1641 0 369 1180 88 375 1186 320 1020 1709 2015 2260 2216 2015 2260 2216 84 373 1184 88 375 1186 1904 1755 2057 1514 1754 2056 1315 1538 1857 1985 1019 1708 1337 1017 1706 1985 1019 1708 1315 1538 1857 897 1018 1707 90 2 28 243 1 26 1987 2261 2217 1988 2262 2218 243 1 26 91 4 30 1989 2263 2219 1987 2261 2217 91 4 30 244 7 35 1990 2264 2220 1989 2263 2219 244 7 35 299 8 36 1991 2265 2221 1990 2264 2220 164 179 1042 163 178 1041 1992 2266 2222 1993 2267 2223 266 181 1045 165 180 1043 1994 2268 2224 1995 2269 2225 163 178 1041 266 181 1045 1995 2269 2225 1992 2266 2222 288 184 1048 90 2 28 1988 2262 2218 1996 2270 2226 167 186 1050 164 179 1042 1993 2267 2223 1997 2271 2227 324 333 1144 288 184 1048 1996 2270 2226 1998 2272 2228 315 351 1162 167 186 1050 1997 2271 2227 1999 2273 2229 165 180 1043 324 333 1144 1998 2272 2228 1994 2268 2224 1991 2265 2221 299 8 36 2017 378 1189 2018 2274 2230 690 432 1228 315 351 1162 1999 2273 2229 2001 2275 2231 622 442 1238 437 441 1237 2002 2276 2232 2003 2277 2233 438 443 1239 622 442 1238 2003 2277 2233 2004 2278 2234 623 446 1242 438 443 1239 2004 2278 2234 2005 2279 2235 440 447 1243 623 446 1242 2005 2279 2235 2006 2280 2236 519 618 1366 520 617 1365 2007 2281 2237 2008 2282 2238 521 619 1367 645 622 1370 2009 2283 2239 2010 2284 2240 645 622 1370 519 618 1366 2008 2282 2238 2009 2283 2239 437 441 1237 661 624 1372 2011 2285 2241 2002 2276 2232 520 617 1365 523 625 1373 2012 2286 2242 2007 2281 2237 661 624 1372 1948 772 1467 2013 2287 2243 2011 2285 2241 672 774 1469 440 447 1243 2006 2280 2236 2000 2288 2244 523 625 1373 690 432 1228 2001 2275 2231 2012 2286 2242 1948 772 1467 521 619 1367 2010 2284 2240 2013 2287 2243 1988 2262 2218 1987 2261 2217 2014 2289 2245 1987 2261 2217 1989 2263 2219 2014 2289 2245 1989 2263 2219 1990 2264 2220 2014 2289 2245 1990 2264 2220 1991 2265 2221 2014 2289 2245 1993 2267 2223 1992 2266 2222 2014 2289 2245 1995 2269 2225 1994 2268 2224 2014 2289 2245 1992 2266 2222 1995 2269 2225 2014 2289 2245 1996 2270 2226 1988 2262 2218 2014 2289 2245 1997 2271 2227 1993 2267 2223 2014 2289 2245 1998 2272 2228 1996 2270 2226 2014 2289 2245 1999 2273 2229 1997 2271 2227 2014 2289 2245 1994 2268 2224 1998 2272 2228 2014 2289 2245 1991 2265 2221 2018 2274 2230 2000 2288 2244 2014 2289 2245 2001 2275 2231 1999 2273 2229 2014 2289 2245 2003 2277 2233 2002 2276 2232 2014 2289 2245 2004 2278 2234 2003 2277 2233 2014 2289 2245 2005 2279 2235 2004 2278 2234 2014 2289 2245 2006 2280 2236 2005 2279 2235 2014 2289 2245 2008 2282 2238 2007 2281 2237 2014 2289 2245 2010 2284 2240 2009 2283 2239 2014 2289 2245 2009 2283 2239 2008 2282 2238 2014 2289 2245 2002 2276 2232 2011 2285 2241 2014 2289 2245 2007 2281 2237 2012 2286 2242 2014 2289 2245 2011 2285 2241 2013 2287 2243 2014 2289 2245 2000 2288 2244 2006 2280 2236 2014 2289 2245 2012 2286 2242 2001 2275 2231 2014 2289 2245 2013 2287 2243 2010 2284 2240 2014 2289 2245 2015 2260 2216 320 1020 1709 884 1002 1691 877 995 1684 877 995 1684 867 985 1674 84 373 1184 2015 2260 2216 1497 1735 2037 1503 1741 2043 1903 1756 2058 672 774 1469 2000 2288 2244 2018 2274 2230 2017 378 1189 308 85 74 228 88 77 2020 406 151 2019 402 150 673 775 1470 590 773 1468 2022 377 1188 2021 379 1190 590 773 1468 672 774 1469 2017 378 1189 2022 377 1188 591 776 1471 673 775 1470 2021 379 1190 2023 380 1191 683 780 1472 591 776 1471 2023 380 1191 2024 409 1213 604 411 1215 683 780 1472 2024 409 1213 2025 412 1216 1978 113 906 142 124 914 2026 413 1217 2025 412 1216 142 124 914 229 126 916 2027 423 2211 2026 413 1217 687 782 229 606 781 228 2027 423 153 2028 422 152 607 783 230 687 782 229 2028 422 152 2029 424 154 688 784 231 607 783 230 2029 424 154 2030 425 155 603 778 224 688 784 231 2030 425 155 2031 408 147 682 779 225 603 778 224 2031 408 147 2032 407 146 601 777 222 682 779 225 2032 407 146 2033 403 145 681 405 223 601 777 222 2033 403 145 2019 402 2263 2020 406 151 228 88 77 312 154 107 2016 420 160 312 154 107 41 140 103 2034 414 156 2016 420 160 41 140 103 311 135 100 2035 415 157 2034 414 156 311 135 921 29 77 897 2036 394 1205 2035 415 1218 29 77 897 307 76 896 2037 395 1206 2036 394 1205 307 76 896 227 79 899 2038 398 1209 2037 395 1206 227 79 899 45 81 901 2039 400 1211 2038 398 1209 45 81 901 162 353 1164 2040 428 1224 2039 400 1211 162 353 1164 79 355 1166 2041 430 1226 2040 428 1224 79 355 1166 233 358 1169 2042 433 1229 2041 430 1226 233 358 1169 3 360 1171 2043 435 1231 2042 433 1229 3 360 1171 774 2256 2212 2044 1653 1955 2043 435 1231 774 2256 2212 761 2259 2215 2045 2255 2210 2044 1653 1955 761 2259 2215 748 2258 2214 2046 2254 2209 2045 2255 2210 748 2258 2214 735 2257 2213 2047 2253 2208 2046 2254 2209 735 2257 2213 722 834 1523 2048 2251 2206 2047 2253 2208 722 834 1523 708 833 1522 2049 2252 2207 2048 2251 2206 907 1029 1718 2049 2252 2207 708 833 1522 1973 1589 1891 2049 2252 2207 907 1029 1718 907 1029 1718 1980 836 1525 1331 831 1520 2050 292 123 2051 291 122 2065 133 1002 2064 288 1003 282 294 125 322 296 127 2067 376 1004 2066 134 1005 2051 291 122 282 294 125 2066 134 1005 2065 133 1002 185 244 52 278 242 50 2069 237 1006 2068 245 1007 184 241 49 279 251 56 2071 246 1008 2070 238 1009 278 242 50 184 241 49 2070 238 1009 2069 237 1006 2052 263 64 185 244 52 2068 245 1007 2072 261 1010 186 250 55 2050 292 123 2064 288 1003 2073 247 1011 279 251 56 186 250 55 2073 247 1011 2071 246 1008 187 259 1104 280 257 1103 2075 252 1099 2074 260 1105 2053 256 59 2054 327 235 2077 328 1014 2076 253 1015 280 257 60 2053 256 59 2076 253 1015 2075 252 2276 2055 266 1109 187 259 1104 2074 260 1105 2078 264 1107 2054 327 235 2052 263 64 2072 261 1010 2077 328 1014 188 268 1111 2055 266 1109 2078 264 1107 2079 269 1112 2056 272 1115 188 268 1111 2079 269 1112 2080 270 1113 189 274 1117 2056 272 1115 2080 270 1113 2081 275 1118 2057 287 1128 189 274 1117 2081 275 1118 2082 285 1126 191 283 88 281 281 2271 2084 276 1021 2083 284 1022 190 280 1123 2057 287 1128 2082 285 1126 2085 277 1120 281 281 1124 190 280 1123 2085 277 1120 2084 276 1119 322 296 127 191 283 88 2083 284 1022 2067 376 1004 1946 735 970 656 733 310 2087 571 1024 2086 2250 1025 2058 731 308 2059 730 307 2089 727 1026 2088 572 1027 656 733 310 2058 731 308 2088 572 1027 2087 571 1024 653 689 279 554 681 274 2091 676 1028 2090 686 1029 652 680 273 555 683 276 2093 684 1030 2092 677 1031 554 681 274 652 680 273 2092 677 1031 2091 676 1028 555 683 276 2060 702 288 2094 700 1032 2093 684 1030 2059 730 307 556 690 280 2095 685 1033 2089 727 1026 556 690 280 653 689 279 2090 686 1029 2095 685 1033 1953 766 1001 557 696 284 2097 691 1034 2096 768 1035 654 695 1427 558 698 1426 2099 699 1428 2098 692 1423 557 696 284 654 695 2270 2098 692 1037 2097 691 1034 558 698 1426 2061 705 1432 2100 703 1430 2099 699 1428 2060 702 288 1953 766 1001 2096 768 1035 2094 700 1032 2061 705 1432 559 707 1434 2101 708 1435 2100 703 1430 559 707 1434 2062 711 1438 2102 709 1436 2101 708 1435 2062 711 1438 560 713 1440 2103 714 1441 2102 709 1436 560 713 1440 2063 726 1451 2104 724 1449 2103 714 1441 2063 726 1451 561 720 1447 2105 715 1442 2104 724 1449 655 719 299 562 722 302 2107 723 1044 2106 716 2266 561 720 1447 655 719 1446 2106 716 1443 2105 715 1442 562 722 302 1946 735 970 2086 2250 1025 2107 723 1044 1686 2081 751 1687 2006 621 1807 2005 620 1117 1276 374 1237 1275 373 1151 1277 375

+
+
+
+
+ + + + 0 0 1 0 + 0 1 0 0 + 1 0 0 0 + + + + + + + + + + + + 400.113 463.264 -431.078 + 0 0 1 0 + 0 1 0 -223.2 + 1 0 0 -38.4 + + + + 148.654 183.672 -292.179 + 0 0 1 -12.8709 + 0 1 0 -191.679 + 1 0 0 -45.6358 + + + + + + + +
diff --git a/data/client/mesh/animal_rabbit.png b/data/client/mesh/animal_rabbit.png new file mode 100644 index 000000000..fd03645fb Binary files /dev/null and b/data/client/mesh/animal_rabbit.png differ diff --git a/data/client/mesh/animal_wolf.dae b/data/client/mesh/animal_wolf.dae new file mode 100644 index 000000000..b640257d7 --- /dev/null +++ b/data/client/mesh/animal_wolf.dae @@ -0,0 +1,199 @@ + + + + + gcorson + Maya 8.0 | ColladaMaya v3.02 | FCollada v3.2 + Collada Maya Export Options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0; +curveConstrainSampling=0;exportCameraAsLookat=0; +exportLights=1;exportCameras=1;exportJointsAndSkin=1; +exportAnimations=1;exportTriangles=0;exportInvisibleNodes=0; +exportNormals=1;exportTexCoords=1;exportVertexColors=1;exportTangents=0; +exportTexTangents=0;exportConstraints=1;exportPhysics=0;exportXRefs=1; +dereferenceXRefs=0;cameraXFov=0;cameraYFov=1 + +Copyright 2006 Sony Computer Entertainment Inc. +Licensed under the SCEA Shared Source License, Version 1.0 (the +"License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at: +http://research.scea.com/scea_shared_source_license.html +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + file:///C:/vs2005/sample_data/Complete_Packages/SCEA_Private/Maya_MoonLander/Moonlander/untitled + + 2006-08-23T22:29:59Z + 2007-02-21T22:47:42Z + + Y_UP + + + + + + + 37.8492 + 1.5 + 1 + 10000 + + + + + + + + + + 1 1 1 + + + + + + + ./animal_wolf.png + + + + + + + + + + + + + file2 + A8R8G8B8 + + + + + file2-surface + LINEAR_MIPMAP_LINEAR + LINEAR + + + + + + 0 0 0 1 + + + 0 0 0 1 + + + + + + 0 0 0 1 + + + 0.3 + + + 0 0 0 1 + + + 0.5 + + + 0 0 0 1 + + + 1 + + + 1 + + + + + + + + + + + 35.0226 89.3874 23.3732 19.5676 89.7173 22.4879 9.22909 91.5427 17.1037 4.33048 88.7008 4.57726 45.0571 89.4178 19.824 -30.5196 11.6272 25.1326 -15.6992 11.4278 34.2321 51.8411 17.7055 36.5602 65.7206 18.372 27.0862 56.0117 11.4345 22.6963 -23.2343 18.1488 41.0429 -40.9218 18.6322 29.6382 62.4487 11.3989 12.9806 60.2326 28.1944 39.5949 71.2984 29.0359 29.3335 -32.9737 29.6914 43.477 -48.95 28.9358 31.4102 73.8118 41.7425 29.8584 65.2513 41.3955 39.884 72.6597 55.003 29.2468 64.6263 55.4849 38.2648 66.5829 66.4165 27.9218 55.5179 67.734 35.7358 43.4971 75.6992 31.8699 56.934 75.0037 25.7495 14.7601 73.8701 35.1574 -12.1248 73.9991 28.9191 14.7016 78.8465 28.8886 -3.37962 78.0576 23.1953 -24.7824 78.2304 7.65121 4.94216 81.4267 15.8195 -54.7257 89.9761 8.84491 -53.6566 74.7375 26.9735 -44.1714 77.8938 26.1268 -64.7587 73.8997 7.15297 -61.5691 65.6958 25.2253 -42.9296 61.2502 39.4496 -64.9663 57.2673 21.7398 -48.9596 49.2561 39.8218 -58.3698 43.9468 28.036 -31.7993 70.8398 33.4366 -33.1153 82.3349 8.62471 48.2452 81.0789 22.327 34.1225 80.5718 26.6473 15.5527 81.3807 24.423 0.65596 81.0723 3.99376 15.1798 11.41 36.4164 17.2973 17.3674 43.2976 43.8649 67.7941 39.8677 55.9835 56.1625 42.7808 56.4187 41.7648 44.4371 46.9566 29.0085 44.2399 18.041 21.337 45.4158 -24.2634 29.7596 46.4694 -37.1346 44.6474 44.4312 -35.8668 57.8953 42.7333 -24.1626 66.8013 39.6298 -14.2645 43.4767 51.8892 10.1522 43.8267 53.9252 -10.3735 36.316 51.8336 -14.5047 52.2745 51.0455 9.35439 52.1796 53.5056 24.5685 36.9247 52.4691 11.2191 35.6243 52.5988 27.0248 44.5585 52.8835 25.4374 55.0852 52.0724 9.23132 59.258 51.2115 21.2751 61.6417 50.3945 -11.0645 57.3325 50.3033 -22.8339 53.8174 48.6047 -22.3883 43.3299 49.8488 -13.3437 34.4469 50.7719 -15.0193 59.7488 48.0109 12.3031 31.6369 51.4681 28.2 34.9703 51.4911 34.9314 44.1559 51.2583 33.7281 55.8993 50.0475 24.8495 63.37 48.6114 9.96162 62.8873 48.4038 6.73344 84.5266 2.83788 10.2211 84.9641 13.1445 19.05 85.0093 20.4734 35.2584 84.9759 22.0089 44.8651 85.199 18.7578 54.1484 90.1992 13.1393 25.84 89.3162 23.5593 14.5318 90.4728 20.5795 5.99276 89.5698 10.1098 59.1034 90.0324 3.37689 -23.9364 11.5353 30.6125 -11.459 10.0413 29.8243 -24.5326 10.1147 22.2069 -35.1528 11.6836 17.7191 61.5472 14.2726 25.2082 43.6854 11.43 30.0164 47.7677 14.1162 33.6212 -19.459 14.309 37.9267 -36.067 14.5054 27.6816 -32.9292 18.5574 36.7248 -46.1733 18.6604 20.5246 73.3418 18.3468 14.9194 68.8732 23.4107 28.4208 55.7803 22.4988 38.5465 -27.0171 23.4671 43.0366 -45.2302 23.6628 30.9246 -41.0731 29.3325 39.4763 79.4615 29.1894 16.0672 76.9844 23.4678 15.5749 72.8865 35.1223 29.8369 63.2406 34.5574 39.8307 81.8608 42.114 16.7292 80.9318 35.3877 16.409 66.0817 48.5555 39.2449 73.9987 48.5347 29.6857 80.1688 55.1853 16.948 81.5894 48.8387 16.9628 61.1927 62.0057 37.295 70.17 61.0152 28.6395 74.8647 66.3268 16.601 77.7874 61.0196 16.7611 61.7637 71.037 26.8557 67.1835 75.4493 16.6366 71.6321 71.1772 16.667 -7.40039 76.1581 26.3759 14.8335 76.3145 32.0471 -20.947 75.0059 21.3995 -9.30957 78.0917 17.6635 2.33308 81.2658 10.7014 -55.3055 81.4823 20.1865 -44.1025 82.8784 21.08 -48.3998 77.2606 26.9595 -63.8341 69.8359 17.705 -58.2579 70.6396 26.4175 -58.1459 60.4109 31.5845 -50.1918 68.7831 33.097 -53.5557 46.1592 34.9928 -63.069 52.729 24.0553 -63.6495 60.7883 23.3658 -54.4261 28.5392 21.6382 -12.4228 39.2454 51.9419 -52.1766 34.1006 30.9987 -39.3582 37.1753 42.8245 -63.2047 33.3562 7.77354 -14.9689 48.0973 51.5712 -13.2184 68.1588 38.5488 -20.841 71.9312 31.5875 -34.0814 73.6573 23.1685 39.0864 77.6536 29.4959 52.286 78.2905 24.2985 28.6752 75.0467 34.74 24.5284 79.4248 29.0977 58.2456 81.6454 14.9372 62.5867 78.8584 16.1198 -40.058 73.3058 29.0169 -62.4832 42.7738 19.6053 -66.2542 57.7677 16.0138 -46.3972 55.562 40.3341 46.1403 83.2928 20.059 52.8472 87.516 12.3304 24.3957 81.2413 26.4145 17.5457 83.2299 21.6568 35.0308 86.9496 21.9178 5.66061 83.0193 2.97282 39.2717 10.0042 25.9897 49.7414 9.99683 19.7068 14.6156 10.0124 31.7958 28.2119 11.4278 34.5791 55.179 10.0309 11.4214 16.1259 13.9798 40.2177 33.0793 17.7336 41.3765 18.9195 36.2041 52.5892 10.6044 39.6524 53.4314 18.2523 44.3116 53.7955 25.9535 39.9994 52.7745 9.73549 48.0914 53.8815 16.9236 53.6009 53.2898 26.8721 49.8693 52.6952 9.12603 55.8675 52.7181 15.9783 60.8706 50.8542 23.2428 59.2083 51.1997 15.2006 70.9348 38.4909 -38.0814 66.6122 37.6368 -31.4745 63.2943 41.295 -12.9337 55.4359 50.6592 -29.8093 42.9681 46.5354 -18.6612 31.1764 47.8255 -30.266 55.8423 44.7033 36.2897 31.2217 48.0605 46.511 42.7776 47.7899 45.6636 56.4673 46.2574 32.8524 66.1703 44.2955 12.3579 67.2602 43.2175 -19.149 38.1518 50.4005 -23.6628 48.8825 49.2194 21.1045 32.7401 51.4785 32.4268 38.9651 51.46 35.2465 50.0413 50.7771 17.9201 63.7837 48.4371 30.018 60.597 49.2453 -20.4236 57.6424 48.1257 -7.11345 60.5511 48.2081 -5.54756 57.4675 50.6459 -6.2067 51.4293 52.475 -5.95461 43.3855 53.166 -4.66971 35.7333 52.2177 -5.70251 32.445 51.1085 -8.3205 17.8723 43.3717 -2.69678 11.3425 36.4653 -27.2981 42.8866 48.0687 -27.8897 55.043 46.5161 -16.4436 32.2248 49.3054 -18.5848 62.3861 45.599 13.6265 28.0639 49.9986 41.3922 43.4352 49.4685 32.3868 32.7171 49.8711 40.4699 56.3449 48.0345 28.9733 65.0389 46.3945 11.0523 65.6624 45.6909 -37.9272 11.78 6.99728 -50.2675 18.389 7.36354 75.8256 18.3928 2.93945 64.2756 11.6576 2.65993 82.8128 29.1368 2.93945 85.8726 42.1384 2.93945 84.9147 55.2091 3.25752 79.936 66.2007 3.25752 72.9207 75.6569 3.11665 -13.2799 78.2816 6.78078 -42.4217 91.5301 9.02211 -66.2519 42.375 7.59116 -67.9758 58.5114 6.99802 8.76422 81.5601 20.2429 8.65004 83.1534 13.7124 6.16626 86.3527 3.3376 10.3479 87.4003 13.9949 7.91973 84.7475 8.18356 19.5238 87.0994 20.6484 13.8638 85.0248 17.2846 35.1961 83.043 23.5111 26.055 84.941 22.3278 44.4291 87.1742 18.6599 55.1672 83.7325 13.2216 53.3737 85.5572 12.3674 -18.7264 10.108 26.6814 -28.5504 10.1785 15.7995 -28.6467 14.412 33.9793 -40.9463 14.6426 19.2219 68.6182 14.2022 14.0757 -36.9819 23.7436 38.5844 48.5084 72.1529 33.9029 -14.7042 76.6096 19.7209 -49.515 83.8778 20.7678 -60.3339 76.3635 19.0618 -54.5522 64.8765 32.9243 -60.8158 55.9957 28.5728 -50.6442 23.4975 21.2438 -45.1383 35.1824 39.0803 -57.747 33.5446 21.51 -27.5531 73.6877 22.8942 26.6207 76.9559 31.9144 -39.393 77.9086 22.2647 -65.5928 51.6658 17.2594 -44.8336 71.3336 32.1213 -65.569 63.5509 16.5565 25.3055 83.1594 23.781 12.1192 83.2358 18.075 25.9631 10.0257 30.0393 30.5288 14.0969 38.2233 18.4628 39.992 53.2994 17.691 48.9863 53.8221 16.1429 57.6002 52.3171 32.2615 71.41 37.9727 51.4408 62.676 41.4618 57.6406 48.9151 43.8433 52.9177 35.0586 44.5773 36.217 23.1483 43.9056 -31.7681 36.6178 45.7769 -37.83 51.5724 43.6927 -25.9576 36.5644 47.2776 -31.2662 49.6491 45.6583 26.7542 27.5116 48.1161 23.2102 67.8126 43.5534 -9.81152 64.5785 42.5347 -5.73514 54.6841 51.8166 -6.34459 47.5345 53.0926 -5.18279 39.3551 52.8687 -13.0679 23.5531 45.6457 -5.21985 14.0791 40.2548 -0.679352 10.0168 31.8299 -28.752 49.271 47.2864 -23.8534 36.6519 48.7626 -24.6964 59.5316 45.8889 -7.15942 29.3978 49.7079 38.1551 37.5127 49.7814 23.9612 29.5453 49.9126 42.2701 49.9123 48.8776 35.8278 61.6884 47.1419 20.5055 66.243 45.9037 -8.95663 63.2617 45.5834 -31.1142 10.1703 6.38486 -44.1714 14.6552 7.27827 70.6407 14.3913 2.92833 79.9353 23.413 2.93945 84.5803 35.3544 2.93945 85.9631 48.8595 3.25752 82.8254 61.0226 3.25826 76.7546 71.3433 3.2553 -19.2017 77.8115 7.33611 -48.5489 92.2656 9.06511 -60.1596 84.4057 8.28143 -55.757 23.043 7.73055 -29.2013 79.6561 8.08569 -37.1064 88.1752 8.91461 -68.0046 51.5783 7.15372 -66.9147 65.618 7.07735 57.0756 10.1525 2.28551 6.64003 83.0734 8.64102 7.67061 86.759 8.63805 14.3983 87.2706 17.8748 26.21 86.9437 22.1654 62.3057 92.5874 2.9313 1.3848 69.2606 38.5873 1.56273 65.4519 43.0262 1.32251 64.1537 45.6605 4.95551 9.99831 32.3904 4.63076 11.3477 37.0599 4.48174 13.922 40.9628 4.08211 17.3859 43.9419 3.02928 21.4474 45.8963 3.07525 28.2293 49.9356 3.11009 31.6361 51.3265 3.03002 35.4574 52.4675 2.61333 39.4033 53.3009 2.11362 43.4389 53.8266 1.75772 47.519 53.7873 1.63762 51.3863 53.3032 1.70287 54.8295 52.4802 1.76736 58.0161 51.0099 1.52196 61.5001 48.3586 1.93642 72.8387 33.8763 3.64763 75.9142 30.548 5.31806 78.4269 26.9639 58.5778 87.5953 2.23361 59.1501 85.8263 2.11721 61.5583 84.2063 2.51758 64.9644 82.1214 2.892 69.0133 79.1475 3.00989 32.7991 89.7151 -30.4233 18.3501 89.4171 -27.9721 8.67525 89.5668 -20.9938 2.39314 90.3705 -9.85685 41.3633 90.1718 -28.7054 -31.106 11.4775 -32.9686 -16.1893 11.413 -41.8242 -37.8441 11.7199 -17.9362 51.1145 17.827 -43.7764 65.4167 18.372 -34.6672 55.5386 11.4663 -30.2365 -22.7101 18.3816 -48.1723 -41.2258 18.6322 -37.22 -49.9064 18.1281 -19.4546 62.0944 11.4196 -20.5393 59.314 28.4606 -46.5397 70.9277 29.0352 -36.8544 -33.1991 29.873 -50.7109 -49.3615 28.878 -39.0246 73.4812 41.7559 -37.3453 64.6226 41.5905 -46.5931 72.9066 55.0971 -37.0309 63.9264 55.2231 -45.5736 67.308 66.4328 -36.116 55.8026 66.7664 -44.1694 43.9561 74.6649 -39.815 57.8297 75.238 -34.1393 15.5401 73.1894 -42.5115 -12.2174 73.8819 -36.4385 15.3978 78.7998 -35.5147 -2.0421 78.412 -29.475 -24.7876 76.5792 -19.7267 -12.534 78.2897 -17.6678 4.34457 81.1227 -24.1642 -55.8163 87.2424 -22.0756 -43.7036 88.3494 -22.3158 -54.1303 74.7924 -34.6324 -44.4888 77.8752 -33.6648 -65.5053 72.5896 -18.5049 -61.9613 65.7536 -32.9553 -43.4634 60.448 -47.4894 -65.1954 57.0723 -29.5143 -59.2654 27.9119 -20.2361 -49.2087 49.1998 -47.3723 -58.9689 43.7199 -35.5858 -66.3446 42.1948 -19.4391 15.5861 70.0443 -46.0785 -33.1287 69.3852 -41.4713 -34.4892 80.0254 -21.5618 48.699 81.1865 -30.8689 34.2382 80.5703 -34.2498 16.5759 81.1153 -31.895 0.727875 81.1872 -12.4148 -68.018 58.2133 -17.8183 14.7802 11.3848 -44.0174 16.9221 17.4452 -50.8066 -13.0864 43.3447 -58.8481 10.4495 43.9097 -61.0858 -9.32663 36.6667 -59.0505 -14.22 51.903 -58.0496 9.45597 51.998 -60.0277 24.246 37.0634 -60.5519 11.3896 35.7436 -60.2776 26.5918 44.6467 -61.0071 25.4626 54.4929 -59.5273 9.00666 58.9948 -57.2808 21.3366 60.5555 -57.2059 -11.1972 57.2725 -56.9708 -22.2438 53.1256 -56.0203 -20.3457 43.0689 -57.3067 -12.1122 35.0371 -58.1689 -14.9222 59.3774 -55.2218 12.2904 31.7184 -59.1973 27.7581 35.2002 -59.4961 33.8971 44.4969 -59.5273 32.7486 55.5991 -57.9969 24.5692 62.5262 -55.8246 9.69026 62.3164 -55.2589 6.31009 84.6215 -9.59067 9.94086 84.9232 -20.0693 19.0219 85.0345 -27.4843 34.7653 85.0426 -29.4209 44.1941 85.119 -26.7866 50.8728 90.6708 -23.6459 25.0482 89.5646 -29.954 12.9607 89.423 -24.9078 5.25504 89.8204 -16.202 3.24726 88.5844 -2.72431 56.928 89.7848 -10.5352 -24.3405 11.4359 -38.3603 -12.0514 9.99387 -37.4698 -25.119 9.92937 -30.186 -35.4745 11.6324 -25.6774 -30.9667 10.1577 -16.9998 61 14.303 -32.6913 42.9826 11.5093 -37.4209 46.9722 14.2133 -40.7944 -19.5197 14.3549 -45.3897 -36.488 14.4595 -35.3605 -33.1887 18.5722 -44.2309 -44.1233 14.4447 -18.6976 -46.6619 18.3928 -28.2843 73.0378 18.3468 -22.5011 68.5692 23.4107 -36.0025 54.8395 22.7093 -45.7182 -26.8814 23.6917 -50.1401 -45.535 23.6628 -38.5063 -41.3718 29.3444 -46.7703 79.1575 29.1894 -23.6481 76.6804 23.4678 -23.1566 72.5633 35.1268 -37.3883 62.517 34.8109 -46.6606 81.5568 42.114 -24.311 80.6278 35.3877 -23.9899 65.2083 48.5511 -46.1149 73.84 48.5629 -37.3 80.6871 55.3477 -24.807 81.674 48.8988 -24.6283 60.7961 61.4452 -45.0316 70.7794 61.119 -36.7907 75.5475 66.5218 -24.6246 78.6126 61.265 -24.804 62.9885 71.049 -35.1951 66.8647 75.4648 -24.4251 71.4756 71.2009 -24.4489 -6.85692 76.1307 -33.2993 15.3904 76.124 -38.9186 -20.6749 74.9933 -28.8188 -18.659 77.1776 -18.9697 -8.319 78.3549 -24.2702 1.96458 81.2562 -18.3514 -55.843 81.314 -28.5504 -49.6254 89.3466 -22.4648 -44.4451 82.6048 -28.9686 -48.6808 77.2324 -34.5316 -64.3131 69.6573 -25.8984 -61.7107 81.899 -20.9783 -58.7835 70.7123 -34.1097 -58.4469 60.3879 -39.1736 -50.5077 68.7809 -40.6817 -54.183 45.9931 -42.2824 -63.8549 52.5711 -32.0063 -63.9335 60.729 -31.1655 -54.957 22.8131 -19.9766 -55.152 28.2115 -29.5499 -11.2032 39.4137 -59.029 -53.076 34.2815 -38.5249 -39.7533 37.3377 -50.1979 -63.1283 33.463 -20.1464 -14.2141 47.7244 -58.4915 -30.0695 77.3155 -20.5683 -21.5757 71.2928 -39.3886 -34.2579 73.9026 -30.84 39.2161 77.6454 -37.0836 52.7939 78.4766 -32.8685 29.7051 73.7336 -42.0511 25.218 79.3136 -35.8083 57.9394 81.7173 -23.2211 62.3879 78.9177 -24.2442 -40.3947 73.317 -36.5831 -38.6256 84.6334 -22.1512 -63.1328 42.5522 -27.8513 -68.0395 51.255 -18.387 -66.6864 57.5891 -24.6884 -46.719 55.3544 -48.0974 -67.0838 65.1042 -17.911 46.0958 83.2499 -28.6417 50.9529 87.3143 -20.6038 25.2513 81.0708 -33.3601 17.9216 83.2039 -29.0153 34.0372 87.1164 -29.0287 5.17719 83.0067 -10.4967 38.7965 10.0502 -33.6129 49.3922 10.0272 -27.3241 14.187 9.93604 -39.5629 27.7425 11.4278 -42.1534 55.0359 10.0176 -19.0023 15.6372 13.9546 -47.8631 32.7953 17.7996 -48.8099 18.8513 36.2745 -60.5645 10.861 39.7903 -60.8997 18.3879 44.3219 -61.3282 25.5709 40.1514 -60.9249 9.98461 48.0417 -60.7803 17.172 53.0256 -60.1664 26.7053 49.7018 -60.6231 9.02446 55.628 -58.8755 15.9709 59.969 -57.3289 23.2776 58.2326 -58.209 44.1377 66.4765 -47.442 32.9162 70.0487 -45.5996 -39.1943 64.8054 -45.7138 55.5401 55.5242 -49.7715 51.248 61.6595 -48.7462 56.0065 41.9561 -51.2803 57.0734 48.8091 -50.5693 46.5132 29.225 -51.505 52.5663 35.3329 -51.6029 17.5056 21.4015 -53.1414 35.7529 23.258 -51.4249 -24.8654 30.3579 -52.8774 -37.595 44.6801 -51.7631 -32.3879 37.056 -52.6379 -36.3175 56.5451 -50.6094 -38.0947 50.8613 -51.419 -25.0582 65.9138 -47.2878 -13.0315 55.2283 -57.5699 -29.5994 42.7331 -54.0504 -17.7196 32.1054 -55.3997 -31.0452 54.9518 -52.1567 14.4814 25.6447 -55.9766 35.6595 31.6265 -55.6473 45.0786 43.2372 -55.4835 44.2682 56.1306 -54.0718 32.613 65.3459 -51.8098 12.2638 66.6664 -50.3239 -16.8788 38.5536 -57.7812 -22.2779 48.1633 -56.692 20.9614 32.7638 -59.3975 31.7892 39.2914 -59.6303 34.2463 50.1711 -58.9927 17.7651 63.1379 -55.4049 29.3959 59.9275 -56.7944 -19.9928 57.0804 -55.4805 -7.23875 60.3598 -55.204 -5.65804 57.5512 -57.0761 -6.0065 51.3551 -59.049 -5.22208 43.4715 -59.8809 -3.96387 36.0409 -59.508 -5.15608 32.8988 -58.5686 -13.5854 23.9342 -52.6112 -9.06415 18.1577 -50.5723 -3.25877 11.387 -43.9714 -26.2193 42.6871 -55.6006 -28.5919 54.4558 -53.8865 -15.0875 33.3422 -56.7928 -18.825 61.9909 -52.8915 13.3618 27.7844 -57.7174 39.8055 43.952 -57.5439 31.8122 33.1212 -57.6826 38.9151 56.1492 -56.0878 28.5307 64.3375 -53.8731 10.8825 65.2576 -52.8604 -38.7872 11.7814 -10.3899 -51.3804 18.2081 -11.1306 75.9308 18.2734 -10.619 64.3713 11.5264 -10.1319 82.6956 29.1294 -10.748 85.6139 42.137 -11.5317 84.7924 55.3455 -12.4133 79.6343 66.3979 -12.9219 71.6684 75.6332 -12.7061 -25.2621 79.1542 -11.2952 -14.3624 78.3676 -10.5812 -55.4174 91.1379 -15.1558 -43.1913 92.0224 -14.9719 -65.5402 74.7902 -11.1558 -61.0434 28.0454 -11.3123 -32.6111 84.6875 -12.5304 -67.2833 42.4839 -10.9141 -68.8802 58.6841 -10.4374 0.543259 81.1205 -6.22162 9.52418 81.0708 -28.7966 8.37571 83.1824 -21.1125 5.53085 86.6678 -9.24443 6.35532 84.3783 -3.72153 9.91936 86.9399 -19.9543 7.46301 84.8157 -15.1358 19.1716 86.9829 -27.1848 13.7244 84.9789 -24.2465 35.0315 83.0667 -31.2656 26.1633 85.0641 -29.3275 42.8321 87.2394 -26.5835 54.4673 83.6613 -21.5529 52.1903 85.3592 -20.4029 -19.1772 9.97014 -34.5627 -29.0093 10.0524 -23.9684 -28.9966 14.3787 -41.6404 -41.4341 14.4313 -27.1351 68.2653 14.2141 -21.6559 -37.1724 23.751 -45.8917 49.1935 70.9503 -42.3484 -14.5648 76.6133 -27.0075 -49.8916 83.6109 -28.9872 -61.1227 76.1114 -27.2671 -55.0601 65.0337 -40.5186 -61.3029 55.8348 -36.2984 -51.2017 23.1727 -29.0783 -45.8464 35.4359 -46.3143 -58.6945 33.6906 -29.4149 -27.3062 73.8878 -30.3291 27.1279 76.7275 -38.8845 -39.6428 78.0687 -29.8339 -66.1326 51.3373 -25.8257 -45.1368 71.2869 -39.6934 -65.8464 63.4174 -25.0094 25.8474 83.1357 -30.877 12.1451 83.2039 -25.5855 25.4849 9.93826 -37.9992 30.078 14.1043 -45.7664 18.448 40.0625 -61.2347 17.9876 48.7616 -61.0605 16.2348 56.7727 -58.8674 -32.2767 62.0154 -49.2051 -13.9368 67.8282 -45.9206 -24.8684 37.0434 -54.8511 -31.525 48.8313 -53.174 26.4258 27.5071 -55.6637 23.2554 67.017 -50.8845 -10.1563 64.4547 -50.0444 -5.75739 54.7064 -58.2557 -5.8419 47.5145 -59.5984 -4.37907 39.5768 -59.8409 -5.9761 14.2111 -47.5917 -0.926239 9.96272 -39.5747 -28.5177 48.5533 -54.7769 -21.6936 37.4949 -56.2842 -25.4638 59.1765 -53.191 -6.8028 30.1029 -57.2111 37.0326 38.1125 -57.7227 23.7499 29.4563 -57.6722 40.6137 50.1599 -57.0286 34.858 61.1842 -54.92 20.4387 65.7863 -53.1414 -9.18353 63.1068 -52.8225 -31.7926 10.1666 -9.9777 -45.2866 14.5017 -10.8326 70.7816 14.2259 -10.5137 79.9368 23.3648 -10.642 84.3683 35.367 -11.0661 85.8037 48.9262 -12.0255 82.7112 61.2146 -12.6921 76.0168 71.4278 -13.3949 -20.2604 77.9924 -11.2248 -49.3845 92.9811 -15.3182 -60.8729 85.6046 -14.2238 -56.4851 22.8762 -11.2211 -64.3531 34.2467 -11.1677 -29.1309 81.0871 -11.445 -37.3177 89.3021 -14.5323 -69.0093 51.6317 -10.622 -67.6547 66.1837 -10.4878 5.71547 83.0356 -4.42811 57.0919 10.0917 -9.5929 6.03725 83.0742 -16.133 5.45968 86.1214 -3.26036 7.12048 86.8962 -15.0149 13.8867 86.9385 -24.0596 25.9809 87.0964 -28.959 -11.6043 122.781 8.68477 -11.2981 122.692 9.69681 -10.977 122.366 10.6888 -10.6656 121.82 11.586 -10.3765 121.078 12.3445 -10.1237 120.175 12.9302 -9.91827 119.156 13.3142 -9.77222 118.067 13.4803 -9.68768 116.96 13.4188 -9.67062 115.887 13.1341 -9.72327 114.899 12.6358 -9.85822 114.021 11.8907 -10.7227 112.914 8.71887 -11.1023 127.944 8.41562 -10.4921 127.767 10.4464 -9.85971 127.122 12.423 -9.24655 126.037 14.2114 -8.68082 124.561 15.7276 -8.18628 122.764 16.8946 -7.78964 120.733 17.6635 -7.49306 118.563 17.9719 -7.3344 116.363 17.8451 -7.30846 114.233 17.2735 -7.41818 112.273 16.2733 -7.69992 110.534 14.786 -8.2775 109.033 12.4727 -9.35776 108.08 8.5424 -9.95609 132.998 7.96262 -9.04932 132.737 10.981 -8.11142 131.781 13.9103 -7.20317 130.173 16.5602 -6.3661 127.988 18.8075 -5.64024 125.328 20.5468 -5.05821 122.318 21.6961 -4.64821 119.099 22.2025 -4.42282 115.824 22.0238 -4.39761 112.65 21.1845 -4.56294 109.746 19.6875 -4.97073 107.211 17.3891 -7.42485 103.383 8.21767 -8.20483 137.879 7.33685 -7.0141 137.537 11.2983 -5.78555 136.284 15.1374 -4.59557 134.176 18.611 -3.49826 131.313 21.5559 -2.54626 127.827 23.8351 -1.78407 123.883 25.3417 -1.24654 119.664 26.006 -0.958862 115.367 25.7954 -0.932175 111.202 24.7018 -1.15683 107.411 22.6977 -1.71957 104.094 19.6809 -4.90993 99.0215 7.7476 -5.87453 142.516 6.54797 -4.41762 142.098 11.3954 -2.91623 140.566 16.0879 -1.46082 137.989 20.3341 -0.119568 134.489 23.9337 1.04373 130.229 26.72 1.97571 125.407 28.5617 2.63261 120.249 29.3728 2.98405 114.998 29.1163 3.01297 109.897 27.8025 2.72233 105.248 25.381 2.00388 101.315 21.4907 -1.90344 95.1527 7.08847 -2.99854 146.84 5.6071 -1.29695 146.353 11.2694 0.45578 144.564 16.7478 2.15439 141.556 21.7035 3.72029 137.47 25.9059 5.07858 132.497 29.1585 6.16626 126.869 31.3079 6.93364 120.848 32.2555 7.3429 114.718 31.9552 7.37701 108.764 30.4219 7.02557 103.335 27.5927 6.15958 98.8146 22.9217 1.31064 91.5316 5.92221 0.38089 150.789 4.52833 2.30194 150.239 10.9231 4.28081 148.22 17.1066 6.19814 144.825 22.7007 7.96496 140.213 27.4444 9.49823 134.6 31.1152 10.7268 128.246 33.5419 11.592 121.45 34.611 12.0547 114.531 34.2722 12.0932 107.81 32.5417 11.6995 101.628 29.4492 10.7461 96.4739 24.1724 4.21408 154.305 3.32648 6.32714 153.7 10.3604 8.50323 151.481 17.1593 10.6111 147.749 23.3102 12.5537 142.677 28.5254 14.2397 136.505 32.5617 15.5905 129.519 35.2301 16.5418 122.048 36.4053 17.0504 114.439 36.0331 17.0919 107.05 34.1306 16.6589 100.258 30.74 15.7233 94.7279 25.791 8.4454 157.338 2.02082 10.7201 156.687 9.59079 13.0608 154.299 16.9057 15.3288 150.283 23.5229 17.4189 144.827 29.1348 19.2332 138.186 33.4774 20.6856 130.67 36.3481 21.7103 122.631 37.6123 22.2575 114.445 37.2119 22.3019 106.495 35.1648 21.8259 99.2209 31.4888 20.825 93.3985 26.5962 13.0133 159.842 0.628418 15.4163 159.154 8.62471 17.8875 156.633 16.3489 20.283 152.392 23.3369 22.4903 146.631 29.2623 24.4054 139.618 33.8481 25.9394 131.682 36.879 27.0211 123.193 38.2151 27.5987 114.549 37.7917 27.6461 106.153 35.6297 27.1561 98.4202 31.8069 26.2026 92.3353 26.7949 17.8512 161.781 -0.829224 20.3468 161.067 7.47549 22.9136 158.449 15.497 25.4011 154.045 22.7534 27.6929 148.063 28.9072 29.6814 140.78 33.6686 31.2747 132.539 36.8168 32.3972 123.724 38.2032 33.0378 114.732 37.7776 33.1394 106.004 35.5511 32.5863 97.9694 31.5919 31.965 91.3737 26.2299 28.0317 162.761 5.43213 30.6652 160.074 13.6627 33.218 155.556 21.1096 35.5698 149.416 27.4236 37.6109 141.943 32.3103 39.2458 133.487 35.5408 40.3779 124.44 36.8931 41.0778 115.182 36.3645 41.3685 106.251 34.3441 40.5714 98.0124 30.0964 39.483 90.8428 24.5869 25.47 163.494 -3.09354 33.2647 163.97 -5.38011 35.8181 163.241 3.11665 38.442 160.564 11.3176 40.9852 156.062 18.737 45.5605 150.164 24.1539 46.9596 143.512 28.5313 48.7731 136.143 30.9839 48.1273 125.112 34.1698 49.5294 116.289 34.2469 49.9179 107.113 32.426 48.6893 98.8206 27.8254 47.2243 91.628 22.178 38.4532 163.455 -6.88224 40.9503 162.742 1.42916 43.5171 160.123 9.45065 47.7967 155.173 17.3906 53.1913 129.392 30.4605 57.4434 120.187 30.353 57.7555 108.881 29.1971 56.501 100.349 24.8901 54.4406 93.4897 18.651 43.5401 162.322 -8.34137 45.9453 161.636 -0.335434 50.4154 158.124 9.95186 48.4521 160.589 -9.73451 50.7305 159.939 -2.15119 54.3182 157.614 6.23138 63.8033 119.565 25.3861 63.9101 110.06 24.7226 62.901 102.219 20.9027 60.7679 96.0876 14.7059 53.1171 158.28 -11.0416 55.2347 157.675 -3.99215 58.19 155.872 2.80748 67.2969 119.573 21.0355 67.7537 111.25 20.0049 67.3733 103.92 17.1459 65.043 98.1407 11.5222 57.4671 155.429 -12.245 59.394 154.879 -5.83163 62.1915 152.982 0.103493 69.6977 119.848 16.5973 70.8076 112.269 15.649 70.4413 106.039 12.8968 68.5447 100.725 8.19913 61.4382 152.077 -13.326 63.1457 151.59 -7.6422 65.78 149.427 -2.04368 72.9933 113.56 10.1899 72.6093 109.123 7.23009 71.4208 102.692 -5.93692 66.1158 146.314 -14.556 67.6306 145.656 -8.87371 68.937 144.641 -4.73136 71.1249 140.238 -3.87204 72.9303 135.432 -3.25369 73.955 129.872 0.956131 73.8222 124.051 6.88754 69.9913 140.169 -15.5436 71.876 138.749 -9.69077 -11.3759 117.634 8.77818 63.3644 132.244 19.7795 58.7861 144.777 19.4836 67.0122 129.764 16.8798 70.6155 138.855 5.83472 63.4756 148.383 9.49515 62.8195 133.184 17.464 65.3848 131.323 15.0306 58.8061 141.77 16.8434 60.1659 137.06 18.4575 67.3103 131.311 12.1873 59.8997 144.627 13.2097 68.6945 133.697 9.63008 62.6779 144.573 10.0134 68.5944 137.783 7.94185 66.1373 141.972 8.0323 63.5846 133.449 17.7798 66.1373 131.523 15.497 59.6002 142.393 17.3936 68.0977 131.472 12.4801 69.5345 133.885 9.64862 63.3399 145.241 10.1906 69.4233 138.273 7.76169 66.8358 142.631 7.99524 70.3049 128.194 12.73 72.5233 132.983 6.70811 70.8876 139.701 3.88477 57.3232 138.168 24.4749 62.3546 131.157 22.7541 67.3926 146.279 4.41341 62.6852 151.575 8.16354 58.5355 152.152 14.7897 56.0087 147.327 21.699 67.4163 128.203 18.5732 61.7689 138.738 16.9517 60.1192 142.066 15.9826 64.1066 135.62 16.4201 65.946 133.39 14.7222 67.2903 132.939 12.8657 68.2793 135.009 11.4955 67.7633 138.355 10.7993 65.6517 141.685 10.9157 62.861 143.967 11.7343 60.6115 144.197 13.6175 60.9733 137.35 18.8824 60.8999 145.33 13.6701 65.4233 132.097 14.9091 64.194 132.052 16.3667 63.0381 133.984 17.1452 60.5626 137.576 18.0038 59.2072 139.485 18.0623 59.179 141.815 16.5439 61.4122 134.887 18.1943 67.2154 132.019 12.4453 66.4087 131.047 13.613 59.0411 143.572 15.1678 60.1096 144.464 13.3409 68.5151 134.306 10.3248 68.0821 132.189 10.829 61.149 144.974 11.4258 62.7831 144.363 10.5976 68.2882 138.059 8.96576 68.9548 135.624 8.61655 64.3898 143.534 8.86493 66.015 141.892 9.0614 67.5801 139.948 7.72906 62.5229 143.343 13.2497 61.0674 143.946 13.8533 64.8184 141.126 13.1519 66.8854 138.187 12.9695 67.3889 133.651 13.1986 66.7994 134.635 14.1328 65.5909 137.242 14.9847 63.4504 140.109 15.2998 61.4471 142.587 14.915 69.5049 129.705 12.5735 72.1177 136.32 4.77299 71.5801 133.393 8.20432 59.2932 134.201 23.8217 59.9546 137.579 21.2023 65.0801 149.359 5.97188 67.3192 144.395 6.27661 56.9459 150.409 18.5398 60.5959 148.729 14.5628 56.1303 142.947 23.7928 65.2135 129.283 20.9902 68.9562 127.783 15.7988 69.2988 142.988 3.69571 60.547 152.61 11.1863 71.7477 130.025 9.56706 72.9533 131.626 4.33482 71.3592 125.34 12.6099 70.8958 140.288 0.80043 60.4142 128.485 25.3476 53.3566 137.368 28.099 60.1785 154.454 5.65604 66.8521 148.152 1.54631 50.4599 149.321 23.457 54.4777 155.19 14.0957 66.8083 125.61 19.6379 60.7657 140.445 16.6648 62.9418 137.1 16.8738 65.1157 134.361 15.6497 66.6044 132.832 13.8036 67.9094 133.728 12.0538 68.246 136.622 11.0736 66.8721 140.078 10.7355 64.2593 143.015 11.2634 61.6205 144.401 12.4393 60.0361 143.345 14.9402 62.2167 135.13 18.5205 60.0235 144.253 15.7061 59.9835 139.927 18.519 64.9258 132.28 16.7923 67.1776 131.236 14.0179 68.9044 132.335 10.9928 69.7696 135.952 8.50682 68.3794 140.573 7.55853 64.9874 144.212 8.9287 61.9957 145.611 11.7513 64.3364 132.866 16.125 59.6128 139.75 17.5893 61.7458 135.583 17.8214 66.3694 131.791 13.6738 59.3318 143.457 15.0788 67.9657 132.894 11.3154 61.3218 144.772 11.7684 68.6738 136.094 9.51442 64.4194 143.374 9.69681 67.3615 140.039 8.78485 61.7844 144.005 13.1407 63.6091 142.365 13.2305 65.9438 139.693 13.0347 67.4912 136.673 12.9257 66.9492 133.714 13.8169 66.3464 135.861 14.5969 64.5685 138.672 15.2167 62.3546 141.447 15.1878 60.8028 143.341 14.6881 70.7571 131.099 10.3129 71.4393 136.084 6.66586 61.5272 134.531 20.6551 65.2209 146.715 7.63861 59.5052 147.331 17.3142 58.8328 141.204 20.8056 65.3699 130.706 18.6303 68.3045 129.387 14.7556 69.1838 141.704 5.63008 61.9527 149.098 11.8158 72.6026 127.566 8.47568 72.3965 136.097 1.70497 56.5247 132.614 27.6949 63.6929 151.685 3.08774 52.022 153.009 18.9305 51.1249 144.226 26.8356 63.9865 126.508 22.5154 69.2202 125.238 16.535 69.0541 144.317 0.692924 57.2187 155.661 9.56113 67.741 135.282 12.8723 67.7907 134.283 12.7419 71.6609 136.111 -15.9358 72.3201 105.969 -15.2641 74.0417 117.157 -16.1597 75.2065 106.525 -16.2769 79.8634 107.308 -17.6552 91.3867 109.457 -21.1013 88.3001 106.164 -20.0804 79.2991 114.295 -17.6596 83.595 107.064 -18.7273 84.1132 113.461 -18.9875 85.3967 106.488 -19.2404 74.3568 135.883 -16.7173 78.9611 134.305 -18.0244 82.9529 133.126 -19.1618 84.9244 134.248 -19.7638 86.99 136.683 -20.4237 90.4947 139.433 -21.5114 93.7133 139.447 -22.4507 94.9967 133.968 -22.6969 95.4994 138.023 -22.9393 92.0955 130.536 -21.7701 88.3638 126.832 -20.5942 85.6599 124.96 -19.7608 81.4537 123.062 -18.4885 74.8654 115.813 -16.3999 75.0456 119.162 -16.437 77.3477 106.901 -16.9108 90.4702 107.067 -20.7351 76.8324 114.944 -16.9597 81.866 106.977 -18.232 81.8267 113.709 -18.3173 87.5994 113.172 -20.0641 72.8517 136.463 -16.4526 76.6211 135.168 -17.3616 81.0749 133.56 -18.6235 84.1259 133.478 -19.5125 85.7941 135.222 -20.0404 95.5972 136.005 -22.9201 93.7963 132.209 -22.3054 90.1255 128.604 -21.1495 87.0197 125.694 -20.1745 83.7714 124.169 -19.1907 77.8207 121.529 -17.3927 90.9181 111.196 -21.0087 72.5032 108.223 -2.09484 75.2258 128.38 -2.75545 73.0089 134.723 -11.6266 74.987 120.808 6.20024 75.9205 117.527 -9.42607 74.9633 116.553 -9.73895 78.1707 127.11 -4.45851 76.4373 109.876 3.38505 75.8359 108.157 -4.45555 81.7666 127.621 -5.91393 76.6804 114.045 7.19746 76.6345 120.205 6.07716 82.3917 119.936 3.28125 80.7256 108.785 -7.12913 83.5075 117.685 2.46864 82.9974 115.277 1.76725 92.4261 111.042 -14.8022 90.3783 110.634 -9.15768 95.4037 129.402 -7.5814 96.0984 136.789 -17.4832 82.3405 119.579 -9.26593 80.8413 115.369 -9.65369 85.2625 124.587 -1.81087 84.8272 129.21 -7.48057 85.7451 117.806 -3.52579 86.8232 121.414 -9.52765 85.9097 118.886 0.325172 87.199 131.776 -9.16064 88.7516 134.416 -11.1099 90.1003 121.341 -5.78863 94.2515 126.991 -9.62626 89.9564 123.624 -10.2795 92.7753 126.838 -11.8772 90.8128 122.536 -2.9371 84.8317 108.856 -9.63812 86.0135 114.746 -2.76731 86.5792 108.162 -11.0609 90.7371 125.097 -2.53673 73.043 106.875 -10.3143 75.0849 116.366 -9.04127 75.9716 116.037 -9.92357 74.6763 117.226 -13.3023 76.6107 127.495 -3.81347 75.8715 107.338 -10.9986 74.2945 131.787 -6.83849 77.6673 130.92 -7.97213 79.9509 127.383 -5.12654 76.4239 117.364 7.49699 79.6098 120.36 4.88643 79.5468 114.305 5.90663 78.3479 108.471 -5.80049 80.1169 108.117 -13.6233 81.3351 130.611 -9.06203 83.483 116.149 2.62879 83.0011 114.026 3.50368 91.761 108.672 -14.126 92.1266 109.889 -18.0081 93.8845 131.645 -7.45462 96.1799 134.037 -11.4887 81.9698 117.706 -6.57603 78.9833 118.659 -9.33636 78.2737 115.773 -9.7916 81.6235 116.026 -5.37269 79.8693 114.493 -14.8934 83.5372 128.01 -6.78511 83.5372 116.896 -3.09725 86.2686 119.313 -6.65833 84.7701 120.477 -9.37344 85.7155 117.814 -1.09836 82.8336 116.065 -0.2435 84.0376 118.31 1.24899 82.4806 122.05 -11.5955 87.1182 124.405 -12.0018 88.0999 133.229 -10.2009 92.2897 123.818 -7.20253 93.4241 126.82 -10.8934 91.5661 125.3 -11.0513 89.9394 122.25 -7.90022 90.4806 121.459 -4.05592 93.4426 125.358 -4.55564 95.0537 127.861 -8.4207 86.6067 133.598 -11.5288 88.5707 135.852 -12.9256 89.8207 126.465 -12.6372 92.9117 128.817 -13.9117 95.0404 130.344 -13.2941 82.9299 109.011 -8.36213 85.6702 113.376 -2.09262 83.9642 114.927 -0.734322 83.2265 115.122 -10.3417 85.751 115.129 -7.31301 84.1511 107.994 -14.6242 84.6693 113.83 -16.0203 88.6597 113.95 -5.64331 88.16 112.314 -5.20661 87.6284 114.616 -8.44739 91.1709 112.257 -10.1186 89.261 107.896 -12.7825 84.4929 131.425 -10.2884 88.4714 122.412 -9.79086 88.4424 120.148 -1.065 85.9995 121.323 0.560211 86.1099 130.434 -8.26055 87.8345 118.872 -4.42515 91.1968 133.419 -9.01013 88.8191 128.275 -4.56676 81.5976 122.873 0.828606 76.9644 122.205 2.94316 81.4612 110.902 -0.296883 85.7392 110.723 -3.63627 75.9894 134.176 -12.4407 80.1251 132.842 -13.5803 83.9442 132.485 -14.6398 85.946 134.022 -15.3694 88.0213 136.327 -16.4059 91.3103 138.582 -16.933 94.3976 138.399 -17.1755 95.3962 132.764 -17.8798 92.8436 130.018 -17.5358 89.2928 126.974 -16.3569 86.4413 124.91 -15.6051 82.4754 123.01 -14.5108 91.896 112.486 -14.9156 82.8751 115.658 -0.544518 86.2805 115.188 -4.50003 76.1644 116.572 -8.83145 75.4185 115.882 -13.8516 76.0488 119.438 -12.6624 75.6543 131.457 -7.41829 79.4986 117.656 6.72963 79.0322 110.008 1.65974 78.0128 107.635 -12.0211 79.5268 130.758 -8.47779 82.1877 117.111 4.66623 91.3177 107.267 -17.6789 94.3523 135.804 -11.3701 79.199 116.397 -7.74822 77.416 115.064 -14.3959 84.1318 118.571 -6.36101 83.3881 117.034 -0.32283 85.0712 123.225 -11.8706 91.807 124.332 -9.03386 92.9703 124.047 -5.59067 87.5542 134.782 -12.3095 91.394 127.808 -13.2948 94.0891 129.464 -13.8324 83.6906 111.07 -2.07482 83.6929 113.909 0.096817 83.6402 115.586 -6.22978 82.2292 108.145 -14.0185 82.2626 114.108 -15.3812 85.9475 107.439 -15.3597 88.2578 113.456 -17.1125 88.2163 114.084 -11.2463 88.9763 106.666 -16.7455 83.1168 130.614 -9.81607 88.5233 125.332 -12.2287 88.5596 122.718 -0.990116 88.1236 120.568 -7.14322 91.5424 136.545 -12.2591 90.1959 130.708 -6.46555 83.1835 123.375 -0.566017 79.5957 122.783 1.99635 74.3672 117.295 7.88031 87.5631 110.072 -6.37584 74.1744 134.769 -11.9588 77.8467 133.564 -12.9456 82.0565 132.388 -14.1586 85.1416 133.114 -14.9897 86.8728 135.108 -15.8513 96.088 134.721 -17.6366 94.3716 131.254 -17.9443 90.9752 128.478 -16.8885 87.8886 125.817 -15.9581 84.6456 124.017 -15.1551 78.798 121.528 -13.6567 91.6357 111.58 -17.9377 84.2971 115.519 -2.50114 83.7426 120.625 1.77541 88.5833 114.451 -6.97195 88.0828 118.976 -2.26166 92.4098 128.085 -4.46593 90.9233 113.198 -10.8133 95.8359 131.912 -12.44 88.8584 109.104 -9.27186 75.6269 121.857 3.65715 78.5266 120.452 -11.3783 85.7325 132.479 -10.7807 87.2109 126.227 -3.03349 82.3865 115.792 -3.39975 85.5323 114.683 -10.7629 88.5351 113.906 -14.361 85.1809 114.135 -13.5766 82.7372 114.618 -13.0324 80.3171 114.815 -12.4815 77.8096 115.265 -12.0804 75.7054 115.895 -11.7089 74.7512 116.96 -11.2522 75.744 118.732 -10.8711 69.843 141.836 -9.30819 67.9679 143.189 -15.0231 72.8213 119.941 10.9157 71.6506 104.986 0.684029 69.456 100.727 -14.47 73.995 114.29 6.9995 73.1142 110.85 3.56299 72.9748 136.288 -10.6843 71.3295 137.732 -15.8765 71.3963 104.177 -15.1099 74.1581 133.103 -5.27631 75.2109 128.825 -1.40012 75.073 122.123 6.21136 74.2901 118.616 8.83824 74.0083 114.133 7.99301 73.4597 110.347 4.91832 72.8198 106.93 -0.967873 82.4554 113.29 2.18171 79.572 111.521 3.2642 80.1607 112.304 4.14649 -10.1429 113.254 10.7089 72.7842 105.382 -7.25814 -5.83078 104.99 14.0223 -2.85619 101.143 15.3198 0.690811 97.9167 16.3207 4.67302 94.8688 16.9057 66.3361 95.2358 0.153168 -11.892 122.645 7.67271 -12.1529 122.274 6.67995 -12.3643 121.685 5.78059 -12.534 120.909 5.0184 -12.626 119.978 4.42898 -12.646 118.938 4.04047 -12.5956 117.84 3.87142 -12.4777 116.734 3.92851 -12.2953 115.674 4.20803 -12.0595 114.707 4.70033 -11.7659 113.862 5.43361 -11.6777 127.672 6.3856 -12.1989 126.934 4.40896 -12.6304 125.765 2.6199 -12.9514 124.219 1.10294 -13.1465 122.369 -0.071487 -13.2072 120.301 -0.848503 -13.1242 118.113 -1.18808 -12.8996 115.91 -1.07389 -12.5437 113.798 -0.511894 -12.0803 111.876 0.468269 -11.5131 110.201 1.90664 -10.7279 108.684 4.35558 -10.8109 132.596 4.94501 -11.5843 131.502 2.01563 -12.2226 129.769 -0.634972 -12.6979 127.479 -2.88298 -12.987 124.738 -4.62311 -13.0768 121.674 -5.77454 -12.9633 118.431 -6.28242 -12.6504 115.16 -6.12376 -12.1492 112.018 -5.30077 -11.4627 109.168 -3.83942 -10.636 106.694 -1.7434 -9.32736 137.352 3.37615 -10.3401 135.919 -0.462959 -11.1772 133.648 -3.93729 -11.8 130.646 -6.88298 -12.1796 127.054 -9.1636 -12.2968 123.039 -10.6717 -12.1477 118.789 -11.3375 -11.7385 114.502 -11.1299 -11.0883 110.379 -10.0578 -10.1881 106.649 -8.12857 -9.11383 103.415 -5.39493 -7.24765 141.871 1.70126 -8.48584 140.119 -2.99197 -9.509 137.344 -7.23812 -10.2704 133.674 -10.8392 -10.7339 129.283 -13.627 -10.8777 124.375 -15.4702 -10.6953 119.179 -16.2843 -10.1948 113.94 -16.03 -9.38 108.916 -14.6924 -8.24042 104.41 -12.2576 -6.81169 100.55 -8.6587 -4.60298 146.087 -0.054435 -6.04802 144.042 -5.53284 -7.24321 140.802 -10.4893 -8.13144 136.519 -14.6932 -8.67267 131.393 -17.9473 -8.84024 125.664 -20.0997 -8.62744 119.599 -21.0494 -8.04318 113.482 -20.7529 -7.08603 107.625 -19.1759 -5.77963 102.353 -16.3577 -4.12698 97.8226 -12.2769 -1.43115 149.939 -1.86574 -3.0623 147.631 -8.04924 -4.41095 143.974 -13.6441 -5.41411 139.139 -18.3892 -6.02504 133.353 -22.0622 -6.21411 126.886 -24.4919 -5.97388 120.04 -25.564 -5.31401 113.136 -25.2289 -4.25377 106.509 -23.4776 -2.81467 100.514 -20.3577 -0.857285 95.3878 -15.9247 2.22112 153.371 -3.70596 0.427597 150.832 -10.5049 -1.05525 146.812 -16.6565 -2.15849 141.496 -21.8739 -2.82948 135.134 -25.9124 -3.03783 128.024 -28.5838 -2.77313 120.497 -29.7627 -2.04877 112.906 -29.3942 -0.897324 105.606 -27.4954 0.658188 98.9955 -24.1115 2.66969 93.7269 -19.7623 6.30045 156.332 -5.54841 4.37052 153.602 -12.8633 2.77497 149.275 -19.4821 1.58868 143.556 -25.0954 0.866531 136.711 -29.4409 0.642624 129.061 -32.3147 0.926575 120.963 -33.5833 1.70657 112.796 -33.1866 2.9455 104.941 -31.144 4.64336 97.9398 -27.491 6.69341 92.8958 -23.465 10.7483 158.78 -7.36639 8.71009 155.896 -15.0906 7.02557 151.328 -22.08 5.77182 145.289 -28.0077 5.00963 138.061 -32.5957 4.77312 129.983 -35.6311 5.07339 121.431 -36.9701 5.89712 112.807 -36.5512 7.20499 104.513 -34.3944 9.05486 97.2925 -30.556 11.2406 92.5807 -26.9734 15.4979 160.678 -9.13321 13.3818 157.684 -17.1547 11.6321 152.94 -24.4125 10.3309 146.669 -30.5671 9.53901 139.163 -35.3323 9.29359 130.775 -38.4834 9.60574 121.895 -39.8743 10.4606 112.939 -39.4398 11.8189 104.326 -37.2 14.0588 96.9514 -33.3467 16.6434 92.4725 -29.9718 23.0545 162.362 -11.6177 20.8829 159.289 -19.8483 19.0871 154.421 -27.2967 17.7525 147.986 -33.6129 16.9392 140.284 -38.5019 16.6871 131.675 -41.736 17.0074 122.563 -43.1632 17.8853 113.373 -42.7169 19.2791 104.535 -40.4185 21.2106 97.0107 -36.2628 23.42 92.7149 -32.4103 30.8573 162.843 -13.8754 28.6938 159.781 -22.0763 26.9055 154.931 -29.4973 27.9242 148.749 -36.2635 26.8335 141.896 -40.4148 27.1308 134.403 -43.1558 24.8332 123.19 -45.306 25.7073 114.033 -44.8611 27.096 105.227 -42.5709 28.977 97.7766 -38.3173 31.01 93.1798 -33.7501 36.0984 162.352 -15.1936 33.9816 159.358 -23.2144 33.3826 154.015 -31.9877 31.2043 127.797 -45.1888 41.2721 161.261 -16.3458 39.5527 157.252 -27.2589 34.1114 118.081 -46.7154 35.274 106.958 -44.7195 36.8836 99.3018 -39.4702 38.9366 94.263 -33.7738 46.3034 159.583 -17.3163 44.8502 156.854 -26.2038 42.5748 117.521 -46.6924 42.9789 108.591 -45.2964 44.501 100.951 -40.6187 47.291 94.8665 -33.4268 51.1197 157.345 -18.0904 49.9772 155.213 -25.3275 48.2059 117.708 -45.7612 48.7168 109.961 -44.0908 50.3568 102.509 -40.027 53.4827 96.7468 -32.9174 55.6498 154.578 -18.6568 54.8409 152.392 -25.0769 52.7864 118.209 -43.2581 53.6228 111.351 -41.2941 55.2413 104.656 -38.0407 58.7364 99.47 -31.8202 59.8286 151.323 -19.0083 59.0656 148.888 -25.0487 58.6371 112.647 -37.2162 60.0213 108.358 -34.3455 66.7364 101.215 -23.2055 64.3461 145.393 -20.1264 63.2939 144.171 -24.2324 64.6093 139.563 -25.8976 66.0209 134.24 -27.224 64.8265 128.137 -31.0498 61.4092 121.344 -36.0211 68.4454 138.292 -21.5291 45.453 130.809 -41.5454 41.6524 143.401 -39.21 50.101 128.433 -40.9145 59.0129 137.957 -33.7931 50.9314 147.376 -33.4765 46.2433 131.854 -39.2708 49.7303 130.061 -38.4737 43.1271 140.511 -36.8678 43.4601 135.718 -38.774 52.9147 130.138 -37.0872 45.9668 143.509 -34.5197 55.443 132.636 -35.7653 50.0284 143.557 -33.3201 56.2208 136.784 -34.4582 54.0432 141.001 -33.4001 46.726 132.091 -39.9847 50.1181 130.245 -39.3182 43.4927 141.099 -37.7857 53.4219 130.291 -37.7879 56.1362 132.807 -36.2509 50.4828 144.208 -33.8546 57.0422 137.29 -34.817 54.643 141.653 -33.7723 55.0842 126.961 -39.0439 60.0643 131.807 -35.2485 60.3282 138.873 -32.42 37.8104 136.599 -42.3736 42.95 129.62 -43.6504 57.0126 145.449 -31.2322 50.941 150.632 -32.0693 43.8723 150.975 -35.442 38.0876 145.889 -39.6926 49.5108 126.802 -42.685 45.605 137.439 -38.4211 44.6923 140.828 -36.8618 47.893 134.316 -39.1277 50.3776 132.134 -38.6198 52.5225 131.75 -37.7278 54.0743 133.869 -37.1666 53.9713 137.248 -36.4482 52.0865 140.596 -35.554 49.2647 142.875 -34.8407 46.3531 143.052 -35.2278 43.9086 135.978 -39.5785 46.5533 144.179 -35.4761 49.8356 130.846 -38.4441 47.9983 130.76 -39.0142 46.6052 132.656 -39.1566 44.0339 136.249 -38.6168 42.8387 138.17 -38.0111 43.6017 140.564 -36.8188 44.6634 133.535 -39.1929 52.6931 130.851 -37.3023 51.3763 129.845 -37.8198 44.2029 142.382 -35.6615 46.0758 143.337 -34.7362 54.9106 133.214 -36.2776 54.299 131.078 -36.3859 47.9753 143.917 -33.7041 49.8059 143.321 -33.8591 55.4037 137.025 -35.1736 56.1837 134.599 -35.1328 52.1021 142.547 -33.2281 53.387 140.878 -34.1972 55.4482 138.973 -33.8331 48.1733 142.19 -35.9091 46.6141 142.785 -35.6607 50.1892 139.952 -36.9649 52.0658 136.997 -37.7961 52.4194 132.447 -38.0845 51.4089 133.398 -38.5931 49.903 135.983 -38.7555 47.893 138.861 -37.994 46.3798 141.377 -36.6995 54.5637 128.486 -38.5583 60.8235 135.305 -33.5811 58.5718 132.382 -36.0552 39.8159 132.627 -42.8845 41.7955 136.119 -41.0087 54.1663 148.483 -31.4153 55.9539 143.477 -32.6654 40.5373 149.092 -37.6693 45.7748 147.539 -36.2109 37.1201 141.421 -41.3319 46.3145 127.804 -43.6823 52.3171 126.477 -40.9857 59.1168 142.133 -31.5495 47.4993 151.562 -33.5084 58.2159 128.907 -37.3334 61.9319 130.28 -33.5996 55.9843 124.214 -39.8068 61.9357 139.512 -29.8517 40.0547 127.159 -44.8752 32.5262 135.693 -43.2641 50.1396 153.648 -28.7343 58.0699 147.457 -28.6001 32.4395 147.874 -38.275 40.7865 154.09 -32.8062 48.5485 123.891 -44.2502 44.8917 139.171 -37.7145 46.6541 135.791 -38.9245 49.1683 133.076 -38.9875 51.4356 131.609 -38.169 53.4767 132.569 -37.389 54.253 135.498 -36.8633 53.2321 138.983 -35.9892 50.709 141.926 -35.1558 47.8345 143.294 -34.7866 45.1675 142.152 -35.9951 45.1713 133.754 -39.9113 44.7331 143.025 -36.6728 43.2421 138.583 -38.8326 48.3979 130.967 -39.812 51.8085 130.009 -38.6079 54.898 131.214 -36.9842 56.9414 134.926 -35.5317 56.2052 139.595 -34.146 52.5633 143.214 -33.6329 48.5055 144.528 -34.4611 48.2504 131.567 -38.9341 43.4311 138.451 -37.8428 45.1446 134.246 -39.058 51.3088 130.573 -37.8872 44.498 142.267 -35.7379 53.9312 131.767 -36.7632 47.939 143.698 -34.0771 55.4586 135.033 -35.7586 51.6817 142.351 -33.9384 54.6942 139.021 -34.6087 47.6009 142.867 -35.4487 49.1112 141.201 -36.4341 51.2183 138.511 -37.4098 52.6196 135.479 -38.0192 51.7129 132.488 -38.381 50.7646 134.609 -38.7822 48.8984 137.414 -38.4633 47.013 140.215 -37.3683 45.949 142.148 -36.1946 56.8747 130.003 -37.3653 59.271 135.122 -34.8148 43.4222 133.063 -41.3875 53.4219 145.768 -32.7803 43.3933 146.037 -37.8806 41.0259 139.775 -40.1938 47.7811 129.312 -41.5937 52.3542 128.12 -39.7631 57.9468 140.752 -33.0391 48.3905 148.009 -34.6435 59.466 126.101 -36.8574 62.769 134.918 -31.1499 35.337 130.917 -44.7544 54.5184 150.949 -28.3414 36.1436 151.734 -35.4628 31.2473 142.63 -41.2578 44.4825 124.75 -45.068 52.223 123.767 -42.08 60.3461 143.735 -29.0309 45.5294 154.723 -30.4826 52.8762 134.088 -38.0496 52.9993 133.095 -37.9288 65.4323 107.528 -26.9171 67.9487 126.833 -28.5074 70.5081 134.319 -20.2732 62.6749 119.616 -35.7438 72.6589 117.278 -23.098 72.2444 116.442 -22.3254 71.3889 125.795 -28.3703 65.5901 109.029 -33.5959 69.3603 107.637 -26.6398 75.0515 126.757 -29.2103 63.5342 113.12 -36.9642 64.2148 119.206 -36.4696 70.5985 118.958 -37.1681 74.9121 108.319 -27.0453 71.9998 116.742 -36.9872 71.9612 114.391 -36.0381 88.8094 110.578 -26.9527 84.1169 110.131 -30.6072 87.2695 128.749 -35.4465 93.0867 136.547 -27.8016 77.576 118.913 -26.6205 76.2215 114.981 -25.3972 75.678 123.817 -34.645 78.3012 128.686 -29.8368 77.0845 117.097 -33.174 81.2906 120.822 -28.8656 75.1464 118.021 -36.546 81.172 131.293 -29.8079 83.4949 133.994 -29.1154 81.9364 120.685 -33.7567 87.4282 126.444 -33.002 84.2007 123.162 -29.9962 87.3956 126.405 -30.3062 80.9881 121.747 -36.5927 79.7217 108.446 -27.144 76.8458 113.737 -33.7746 81.9683 107.792 -26.8548 80.6767 124.289 -36.9998 70.1714 106.645 -20.1493 72.022 116.241 -22.9037 72.8888 115.884 -22.6383 73.3892 117.141 -19.0068 69.7533 125.895 -28.1175 72.9185 107.101 -21.1147 69.1965 130.484 -24.8144 72.6997 129.897 -25.4795 73.1742 126.294 -28.81 63.1531 116.358 -37.3542 67.3688 119.359 -37.0517 66.7935 113.286 -37.5877 72.197 107.977 -26.8719 77.8994 107.939 -21.2215 76.3201 129.88 -26.4826 71.9026 115.225 -37.0598 71.0463 113.066 -37.4483 87.9791 108.369 -27.0824 90.3568 109.787 -24.1197 85.8919 131.003 -34.834 89.9668 133.538 -32.7744 75.3807 117.261 -28.6335 74.2589 118.273 -24.8974 74.5081 115.555 -23.9173 74.7186 115.201 -29.2771 78.273 114.414 -20.2702 76.9377 127.337 -29.5447 74.9877 116.19 -32.3036 79.228 118.61 -30.8741 79.7455 119.59 -27.752 75.7618 117.015 -35.1966 72.8947 115.268 -34.2906 73.0867 117.445 -36.2917 78.8617 122.15 -25.111 82.7305 124.079 -27.0743 82.4725 132.777 -29.4795 84.5114 123.193 -33.8509 87.4141 126.338 -31.4821 85.952 124.849 -30.2847 82.9247 121.687 -31.9314 81.3232 120.724 -35.4257 84.0399 124.603 -36.7655 87.4445 127.25 -34.4856 81.9223 133.222 -27.574 84.3016 135.509 -27.551 85.3181 126.104 -28.0604 88.5803 128.469 -28.7521 90.0231 129.941 -30.4819 77.43 108.57 -27.2025 76.3149 112.625 -34.143 74.121 114.113 -34.4307 78.5236 114.752 -26.0741 79.2235 114.861 -29.7308 81.84 107.809 -22.5419 82.8432 113.477 -21.7471 80.6945 113.198 -32.7484 80.1006 111.667 -32.8137 81.4167 114.445 -29.7768 85.2891 111.653 -30.1957 85.1586 107.567 -26.8363 79.5016 131.024 -27.3879 82.7149 121.901 -29.5647 78.0128 119.311 -36.7914 75.0649 120.445 -36.8974 79.7863 129.926 -29.9221 79.3229 118.187 -33.5803 84.4402 132.877 -32.1553 80.111 127.576 -34.3959 71.2569 121.989 -34.7844 66.2834 120.958 -33.9154 71.8315 110.129 -33.2852 77.2358 110.04 -32.7655 73.4782 133.884 -21.131 77.6228 132.464 -22.2276 81.3655 132.277 -23.4746 83.426 133.82 -24.0033 85.7036 136.141 -24.3458 88.7308 138.375 -25.7679 91.4667 138.163 -27.2159 92.7583 132.552 -26.9171 90.4562 129.827 -25.7152 86.8669 126.78 -24.6669 84.0844 124.721 -23.6771 80.1888 122.834 -22.3988 88.4224 111.98 -26.642 73.0971 114.872 -34.0422 78.0365 114.257 -32.4652 72.6559 116.366 -23.6348 74.0565 115.738 -18.8756 74.3546 119.371 -20.3332 70.6786 130.252 -24.9797 66.3234 116.559 -38.424 68.7427 109.182 -33.5877 75.2695 107.415 -21.4172 74.5162 129.923 -26.0103 69.7229 116.044 -38.0771 89.5331 107.124 -23.792 88.3401 135.32 -31.9677 74.1388 115.95 -26.0645 75.9612 114.948 -19.4391 77.1416 118.114 -30.0044 73.3922 116.231 -34.5642 80.9955 123.121 -26.1556 85.0815 123.793 -32.0715 84.2148 123.344 -35.5836 83.1264 134.427 -27.4776 86.9811 127.454 -28.4118 89.522 129.098 -29.4795 74.6652 110.346 -32.9938 73.4634 113.087 -34.946 76.8228 114.888 -29.5521 79.8915 107.956 -22.0252 80.6122 114.073 -21.0487 83.7573 107.262 -22.8645 86.4999 113.195 -22.8837 83.3651 113.698 -27.6845 87.0649 106.513 -23.293 78.1729 130.027 -26.8719 84.0191 124.97 -27.6585 78.0395 121.874 -37.0279 80.9955 119.953 -31.531 86.4391 136.135 -29.7404 82.2626 130.071 -33.6418 73.3188 122.63 -34.5204 68.9993 121.598 -34.5597 61.1201 116.288 -36.4563 80.2549 109.485 -31.4116 71.6743 134.356 -20.764 75.3384 133.298 -21.6337 79.5527 132.054 -22.774 82.5547 132.906 -23.8513 84.4528 134.914 -24.1434 93.1861 134.488 -27.5777 91.9487 131.059 -26.2461 88.5515 128.283 -25.1888 85.4827 125.624 -24.1983 82.3397 123.833 -23.052 76.6708 121.456 -21.1288 89.869 111.457 -23.9848 75.2791 114.471 -33.131 72.5418 119.712 -36.6595 81.3907 113.876 -31.5584 78.3679 118.196 -35.5399 83.0864 127.336 -36.4037 85.4308 112.541 -29.518 90.2145 131.46 -31.6971 82.9166 108.627 -29.6277 64.7835 120.521 -33.7531 75.2428 120.861 -23.2937 80.7976 132.083 -27.6852 77.9572 125.484 -34.7339 74.1796 115.013 -31.4161 80.9021 114.638 -26.7177 85.1483 113.312 -25.263 82.0676 114.019 -24.0982 79.6802 114.358 -23.3746 77.3173 114.669 -22.6413 75.2124 115.161 -21.7041 73.588 115.837 -21.0027 72.7523 116.861 -20.956 73.4137 118.581 -21.8902 66.4762 141.604 -20.8641 58.3546 118.743 -38.2809 63.6573 103.164 -29.6181 61.2017 113.464 -35.2759 62.603 110.079 -31.8602 69.9438 135.891 -21.1621 68.2393 131.67 -26.2038 67.4378 127.136 -29.5202 62.8091 120.687 -35.9907 60.5767 117.653 -37.3935 60.7761 113.247 -36.1998 62.0921 109.556 -33.1525 65.2417 105.935 -28.1842 71.3073 112.394 -36.0092 68.3164 110.617 -35.2945 68.3445 111.331 -36.3747 -11.3552 113.133 6.63324 68.4684 104.805 -22.5375 -9.45044 104.401 1.95409 -7.56053 100.492 -0.627556 -5.0686 97.2087 -3.46945 -1.8849 93.9531 -6.38548 56.808 93.3547 -23.3279 61.9223 96.6682 -23.3508 59.4081 140.566 19.6623 60.4639 137.464 20.042 61.8763 134.831 19.5882 63.4845 132.857 18.7674 59.1931 143.585 18.4382 65.1653 131.503 17.6961 59.7648 145.792 16.5098 66.574 130.654 16.1776 60.7479 147.03 14.1165 67.7426 130.322 14.3856 61.9742 147.354 11.7839 68.7983 130.581 12.5261 63.4081 146.812 9.84286 69.823 131.736 10.6896 65.1046 145.464 8.28365 70.6207 133.636 8.99838 67.079 143.51 7.13741 70.6489 135.976 7.7083 68.7916 141.109 6.6273 70.0306 138.529 6.87865 46.0899 131.451 -40.7647 44.2964 133.408 -40.6498 42.8521 136.048 -40.2939 42.1344 139.179 -39.5132 48.0895 130.139 -40.7032 42.5725 142.25 -38.4974 50.1107 129.339 -40.116 44.0636 144.531 -37.2763 52.0814 129.065 -39.1855 46.164 145.859 -35.8431 53.992 129.384 -38.172 48.4484 146.268 -34.5523 55.8478 130.62 -37.1918 50.7075 145.792 -33.6656 57.2832 132.639 -36.2405 52.9926 144.492 -33.2066 58.0113 135.002 -35.2811 55.2984 142.565 -33.2185 57.9772 137.569 -34.3714 57.0771 140.172 -33.5929 1.38182 68.9774 -45.9569 1.47894 65.0285 -50.2728 1.09637 63.909 -52.87 4.59888 9.97681 -40.0908 4.56625 11.4122 -44.5415 4.27933 14.0176 -48.351 3.6239 17.5846 -51.2515 2.5518 21.6054 -53.3934 2.81797 25.9316 -56.0077 3.01964 28.3271 -57.5284 3.3214 31.8267 -58.9081 3.45486 35.6754 -59.9047 3.14198 39.6169 -60.4303 2.63558 43.6332 -60.5215 2.15143 47.625 -60.2798 1.8074 51.4352 -59.6459 1.64281 54.9177 -58.6553 1.54494 58.1214 -57.1999 1.24614 61.2169 -55.2299 2.20258 72.8765 -41.2252 4.0999 75.8378 -37.4454 6.18702 78.5203 -33.435 56.4936 87.4619 -10.08 57.7629 85.6098 -10.3506 59.9983 84.0135 -10.7406 63.4852 82.0057 -11.5406 67.5801 79.1089 -12.265 -10.1652 108.262 6.21582 -11.0734 112.965 7.57632 -0.481384 91.8178 -0.502998 -8.62003 103.705 4.73889 -6.45135 99.499 2.95057 -3.73181 95.6969 0.985786 -60.1092 28.2359 7.92776 -8.84988 108.395 10.4182 -10.438 113.006 9.67531 2.73864 92.5778 10.975 -6.7205 103.892 10.9765 -4.01207 99.6658 11.3213 -0.806137 95.8341 11.3643 64.3527 94.8043 -12.5052 60.0369 91.4033 -11.0824 -11.539 10.151 19.9241 -5.49863 10.1436 21.8177 -15.9268 10.1577 16.38 -19.33 10.1651 11.6357 -22.5381 10.1681 4.40154 32.719 10.1303 18.5309 40.266 10.1244 13.6679 14.2263 10.1377 23.0462 22.7994 10.1333 21.7028 2.70157 10.137 23.1159 44.4157 10.1281 7.56966 6.82094 10.137 23.6438 46.5807 10.1555 0.804138 -22.7316 10.1651 -8.79883 46.5392 10.1481 -8.35619 -6.5737 10.1422 -30.0845 -12.5993 10.151 -28.2717 -18.4966 10.1644 -25.6115 -21.6988 10.1659 -20.5282 -21.6462 10.1607 -14.2928 40.6619 10.1362 -21.951 32.9614 10.1496 -27.1618 22.9625 10.1599 -31.832 13.8408 10.1637 -33.647 2.11658 10.1488 -32.443 44.7679 10.1347 -15.5147 6.04318 10.1488 -32.526 12.5907 10.1733 -3.80531 59.1887 91.8044 8.95242 -37.1383 88.9529 -2.97714 -31.8022 10.0858 -1.97102 -25.1531 10.1622 -2.2068 -48.967 94.3801 -3.43312 -42.7435 92.7505 -3.24479 -45.2458 14.541 -1.9814 -38.8006 11.688 -1.94433 -51.5643 18.2037 -2.1067 -56.8395 22.9229 -2.04294 -61.3273 28.167 -2.00068 -64.683 34.1592 -1.92802 -67.7244 42.676 -1.88947 -69.2985 52.0358 -1.98363 -69.0782 59.0674 -1.98585 -68.0128 66.587 -1.96361 -66.3149 75.4782 -2.11857 -61.6254 86.6775 -2.9586 -55.4464 92.4777 -3.38715 -32.8632 83.5116 -1.95249 -29.1664 80.3716 -1.67964 -25.0219 78.6923 -1.82199 -19.731 77.9019 -1.94433 -13.8211 78.3245 -1.89985 0.599609 81.0967 -1.11393 5.68803 83.0274 -0.72765 6.50954 84.4391 -0.967133 5.72511 86.2104 -0.331726 3.73808 88.5303 1.10886 0.442429 91.5093 2.82008 -2.82133 95.1602 4.04714 -5.66766 99.1208 5.2742 -8.03503 103.465 6.34038 -9.79816 108.128 7.22415 -10.9333 112.931 8.02786 -26.7479 60.7542 43.6698 -20.1774 63.8423 42.5992 -8.42801 27.4619 48.2347 14.9477 25.7121 48.3904 3.09452 25.896 48.4757 42.6645 36.5214 48.0598 47.7344 49.638 47.1827 40.5551 62.2549 45.2372 -20.4769 63.1994 -50.3046 -27.628 60.1306 -51.1217 -8.33606 28.1588 -55.7549 41.6947 37.0493 -55.6696 46.1069 49.7648 -54.9594 39.661 61.5616 -52.9449 -28.2701 61.5994 42.6785 -21.096 64.5792 41.7131 -10.6093 65.5757 41.2676 1.58052 66.8139 41.2357 -20.6037 30.6107 47.064 -27.9498 36.4747 46.6355 -32.0076 43.3195 45.7562 -33.3289 50.1288 44.8568 -9.84192 26.1273 47.153 -32.1367 56.4888 43.8329 40.1118 30.266 46.5139 29.9349 25.9004 46.5236 16.4046 23.9305 47.0581 3.12344 24.0639 47.2805 46.8217 35.817 46.5762 50.7757 42.2756 46.3478 52.0569 49.3051 45.7651 50.1277 56.399 44.7582 45.0638 62.5551 43.5645 13.7088 68.7742 41.1082 26.4851 69.2584 41.2994 37.1171 66.9377 42.3456 1.53827 66.2289 -48.7276 -11.1349 65.489 -48.6957 -21.7418 64.0098 -49.2903 -29.2399 60.7943 -50.2557 -33.7448 49.2984 -52.3954 -32.2894 43.1438 -53.1362 -27.8334 36.8602 -53.862 -20.3917 31.2343 -54.2831 -10.0503 26.5855 -54.5085 -32.8298 55.3737 -51.4331 2.729 24.1781 -54.8289 15.8893 23.9164 -54.731 29.5034 26.0458 -54.0829 39.6795 30.5618 -53.8806 46.253 36.21 -53.7901 50.0128 42.5536 -53.5439 51.139 49.2547 -52.9597 49.321 55.8341 -52.0848 44.6241 61.6202 -51.0127 37.1431 65.7944 -49.8316 26.732 68.0261 -48.7847 13.6339 67.8667 -48.6371 + + + + + + + + + + -0.192109 -0.934569 0.299458 -0.06315 -0.993623 0.093407 -0.038767 -0.993005 0.111528 -0.11695 -0.921313 0.370816 -0.085264 -0.993927 0.06957 -0.25821 -0.942076 0.214058 -0.305238 -0.944237 0.123473 -0.103012 -0.993873 0.04007 -0.109849 -0.993698 0.02232 -0.319871 -0.945464 0.061492 0.322015 -0.653105 0.68539 0.238016 -0.809438 0.536805 0.39559 -0.829362 0.394547 0.547107 -0.665777 0.50736 0.149283 -0.925897 0.34703 0.227375 -0.943129 0.242504 -0.182106 -0.7902 0.585167 -0.310544 -0.820667 0.479654 -0.418246 -0.841388 0.342252 -0.407245 -0.671943 0.618582 -0.544891 -0.711903 0.443045 -0.234371 -0.618101 0.750347 -0.474249 -0.857348 0.200104 -0.472515 -0.875412 0.101901 -0.601129 -0.750567 0.274396 -0.593419 -0.791427 0.146617 0.282256 -0.953514 0.105559 0.497204 -0.845385 0.195227 0.680184 -0.678639 0.277127 0.475425 -0.378716 0.794069 0.394699 -0.508097 0.765539 0.651796 -0.507567 0.563506 0.728714 -0.35445 0.585953 -0.280085 -0.456993 0.844222 -0.472084 -0.52749 0.706322 -0.629949 -0.5896 0.505505 -0.525528 -0.402813 0.749375 -0.688269 -0.483465 0.540877 -0.345696 -0.333643 0.877027 0.797494 -0.502759 0.333521 0.868857 -0.332163 0.36709 0.779236 -0.208323 0.591094 0.556733 -0.232343 0.797537 0.611419 -0.086952 0.786515 0.805975 -0.07802 0.586786 0.901017 -0.198547 0.385677 0.912954 -0.073233 0.401437 0.587309 0.31693 0.74473 0.626298 0.112282 0.771455 0.807598 0.10215 0.580819 0.767563 0.296279 0.568389 0.905959 0.097128 0.412074 0.868972 0.273148 0.412646 0.369046 0.664292 0.650016 0.498279 0.502362 0.706648 0.692864 0.459155 0.555982 0.584348 0.597963 0.548615 0.813067 0.415121 0.408163 0.751114 0.515121 0.41289 0.19627 0.766932 0.610977 0.270011 0.7156 0.644213 0.477417 0.672112 0.565984 0.38089 0.730939 0.56626 0.665617 0.613839 0.424448 0.5601 0.712938 0.42191 -0.142237 0.892596 0.427833 -0.115435 0.801937 0.586149 -0.145778 0.823148 0.548795 -0.183731 0.901347 0.392196 -0.170598 0.892172 0.418242 -0.198923 0.94046 0.275618 -0.083913 0.784617 0.614276 -0.104776 0.836925 0.537195 -0.07128 0.762805 0.642687 -0.083732 0.95816 0.273711 -0.152017 0.963903 0.218593 -0.043758 0.995476 0.084341 0.11433 0.983142 0.142691 -0.188565 0.971095 0.146345 -0.153667 0.986837 0.050398 -0.277878 0.955105 0.102752 -0.278528 0.959779 0.035299 -0.266228 0.943946 0.195163 -0.494465 0.642119 0.585822 -0.123678 0.744163 0.656449 -0.094312 0.919596 0.381378 -0.521981 0.776809 0.352284 0.287464 0.72515 0.625717 0.35104 0.866307 0.355363 -0.085399 0.659129 0.747166 0.224013 0.689809 0.688464 -0.41145 0.564912 0.715251 -0.896437 0.304297 0.322186 -0.755967 0.475931 0.449448 -0.804069 0.52634 0.276477 -0.929837 0.307416 0.202235 -0.651421 0.428251 0.626301 -0.812838 0.261118 0.520685 -0.700828 0.14352 0.698743 -0.528973 0.340042 0.777534 -0.323564 0.505566 0.799819 -0.384671 0.217738 0.897005 -0.26768 0.410295 0.871783 -0.51729 -0.021456 0.855541 -0.703157 -0.1848 0.686599 -0.802326 -0.033833 0.595927 -0.877917 -0.14451 0.456484 -0.806047 -0.267053 0.528176 -0.89323 0.116397 0.434273 -0.92976 -0.00252 0.368157 -0.693473 -0.636086 0.338364 -0.705373 -0.68381 0.186692 -0.75587 -0.532488 0.380943 -0.796546 -0.566484 0.211211 -0.077417 -0.240522 0.967551 -0.089798 -0.134723 0.986806 -0.168487 -0.121841 0.978145 -0.138523 -0.221426 0.965289 -0.113525 -0.038943 0.992772 -0.195995 -0.017488 0.980449 -0.602195 -0.290799 0.743503 -0.742439 -0.374894 0.555193 -0.432918 -0.200289 0.878901 -0.818103 -0.413906 0.399236 -0.879805 -0.419705 0.22314 -0.8832 -0.285146 0.372357 -0.940384 -0.263381 0.215195 -0.205308 0.092751 0.974293 -0.12459 0.080228 0.988959 -0.122228 0.178941 0.976238 -0.196017 0.189929 0.962031 -0.04789 0.778827 0.625407 -0.065661 0.712179 0.698921 -0.086279 0.666075 0.740878 -0.054107 0.736647 0.674109 0.32735 0.918436 0.222077 0.038245 0.947019 0.318892 -0.067436 0.912058 0.404479 0.299059 0.868082 0.396229 0.020777 0.864061 0.502958 0.601008 0.74983 0.276665 0.10013 0.787789 0.607752 0.137884 0.80072 0.582954 0.293157 0.782715 0.549014 0.251535 0.793724 0.553834 0.033793 0.760625 0.648311 0.012829 0.792843 0.609291 -0.001462 0.805911 0.592035 0.470195 0.782277 0.408607 0.406592 0.824118 0.394351 -0.228092 0.919665 0.319673 -0.149194 0.877198 0.45636 0.221981 0.775644 0.590848 0.477153 0.718896 0.505483 0.642223 0.702693 0.306223 -0.941954 -0.151996 0.299365 -0.977272 -0.097629 0.18817 -0.969667 0.027366 0.242894 -0.984274 0.065087 0.16422 -0.081923 0.660823 0.746057 -0.143863 0.635643 0.75846 -0.950758 0.179022 0.253002 -0.969441 0.180582 0.166057 0.433741 0.791171 0.431182 0.286611 0.730746 0.619568 0.635928 0.49935 0.588427 0.410194 0.41588 0.811655 -0.030936 0.832088 0.553781 -0.063268 0.738092 0.671727 -0.236437 0.785277 0.572222 -0.098454 0.365739 0.925495 -0.356861 0.365039 0.859882 0.116456 0.704283 0.700303 0.160354 0.369389 0.915335 -0.380395 0.81813 0.431235 -0.491132 0.823545 0.283836 -0.59916 0.341103 0.724332 -0.798743 0.301719 0.520552 0.047573 -0.992573 0.111966 0.069354 -0.994739 0.075398 0.015592 -0.990695 0.135202 0.028503 -0.991144 0.129693 0.0864 -0.911356 0.402449 0.046371 -0.905885 0.420977 -0.018844 -0.991895 0.125654 -0.057065 -0.909815 0.411073 0.087743 -0.99576 0.027619 0.126144 -0.779499 0.613571 0.067151 -0.760559 0.645787 0.153713 -0.607983 0.778928 0.075394 -0.57677 0.81342 -0.085238 -0.760064 0.644234 -0.102578 -0.566247 0.817827 0.045094 -0.227711 0.972684 0.047131 -0.133922 0.98987 0.005657 -0.158915 0.987276 0.006376 -0.238835 0.971039 0.058631 -0.040878 0.997442 0.002975 -0.056704 0.998387 0.127635 -0.116289 0.98498 0.152279 -0.014755 0.988227 0.100619 -0.20516 0.973543 0.059288 0.068169 0.995911 -0.006745 0.055506 0.998436 0.05032 0.180626 0.982264 -0.021925 0.163036 0.986376 0.163736 0.099069 0.981517 0.156175 0.220652 0.962768 0.020684 0.317842 0.947918 -0.050294 0.316731 0.947181 -0.025411 0.533931 0.845146 -0.086911 0.5228 0.848014 0.127716 0.356862 0.925385 0.071441 0.516034 0.853584 -0.061054 0.766638 0.63917 0.078289 0.741306 0.666586 0.208508 0.671416 0.711144 0.313289 0.499706 0.807554 0.378689 0.310587 0.871855 0.400342 0.118619 0.908656 0.381543 -0.070384 0.921668 0.331083 -0.22771 0.915714 0.260306 -0.364971 0.893889 0.178111 -0.473128 0.862802 0.071351 -0.485088 0.87155 -0.127917 -0.411323 0.902469 -0.217134 -0.272275 0.9374 -0.28612 -0.114565 0.95132 -0.297833 0.014133 0.954513 -0.259212 0.153056 0.953616 -0.214461 0.319798 0.922895 -0.151901 0.528641 0.835144 -0.103669 0.295387 0.949736 -0.165776 0.313209 0.935104 -0.083675 0.492895 0.866056 -0.119834 0.470121 0.874429 -0.087588 0.774585 0.626376 -0.256922 -0.123444 0.958516 -0.282852 0.013185 0.959073 -0.378724 -0.276752 0.883163 -0.438423 -0.070607 0.895991 -0.437651 -0.063548 0.896897 -0.390678 -0.27619 0.878117 -0.251518 -0.431278 0.866451 -0.276371 -0.456203 0.845871 -0.19905 -0.303218 0.9319 -0.274611 0.135247 0.951996 -0.249887 0.293965 0.922573 -0.442099 0.099565 0.891423 -0.416837 0.295755 0.859521 -0.412837 0.32408 0.851198 -0.438351 0.113033 0.891668 0.156401 -0.497394 0.85331 0.061408 -0.535686 0.842181 0.119454 -0.452018 0.883974 0.032667 -0.468626 0.882793 0.050048 -0.559259 0.827481 0.150699 -0.524664 0.837865 0.208739 -0.361482 0.908713 0.238743 -0.413555 0.878621 0.232419 -0.391651 0.890276 -0.125806 -0.451337 0.883441 -0.128663 -0.465603 0.875591 -0.150994 -0.530967 0.833832 0.284031 -0.235212 0.929517 0.269401 -0.199777 0.942079 0.293517 -0.238502 0.925724 0.286186 -0.032306 0.957629 0.310905 -0.056264 0.948774 0.312743 -0.062252 0.947795 0.322676 0.120164 0.938851 0.286685 0.125421 0.94978 0.312932 0.123775 0.941676 0.279716 0.294166 0.913907 0.303905 0.313656 0.89959 0.309104 0.311381 0.898608 0.037576 0.808415 0.587412 0.169817 0.698638 0.69503 -0.000992 0.780213 0.625514 0.138259 0.681294 0.718834 0.161529 0.715447 0.679738 0.018778 0.826522 0.562592 -0.09996 0.801388 0.589733 -0.098648 0.85295 0.512587 -0.076807 0.814801 0.574631 0.262922 0.511395 0.818137 0.242579 0.49202 0.836105 0.262895 0.521513 0.811733 -0.185749 0.495789 0.848346 -0.322481 0.52883 0.785076 -0.160242 0.722224 0.672841 -0.146317 0.772841 0.617501 -0.312096 0.577251 0.754571 -0.076559 0.797941 0.597853 -0.071594 0.840171 0.537576 -0.107376 0.806238 0.581766 -0.112987 0.848782 0.51653 -0.287568 -0.01818 0.957588 -0.246849 -0.15606 0.956405 -0.173556 -0.290795 0.940913 -0.283237 0.22681 0.931844 -0.297529 0.100463 0.949412 0.014537 -0.330354 0.943745 0.072188 -0.329168 0.941508 0.150177 -0.268878 0.951394 -0.091484 -0.341365 0.935468 0.211928 -0.141481 0.96699 0.233591 -0.009434 0.972289 0.24083 0.120366 0.963075 0.233787 0.260424 0.936762 0.102888 0.613185 0.78321 -0.030399 0.694019 0.719314 -0.098708 0.675427 0.730791 0.204918 0.428836 0.879834 -0.132475 0.557408 0.819602 -0.232943 0.388015 0.89173 -0.075386 0.634728 0.769049 -0.09685 0.652599 0.751489 -0.092397 0.509504 0.855493 -0.081276 0.316551 0.945087 -0.068265 0.172012 0.982727 -0.054553 0.065325 0.996372 -0.043341 -0.055449 0.99752 -0.033383 -0.160096 0.986537 -0.028874 -0.24536 0.969002 -0.033304 -0.336054 0.941254 -0.042357 -0.467717 0.882863 -0.046567 -0.556118 0.829798 -0.037674 -0.519487 0.853647 -0.022566 -0.457423 0.888963 -0.012961 -0.556886 0.830488 -0.007732 -0.753873 0.656974 -0.003792 -0.90729 0.420489 -0.001149 -0.991208 0.132304 0.512335 -0.857386 0.049017 0.70555 -0.704425 0.077354 0.297092 -0.954566 0.023258 0.84286 -0.528889 0.09931 0.930258 -0.348816 0.113782 0.968103 -0.21837 0.122848 0.986591 -0.093131 0.134031 0.985676 0.081564 0.147617 0.95281 0.259757 0.157095 0.894834 0.417704 0.157465 0.844113 0.514896 0.149516 0.774064 0.618654 0.134508 0.673761 0.729252 0.119321 0.59429 0.795832 0.116061 0.5205 0.84585 0.116695 0.525074 0.841884 0.124616 0.765546 0.621669 0.16573 0.097097 -0.995263 0.004896 -0.565407 0.809464 0.158374 -0.611313 0.789337 0.056957 -0.920895 0.236324 0.310006 -0.979363 0.144989 0.140806 -0.738247 -0.362498 0.568846 -0.830423 -0.418752 0.367485 -0.844491 -0.498578 0.195588 -0.637358 -0.672695 0.37584 -0.668066 -0.709833 0.223216 -0.553902 -0.635855 0.537476 -0.346188 -0.291036 0.891881 -0.564224 -0.330618 0.756534 -0.436173 -0.617389 0.654663 -0.266348 -0.628612 0.730688 -0.097978 -0.251576 0.962865 -0.086895 -0.643915 0.760146 0.176816 -0.222898 0.958672 0.120695 -0.699248 0.704617 0.465192 -0.190422 0.864486 0.373032 -0.681742 0.629345 0.749171 -0.141411 0.647105 0.57208 -0.682024 0.455597 0.984143 0.023025 0.175875 0.738366 -0.656556 0.154109 -0.095635 0.76965 0.631263 -0.315057 -0.948903 0.017974 -0.110306 -0.993886 0.004918 -0.457702 -0.888528 0.032039 -0.589111 -0.807168 0.037792 0.510058 -0.858624 -0.051043 0.70623 -0.703125 -0.082786 0.294439 -0.955391 -0.023102 0.843862 -0.525198 -0.109834 0.928966 -0.346434 -0.130403 0.964683 -0.219414 -0.145751 0.981881 -0.104853 -0.157847 0.98501 0.058597 -0.162241 0.95819 0.238399 -0.158234 0.897823 0.414043 -0.149942 0.829346 0.538002 -0.150797 0.747675 0.644543 -0.159833 0.659153 0.734437 -0.161615 0.265044 0.963485 0.038059 0.039034 0.999086 0.017437 0.018622 0.997848 -0.062875 0.244836 0.962544 -0.116463 -0.130658 0.991351 0.012349 -0.138096 0.990164 -0.022449 -0.273293 0.96189 0.008822 -0.274255 0.961657 0.000421 -0.053579 0.998129 0.029453 -0.515915 0.855204 0.049583 0.344116 0.89883 -0.271457 -0.055876 0.956544 -0.286182 0.365283 0.930753 0.01632 -0.828131 0.557888 0.054409 -0.952772 0.299578 0.049783 -0.711727 -0.701459 0.037422 -0.905755 -0.418034 -0.069676 -0.8121 -0.578723 -0.074656 -0.818385 -0.573492 0.036778 -0.910268 -0.412077 0.040054 0.709552 0.701423 0.067393 0.515618 0.854187 0.067105 0.52626 0.835416 -0.158524 0.711562 0.67733 -0.186822 0.587221 0.793907 -0.157743 0.504751 0.849895 -0.151344 0.655685 0.754174 0.036026 0.627882 0.742251 -0.234154 -0.995755 -0.076042 0.051857 -0.966252 -0.253074 0.048064 -0.995208 0.084624 0.048994 -0.98245 0.180559 0.046801 0.500696 0.849415 -0.166726 0.699452 0.674292 -0.236847 -0.644888 0.764208 0.010314 -0.658085 0.75262 0.022063 -0.996997 0.052783 0.056672 -0.999004 0.031144 0.031952 0.095211 -0.995451 -0.003478 -0.828476 -0.551185 0.099113 -0.83354 -0.552229 0.015914 -0.680841 -0.722996 0.117184 -0.70438 -0.709823 0.000289 0.942473 0.130036 -0.307954 0.760792 -0.603232 -0.239387 -0.191598 -0.926128 -0.324926 -0.11404 -0.910397 -0.397707 -0.034523 -0.992382 -0.118262 -0.056307 -0.993628 -0.097639 -0.08229 -0.99447 -0.065257 -0.263919 -0.93806 -0.224478 -0.301453 -0.945273 -0.124839 -0.10268 -0.994176 -0.032728 -0.109842 -0.993816 -0.016268 -0.306215 -0.95011 -0.059356 0.319117 -0.647606 -0.691933 0.534285 -0.666968 -0.519319 0.385251 -0.83007 -0.403195 0.239592 -0.805165 -0.542499 0.228594 -0.939199 -0.256224 0.158278 -0.918607 -0.362089 -0.178484 -0.75672 -0.628902 -0.309497 -0.797477 -0.51792 -0.420841 -0.831771 -0.362009 -0.538657 -0.700909 -0.467519 -0.394197 -0.64598 -0.653696 -0.222745 -0.580396 -0.783278 -0.463953 -0.858375 -0.218951 -0.461429 -0.880375 -0.109649 -0.599801 -0.782405 -0.167575 -0.59309 -0.744341 -0.306921 0.280118 -0.952342 -0.120743 0.489162 -0.845976 -0.212238 0.674722 -0.67782 -0.292079 0.467443 -0.364911 -0.805194 0.712309 -0.345361 -0.611018 0.641575 -0.494023 -0.586791 0.39121 -0.489528 -0.779305 -0.257887 -0.431057 -0.864687 -0.450347 -0.520374 -0.725533 -0.610796 -0.588414 -0.529809 -0.665056 -0.488467 -0.56489 -0.505193 -0.408993 -0.759938 -0.312897 -0.314982 -0.896037 0.796286 -0.495922 -0.346396 0.865739 -0.328626 -0.377493 0.760432 -0.204661 -0.616326 0.545204 -0.224716 -0.807623 0.593644 -0.079984 -0.800743 0.783915 -0.086134 -0.614865 0.896384 -0.199742 -0.395726 0.906271 -0.095045 -0.411874 0.551478 0.253954 -0.794594 0.749758 0.226635 -0.62169 0.783116 0.056593 -0.619295 0.5969 0.085909 -0.797703 0.90526 0.04554 -0.42241 0.880719 0.218398 -0.420282 0.336343 0.599609 -0.726183 0.572035 0.582293 -0.577677 0.679985 0.408785 -0.6087 0.461982 0.425407 -0.778204 0.822759 0.398489 -0.405308 0.73865 0.550111 -0.389581 0.158279 0.713924 -0.6821 0.37644 0.723509 -0.578643 0.467127 0.676077 -0.569835 0.228363 0.685665 -0.691168 0.648361 0.657528 -0.383777 0.564637 0.73282 -0.379684 -0.132948 0.895471 -0.424801 -0.16783 0.911023 -0.376656 -0.12755 0.841928 -0.524298 -0.095044 0.810733 -0.577649 -0.191234 0.937857 -0.289574 -0.161097 0.88789 -0.430929 -0.099619 0.831047 -0.547207 -0.068866 0.782563 -0.618751 -0.042804 0.75673 -0.652324 -0.106611 0.95728 -0.268792 0.061832 0.967519 -0.24512 -0.090989 0.984179 -0.152028 -0.171442 0.958937 -0.225938 -0.170146 0.982001 -0.081999 -0.195635 0.967138 -0.16239 -0.282706 0.95847 -0.037576 -0.282545 0.952356 -0.114834 -0.262642 0.936921 -0.230646 -0.457702 0.605028 -0.651498 -0.494691 0.715297 -0.493589 -0.076223 0.822259 -0.563986 -0.087936 0.702019 -0.706709 0.319664 0.765998 -0.557729 0.294833 0.694844 -0.655946 0.224172 0.682804 -0.695361 -0.063717 0.649517 -0.757673 -0.387084 0.558006 -0.734027 -0.896043 0.261582 -0.358722 -0.944002 0.274393 -0.183216 -0.810194 0.488173 -0.324457 -0.742944 0.435424 -0.508371 -0.645648 0.412332 -0.642745 -0.811086 0.243382 -0.531887 -0.699157 0.136155 -0.701885 -0.530892 0.331786 -0.77979 -0.30426 0.511436 -0.803654 -0.248492 0.408629 -0.878222 -0.387347 0.198969 -0.900208 -0.511763 -0.033699 -0.858465 -0.688173 -0.178311 -0.703294 -0.790784 -0.260454 -0.553917 -0.872048 -0.112083 -0.476413 -0.794394 -0.013341 -0.607256 -0.920109 0.042291 -0.389372 -0.884532 0.127633 -0.44868 -0.676964 -0.636735 -0.369174 -0.702442 -0.678564 -0.214769 -0.78028 -0.57775 -0.239514 -0.733839 -0.540713 -0.41123 -0.092147 -0.181509 -0.979062 -0.144369 -0.166467 -0.975421 -0.159435 -0.079334 -0.984015 -0.094565 -0.065989 -0.993329 -0.168501 -0.000101 -0.985701 -0.104493 0.01153 -0.994459 -0.726284 -0.369697 -0.579514 -0.588438 -0.292192 -0.753899 -0.407291 -0.20071 -0.890971 -0.869486 -0.42871 -0.245363 -0.799739 -0.41079 -0.4378 -0.938755 -0.260153 -0.225963 -0.869609 -0.274794 -0.410206 -0.170534 0.079532 -0.982137 -0.161151 0.169743 -0.972223 -0.090409 0.181448 -0.979236 -0.10396 0.092065 -0.990311 -0.061474 0.779505 -0.623373 -0.054952 0.743789 -0.666152 -0.103099 0.66864 -0.736404 -0.089248 0.714186 -0.694242 0.313646 0.879357 -0.358269 0.027421 0.941997 -0.334499 -0.080622 0.891857 -0.445073 0.022338 0.831019 -0.555795 0.289168 0.850636 -0.43909 0.556005 0.699289 -0.449281 0.050624 0.773712 -0.631511 0.231632 0.808083 -0.541616 0.288863 0.771715 -0.566581 0.103245 0.744807 -0.659244 0.031939 0.724546 -0.688486 0.003268 0.749951 -0.661485 -0.026171 0.792703 -0.609046 0.482137 0.794981 -0.36817 0.398207 0.851469 -0.34122 -0.221077 0.901734 -0.371484 -0.143622 0.850839 -0.505417 0.234374 0.743588 -0.626216 0.46128 0.703836 -0.540218 0.562017 0.649813 -0.511741 -0.977474 -0.09123 -0.19032 -0.936551 -0.12725 -0.326619 -0.984003 0.070682 -0.163533 -0.961337 0.050417 -0.270718 -0.12138 0.620783 -0.774529 -0.05521 0.647511 -0.760053 -0.944461 0.162933 -0.285388 -0.972855 0.171501 -0.15537 0.237565 0.800499 -0.55024 0.395586 0.847721 -0.353385 0.35269 0.570432 -0.741766 0.568049 0.652016 -0.502191 -0.054488 0.806873 -0.588206 -0.221404 0.774347 -0.592762 -0.082141 0.728443 -0.680164 -0.34248 0.449493 -0.825023 -0.1184 0.432945 -0.893611 0.102358 0.477975 -0.872389 0.062161 0.735187 -0.675008 -0.351621 0.822971 -0.446186 -0.453177 0.839825 -0.298872 -0.753559 0.408132 -0.515341 -0.56556 0.457673 -0.686059 0.070662 -0.994095 -0.082354 0.053046 -0.991548 -0.1184 0.013209 -0.990078 -0.139895 0.042006 -0.899343 -0.435221 0.096965 -0.90473 -0.414802 0.032991 -0.99044 -0.133938 -0.056118 -0.897897 -0.436614 -0.016738 -0.990736 -0.134764 0.086464 -0.995644 -0.034877 0.061043 -0.750045 -0.658564 0.137198 -0.774505 -0.61751 0.069229 -0.578014 -0.813085 0.165722 -0.607498 -0.776841 -0.08926 -0.735213 -0.671934 -0.114239 -0.544747 -0.830783 0.019911 -0.230638 -0.972836 -0.030593 -0.214954 -0.976145 -0.045955 -0.097756 -0.994149 0.002659 -0.095509 -0.995425 -0.052141 0.011297 -0.998576 0.002127 0.01818 -0.999832 0.120697 0.01473 -0.99258 0.113372 -0.110702 -0.987366 0.096736 -0.223211 -0.969958 -0.055442 0.119889 -0.991238 -0.003618 0.136061 -0.990694 -0.057352 0.236947 -0.969828 -0.01353 0.263616 -0.964533 0.087309 0.294367 -0.951696 0.113304 0.153076 -0.981697 -0.061332 0.359879 -0.930981 -0.028754 0.371752 -0.927887 -0.069217 0.479884 -0.874597 -0.04309 0.485197 -0.873342 0.017067 0.479437 -0.87741 0.052641 0.398131 -0.915817 -0.034654 0.760876 -0.647972 0.07156 0.732098 -0.67743 0.191934 0.634425 -0.748777 0.303753 0.458556 -0.835141 0.384402 0.282027 -0.879031 0.419845 0.110042 -0.9009 0.406427 -0.062856 -0.911518 0.353955 -0.220425 -0.908916 0.281504 -0.354287 -0.89176 0.067511 -0.500136 -0.863311 0.193668 -0.469971 -0.861174 -0.14958 -0.414815 -0.897527 -0.228363 -0.298833 -0.926579 -0.288297 -0.161724 -0.943785 -0.298702 -0.022525 -0.954081 -0.190826 0.301532 -0.934165 -0.246409 0.126265 -0.960906 -0.15017 0.520238 -0.840715 -0.129702 0.309072 -0.942153 -0.066417 0.305119 -0.949995 -0.055085 0.462192 -0.885067 -0.090042 0.449004 -0.888981 -0.071733 0.766958 -0.637675 -0.283007 -0.028509 -0.958694 -0.281863 -0.191917 -0.940065 -0.351312 -0.084797 -0.932411 -0.309888 -0.241843 -0.919501 -0.329877 -0.256795 -0.908426 -0.371873 -0.083592 -0.924512 -0.244245 -0.370528 -0.896133 -0.261882 -0.399787 -0.878401 -0.239012 -0.350966 -0.905371 -0.228514 0.26963 -0.935457 -0.253264 0.114721 -0.960571 -0.387754 0.261515 -0.883887 -0.38213 0.068912 -0.921536 -0.395833 0.087229 -0.914171 -0.400411 0.295266 -0.867461 0.059717 -0.537384 -0.841221 0.170799 -0.490618 -0.854471 0.023673 -0.491984 -0.870282 0.138029 -0.482666 -0.864859 0.172547 -0.546798 -0.819292 0.048051 -0.585369 -0.809342 0.24535 -0.391127 -0.88703 0.271557 -0.425603 -0.863203 0.253362 -0.383231 -0.888224 -0.16392 -0.464478 -0.870282 -0.156074 -0.43633 -0.886147 -0.174103 -0.495914 -0.85074 0.311338 -0.234144 -0.921002 0.314452 -0.22765 -0.921573 0.331844 -0.253055 -0.908759 0.334948 -0.047443 -0.941041 0.358791 -0.06942 -0.930833 0.352034 -0.064094 -0.93379 0.370008 0.120956 -0.921121 0.325861 0.13785 -0.935314 0.365501 0.126808 -0.922133 0.293842 0.331419 -0.896559 0.345775 0.339247 -0.874843 0.349666 0.318511 -0.88107 0.181191 0.722006 -0.667741 0.050427 0.826013 -0.561391 0.124911 0.682336 -0.720288 -8.3e-005 0.771418 -0.636329 0.029371 0.862647 -0.504953 0.172441 0.753171 -0.634821 -0.088449 0.796983 -0.597491 -0.084759 0.878493 -0.470177 -0.056365 0.816918 -0.573992 0.28721 0.527283 -0.799677 0.229314 0.522426 -0.821271 0.28443 0.557632 -0.779838 -0.184783 0.47937 -0.857939 -0.159072 0.705689 -0.690434 -0.306838 0.513915 -0.801088 -0.313651 0.56677 -0.761837 -0.157757 0.765176 -0.624195 -0.073978 0.778021 -0.623867 -0.070331 0.835642 -0.544753 -0.087799 0.795672 -0.599331 -0.090591 0.859197 -0.503561 -0.232887 -0.144487 -0.961711 -0.244705 -0.029472 -0.96915 -0.189644 -0.261806 -0.946305 -0.251478 0.075314 -0.964928 -0.245154 0.195506 -0.949567 0.069738 -0.345456 -0.93584 -0.006898 -0.32309 -0.946343 0.169707 -0.300933 -0.938424 -0.116208 -0.315517 -0.941778 0.239122 -0.166926 -0.956533 0.255866 -0.011563 -0.966643 0.242809 0.152646 -0.957989 0.202267 0.315072 -0.927264 -0.032641 0.607102 -0.793953 0.060458 0.564272 -0.823372 -0.076278 0.598808 -0.797252 0.144831 0.45396 -0.879173 -0.202967 0.364176 -0.908945 -0.116061 0.523868 -0.843856 -0.061288 0.585836 -0.808109 -0.069247 0.590821 -0.803825 -0.06147 0.471147 -0.87991 -0.062087 0.339494 -0.938557 -0.069753 0.213116 -0.974534 -0.075711 0.106988 -0.991373 -0.074759 0.010224 -0.997149 -0.065915 -0.084862 -0.99421 -0.056359 -0.195476 -0.979088 -0.058264 -0.312594 -0.948098 -0.069962 -0.465689 -0.882179 -0.071195 -0.557949 -0.826815 -0.045754 -0.47841 -0.876944 -0.060646 -0.52652 -0.847997 -0.029989 -0.553187 -0.832517 -0.018388 -0.737572 -0.675018 -0.009087 -0.897441 -0.441041 -0.00158 -0.989993 -0.141109 -0.308322 -0.951065 -0.020322 -0.110713 -0.99381 -0.009215 -0.455221 -0.889796 -0.032191 -0.596471 -0.800898 -0.052761 -0.511407 0.823202 -0.246578 -0.952243 0.291325 -0.09145 -0.828387 0.538442 -0.154449 -0.712918 -0.697663 -0.070811 -0.964192 -0.256036 -0.069136 -0.99426 -0.077609 -0.073642 -0.993521 0.085088 -0.075342 -0.980403 0.180699 -0.07847 -0.618484 0.785248 -0.029371 -0.985065 0.143698 -0.094851 -0.540296 0.826158 -0.159823 -0.899944 0.302263 -0.314224 -0.858864 -0.489238 -0.15165 -0.711588 -0.680949 -0.173063 -0.767866 -0.270651 -0.580629 -0.848883 -0.383401 -0.36387 -0.671939 -0.656576 -0.342645 -0.602072 -0.614193 -0.510173 -0.382168 -0.137855 -0.913752 -0.607476 -0.181274 -0.773377 -0.492091 -0.563373 -0.66367 -0.327921 -0.53701 -0.777231 -0.13782 -0.132667 -0.981532 -0.138241 -0.548212 -0.824835 0.069946 -0.573914 -0.815923 0.11889 -0.117351 -0.985948 0.269629 -0.627654 -0.730309 0.418909 -0.085153 -0.904027 0.751138 0.018205 -0.659894 0.495888 -0.698066 -0.516526 -0.95931 0.034968 0.280182 -0.952229 0.032635 0.303636 -0.93144 0.167086 0.323268 -0.946666 0.171861 0.272557 -0.944846 0.025037 0.326557 -0.91551 0.150958 0.372899 -0.937578 0.012119 0.347564 -0.899986 0.12397 0.417919 -0.930687 -0.005661 0.365772 -0.885622 0.08696 0.456193 -0.924746 -0.02703 0.379623 -0.873384 0.042333 0.485189 -0.919713 -0.051956 0.389139 -0.863691 -0.010116 0.503919 -0.915891 -0.078133 0.39375 -0.857075 -0.064545 0.511132 -0.913924 -0.104134 0.392301 -0.854193 -0.116994 0.506623 -0.913686 -0.130204 0.385001 -0.854276 -0.170718 0.490986 -0.915221 -0.154787 0.372036 -0.856986 -0.224754 0.463745 -0.918574 -0.175545 0.354127 -0.862661 -0.271395 0.426803 -0.924357 -0.190998 0.330279 -0.874699 -0.302741 0.378484 -0.93489 -0.202027 0.291831 -0.900162 -0.32556 0.289342 -0.890596 -0.319641 0.323525 -0.930807 -0.199874 0.306022 -0.896 0.289458 0.336747 -0.918721 0.296141 0.261252 -0.872107 0.26593 0.410745 -0.848724 0.226438 0.477905 -0.827137 0.172709 0.534805 -0.80861 0.10747 0.578446 -0.794368 0.032855 0.606547 -0.785336 -0.046853 0.617294 -0.781515 -0.12666 0.610894 -0.781913 -0.208771 0.58739 -0.785856 -0.293485 0.544332 -0.793937 -0.361184 0.489091 -0.811021 -0.403504 0.423592 -0.835242 -0.430573 0.342022 -0.847345 0.403795 0.3449 -0.876998 0.412515 0.246384 -0.816114 0.373023 0.441375 -0.785473 0.321444 0.528872 -0.757102 0.251755 0.60284 -0.732492 0.167285 0.659903 -0.71285 0.071993 0.697612 -0.699448 -0.030237 0.714044 -0.693366 -0.135002 0.707826 -0.694705 -0.244186 0.676579 -0.700161 -0.36004 0.616559 -0.706167 -0.453566 0.543697 -0.723583 -0.510419 0.464651 -0.757493 -0.546167 0.357639 -0.786239 0.510828 0.347683 -0.822283 0.521471 0.227858 -0.748188 0.473296 0.464978 -0.710816 0.41044 0.571208 -0.676265 0.32557 0.66081 -0.646313 0.222825 0.729815 -0.622397 0.107069 0.775344 -0.605751 -0.016281 0.795488 -0.597541 -0.142104 0.789146 -0.599072 -0.273389 0.752576 -0.605625 -0.422009 0.67463 -0.607323 -0.542234 0.580639 -0.62045 -0.60942 0.493609 -0.663091 -0.648882 0.373178 -0.713977 0.609147 0.34522 -0.755821 0.6215 0.206088 -0.669772 0.565403 0.481378 -0.626414 0.492206 0.604433 -0.58635 0.393512 0.708055 -0.551603 0.274208 0.787746 -0.523909 0.140003 0.84019 -0.504656 -0.002861 0.863316 -0.494725 -0.148092 0.856339 -0.496885 -0.296649 0.81554 -0.511217 -0.470298 0.719359 -0.523448 -0.603062 0.601929 -0.54514 -0.6692 0.504969 -0.589688 -0.712391 0.380483 -0.632092 0.697412 0.337752 -0.679083 0.71125 0.181575 -0.582478 0.648166 0.490511 -0.533908 0.565768 0.62837 -0.489063 0.454778 0.744308 -0.450216 0.320826 0.833293 -0.419311 0.170384 0.891711 -0.397828 0.010371 0.917402 -0.386738 -0.152189 0.909545 -0.388906 -0.314579 0.865905 -0.416834 -0.497637 0.760662 -0.460989 -0.625959 0.629018 -0.542107 0.774681 0.32556 -0.593506 0.78981 0.15476 -0.487909 0.720672 0.492521 -0.434921 0.630341 0.64305 -0.3861 0.508756 0.769476 -0.343913 0.362223 0.866325 -0.310381 0.197869 0.929791 -0.287052 0.023243 0.957633 -0.274984 -0.154056 0.949026 -0.274153 -0.330443 0.903132 -0.301736 -0.514601 0.802584 -0.360883 -0.638403 0.679857 -0.445437 0.840329 0.308923 -0.50045 0.856542 0.126038 -0.387543 0.782319 0.487634 -0.331043 0.685354 0.648614 -0.279115 0.554987 0.783636 -0.234323 0.398047 0.886934 -0.198766 0.222238 0.954517 -0.174032 0.035606 0.984096 -0.161146 -0.153806 0.974872 -0.161623 -0.341915 0.925728 -0.183322 -0.527132 0.829774 -0.220903 -0.657095 0.720714 -0.343523 0.893833 0.288192 -0.401399 0.910874 0.095845 -0.282773 0.832684 0.476106 -0.223681 0.730476 0.645269 -0.169508 0.593188 0.787016 -0.122852 0.428085 0.895349 -0.085869 0.24334 0.966133 -0.060478 0.047525 0.997037 -0.048298 -0.151042 0.987347 -0.051169 -0.346801 0.936542 -0.071334 -0.536879 0.840638 -0.087789 -0.68823 0.720162 -0.21986 0.940431 0.259327 -0.28005 0.958152 0.059303 -0.156918 0.876718 0.454689 -0.095926 0.770248 0.630489 -0.040164 0.627316 0.777728 0.007734 0.455603 0.890149 0.046891 0.262808 0.963708 0.076503 0.059129 0.995315 0.087975 -0.141662 0.985998 0.082632 -0.346525 0.934394 0.066735 -0.543112 0.837004 0.044893 -0.70688 0.705907 -0.074449 0.972485 0.220751 -0.13589 0.990587 0.016451 -0.0105 0.907325 0.420298 0.052421 0.798072 0.600278 0.112271 0.651463 0.750327 0.17284 0.475296 0.862682 0.224622 0.286559 0.931359 0.237263 0.088989 0.967361 0.218281 -0.113 0.969322 0.208533 -0.342413 0.916116 0.208343 -0.548433 0.809824 0.177566 -0.726111 0.664254 0.072457 0.981536 0.17702 0.011184 0.999581 -0.026697 0.13045 0.91774 0.375149 0.17379 0.810665 0.559124 0.202259 0.677497 0.70717 0.281823 0.466274 0.838549 0.389486 0.279956 0.877454 0.38011 0.146887 0.913204 0.357385 -0.040932 0.93306 0.345941 -0.321259 0.881543 0.34413 -0.559385 0.754098 0.331752 -0.740685 0.584232 0.196145 0.971318 0.134422 0.140044 0.988072 -0.064045 0.22226 0.915547 0.335221 0.215212 0.826522 0.520139 0.485045 0.203691 0.850436 0.549186 0.085396 0.831326 0.51886 -0.274121 0.809717 0.494351 -0.559544 0.665228 0.486216 -0.716967 0.499552 0.288962 0.953069 0.090338 0.249176 0.963756 -0.09532 0.279421 0.910567 0.304618 0.388152 0.921065 0.031265 0.355698 0.926134 -0.125519 0.404067 0.903782 0.141097 0.68549 -0.217008 0.69499 0.702569 0.095581 0.705167 0.629523 -0.529053 0.569037 0.593718 -0.693079 0.408828 0.496683 0.867503 -0.027267 0.458279 0.875316 -0.154276 0.528047 0.848543 0.03378 0.806768 -0.152023 0.570977 0.808457 0.086821 0.582116 0.751952 -0.463847 0.468417 0.679141 -0.659907 0.321388 0.597185 0.799146 -0.068811 0.555473 0.811556 -0.181181 0.641605 0.76683 -0.017718 0.890943 -0.106367 0.441483 0.8665 0.068021 0.494522 0.874776 -0.373384 0.30879 0.812876 -0.546789 0.200637 0.713003 0.692155 -0.112017 0.675208 0.706006 -0.213658 0.760001 0.64795 -0.050575 0.881663 0.086627 0.463859 0.915057 -0.143088 0.377089 0.91943 -0.337729 0.201463 0.893271 -0.433495 0.118948 0.740476 -0.66906 0.063675 0.859379 -0.511092 0.015908 0.647012 -0.745143 -0.161672 0.622061 -0.770384 0.139818 0.519697 -0.840964 -0.150645 0.82048 0.555122 -0.136569 0.782459 0.574043 -0.241314 0.857424 0.511442 -0.057009 0.806681 0.536729 -0.247364 0.862468 0.496193 -0.099707 0.878972 0.473396 -0.057475 0.818208 0.516312 -0.252897 -0.95504 -0.087036 0.283414 0.458007 0.336509 0.822795 0.548647 0.436829 0.712858 0.498793 0.508214 0.702085 0.40895 0.438856 0.800103 0.458788 0.419381 0.783347 0.488579 0.295919 0.820806 0.338496 0.547557 0.765246 0.40128 0.540787 0.739273 0.447903 0.573978 0.685516 0.572577 0.090453 0.814846 0.659971 0.242585 0.711049 0.600793 0.356629 0.715446 0.507798 0.222804 0.832165 0.525407 0.175386 0.832579 0.592642 0.076696 0.801806 0.696495 -0.160757 0.699323 0.747071 -0.060562 0.66198 0.716368 0.089686 0.691935 0.643654 -0.044528 0.76402 0.679875 -0.004061 0.733317 0.751902 -0.071444 0.655392 0.836517 -0.293072 0.462977 0.828132 -0.230473 0.510959 0.762807 -0.199352 0.61513 0.753672 -0.259258 0.603957 0.803598 -0.130297 0.580735 0.857252 -0.175255 0.484153 0.916775 -0.199713 0.345889 0.913851 -0.163134 0.371839 0.958882 -0.051876 0.279022 0.954667 -0.015331 0.297282 0.878559 0.023718 0.477045 0.887732 -0.142315 0.437811 0.881622 0.374121 0.287709 0.786275 0.361357 0.501191 0.845764 0.203036 0.493417 0.938392 0.191581 0.287606 0.964699 0.141352 0.222208 0.919874 0.344658 0.187198 0.735833 0.601185 0.31165 0.66518 0.53777 0.518014 0.724119 0.464664 0.509645 0.811286 0.503396 0.297333 0.847399 0.503007 0.169996 0.757311 0.630422 0.170435 0.55095 0.766953 0.328993 0.550236 0.662384 0.508417 0.604139 0.603421 0.520479 0.650213 0.6874 0.32358 0.647232 0.739853 0.183595 0.52066 0.823219 0.226328 0.232539 0.84106 0.48841 0.333081 0.772484 0.540672 0.4542 0.75815 0.467879 0.390892 0.846896 0.360515 0.372475 0.869089 0.325495 0.285053 0.827495 0.483733 0.339781 0.673393 0.656575 0.238562 0.704887 0.668 0.320797 0.691569 0.647164 0.829927 0.324203 0.453996 0.78816 0.413058 0.456275 0.818961 0.437724 0.37108 0.868606 0.367447 0.332424 0.594766 0.761672 -0.257117 0.732865 0.586033 -0.345649 0.753901 0.533838 0.38295 0.862991 0.204761 0.461865 0.867214 0.193679 0.458725 0.940858 -0.000486 0.3388 0.908483 -0.022324 0.417326 0.966409 -0.169051 -0.193584 0.923393 -0.383468 0.01723 0.951149 0.102662 0.291162 0.867316 0.198019 0.456675 0.856872 0.261318 0.444391 0.920131 0.262219 0.290862 0.845974 0.375555 -0.378531 0.934245 0.115443 -0.337429 0.724297 0.540152 0.42852 0.705159 0.593618 0.387773 0.719293 0.595991 0.356949 0.405662 0.913937 -0.012545 0.486535 0.862055 -0.141935 0.71787 0.605721 0.343167 0.730039 0.584407 0.354276 0.725686 0.562032 0.396862 0.693853 0.591752 0.410363 0.217331 0.868422 0.445659 0.312452 0.932842 0.179389 0.629841 0.545507 0.552922 0.214362 0.527633 0.821981 0.173015 0.7023 0.690536 0.57713 0.459556 0.675077 0.602476 0.389152 0.696838 0.688167 0.493994 0.531411 0.689409 0.382203 0.615335 0.751692 0.33439 0.568456 0.797599 0.361585 0.482797 0.671211 0.364963 0.645196 0.411128 0.319273 0.853838 0.313319 0.402291 0.860228 0.718031 0.380064 0.58308 0.802641 0.402836 0.439876 0.786668 0.41629 0.455912 0.7261 0.396288 0.561903 0.493842 0.121551 0.861014 0.469657 0.240907 0.849345 0.710366 0.36318 0.602894 0.767343 0.380847 0.515888 0.773688 0.31236 0.551215 0.718919 0.257235 0.645744 0.615801 -0.251493 0.746687 0.530844 -0.044491 0.846301 0.775459 0.113009 0.621203 0.81328 0.246247 0.527199 0.846491 0.212923 0.487972 0.849483 0.012404 0.52747 0.842402 -0.47405 0.256193 0.735809 -0.426295 0.526173 0.762121 0.060604 0.644592 0.762121 0.060604 0.644592 0.670388 0.105094 0.734531 0.670388 0.105094 0.734531 0.53593 0.35712 0.765013 0.53593 0.35712 0.765013 0.519593 0.470857 0.712963 0.519593 0.470857 0.712963 0.592721 0.147272 0.791829 0.592721 0.147272 0.791829 0.539402 0.227876 0.810628 0.539402 0.227876 0.810628 0.838046 -0.041961 0.543984 0.838046 -0.041961 0.543984 0.805134 0.024108 0.592603 0.805134 0.024108 0.592603 0.458987 0.56981 0.681651 0.458987 0.56981 0.681651 0.36131 0.737053 0.571146 0.36131 0.737053 0.571146 0.930114 -0.106536 0.351481 0.930114 -0.106536 0.351481 0.880661 -0.11099 0.460561 0.880661 -0.11099 0.460561 0.320732 0.857422 0.402441 0.320732 0.857422 0.402441 0.44726 0.859353 0.247932 0.44726 0.859353 0.247932 0.95182 0.231775 0.200795 0.95182 0.231775 0.200795 0.964167 0.021103 0.264456 0.964167 0.021103 0.264456 0.579093 0.8006 0.153919 0.579093 0.8006 0.153919 0.697437 0.705567 0.12553 0.697437 0.705567 0.12553 0.814036 0.566095 0.129927 0.814036 0.566095 0.129927 0.890074 0.43096 0.148464 0.890074 0.43096 0.148464 0.029208 0.881474 -0.471328 0.029208 0.881474 -0.471328 0.096449 0.728365 -0.678368 0.096449 0.728365 -0.678368 0.4685 0.04873 -0.882118 0.4685 0.04873 -0.882118 0.638087 -0.253445 -0.727056 0.638087 -0.253445 -0.727056 0.178322 0.511529 -0.840559 0.178322 0.511529 -0.840559 0.316697 0.307225 -0.897394 0.316697 0.307225 -0.897394 -0.229597 0.97301 0.023188 -0.229597 0.97301 0.023188 -0.099111 0.961282 -0.257125 -0.099111 0.961282 -0.257125 0.690989 -0.552351 -0.466307 0.690989 -0.552351 -0.466307 0.614728 -0.774975 -0.146708 0.614728 -0.774975 -0.146708 -0.213285 0.674612 0.706689 -0.213285 0.674612 0.706689 -0.277125 0.880387 0.384865 -0.277125 0.880387 0.384865 0.522099 -0.831492 0.189823 0.522099 -0.831492 0.189823 0.41303 -0.701304 0.581016 0.41303 -0.701304 0.581016 0.016451 0.304495 0.952372 0.016451 0.304495 0.952372 -0.102423 0.482133 0.87009 -0.102423 0.482133 0.87009 0.321342 -0.449506 0.833477 0.321342 -0.449506 0.833477 0.240502 -0.251619 0.937468 0.240502 -0.251619 0.937468 0.177609 -0.048219 0.982919 0.177609 -0.048219 0.982919 0.113264 0.143803 0.983103 0.113264 0.143803 0.983103 0.856752 0.237426 0.457827 0.923385 0.210649 0.320917 0.807841 0.342573 0.479622 0.926355 0.306361 0.219111 0.893024 0.401372 0.203491 0.707489 0.350542 0.613661 0.690028 0.404138 0.600445 0.701459 0.296818 0.647962 0.79174 0.518629 0.322757 0.756722 0.567339 0.324806 0.829456 0.472735 0.297531 0.598529 0.538416 0.593188 0.611969 0.432342 0.662249 0.636119 0.597396 0.488334 0.661695 0.3349 0.670821 0.723255 0.374582 0.580165 0.790325 0.34767 0.504491 0.811959 0.371822 0.449969 0.863778 0.442517 0.24097 0.701135 0.600411 0.384599 0.932766 0.160597 0.322732 0.970845 0.170441 0.168552 0.883636 0.175716 0.433947 0.958137 0.275993 0.076165 0.918477 0.391142 0.058382 0.596042 0.268924 0.756581 0.631692 0.23949 0.737299 0.526233 0.296752 0.79688 0.713347 0.696389 0.078601 0.607873 0.785114 0.118686 0.815341 0.574919 0.068466 0.317442 0.747572 0.583409 0.328784 0.607429 0.72314 0.382484 0.824581 0.416859 0.421264 0.422347 0.802596 0.694449 0.183029 0.695875 0.790988 0.142639 0.594973 0.851498 0.154648 0.501034 0.88206 0.467139 0.061249 0.494106 0.834447 0.244044 0.898388 0.239427 0.368203 0.928433 0.290662 0.231361 0.927907 0.362185 0.088373 0.90613 0.422899 -0.009252 0.502343 -0.531378 -0.68212 0.481433 0.034979 -0.875785 0.821621 0.007587 -0.569984 0.601173 0.059321 -0.796914 0.288385 0.93379 -0.211824 0.988457 0.045901 -0.144378 0.606647 0.786641 -0.114787 0.631147 0.75431 -0.180748 0.972584 0.01879 -0.231792 0.50542 0.85821 -0.089584 0.979429 0.125423 -0.158074 0.681238 -0.704485 -0.199036 0.649817 -0.670326 -0.358331 0.486326 -0.865845 -0.117473 0.446328 -0.866561 -0.223303 0.749936 -0.639396 -0.169616 0.164446 0.814374 0.556554 0.230868 0.7458 0.624886 0.513037 0.656869 0.552553 0.434017 0.729299 0.528916 0.753221 0.48407 0.445347 0.753221 0.48407 0.445347 0.124146 -0.973254 0.193296 0.136691 -0.979344 0.149 0.136691 -0.979344 0.149 0.184839 -0.973906 0.131688 0.16227 -0.986484 -0.022769 0.212195 -0.968006 0.133929 0.212195 -0.968006 0.133929 0.404326 0.749489 0.524201 0.579587 0.654669 0.485269 0.579587 0.654669 0.485269 0.267339 0.835446 0.480167 0.245983 0.889628 0.38478 0.267339 0.835446 0.480167 0.316456 0.757992 0.570354 0.349573 0.870764 0.345787 0.299173 0.736411 0.60679 0.210334 0.763548 0.610536 0.173912 0.765408 0.619601 0.197207 0.7873 0.584182 0.208134 0.150701 0.966421 0.45413 0.145812 0.878922 0.34138 0.606573 0.718004 0.193961 0.656473 0.728987 0.702212 0.014831 0.711813 0.629702 0.408791 0.660579 0.464374 -0.299888 0.833321 0.195845 -0.470873 0.860188 0.247334 -0.957018 0.151467 0.40013 -0.846054 0.352263 0.156142 -0.842984 0.51478 0.487382 -0.796965 0.356799 0.24234 -0.955279 0.169453 0.220077 -0.968074 0.119991 0.144759 -0.978459 0.147185 0.183204 -0.982603 -0.03045 0.067622 -0.997704 0.003667 0.333609 0.885237 0.324131 0.26257 0.786829 0.558531 0.249027 0.818022 0.518484 0.310909 0.905688 0.288211 0.981618 -0.064667 0.179569 0.953472 -0.110057 0.280676 0.829047 -0.397145 0.393645 0.92859 0.156172 0.336647 0.777747 -0.421784 0.466056 0.769156 -0.579058 0.270354 0.995933 0.044395 0.078399 0.452986 -0.772336 0.445309 0.25562 -0.911562 0.322045 0.985612 -0.013881 -0.168452 0.7241 -0.689125 0.028032 0.669094 -0.721471 -0.178308 0.959852 -0.03757 -0.277979 0.142983 -0.970854 0.192352 0.080246 -0.996775 0.00032 0.399717 0.880195 0.255896 0.376418 0.74386 0.552252 0.932941 0.251988 0.257146 0.923519 0.376658 0.072404 0.341071 0.563945 0.752088 0.901143 0.06264 0.428972 0.473307 -0.704975 -0.528197 0.53861 0.034196 -0.841861 0.284747 -0.650038 -0.704536 0.28859 -0.717857 -0.633559 0.66476 -0.69131 -0.283167 0.687122 0.601648 -0.407288 0.19454 0.943367 -0.268726 0.142669 0.967481 -0.20887 0.158097 0.977372 -0.140534 0.267227 0.956959 -0.113221 0.206618 0.964826 -0.16254 0.111176 0.975912 -0.187714 0.29006 0.951394 -0.103509 0.197728 0.977642 -0.071559 0.133329 0.730763 0.669484 -0.021072 0.776457 0.629818 -0.048861 0.692427 0.719831 -0.267381 0.736738 0.621067 0.502201 -0.841758 -0.198082 0.347489 -0.823244 -0.44891 0.323269 -0.832159 -0.450565 0.365532 -0.909977 -0.195774 0.278989 -0.744812 -0.606152 0.310543 -0.724294 -0.615598 0.470573 -0.845704 0.251686 0.639991 -0.751749 0.159014 0.847528 -0.526779 -0.064814 0.931762 0.360605 -0.042234 0.731131 -0.37377 0.57074 0.545828 -0.440059 0.713036 0.28654 -0.807827 -0.515083 0.336227 -0.798398 -0.499512 0.390344 -0.778946 -0.490791 0.394888 -0.900382 -0.182694 0.453746 -0.877199 -0.156959 0.356802 -0.910855 -0.207449 -0.344161 0.695104 0.631176 -0.149439 0.640429 0.753338 -0.149043 0.665502 0.731364 -0.349826 0.693839 0.629452 -0.136209 0.702366 0.698663 -0.323407 0.705435 0.63069 0.682989 -0.682468 -0.260315 0.59895 -0.703991 -0.381648 0.629914 -0.656157 -0.415531 0.77097 -0.571238 -0.281588 0.426971 -0.693708 -0.580055 0.470882 -0.685627 -0.555145 0.547183 -0.735019 -0.400422 0.403878 -0.692278 -0.598025 0.639219 -0.729933 -0.242067 0.756317 -0.646196 0.102054 0.818345 -0.573567 0.036491 0.814869 -0.159464 0.557279 0.753505 -0.300809 0.584589 0.916322 -0.395282 -0.064085 -0.552229 0.717565 0.424433 -0.549898 0.723485 0.417351 -0.689114 0.695621 0.20306 -0.692124 0.693865 0.198787 -0.449937 0.772191 0.44864 -0.582332 0.776773 0.23982 0.4591 -0.736156 -0.497294 0.428557 -0.75507 -0.496193 0.470093 -0.756298 -0.455001 0.604445 -0.773438 -0.190894 0.573109 -0.784752 -0.236031 0.620477 -0.767507 -0.161065 -0.154659 0.830449 0.535196 -0.208047 0.933434 0.292262 0.839948 -0.488026 -0.237313 0.649751 -0.668884 -0.361136 0.686328 -0.685198 -0.243841 0.870409 -0.456272 -0.184943 0.113928 -0.971144 0.209524 0.420169 -0.778433 0.466369 0.36716 -0.763202 0.531711 -0.02591 -0.968892 0.246125 0.735247 0.502746 0.454597 0.760736 -0.231899 0.60622 0.709739 -0.164748 0.68493 0.677088 0.518341 0.522374 0.150157 0.985896 -0.073902 0.110758 0.979195 -0.170028 0.14924 0.977328 -0.150193 0.102024 0.980668 -0.166976 0.092901 0.976521 -0.194362 0.035026 -0.981694 0.187218 -0.094184 -0.972517 0.212932 -0.040179 -0.998571 0.035247 -0.134425 -0.988935 0.062742 0.104938 0.981244 -0.161707 0.151335 0.986059 -0.069173 0.069929 0.986197 -0.150086 0.095076 0.992657 -0.074781 -0.031932 -0.959846 0.278703 0.3959 -0.771292 0.498369 0.753955 -0.269659 0.599029 0.811465 0.345679 0.471202 0.245701 0.963498 -0.106314 0.226774 0.963215 -0.144187 -0.201856 -0.975954 0.082263 -0.144695 -0.963786 0.22401 0.238399 0.953876 -0.182445 0.263237 0.957272 -0.119739 0.137189 0.954008 0.266548 0.004047 0.860303 0.509766 -0.324412 0.82325 0.46585 -0.221133 0.946632 0.234497 0.552688 -0.819889 -0.14939 0.435697 -0.752668 -0.493618 0.365249 -0.701895 -0.611504 0.358271 0.298744 0.88453 0.369064 0.261778 0.891776 0.680582 -0.368671 0.633159 0.35026 0.27383 0.895732 -0.101362 0.652868 0.750659 -0.31403 0.712829 0.627104 0.528306 -0.819128 -0.223433 0.448996 -0.780542 -0.434921 0.341896 0.423686 0.838807 0.504935 0.340193 0.79329 0.181522 0.411952 0.892942 0.181522 0.411952 0.892942 0.465736 -0.606641 0.644264 -0.0363 0.939717 0.340021 0.06455 0.996125 -0.059741 -0.0363 0.939717 0.340021 0.286421 0.951044 -0.116095 0.288616 0.950349 -0.116354 0.275757 0.953921 -0.118292 0.150003 0.985457 -0.079833 -0.160278 0.98687 0.019962 -0.557805 0.804225 0.205125 -0.528811 0.837981 0.134713 -0.689987 0.699784 0.184985 -0.704052 0.684413 0.189445 -0.639015 0.750411 0.168948 -0.301208 0.951297 0.065638 0.321965 0.939617 -0.116016 0.978366 -0.179418 -0.103002 0.950511 -0.146462 -0.274005 0.864752 0.428163 -0.262451 0.86448 -0.440579 -0.242001 0.720676 -0.665351 -0.194768 0.631835 -0.756962 -0.166709 0.640249 -0.749264 -0.169365 0.627443 -0.760901 -0.165364 0.541996 -0.828837 -0.138816 0.434754 -0.894291 -0.105989 0.396475 -0.913174 -0.094449 0.3782 -0.921198 -0.091428 0.733887 0.635327 -0.240355 0.720343 0.687761 -0.089944 0.744559 0.62451 -0.235838 0.345736 0.9286 0.13479 0.993133 0.093733 0.070012 0.356159 0.925036 0.132136 0.187307 0.978163 -0.09007 0.502357 0.858922 0.099456 0.251333 0.962401 -0.103033 0.65335 -0.735934 0.17758 0.65112 0.755621 0.071276 0.96166 -0.25776 -0.093651 0.209729 0.846026 0.490157 0.369985 -0.806261 -0.461579 -0.486759 0.759504 0.431532 0.951681 0.185976 -0.24437 0.902737 0.332183 -0.273352 0.941165 0.315326 -0.121568 0.951681 0.185976 -0.24437 0.956675 0.290442 0.020395 0.999368 -0.03479 -0.007251 0.964422 0.229761 0.130768 0.952504 0.13236 0.274258 0.999368 -0.03479 -0.007251 0.940577 -0.003262 0.339566 0.985356 -0.047323 -0.163812 0.973149 -0.138935 0.183517 0.98634 -0.163979 0.015638 0.985356 -0.047323 -0.163812 0.800077 -0.569905 -0.187309 0.874318 -0.431977 -0.221278 0.945305 -0.32607 -0.008707 0.031586 -0.183913 0.982435 0.031586 -0.183913 0.982435 -0.030751 -0.950601 0.30889 -0.030751 -0.950601 0.30889 0.985137 -0.170059 0.024169 -0.138803 -0.672288 0.727161 -0.138803 -0.672288 0.727161 0.909257 -0.407951 -0.082632 0.909257 -0.407951 -0.082632 0.975975 0.172973 -0.132486 0.975975 0.172973 -0.132486 0.980139 0.18814 -0.062699 0.980139 0.18814 -0.062699 0.977763 -0.075286 0.195733 0.977763 -0.075286 0.195733 0.989301 -0.108793 0.097195 0.989301 -0.108793 0.097195 0.977445 0.124096 -0.170885 0.977445 0.124096 -0.170885 0.998153 0.056019 0.023506 0.998153 0.056019 0.023506 0.796335 -0.523715 0.302611 0.474101 -0.734714 0.485204 -0.961031 0.165053 0.221757 -0.966015 0.031778 0.256527 -0.974186 0.146597 0.171671 -0.972365 0.022683 0.232362 -0.984794 0.118521 0.127015 -0.97678 0.011602 0.213931 -0.992779 0.080892 0.088578 -0.980405 -0.006081 0.1969 -0.997692 0.034776 0.058321 -0.983084 -0.030932 0.180525 -0.999084 -0.01652 0.039467 -0.983546 -0.055798 0.171824 -0.996955 -0.071034 0.03217 -0.982323 -0.081459 0.168542 -0.991355 -0.12588 0.037019 -0.979425 -0.107879 0.170556 -0.982538 -0.178319 0.053122 -0.975168 -0.132497 0.177459 -0.97118 -0.224992 0.078667 -0.9699 -0.153567 0.188972 -0.957807 -0.263848 0.113978 -0.963903 -0.170188 0.204763 -0.939615 -0.29636 0.171153 -0.955655 -0.183417 0.230396 -0.916192 -0.318352 0.243403 -0.943673 -0.194814 0.26745 -0.940074 0.285894 0.18581 -0.959445 0.258862 0.111609 -0.975323 0.216319 0.04416 -0.986978 0.160325 -0.013014 -0.993968 0.093475 -0.057363 -0.996059 0.018754 -0.086686 -0.993227 -0.06055 -0.099163 -0.985628 -0.140582 -0.09367 -0.972899 -0.220345 -0.070116 -0.955697 -0.29262 -0.031897 -0.933885 -0.356815 0.023271 -0.904554 -0.412768 0.106793 -0.874187 -0.443341 0.198105 -0.904883 0.399162 0.14784 -0.930066 0.363832 0.051015 -0.950616 0.308169 -0.036885 -0.965592 0.235032 -0.111317 -0.974471 0.147814 -0.168987 -0.976979 0.05078 -0.207202 -0.973161 -0.05162 -0.224262 -0.963025 -0.155851 -0.219756 -0.94516 -0.263631 -0.192798 -0.918341 -0.367435 -0.147108 -0.884469 -0.46033 -0.076225 -0.846414 -0.531736 0.028979 -0.81683 -0.561478 0.132408 -0.856198 0.505244 0.107954 -0.886734 0.462178 -0.009715 -0.911564 0.394322 -0.116455 -0.92955 0.305236 -0.206801 -0.940103 0.199203 -0.276631 -0.942966 0.081326 -0.322801 -0.938215 -0.042948 -0.343377 -0.925514 -0.170798 -0.338011 -0.90304 -0.303133 -0.304351 -0.869126 -0.43109 -0.242446 -0.825613 -0.542663 -0.154533 -0.78679 -0.615366 -0.04782 -0.763783 -0.641746 0.069265 -0.795208 0.602633 0.06691 -0.830597 0.552504 -0.069627 -0.85928 0.473551 -0.193358 -0.879991 0.369951 -0.297914 -0.892055 0.246859 -0.378547 -0.895219 0.110198 -0.431786 -0.889617 -0.03377 -0.455457 -0.87547 -0.181874 -0.447743 -0.852671 -0.3311 -0.404135 -0.819795 -0.473097 -0.322669 -0.773161 -0.597383 -0.21297 -0.732323 -0.672114 -0.109388 -0.703802 -0.710148 0.018793 -0.723285 0.690084 0.025367 -0.762965 0.633675 -0.127835 -0.79508 0.544841 -0.266451 -0.818228 0.428382 -0.383395 -0.831653 0.290204 -0.47343 -0.835118 0.137002 -0.532737 -0.828804 -0.024239 -0.559013 -0.813771 -0.188224 -0.549862 -0.79107 -0.350428 -0.501406 -0.757687 -0.507139 -0.410755 -0.712161 -0.640658 -0.287028 -0.672656 -0.725938 0.143347 -0.641851 0.766661 -0.016075 -0.68527 0.704796 -0.183489 -0.720395 0.607414 -0.334782 -0.745674 0.479891 -0.46225 -0.760327 0.328783 -0.560182 -0.764125 0.161453 -0.624537 -0.757252 -0.014499 -0.652962 -0.740618 -0.191819 -0.643964 -0.713493 -0.368156 -0.596145 -0.67319 -0.539525 -0.505696 -0.633594 -0.66652 -0.392824 -0.552217 0.831757 -0.056883 -0.598779 0.765354 -0.236001 -0.636491 0.660838 -0.397708 -0.663675 0.524103 -0.533716 -0.679467 0.362301 -0.638015 -0.683616 0.18334 -0.706439 -0.676308 -0.004709 -0.736604 -0.658096 -0.193709 -0.72759 -0.624976 -0.385418 -0.678866 -0.57331 -0.567527 -0.590956 -0.539712 -0.669892 -0.509859 -0.455829 0.884817 -0.096532 -0.504906 0.814845 -0.284776 -0.544771 0.704701 -0.454557 -0.573584 0.560728 -0.597148 -0.59041 0.390539 -0.706325 -0.594941 0.202476 -0.777849 -0.58738 0.005005 -0.809296 -0.568315 -0.193377 -0.799765 -0.531724 -0.399254 -0.746904 -0.472063 -0.588647 -0.65624 -0.438252 -0.663694 -0.606173 -0.336649 0.931055 -0.140727 -0.387856 0.858178 -0.336301 -0.429627 0.743452 -0.512543 -0.459974 0.593597 -0.660353 -0.477869 0.416607 -0.773356 -0.482921 0.221168 -0.847273 -0.475295 0.016124 -0.879678 -0.455543 -0.189817 -0.869741 -0.417917 -0.406061 -0.812687 -0.353552 -0.60422 -0.714086 -0.307968 -0.666598 -0.678825 -0.193714 0.962913 -0.187815 -0.246267 0.8884 -0.387424 -0.288613 0.77069 -0.568101 -0.317008 0.616998 -0.720292 -0.324374 0.435579 -0.839674 -0.320365 0.248902 -0.91401 -0.326185 0.041175 -0.944409 -0.317893 -0.181748 -0.930544 -0.279515 -0.404386 -0.870829 -0.213288 -0.614544 -0.759503 -0.156721 -0.682515 -0.713871 -0.046463 0.971992 -0.230375 -0.103325 0.898972 -0.425645 -0.164362 0.783516 -0.59924 -0.218293 0.643744 -0.733446 -0.220032 0.426957 -0.877094 -0.163378 0.257767 -0.952294 -0.189104 0.091231 -0.97771 -0.196106 -0.137994 -0.970824 -0.15848 -0.395997 -0.904473 -0.068774 -0.626707 -0.776214 0.011498 -0.702817 -0.711278 0.080842 0.962059 -0.260588 -0.004368 0.897342 -0.441313 -0.108637 0.80053 -0.589364 -0.077282 0.160772 -0.983961 -0.047366 -0.005136 -0.998864 -0.055321 -0.376835 -0.924627 0.024205 -0.64051 -0.767568 0.122657 -0.746286 -0.654227 0.182989 0.944565 -0.272601 0.060296 0.892968 -0.446064 0.298773 0.913904 -0.274797 0.253313 0.891687 -0.375137 0.114854 -0.338324 -0.933994 0.102232 0.013353 -0.994671 0.151765 -0.614693 -0.774028 0.247572 -0.789545 -0.561539 0.422501 0.861523 -0.281553 0.416333 0.839555 -0.34902 0.37199 -0.274879 -0.886603 0.353485 0.017625 -0.935274 0.378321 -0.507369 -0.774242 0.386435 -0.730111 -0.563565 0.530382 0.793788 -0.297652 0.540498 0.759214 -0.362568 0.588887 -0.200332 -0.782994 0.56861 0.014756 -0.822475 0.582449 -0.344028 -0.736476 0.575726 -0.569224 -0.586961 0.65241 0.687716 -0.318445 0.658927 0.642592 -0.391012 0.527988 0.032741 -0.848621 0.572271 -0.222348 -0.789346 0.647447 -0.270239 -0.712589 0.71954 -0.352064 -0.598592 0.761452 -0.51329 -0.395884 0.588683 -0.724004 -0.359542 0.425419 -0.825843 -0.370137 0.75829 0.548346 -0.35258 0.752446 0.495489 -0.433954 0.762878 0.455469 -0.458873 0.774527 0.480972 -0.410821 -0.059483 0.299655 -0.952191 -0.090596 0.399221 -0.912368 0.036545 0.471124 -0.881309 0.07364 0.399264 -0.913874 -0.030114 0.266255 -0.963432 -0.038844 0.381241 -0.923659 -0.13284 0.509742 -0.85001 -0.066453 0.503298 -0.861554 0.001768 0.538105 -0.842876 0.050754 0.065758 -0.996544 -0.019181 0.193572 -0.980899 0.117727 0.320417 -0.939933 0.173089 0.209675 -0.962329 0.073986 0.047418 -0.996131 -0.002861 0.154045 -0.98806 0.22268 -0.189591 -0.956279 0.142047 -0.070696 -0.987332 0.235945 0.061061 -0.969846 0.284019 -0.085242 -0.955022 0.284187 -0.119522 -0.95129 0.18495 -0.046926 -0.981627 0.469944 -0.314762 -0.824668 0.324898 -0.286474 -0.901318 0.327435 -0.220891 -0.918691 0.436096 -0.251459 -0.864054 0.473624 -0.209127 -0.855538 0.371679 -0.174482 -0.911817 0.593781 -0.220328 -0.773873 0.64569 -0.038921 -0.762607 0.659388 -0.074842 -0.748068 0.577338 -0.188497 -0.794449 0.520053 -0.164818 -0.838081 0.486574 -0.003404 -0.873633 0.583694 0.350278 -0.732535 0.633952 0.167061 -0.755112 0.445809 0.172583 -0.878333 0.388775 0.329865 -0.860258 0.670839 0.324639 -0.666772 0.692093 0.11947 -0.711852 0.445222 0.577844 -0.684013 0.517686 0.479897 -0.708308 0.330597 0.433029 -0.838565 0.275479 0.50654 -0.817024 0.53871 0.612813 -0.578145 0.616696 0.484403 -0.620516 0.278003 0.744964 -0.606418 0.365453 0.664551 -0.651779 0.221829 0.57283 -0.789087 0.182217 0.632878 -0.752504 0.306851 0.80584 -0.506422 0.437533 0.722967 -0.534681 -0.077112 0.816166 -0.572649 0.125172 0.825515 -0.550324 0.121846 0.731498 -0.670868 -0.019603 0.743964 -0.667932 -0.030227 0.802231 -0.596248 0.128031 0.849287 -0.512171 -0.166759 0.672289 -0.721262 -0.074919 0.639876 -0.764817 -0.086363 0.65898 -0.747185 0.419268 0.406688 -0.811677 0.45283 0.31045 -0.835802 0.550354 0.354523 -0.755926 0.488995 0.426269 -0.761038 0.798505 0.589542 -0.121777 0.629664 0.764854 -0.136094 0.428097 0.516657 -0.741484 0.481992 0.162651 -0.860946 0.476625 0.173666 -0.861782 0.541781 -0.051837 -0.83892 0.610962 -0.026965 -0.7912 0.77405 -0.395398 -0.494477 0.920958 -0.172543 -0.349378 0.643893 0.078074 -0.761122 0.480736 0.233816 -0.845117 0.483133 0.167149 -0.859444 0.616661 0.240115 -0.749715 0.967736 0.117908 -0.222674 0.913198 0.379905 -0.147451 0.390578 0.591083 -0.705741 0.382839 0.535126 -0.753044 0.414139 0.577573 -0.70349 0.47634 0.860797 -0.179246 0.340392 0.907818 -0.24495 0.421549 0.584377 -0.693397 0.405414 0.540989 -0.736865 0.431518 0.576007 -0.694268 0.364935 0.56563 -0.739517 0.160295 0.921034 -0.354968 -0.063838 0.850342 -0.522343 0.231853 0.516573 -0.824255 -0.234963 0.674542 -0.699847 -0.263787 0.488611 -0.831671 0.143761 0.349005 -0.926028 0.121957 0.430188 -0.894463 0.244238 0.368175 -0.897104 0.286839 0.465666 -0.837185 0.431825 0.308888 -0.847417 0.349106 0.306214 -0.88564 0.242828 0.317447 -0.916658 -0.193183 0.358321 -0.913393 -0.108882 0.280328 -0.953709 0.308743 0.342271 -0.887428 0.400235 0.380025 -0.833902 0.437071 0.358464 -0.824907 0.306876 0.362809 -0.879885 -0.062544 0.201463 -0.977497 -0.04802 0.0781 -0.995788 0.266858 0.326827 -0.906626 0.350138 0.278047 -0.894479 0.354862 0.347322 -0.868009 0.255429 0.219947 -0.941477 -0.006971 -0.087812 -0.996113 0.120653 -0.291438 -0.94895 0.318338 0.07641 -0.944893 0.448609 0.180967 -0.875215 0.399034 0.212972 -0.89186 0.432397 -0.02109 -0.901437 0.342686 -0.457883 -0.820311 0.578434 -0.49519 -0.648229 0.296419 -0.000702 -0.955058 0.296419 -0.000702 -0.955058 0.172523 0.052896 -0.983584 0.172523 0.052896 -0.983584 0.039158 0.322577 -0.945733 0.039158 0.322577 -0.945733 0.047516 0.433082 -0.900101 0.047516 0.433082 -0.900101 0.073663 0.121903 -0.989805 0.073663 0.121903 -0.989805 0.020637 0.212144 -0.977021 0.020637 0.212144 -0.977021 0.424054 -0.091556 -0.900997 0.424054 -0.091556 -0.900997 0.357272 -0.03225 -0.933444 0.357272 -0.03225 -0.933444 0.012525 0.534209 -0.84526 0.012525 0.534209 -0.84526 -0.011494 0.7071 -0.707021 -0.011494 0.7071 -0.707021 0.597526 -0.131026 -0.791072 0.597526 -0.131026 -0.791072 0.505826 -0.146625 -0.850083 0.505826 -0.146625 -0.850083 0.043082 0.835064 -0.548463 0.043082 0.835064 -0.548463 0.232892 0.841802 -0.486962 0.232892 0.841802 -0.486962 0.692441 0.211038 -0.689919 0.692441 0.211038 -0.689919 0.670034 -0.002279 -0.742327 0.670034 -0.002279 -0.742327 0.395537 0.785831 -0.475416 0.395537 0.785831 -0.475416 0.511415 0.69064 -0.511342 0.511415 0.69064 -0.511342 0.608864 0.549501 -0.572131 0.608864 0.549501 -0.572131 0.665886 0.412472 -0.621662 0.665886 0.412472 -0.621662 0.267718 0.900516 0.342634 0.267718 0.900516 0.342634 0.434491 0.763425 0.477912 0.434491 0.763425 0.477912 0.869912 0.076138 0.487294 0.869912 0.076138 0.487294 0.932155 -0.229683 0.279881 0.932155 -0.229683 0.279881 0.602872 0.538559 0.588642 0.602872 0.538559 0.588642 0.752279 0.323048 0.574209 0.752279 0.323048 0.574209 -0.213672 0.974192 0.072768 -0.213672 0.974192 0.072768 0.039021 0.973056 0.227243 0.039021 0.973056 0.227243 0.840289 -0.540248 0.045233 0.840289 -0.540248 0.045233 0.606818 -0.775669 -0.17352 0.606818 -0.775669 -0.17352 -0.573632 0.648601 -0.500262 -0.573632 0.648601 -0.500262 -0.459052 0.865899 -0.198721 -0.459052 0.865899 -0.198721 0.348772 -0.845309 -0.404736 0.348772 -0.845309 -0.404736 0.044107 -0.731158 -0.680781 0.044107 -0.731158 -0.680781 -0.526631 0.262875 -0.808429 -0.526631 0.262875 -0.808429 -0.572583 0.444835 -0.688673 -0.572583 0.444835 -0.688673 -0.171813 -0.489749 -0.854767 -0.171813 -0.489749 -0.854767 -0.298216 -0.294897 -0.907801 -0.298216 -0.294897 -0.907801 -0.378075 -0.092709 -0.921121 -0.378075 -0.092709 -0.921121 -0.44719 0.096281 -0.889242 -0.44719 0.096281 -0.889242 0.612429 0.206829 -0.762989 0.464886 0.248405 -0.849809 0.407407 0.351958 -0.842701 0.648197 0.357749 -0.672202 0.671753 0.259933 -0.693674 0.260779 0.444292 -0.857088 0.266283 0.359019 -0.894538 0.239549 0.282383 -0.928911 0.456076 0.54318 -0.704947 0.484975 0.494828 -0.721072 0.523431 0.452679 -0.721874 0.154432 0.395601 -0.905345 0.17883 0.504716 -0.84456 0.266157 0.567731 -0.779001 0.193307 0.300033 -0.934138 0.427534 0.439385 -0.790035 0.307666 0.464115 -0.830626 0.465664 0.419078 -0.779442 0.586011 0.418412 -0.693919 0.376686 0.574397 -0.726757 0.72401 0.167928 -0.669036 0.615211 0.144276 -0.775048 0.538442 0.194451 -0.81992 0.755996 0.352652 -0.551458 0.765047 0.251817 -0.592698 0.104303 0.251884 -0.96212 0.084593 0.265317 -0.960443 0.005837 0.281933 -0.959416 0.438714 0.77153 -0.460728 0.549094 0.684577 -0.479427 0.639111 0.567102 -0.51955 -0.119349 0.571474 -0.811895 -0.055497 0.717664 -0.694175 0.087893 0.80095 -0.592244 -0.082255 0.383999 -0.919662 0.371981 0.25099 -0.893663 0.168173 0.254214 -0.952414 0.515832 0.244885 -0.820943 0.711746 0.448691 -0.540457 0.274747 0.816832 -0.507247 0.645705 0.281916 -0.70964 0.539281 0.220414 -0.812769 0.769022 0.394085 -0.503292 0.726749 0.338639 -0.597628 0.910687 0.132665 0.391214 0.999599 0.019627 0.020427 0.95412 0.024299 0.298438 0.445708 0.894704 -0.029136 0.965917 0.00636 -0.258774 0.63813 0.749781 -0.174984 0.564478 0.808758 -0.165152 0.955888 0.074409 -0.28415 0.833027 -0.550995 -0.049699 0.747769 -0.638876 -0.180774 0.496269 -0.862279 -0.100952 -0.207933 0.848115 -0.487303 0.067624 0.763984 -0.641681 0.12728 0.626188 -0.769213 -0.218784 0.728379 -0.649305 0.477035 0.407812 -0.778542 0.477035 0.407812 -0.778542 0.017333 -0.981177 -0.192329 0.100697 -0.980826 -0.166857 0.066985 -0.985016 -0.158922 0.066985 -0.985016 -0.158922 0.113176 -0.977596 -0.177477 0.113176 -0.977596 -0.177477 0.260639 0.584649 -0.768279 0.260639 0.584649 -0.768279 0.016554 0.67435 -0.738226 -0.106362 0.750404 -0.652366 -0.106362 0.750404 -0.652366 -0.052394 0.836039 -0.546163 0.073173 0.824552 -0.561034 -0.11046 0.686583 -0.718611 -0.155032 0.743111 -0.650962 -0.209657 0.806439 -0.552901 -0.277141 0.74834 -0.602644 -0.254322 0.755762 -0.603444 -0.358109 0.092557 -0.929081 -0.250923 0.673348 -0.695442 -0.112663 0.603179 -0.789609 -0.09202 0.089713 -0.991708 0.154625 0.382352 -0.910988 0.205405 -0.026468 -0.978319 -0.072607 -0.353019 -0.932795 -0.315135 -0.516218 -0.796372 0.137801 -0.96591 -0.219155 -0.147037 -0.862058 -0.485012 0.15353 -0.866566 -0.474859 0.229098 -0.817711 -0.528075 0.125194 -0.964684 -0.231758 0.055128 -0.985656 -0.159509 0.133227 -0.975043 -0.1776 0.08158 0.845691 -0.5274 0.078804 0.875247 -0.477213 -0.135909 0.78308 -0.606889 -0.14307 0.731129 -0.667069 0.652262 -0.134271 -0.746006 0.728452 -0.084587 -0.679855 0.489926 -0.423017 -0.762253 0.604152 0.140091 -0.784458 0.789901 0.036981 -0.612119 0.511155 -0.597093 -0.618224 0.41548 -0.442463 -0.794735 0.053874 -0.927755 -0.369281 0.152238 -0.796477 -0.58519 0.917433 -0.01634 -0.397554 0.60325 -0.699086 -0.383887 0.029478 -0.980033 -0.196639 0.188278 0.863211 -0.468421 0.734878 0.361526 -0.573806 0.645074 0.228829 -0.729052 0.011092 0.714503 -0.699544 0.528285 0.032629 -0.84844 -0.123905 0.526586 -0.841044 0.709036 -0.679127 0.189881 0.54884 -0.680148 0.485977 0.696633 -0.536154 0.476698 0.937025 0.142119 0.319041 0.883729 -0.390989 0.257199 0.771856 0.621298 -0.135006 0.80244 -0.582305 -0.130427 0.360455 0.931906 0.040288 0.246781 0.968966 0.014261 0.199409 0.979909 0.003657 0.20259 0.97835 0.042279 0.297397 0.954751 0.002279 0.296878 0.953346 -0.054732 -0.448272 0.750301 -0.485901 -0.299256 0.711329 -0.635969 -0.449932 0.662013 -0.599417 -0.604373 0.702658 -0.375506 0.543677 -0.837776 -0.05046 0.41825 -0.908309 0.006481 0.525642 -0.828016 0.195167 0.513327 -0.837473 0.187441 0.632445 -0.690176 0.351668 0.562937 -0.723503 0.399556 0.270888 -0.860723 -0.431018 0.466072 -0.760826 -0.451575 0.785817 -0.470274 -0.401664 0.806986 0.379916 -0.452147 0.311722 -0.406116 -0.859011 0.08011 -0.476468 -0.875534 0.492226 -0.783275 0.379728 0.564196 -0.75938 0.324076 0.615425 -0.747397 0.250297 0.467281 -0.880804 -0.076373 0.423525 -0.905139 -0.036738 0.388235 -0.921287 -0.022439 -0.638353 0.671458 -0.376365 -0.642083 0.670375 -0.371923 -0.527289 0.635121 -0.564436 -0.53912 0.609156 -0.581618 -0.499354 0.673213 -0.545371 -0.620665 0.681581 -0.387585 0.724403 -0.679107 -0.118553 0.808578 -0.568186 -0.152862 0.76273 -0.645516 0.039393 0.719046 -0.694329 0.029644 0.704086 -0.666952 0.243799 0.68063 -0.673335 0.288725 0.675478 -0.668555 0.311069 0.688796 -0.721756 0.068031 0.678689 -0.726051 -0.110594 0.590821 -0.659388 -0.464906 0.324614 -0.335183 -0.884465 0.389368 -0.193616 -0.900503 0.677507 -0.584788 -0.446103 0.811911 -0.403641 -0.421752 -0.702864 0.705439 -0.091315 -0.699069 0.693346 0.174852 -0.698884 0.694843 0.169571 -0.697074 0.711711 -0.08692 -0.629707 0.772938 0.077689 -0.630257 0.757744 -0.169115 0.665495 -0.718329 0.202779 0.637554 -0.7383 0.220087 0.650398 -0.741869 0.163133 0.619906 -0.781037 -0.075482 0.62189 -0.772088 -0.130895 0.619404 -0.767547 -0.164959 -0.428525 0.808484 -0.403384 -0.344282 0.922494 -0.174568 0.841854 -0.487833 -0.230867 0.838993 -0.458769 -0.292613 0.718357 -0.682624 -0.134116 0.750372 -0.66081 -0.016469 -0.004385 -0.980634 -0.195802 0.11327 -0.803082 -0.585003 0.033162 -0.790045 -0.612151 -0.142029 -0.978203 -0.151482 0.398848 0.500353 -0.768484 0.284867 0.522124 -0.803889 0.240759 -0.182234 -0.953324 0.326055 -0.256882 -0.90978 0.106126 0.992625 0.058596 0.101925 0.991712 -0.078227 0.185058 0.981762 0.043548 0.161241 0.98316 0.086007 0.203627 0.976108 0.075821 -0.181266 -0.979622 -0.086502 -0.058418 -0.989239 -0.134139 0.18691 0.981774 0.034418 0.16088 0.98655 0.028917 -0.164751 -0.970502 -0.176023 0.075477 -0.797038 -0.599194 0.41959 0.332341 -0.844685 0.322606 -0.288805 -0.901397 0.338129 0.937695 -0.079978 0.299596 0.953203 -0.040569 -0.230271 -0.970692 -0.068787 0.273756 0.960659 -0.046809 -0.093554 0.935084 -0.341855 -0.357811 0.927392 -0.109158 -0.580229 0.784645 -0.218327 -0.370232 0.823908 -0.429073 0.555442 -0.82035 -0.136052 0.648256 -0.730721 0.214037 0.665073 -0.670138 0.329534 -0.177345 0.255741 -0.950339 0.237945 -0.404121 -0.883215 -0.171659 0.218398 -0.960643 -0.191232 0.22974 -0.95428 -0.611039 0.688951 -0.389844 -0.497376 0.621066 -0.605717 0.578572 -0.812132 -0.075471 0.636769 -0.760919 0.124606 -0.168096 0.382717 -0.908445 -0.01579 0.29859 -0.954251 -0.354497 0.372019 -0.857866 -0.354497 0.372019 -0.857866 0.030753 -0.642052 -0.766044 -0.28865 0.899627 -0.327645 -0.28865 0.899627 -0.327645 -0.590748 0.801531 0.092551 0.882451 -0.187177 -0.431561 0.631213 0.690214 -0.3538 0.716773 0.651128 -0.249539 0.810085 0.079366 -0.580916 0.218435 0.918014 -0.330963 0.140919 0.983259 -0.115515 0.178425 0.905077 -0.386006 0.364259 0.817074 -0.446884 0.299785 0.939825 -0.163886 0.464631 -0.750462 -0.470027 0.536199 0.720631 -0.439525 0.864301 -0.265631 -0.427112 -0.127859 0.902899 -0.410396 0.648779 -0.746777 0.14632 -0.65206 0.746179 -0.134292 0.932257 0.179954 -0.313868 0.932257 0.179954 -0.313868 0.85443 0.301563 -0.423095 0.797829 0.26596 -0.541049 0.873116 -0.177098 -0.454207 0.873116 -0.177098 -0.454207 0.649289 0.072699 -0.757059 0.753442 0.191783 -0.628923 0.6043 -0.0704 -0.793641 0.921298 -0.001363 -0.388856 0.921298 -0.001363 -0.388856 0.805464 -0.09727 -0.584608 0.710857 -0.181827 -0.679427 0.859553 -0.250977 -0.445172 -0.504833 -0.252405 -0.825491 -0.504833 -0.252405 -0.825491 -0.176988 -0.95937 -0.219738 -0.176988 -0.95937 -0.219738 0.838581 -0.043777 -0.543014 -0.50884 -0.695521 -0.507279 -0.50884 -0.695521 -0.507279 0.843621 -0.371969 -0.387224 0.843621 -0.371969 -0.387224 0.897769 0.154532 -0.41247 0.897769 0.154532 -0.41247 0.883068 0.157461 -0.442037 0.883068 0.157461 -0.442037 0.71598 -0.20424 -0.667576 0.71598 -0.20424 -0.667576 0.84052 -0.139279 -0.523572 0.84052 -0.139279 -0.523572 0.889164 0.201883 -0.410647 0.889164 0.201883 -0.410647 0.844759 0.094819 -0.526679 0.844759 0.094819 -0.526679 0.516769 -0.546521 -0.658988 0.137687 -0.761356 -0.633545 -0.073521 0.769689 -0.634171 -0.902895 -0.325759 0.280467 -0.936415 -0.200727 0.287811 -0.858832 -0.448083 0.248252 -0.80054 -0.564124 0.202238 -0.740856 -0.649577 0.170825 -0.640499 -0.727822 0.245023 -0.852262 -0.443442 0.277505 -0.785146 -0.561254 0.261802 -0.709343 -0.657204 0.254784 0.578683 -0.759785 0.2964 -0.000115 -0.99999 -0.004589 -0.00051 -0.999977 -0.006811 -3.4e-005 -0.999995 -0.003095 -0.0006 -0.999998 -0.001658 0.001309 -0.999998 0.001288 -0.003465 -0.999976 -0.006061 -0.004195 -0.999979 -0.004981 -0.000633 -0.99997 -0.007748 -0.001948 -0.999974 -0.00693 -6e-006 -0.999971 -0.007673 -0.00264 -0.99998 -0.005704 -6.6e-005 -0.999967 -0.008151 -0.00142 -0.999996 -0.002481 0.003645 -0.999993 4.6e-005 -0.002686 -0.999991 0.003221 0.002724 -0.999944 0.010221 0.004946 -0.999932 0.010546 0.006765 -0.99992 0.010688 0.004595 -0.999966 0.006817 0.001146 -0.999997 0.002298 -0.004822 -0.999982 0.003527 -0.003588 -0.999964 0.00771 -0.00298 -0.999888 0.014663 -0.001243 -0.999863 0.016531 0.001848 -0.999933 0.011451 -0.004415 -0.999984 0.003674 0.001118 -0.999907 0.013595 0.001334 -0.999999 -0.000699 -0.00033 -1 -0.000292 + + + + + + + + + + 0.245158 0.423975 0.25011 0.468112 0.150442 0.543685 0.148569 0.498875 0.302841 0.416173 0.345064 0.636086 0.339502 0.673242 0.260986 0.672117 0.283208 0.642063 0.331126 0.714598 0.241009 0.71553 0.233372 0.762934 0.302959 0.373132 0.224027 0.289653 0.23558 0.359702 0.143764 0.429085 0.134156 0.320572 0.298228 0.319321 0.288073 0.263566 0.326898 0.757163 0.328393 0.797118 0.23841 0.805793 0.60087 0.640918 0.866606 0.398924 0.510699 0.676291 0.517366 0.634965 0.871384 0.397619 0.505796 0.719121 0.878048 0.397558 0.87416 0.398826 0.86606 0.397625 0.86057 0.399008 0.501279 0.762876 0.856321 0.39906 0.497144 0.804816 0.862375 0.397683 0.860024 0.397676 0.853776 0.399148 0.494669 0.842655 0.936097 0.40457 0.495808 0.877438 0.932361 0.401286 0.944998 0.401429 0.333511 0.830512 0.255441 0.838224 0.335539 0.859065 0.275714 0.857682 0.13703 0.645509 0.099669 0.709478 0.072436 0.710311 0.114209 0.64461 0.217381 0.600094 0.193334 0.589335 0.083907 0.774978 0.093256 0.834193 0.067488 0.842396 0.056643 0.778851 0.948825 0.405179 0.543475 0.557405 0.5578 0.533271 0.685834 0.551732 0.928618 0.398828 0.939922 0.398832 0.318062 0.571086 0.304302 0.551225 0.870712 0.401462 0.862287 0.401557 0.855482 0.401642 0.85836 0.405349 0.85103 0.405417 0.86725 0.404976 0.851008 0.401767 0.84805 0.401779 0.618068 0.949096 0.595914 0.442419 0.701364 0.36472 0.704143 0.312403 0.595493 0.387203 0.757075 0.288915 0.749567 0.262372 0.79867 0.019963 0.720188 0.090411 0.342229 0.232442 0.353643 0.285267 0.846214 0.405443 0.84246 0.405195 0.945825 0.3988 0.51556 0.94314 0.529717 0.959537 0.951482 0.401365 0.955814 0.405156 0.355112 0.336459 0.416748 0.23909 0.409212 0.301844 0.412385 0.174765 0.722678 0.141004 0.371257 0.129527 0.316583 0.183819 0.278107 0.146712 0.815355 0.094326 0.586596 0.164171 0.31201 0.090946 0.272238 0.213152 0.591566 0.221736 0.775513 0.183818 0.258385 0.177707 0.714664 0.225413 0.594393 0.311859 0.803506 0.201004 0.853165 0.100422 0.240207 0.064107 0.220228 0.127313 0.134162 0.116701 0.137886 0.045291 0.20962 0.176711 0.132836 0.176022 0.393776 0.367451 0.346805 0.380154 0.21424 0.228892 0.133514 0.241035 0.127886 0.880246 0.194162 0.909528 0.176891 0.924466 0.105635 0.892789 0.298575 0.918513 0.289302 0.932026 0.41004 0.927663 0.412647 0.940987 0.152917 0.714025 0.188039 0.660899 0.251002 0.622891 0.148083 0.821618 0.139091 0.770988 0.529124 0.59406 0.624566 0.605374 0.943792 0.414167 0.33386 0.602351 0.939709 0.408955 0.951716 0.40979 0.95394 0.414936 0.863781 0.409841 0.854643 0.410095 0.847079 0.410021 0.50373 0.914675 0.043999 0.560029 0.039161 0.51728 0.035514 0.442488 0.02836 0.327681 0.57657 0.399149 0.579657 0.45714 0.483058 0.467543 0.484696 0.402538 0.027211 0.11532 0.026409 0.041836 0.027231 0.176259 0.027041 0.244825 0.496033 0.232082 0.498386 0.171519 0.545104 0.178866 0.55478 0.242428 0.486973 0.320445 0.572701 0.32584 0.253473 0.42034 0.198325 0.471074 0.201641 0.514357 0.257191 0.464291 0.304409 0.414784 0.305266 0.371658 0.230885 0.286168 0.167912 0.306331 0.188981 0.401339 0.242536 0.354324 0.300813 0.31779 0.290984 0.262458 0.644363 0.422582 0.643061 0.366324 0.70337 0.314326 0.703499 0.366966 0.745969 0.26707 0.75382 0.293297 0.343946 0.231017 0.355397 0.284532 0.356783 0.335152 0.414764 0.29281 0.419941 0.236001 0.413771 0.173263 0.370421 0.125545 0.313385 0.086563 0.282902 0.142155 0.319456 0.18046 0.261679 0.175104 0.275739 0.211488 0.247515 0.05956 0.175872 0.043369 0.166908 0.113803 0.230266 0.122298 0.162066 0.173298 0.220575 0.173418 0.399643 0.347472 0.348371 0.378515 0.850892 0.415208 0.23283 0.882474 0.174218 0.860862 0.318561 0.890705 0.412205 0.900441 0.414872 0.864697 0.414169 0.832004 0.413463 0.796679 0.414763 0.757 0.418623 0.715141 0.424042 0.67374 0.797949 0.022112 0.816816 0.093012 0.720595 0.147032 0.715991 0.092651 0.636546 0.210325 0.627672 0.148444 0.772502 0.189202 0.711355 0.231084 0.641706 0.289174 0.223314 0.226619 0.162858 0.235961 0.139391 0.505963 0.140772 0.546375 0.105327 0.324975 0.131454 0.436403 0.855305 0.0942 0.800674 0.205793 0.103269 0.042003 0.100779 0.11305 0.099208 0.173793 0.099637 0.242841 0.428561 0.633258 0.429426 0.594048 0.429051 0.559095 0.429259 0.535162 0.35272 0.639241 0.294558 0.645659 0.274212 0.673847 0.348213 0.675519 0.253789 0.714174 0.339072 0.715472 0.241562 0.759109 0.241492 0.801977 0.330569 0.796358 0.332348 0.756954 0.843668 0.414845 0.519216 0.636196 0.513483 0.677706 0.858319 0.415536 0.509018 0.719971 0.595108 0.724198 0.959154 0.409842 0.961426 0.415077 0.955396 0.420505 0.503982 0.762367 0.946551 0.419988 0.498249 0.80295 0.581926 0.813498 0.948394 0.426244 0.956245 0.426562 0.493564 0.840197 0.962774 0.420748 0.49337 0.874734 0.5689 0.884732 0.963626 0.426902 0.947821 0.439136 0.254385 0.836095 0.333265 0.830744 0.334347 0.859927 0.274272 0.857068 0.111374 0.707428 0.160452 0.654158 0.126019 0.649524 0.074711 0.707898 0.232092 0.611555 0.203545 0.598866 0.085639 0.828171 0.086444 0.767612 0.053832 0.770468 0.05904 0.833261 0.5406 0.554531 0.653253 0.57169 0.949156 0.432796 0.552741 0.532581 0.956416 0.432776 0.955188 0.438695 0.321928 0.578317 0.3053 0.558373 0.963377 0.433055 0.962074 0.438861 0.939469 0.450342 0.944673 0.445101 0.952905 0.444195 0.949616 0.449137 0.959891 0.444199 0.95721 0.449055 0.928445 0.45763 0.933041 0.454385 0.647892 0.957038 0.945196 0.453364 0.513713 0.938992 0.528694 0.953445 0.940767 0.456994 0.954246 0.453493 0.191556 0.905473 0.119561 0.876603 0.09609 0.886393 0.173642 0.917872 0.296111 0.916924 0.285563 0.930752 0.407594 0.925155 0.699705 0.808301 0.767751 0.813767 0.770203 0.857847 0.710393 0.859091 0.67046 0.86001 0.652167 0.800156 0.732575 0.902022 0.706983 0.910753 0.776574 0.894725 0.709069 0.706824 0.772884 0.721001 0.769128 0.766819 0.69961 0.756109 0.650715 0.739559 0.665169 0.685443 0.747389 0.629544 0.781976 0.645207 0.777571 0.679447 0.726035 0.663915 0.69251 0.641696 0.7256 0.608173 0.800842 0.598447 0.800844 0.613722 0.782354 0.62203 0.77064 0.606739 0.761516 0.586356 0.801211 0.57812 0.833474 0.606525 0.843418 0.585771 0.884582 0.608278 0.861681 0.62927 0.826927 0.645008 0.821482 0.621769 0.901508 0.709495 0.841154 0.721344 0.835351 0.679466 0.88519 0.664947 0.920582 0.64464 0.946246 0.692573 0.905321 0.811872 0.840491 0.814502 0.842749 0.767471 0.908491 0.759591 0.957769 0.748636 0.953229 0.808266 0.87648 0.901039 0.832824 0.894364 0.83647 0.858222 0.893987 0.860506 0.934495 0.863509 0.904941 0.908789 0.811165 0.93926 0.808557 0.928096 0.833115 0.918674 0.850764 0.928355 0.866017 0.939324 0.815782 0.955298 0.781351 0.919619 0.767445 0.930389 0.756778 0.947206 0.874321 0.260529 0.87457 0.258357 0.870642 0.262514 0.870232 0.260129 0.875205 0.262091 0.87418 0.274349 0.878088 0.275377 0.879128 0.284194 0.875282 0.284248 0.876451 0.268146 0.87176 0.26763 0.879196 0.270887 0.875496 0.265391 0.893101 0.28442 0.892287 0.271326 0.879947 0.284131 0.862255 0.219399 0.877309 0.242158 0.869772 0.241647 0.855575 0.218438 0.862432 0.239621 0.84944 0.210845 0.867315 0.244511 0.849901 0.240235 0.863194 0.266321 0.876212 0.265675 0.880423 0.283451 0.866718 0.283089 0.870498 0.254293 0.863904 0.253791 0.870234 0.270504 0.864805 0.270607 0.879852 0.25405 0.878645 0.27023 0.884908 0.221559 0.894641 0.243235 0.885819 0.242521 0.87478 0.219802 0.853855 0.205189 0.868038 0.204565 0.870975 0.210424 0.856654 0.209577 0.882303 0.208527 0.885027 0.21281 0.869343 0.207181 0.855354 0.205901 0.879862 0.246326 0.872817 0.221463 0.859409 0.2185 0.885826 0.225344 0.891813 0.248223 0.886742 0.266822 0.897889 0.269881 0.890434 0.283337 0.902191 0.283202 0.887267 0.269985 0.888486 0.253806 0.897003 0.253871 0.897865 0.269734 0.890567 0.21382 0.890889 0.214313 0.887336 0.211472 0.940502 0.247339 0.935827 0.245027 0.948386 0.259727 0.952135 0.261243 0.929477 0.246937 0.935892 0.257903 0.955141 0.271935 0.951237 0.271687 0.951697 0.282445 0.956107 0.282705 0.939971 0.271031 0.941535 0.28252 0.963745 0.266939 0.955791 0.248173 0.96377 0.246708 0.971434 0.266214 0.948554 0.235961 0.955224 0.234835 0.896396 0.245174 0.886107 0.251776 0.887306 0.25714 0.901578 0.253513 0.893935 0.234459 0.893306 0.241625 0.88488 0.259333 0.895682 0.256287 0.898524 0.274248 0.887363 0.275119 0.885952 0.26722 0.897217 0.265981 0.888292 0.284017 0.899782 0.283788 0.893557 0.224473 0.903384 0.244263 0.904117 0.226402 0.909834 0.245212 0.898452 0.232315 0.90536 0.242289 0.914901 0.24109 0.908475 0.23147 0.912117 0.251402 0.92111 0.249824 0.905103 0.223634 0.894105 0.223477 0.891627 0.223783 0.892209 0.224715 0.894785 0.217728 0.904032 0.218825 0.905292 0.26092 0.916745 0.259188 0.925679 0.257542 0.919312 0.270264 0.927598 0.269904 0.909165 0.270372 0.922229 0.248254 0.923018 0.231732 0.931448 0.236491 0.927474 0.250713 0.939132 0.243721 0.931475 0.252998 0.941395 0.236759 0.941774 0.24318 0.951181 0.24757 0.953028 0.242625 0.943442 0.249961 0.949719 0.251412 0.932269 0.241398 0.935522 0.24909 0.930136 0.234395 0.929446 0.228394 0.942151 0.230847 0.942787 0.227016 0.929372 0.224433 0.954848 0.237908 0.922857 0.256527 0.927955 0.258098 0.929776 0.270263 0.925166 0.269641 0.93313 0.259066 0.935431 0.270899 0.938091 0.256867 0.945703 0.257403 0.953024 0.257866 0.948714 0.269472 0.957575 0.269677 0.940805 0.269454 0.944953 0.253898 0.950208 0.269278 0.961307 0.253711 0.957956 0.256418 0.964661 0.269455 0.96896 0.268209 0.902892 0.249987 0.897745 0.228849 0.908596 0.231834 0.912735 0.252197 0.897122 0.224227 0.89485 0.22181 0.90624 0.226903 0.908607 0.228742 0.903082 0.242361 0.906809 0.256103 0.917237 0.255133 0.919494 0.264606 0.908311 0.265315 0.907454 0.269025 0.916487 0.269043 0.911531 0.283044 0.919593 0.2829 0.909419 0.273405 0.911476 0.28336 0.920571 0.273041 0.922157 0.283218 0.922114 0.255039 0.920062 0.238863 0.921052 0.234472 0.923775 0.23538 0.929369 0.253983 0.934895 0.263753 0.927988 0.282737 0.92516 0.269608 0.937386 0.272947 0.938515 0.283177 0.906903 0.269654 0.905634 0.25451 0.912156 0.254648 0.915624 0.269303 0.934262 0.269581 0.931993 0.256855 0.928513 0.24901 0.928512 0.223212 0.917128 0.220406 0.916725 0.220767 0.9041 0.217973 0.914088 0.228391 0.916363 0.246441 0.918617 0.23227 0.923487 0.240784 0.938248 0.22777 0.892821 0.216321 0.844542 0.206031 0.874322 0.212263 0.870581 0.286403 0.864795 0.285932 0.877377 0.285736 0.887924 0.285532 0.898823 0.285311 0.908672 0.285115 0.917425 0.284957 0.921216 0.269224 0.922914 0.284906 0.926665 0.284912 0.930758 0.284928 0.936388 0.28496 0.952837 0.284936 0.967867 0.284724 0.971593 0.266723 0.976556 0.284338 0.976161 0.284497 0.973686 0.284223 0.968029 0.284169 0.960033 0.284154 0.950775 0.284138 0.942494 0.284121 0.936182 0.284123 0.929809 0.284158 0.920968 0.284223 0.910111 0.284292 0.952943 0.272204 0.950019 0.262148 0.953976 0.282879 0.900909 0.229617 0.889642 0.217102 0.912068 0.234085 0.913562 0.243735 0.925227 0.239763 0.92311 0.245509 0.916786 0.225007 0.940372 0.24984 0.963568 0.250138 0.888081 0.264217 0.918118 0.254988 0.844126 0.209259 0.844951 0.221286 0.886769 0.216308 0.872985 0.215718 0.879346 0.309871 0.875833 0.306046 0.875654 0.308144 0.879007 0.306407 0.876295 0.294136 0.878977 0.293033 0.879812 0.300399 0.876175 0.301094 0.880254 0.30345 0.882198 0.297454 0.893175 0.297687 0.865817 0.349629 0.859181 0.350621 0.872916 0.327332 0.880252 0.326495 0.865713 0.330422 0.852822 0.359205 0.869257 0.322943 0.877097 0.301439 0.864055 0.301093 0.852819 0.327816 0.866118 0.317194 0.872679 0.31623 0.865658 0.301152 0.871305 0.301562 0.879516 0.300927 0.881998 0.315802 0.888262 0.347411 0.878301 0.348969 0.888479 0.326114 0.897047 0.325511 0.857019 0.363938 0.860381 0.359999 0.874655 0.358691 0.872015 0.364197 0.888629 0.3558 0.886097 0.359632 0.872907 0.361011 0.858128 0.36229 0.881706 0.320824 0.862423 0.349295 0.875903 0.346079 0.888714 0.341972 0.893556 0.318638 0.898554 0.296744 0.887564 0.300041 0.888147 0.300674 0.898715 0.300283 0.89883 0.31539 0.89048 0.315686 0.894383 0.353795 0.894065 0.354129 0.890921 0.356254 0.942171 0.318343 0.9529 0.304272 0.949521 0.305533 0.937705 0.320863 0.937122 0.30759 0.931259 0.318903 0.955735 0.293528 0.951772 0.293299 0.940544 0.294181 0.964624 0.302435 0.972337 0.302695 0.965634 0.321964 0.957594 0.320997 0.957663 0.333351 0.950951 0.332759 0.897685 0.323309 0.904388 0.314564 0.887892 0.312338 0.888936 0.316243 0.699423 0.809253 0.710111 0.860044 0.769921 0.8588 0.767468 0.81472 0.651885 0.801109 0.669688 0.860514 0.732293 0.902975 0.706453 0.911484 0.776292 0.895678 0.708787 0.707777 0.699329 0.757062 0.768846 0.767772 0.772602 0.721954 0.664887 0.686395 0.650433 0.740512 0.747107 0.630497 0.725753 0.664868 0.777288 0.6804 0.781693 0.64616 0.725318 0.609127 0.692228 0.642648 0.80056 0.5994 0.770358 0.607692 0.782072 0.622983 0.800562 0.614675 0.800928 0.579073 0.761234 0.587309 0.833192 0.607478 0.861399 0.630223 0.8843 0.609231 0.843136 0.586725 0.8212 0.622722 0.826645 0.645961 0.901226 0.710448 0.884907 0.6659 0.835069 0.680418 0.840872 0.722297 0.945964 0.693526 0.920299 0.645594 0.905039 0.812825 0.908209 0.760544 0.842467 0.768423 0.840209 0.815454 0.952947 0.809219 0.957487 0.749588 0.876198 0.901993 0.893705 0.861459 0.836187 0.859175 0.832541 0.895317 0.904659 0.909742 0.934213 0.864462 0.810883 0.940213 0.850482 0.929308 0.832833 0.919627 0.808275 0.929049 0.815494 0.955807 0.865735 0.940277 0.767163 0.931342 0.781069 0.920572 0.878641 0.308129 0.757688 0.947696 0.89571 0.326063 0.896265 0.333541 0.887647 0.308911 0.896958 0.311973 0.898883 0.293285 0.897963 0.301935 0.887703 0.301029 0.887878 0.29293 0.905567 0.324686 0.896731 0.344468 0.906991 0.342485 0.911791 0.324251 0.900908 0.335596 0.911043 0.336295 0.917143 0.326675 0.907054 0.325968 0.923285 0.31808 0.915184 0.316034 0.908088 0.344187 0.897103 0.344536 0.894607 0.344154 0.895142 0.343144 0.898106 0.350443 0.90726 0.349181 0.907871 0.308374 0.918398 0.309598 0.927049 0.310818 0.928305 0.298442 0.920004 0.298182 0.909927 0.298243 0.924036 0.321254 0.929162 0.318872 0.933826 0.332572 0.925629 0.337191 0.941158 0.32555 0.933051 0.316658 0.943727 0.330971 0.955075 0.325269 0.952983 0.320359 0.943791 0.324629 0.951332 0.316568 0.945126 0.31796 0.937248 0.318798 0.934373 0.326359 0.932584 0.333273 0.932192 0.3393 0.932318 0.343421 0.945607 0.340893 0.944776 0.336887 0.957129 0.33006 0.924262 0.313255 0.925922 0.300164 0.930502 0.299579 0.929283 0.311724 0.936126 0.298969 0.93441 0.310774 0.939442 0.311396 0.947027 0.310849 0.954323 0.310334 0.958291 0.298597 0.94944 0.298819 0.941532 0.298832 0.946483 0.315703 0.950981 0.300512 0.962811 0.314479 0.969751 0.300159 0.965388 0.298807 0.959326 0.311738 0.904541 0.316598 0.900452 0.33816 0.911146 0.334819 0.914268 0.314088 0.900043 0.343367 0.910827 0.338483 0.909045 0.340214 0.897918 0.345703 0.907714 0.311836 0.905082 0.324826 0.918749 0.311513 0.909052 0.30192 0.920236 0.301846 0.91718 0.297035 0.908155 0.297332 0.909931 0.29344 0.92041 0.293444 0.923496 0.310879 0.922253 0.327378 0.925923 0.331262 0.923469 0.332076 0.930583 0.312153 0.934974 0.302503 0.925817 0.29614 0.93758 0.293425 0.907706 0.300101 0.916398 0.300537 0.913653 0.315103 0.907277 0.314776 0.934984 0.298714 0.933344 0.311407 0.930312 0.318902 0.931529 0.345055 0.919853 0.347075 0.920283 0.347817 0.907379 0.350402 0.918259 0.323025 0.916863 0.340467 0.921166 0.335346 0.925584 0.327014 0.941044 0.340685 0.896265 0.352186 0.847118 0.363087 0.877923 0.355511 0.921992 0.300554 0.972463 0.301867 0.950828 0.303658 0.953466 0.293583 0.892951 0.350759 0.90326 0.337983 0.915596 0.322974 0.91417 0.333036 0.927312 0.326701 0.92504 0.320904 0.919699 0.342662 0.941871 0.316003 0.965254 0.318221 0.889956 0.306147 0.919598 0.314755 0.845891 0.359181 0.847322 0.346695 0.890112 0.35133 0.87636 0.352039 0.950166 0.457401 0.877438 0.456074 0.890333 0.455013 0.891902 0.457826 0.881771 0.45805 0.893433 0.460126 0.885457 0.459788 0.90216 0.458193 0.902038 0.46051 0.902093 0.455956 0.869348 0.456995 0.875073 0.458463 0.870949 0.459563 0.865831 0.459946 0.88002 0.459819 0.876379 0.459992 0.890696 0.462723 0.889158 0.462546 0.893089 0.46287 0.842115 0.409869 0.837426 0.409453 0.838646 0.414482 0.833434 0.414204 0.847163 0.42056 0.840709 0.41957 0.839445 0.430603 0.83503 0.428579 0.852464 0.422383 0.843659 0.433436 0.835601 0.419062 0.830596 0.418889 0.831257 0.427506 0.827802 0.427141 0.876435 0.450731 0.866399 0.449489 0.869211 0.447456 0.878828 0.448367 0.861778 0.461251 0.86329 0.45579 0.869445 0.454182 0.919848 0.462088 0.9244 0.459418 0.936505 0.460001 0.932799 0.462552 0.914853 0.457033 0.912969 0.45878 0.983064 0.742705 0.970242 0.681277 0.978343 0.807461 0.961861 0.871181 0.925 0.920764 0.93957 0.629718 0.896636 0.591965 0.87816 0.953598 0.820182 0.969676 0.849136 0.56846 0.801508 0.561342 0.753635 0.961316 0.693916 0.922274 0.756457 0.570463 0.715065 0.59271 0.62759 0.729278 0.628526 0.797321 0.647916 0.672373 0.648988 0.865355 0.678001 0.627321 0.970524 0.680324 0.983346 0.741752 0.978626 0.806509 0.962143 0.870229 0.925282 0.919811 0.896919 0.591012 0.939853 0.628765 0.878442 0.952645 0.819304 0.969461 0.80179 0.560389 0.849419 0.567507 0.753465 0.960832 0.694447 0.921544 0.715348 0.591757 0.756739 0.569509 0.628808 0.796368 0.627873 0.728326 0.648199 0.671421 0.648584 0.866073 0.678283 0.626368 0.411737 0.936637 0.212659 0.665019 0.175067 0.711347 0.264355 0.628942 0.154113 0.763611 0.154483 0.81452 0.911051 0.461039 0.528987 0.594894 0.945951 0.460521 0.339791 0.607004 0.94197 0.46307 0.896594 0.462992 0.902819 0.462828 0.939147 0.46498 0.588358 0.917245 0.930869 0.464578 0.500784 0.908814 0.937502 0.466649 0.178893 0.855096 0.23388 0.878659 0.317203 0.888741 0.409219 0.897533 0.412456 0.865776 0.413517 0.832907 0.415303 0.797177 0.41903 0.758087 0.424284 0.717135 0.429773 0.675932 0.433166 0.635493 0.431719 0.596003 0.42845 0.560105 0.426262 0.535529 0.166927 0.932027 0.089131 0.90146 0.412839 0.954955 0.280654 0.94225 0.092604 0.643694 0.172265 0.583534 0.034269 0.783775 0.048602 0.713913 0.288973 0.53753 0.047197 0.849027 0.9297 0.466322 0.910929 0.462701 0.429574 0.516361 0.573602 0.514995 0.911763 0.464455 0.904647 0.46452 0.91245 0.466086 0.906026 0.466148 0.920833 0.464349 0.682918 0.980037 0.544365 0.975068 0.92089 0.466118 0.274953 0.94136 0.412382 0.948959 0.078614 0.893197 0.159929 0.926191 0.045546 0.712112 0.029763 0.775258 0.174568 0.589926 0.093871 0.647648 0.286715 0.542233 0.039682 0.837587 0.568016 0.514851 0.425296 0.517534 0.89967 0.464526 0.715649 0.536695 0.89649 0.46445 0.90127 0.466162 0.89793 0.466107 0.92457 0.397524 0.934172 0.397517 0.90196 0.397532 0.543555 0.96576 0.912366 0.397543 0.914428 0.398827 0.902477 0.39881 0.887934 0.397535 0.886084 0.398748 0.939158 0.397548 0.916553 0.401268 0.903345 0.401161 0.918892 0.404595 0.904419 0.40426 0.88377 0.401252 0.880927 0.404722 0.905294 0.428912 0.905488 0.424961 0.912357 0.424967 0.91334 0.429138 0.905906 0.421495 0.911087 0.422154 0.904076 0.437412 0.90478 0.43319 0.913199 0.433998 0.911884 0.43877 0.90321 0.444063 0.903361 0.441071 0.909872 0.442542 0.908067 0.444769 0.902496 0.453271 0.918142 0.453706 0.928783 0.450398 0.93573 0.445715 0.939896 0.439756 0.941415 0.433124 0.940295 0.426582 0.937084 0.420446 0.931618 0.414911 0.921769 0.409549 0.905101 0.407893 0.876573 0.40992 0.866307 0.415598 0.859425 0.421874 0.854503 0.429219 0.846009 0.439206 0.853866 0.435555 0.855666 0.44134 0.849189 0.44441 0.859693 0.44628 0.853635 0.449316 0.859396 0.453185 0.889827 0.45174 0.862926 0.421743 0.859205 0.428005 0.869662 0.416377 0.857993 0.434235 0.859086 0.440054 0.916008 0.412068 0.903601 0.410265 0.918257 0.418305 0.91053 0.415402 0.913091 0.413541 0.921836 0.416936 0.92534 0.416062 0.879532 0.412275 0.931494 0.42114 0.923547 0.422692 0.927682 0.421785 0.926515 0.428111 0.931209 0.427509 0.93512 0.42705 0.936295 0.433481 0.92732 0.434037 0.932331 0.433786 0.925669 0.439922 0.930432 0.440034 0.934525 0.439972 0.912845 0.451737 0.922595 0.449614 0.907361 0.448978 0.915126 0.447877 0.918684 0.448912 0.909842 0.450414 0.901128 0.451294 0.929882 0.445604 0.921412 0.444811 0.925747 0.445329 0.862632 0.44473 0.90791 0.418325 0.914417 0.420366 0.918293 0.424021 0.92059 0.42877 0.920879 0.434155 0.919487 0.439514 0.911345 0.446349 0.90499 0.446728 0.916084 0.443813 0.891421 0.410387 0.891335 0.407994 0.8923 0.404278 0.892667 0.401108 0.892803 0.398753 0.893101 0.397518 0.953337 0.401538 0.958091 0.405199 0.9475 0.399036 0.96186 0.409791 0.964499 0.415028 0.96612 0.420717 0.967305 0.426924 0.967388 0.433074 0.966427 0.438883 0.96451 0.444202 0.961861 0.44894 0.958944 0.453645 0.955428 0.457592 0.951844 0.460785 0.948132 0.463506 0.945008 0.465414 0.9428 0.466896 0.940897 0.39766 0.894646 0.464377 0.893748 0.464327 0.895819 0.465909 0.894732 0.465707 0.898046 0.468336 0.895591 0.467749 0.894211 0.467377 0.894053 0.470321 0.892528 0.469525 0.89702 0.472125 0.906461 0.46806 0.901761 0.468217 0.901883 0.471147 0.906501 0.470456 0.912592 0.467918 0.912253 0.470089 0.920682 0.467923 0.920674 0.470154 0.9293 0.468129 0.929876 0.470181 0.93702 0.468441 0.938213 0.470896 0.942275 0.468514 0.942757 0.470744 0.890006 0.4495 0.852976 0.399065 0.859393 0.397599 0.847065 0.401675 0.84127 0.405026 0.953466 0.401386 0.958188 0.405089 0.947588 0.398916 0.961862 0.409747 0.964391 0.415022 0.965926 0.420729 0.967068 0.426923 0.967242 0.433135 0.966314 0.439008 0.964406 0.444378 0.961584 0.44912 0.958267 0.453722 0.954279 0.457569 0.865611 0.460368 0.870463 0.459645 0.869977 0.459728 0.865391 0.460791 0.875883 0.460032 0.875386 0.460071 0.889107 0.462568 0.889055 0.46259 0.836433 0.409343 0.829542 0.419704 0.832578 0.41403 0.832317 0.414141 0.82924 0.419624 0.86181 0.461905 0.861843 0.46256 0.95053 0.46075 0.946775 0.4634 0.943577 0.465237 0.941527 0.466697 0.893773 0.464335 0.893798 0.464342 0.894526 0.465626 0.894385 0.465571 0.940912 0.397604 0.893807 0.467247 0.893563 0.467166 0.891985 0.469369 0.891535 0.469419 0.940364 0.468392 0.940762 0.470517 0.866236 0.398834 0.873711 0.398813 0.877506 0.397514 0.870971 0.397493 0.865522 0.397455 0.860032 0.398872 0.856026 0.399014 0.861954 0.397568 0.860159 0.397664 0.853853 0.399094 0.935431 0.404681 0.948546 0.405179 0.944496 0.401457 0.931632 0.401375 0.939488 0.398861 0.927974 0.398901 0.870657 0.401504 0.861966 0.401526 0.855096 0.4016 0.850751 0.405417 0.858121 0.405363 0.867731 0.405188 0.850561 0.401575 0.848094 0.401586 0.842791 0.404957 0.845766 0.405198 0.9455 0.398818 0.951158 0.401375 0.955535 0.405156 0.94295 0.41441 0.9536 0.414936 0.951437 0.40979 0.938847 0.409148 0.863906 0.410047 0.854469 0.410101 0.8468 0.410021 0.843291 0.414792 0.850618 0.415218 0.858112 0.415702 0.958875 0.409842 0.961147 0.415077 0.9551 0.420509 0.945887 0.42022 0.947818 0.426423 0.955942 0.426574 0.962495 0.420748 0.963347 0.426902 0.947179 0.438896 0.955415 0.438781 0.95627 0.432802 0.948355 0.432791 0.963455 0.433109 0.96255 0.43901 0.93973 0.449457 0.950281 0.449152 0.953464 0.44429 0.944309 0.444589 0.960647 0.444424 0.957836 0.449233 0.928866 0.456683 0.941589 0.457208 0.946319 0.453375 0.933669 0.453285 0.954103 0.453514 0.949874 0.457416 0.877353 0.455968 0.882269 0.458025 0.892317 0.457757 0.890577 0.455047 0.886684 0.460112 0.89423 0.460211 0.902677 0.460467 0.90267 0.458019 0.902808 0.455334 0.869597 0.456984 0.865825 0.458435 0.871446 0.458982 0.8752 0.458466 0.877063 0.46 0.880928 0.46006 0.889224 0.462652 0.890358 0.462714 0.892541 0.462593 0.841603 0.409572 0.838159 0.409243 0.834209 0.413908 0.837981 0.414182 0.839885 0.419736 0.846514 0.420792 0.834481 0.428371 0.838869 0.430451 0.84343 0.433385 0.852102 0.422532 0.830666 0.418987 0.834732 0.419195 0.827717 0.426976 0.830662 0.427303 0.875777 0.450429 0.878346 0.448288 0.868619 0.446935 0.865577 0.448677 0.860982 0.459109 0.863516 0.455972 0.868771 0.453598 0.919955 0.462087 0.933215 0.46265 0.936971 0.460171 0.92452 0.45941 0.915797 0.455832 0.913434 0.458571 0.911682 0.460937 0.945768 0.460575 0.941689 0.463136 0.897291 0.462545 0.903757 0.462585 0.930828 0.464538 0.938505 0.464915 0.929084 0.466249 0.936418 0.466469 0.911714 0.462545 0.904992 0.464496 0.91226 0.464434 0.906001 0.466171 0.912549 0.466198 0.920438 0.466178 0.920682 0.464371 0.899694 0.464496 0.896238 0.464476 0.897673 0.46607 0.901142 0.46612 0.933851 0.397545 0.924135 0.397565 0.901567 0.397461 0.902111 0.398787 0.913998 0.398826 0.911927 0.397463 0.885568 0.398789 0.887707 0.397486 0.939027 0.397536 0.902897 0.401138 0.916139 0.401275 0.904075 0.404332 0.918631 0.404656 0.883077 0.401373 0.880245 0.404983 0.905419 0.428922 0.912942 0.429219 0.912006 0.425106 0.905474 0.425025 0.910791 0.422281 0.905844 0.421559 0.904305 0.436885 0.911907 0.438227 0.913047 0.433844 0.905052 0.432984 0.903203 0.443238 0.908124 0.443775 0.909903 0.441649 0.903445 0.440313 0.90285 0.452456 0.918742 0.45246 0.929033 0.449192 0.935553 0.444785 0.939489 0.439171 0.940895 0.433027 0.939916 0.426757 0.936762 0.420698 0.931211 0.415109 0.90461 0.407951 0.921344 0.40965 0.876099 0.410269 0.865754 0.416146 0.858856 0.422274 0.85408 0.42925 0.845714 0.439016 0.8487 0.443676 0.855252 0.440105 0.853622 0.434905 0.852614 0.447663 0.858958 0.44511 0.858176 0.451853 0.889824 0.45148 0.858947 0.427844 0.863033 0.422095 0.869857 0.416948 0.858451 0.439034 0.857612 0.433475 0.903128 0.410252 0.915613 0.4122 0.910336 0.415321 0.91773 0.418674 0.921258 0.417307 0.91279 0.413538 0.924944 0.416332 0.879341 0.412694 0.930972 0.4215 0.922517 0.423241 0.926792 0.422268 0.92506 0.428584 0.929895 0.42793 0.93442 0.427304 0.935453 0.433435 0.925801 0.434263 0.930838 0.433902 0.924243 0.439743 0.929152 0.439726 0.933786 0.439455 0.922618 0.448568 0.913071 0.450609 0.91472 0.447235 0.9073 0.44856 0.909883 0.449686 0.918464 0.448158 0.90106 0.450464 0.929479 0.444749 0.920523 0.44435 0.924927 0.444695 0.861743 0.443993 0.907779 0.418347 0.914012 0.420577 0.917709 0.42432 0.919641 0.429082 0.919962 0.434273 0.918588 0.43924 0.904848 0.446138 0.911088 0.445577 0.915514 0.4432 0.890897 0.408138 0.891059 0.410492 0.89188 0.404459 0.892481 0.401195 0.892744 0.398811 0.892774 0.397499 0.852987 0.39915 0.859402 0.397672 0.847027 0.401638 0.84144 0.40503 0.836758 0.409301 0.826856 0.427241 0.893304 0.464316 0.894343 0.465793 0.894093 0.464377 0.895401 0.465971 0.893628 0.467665 0.890751 0.471053 0.897653 0.467915 0.895086 0.467874 0.893376 0.47055 0.896513 0.470318 0.906138 0.467954 0.901291 0.467913 0.900442 0.470186 0.905385 0.470181 0.912382 0.468058 0.911527 0.470316 0.918635 0.470453 0.91977 0.468076 0.926488 0.470872 0.927835 0.468189 0.935282 0.468257 0.935209 0.471328 0.877915 0.500707 0.878197 0.500625 0.878935 0.505269 0.878376 0.50543 0.87849 0.500327 0.879515 0.504678 0.878776 0.499827 0.880077 0.503685 0.879041 0.499148 0.880596 0.502336 0.879273 0.498323 0.88105 0.500691 0.879461 0.49739 0.881414 0.498833 0.879595 0.496393 0.881685 0.496848 0.879673 0.495381 0.881831 0.494834 0.879688 0.4944 0.881855 0.492886 0.879641 0.493495 0.881754 0.491093 0.879517 0.492692 0.881496 0.489502 0.879256 0.49199 0.880966 0.488128 0.878724 0.491679 0.879976 0.487255 0.880441 0.487544 0.878985 0.491764 0.880259 0.509816 0.879427 0.510054 0.881118 0.508941 0.881951 0.507469 0.882719 0.50547 0.883385 0.503037 0.883918 0.500283 0.884295 0.497337 0.884501 0.494341 0.884524 0.491438 0.884373 0.488781 0.883999 0.486461 0.88321 0.484429 0.882394 0.483424 0.882124 0.514208 0.881033 0.51452 0.883251 0.513061 0.884343 0.511133 0.885349 0.508513 0.886222 0.505324 0.886921 0.501715 0.887414 0.497854 0.887677 0.493924 0.887702 0.490113 0.887496 0.486645 0.88698 0.48361 0.885938 0.48091 0.884878 0.479558 0.884506 0.51838 0.88317 0.518762 0.885883 0.516979 0.887217 0.514621 0.888447 0.511419 0.889514 0.507521 0.890369 0.503109 0.890971 0.49839 0.891293 0.493586 0.89132 0.488919 0.891054 0.484665 0.890395 0.481066 0.88919 0.477958 0.887817 0.476052 0.887367 0.522273 0.885807 0.522719 0.888975 0.520637 0.890533 0.517885 0.891968 0.514147 0.893214 0.509596 0.894212 0.504446 0.894915 0.498938 0.895291 0.493329 0.895322 0.487882 0.895 0.482915 0.894205 0.478779 0.892842 0.475169 0.891068 0.473073 0.890668 0.525829 0.888906 0.526332 0.892483 0.523982 0.894241 0.520876 0.895861 0.516656 0.897267 0.51152 0.898394 0.505707 0.899187 0.499489 0.899612 0.493158 0.899646 0.487009 0.899286 0.481354 0.898411 0.476638 0.894359 0.528996 0.892421 0.529549 0.896354 0.526965 0.898288 0.52355 0.900069 0.518911 0.901615 0.513263 0.902854 0.506872 0.903726 0.500036 0.904193 0.493075 0.904231 0.486314 0.903834 0.4801 0.902975 0.47504 0.898388 0.531728 0.896302 0.532323 0.900534 0.529543 0.902614 0.525869 0.904531 0.520877 0.906194 0.514801 0.907527 0.507925 0.908466 0.50057 0.908967 0.493081 0.909009 0.485806 0.908572 0.479151 0.907654 0.473824 0.902694 0.533986 0.900491 0.534614 0.90496 0.531679 0.907157 0.527799 0.909181 0.522528 0.910937 0.516111 0.912345 0.50885 0.913336 0.501084 0.913866 0.493175 0.913909 0.485494 0.91346 0.478418 0.912585 0.472851 0.907215 0.535736 0.904927 0.536388 0.909569 0.53334 0.91185 0.529311 0.913952 0.523838 0.915776 0.517175 0.917237 0.509635 0.918266 0.50157 0.918854 0.493342 0.918947 0.485357 0.91844 0.478006 0.91787 0.471971 0.914263 0.537286 0.911914 0.537955 0.916678 0.534827 0.919019 0.530693 0.921175 0.525076 0.923047 0.518239 0.924546 0.510502 0.925585 0.502224 0.926227 0.493754 0.926493 0.485583 0.925762 0.478045 0.924764 0.471485 0.921403 0.537724 0.919062 0.538392 0.92381 0.535275 0.926142 0.531156 0.930338 0.525761 0.93162 0.519674 0.933283 0.512932 0.932692 0.502839 0.933977 0.494768 0.934333 0.486371 0.933206 0.478784 0.931863 0.472204 0.92611 0.537268 0.92382 0.53792 0.928464 0.534872 0.932388 0.530343 0.937335 0.506755 0.941235 0.498334 0.941521 0.487989 0.940371 0.480184 0.938481 0.473907 0.930691 0.536256 0.928485 0.536884 0.934789 0.533043 0.935078 0.534703 0.932989 0.535298 0.938368 0.532576 0.947164 0.489068 0.947066 0.497764 0.946239 0.481893 0.944283 0.476284 0.939209 0.532632 0.937267 0.533185 0.941919 0.530982 0.950689 0.490156 0.950271 0.497772 0.95034 0.48345 0.948203 0.478162 0.943023 0.530074 0.941256 0.530577 0.945589 0.528338 0.95349 0.491089 0.952472 0.498024 0.953154 0.485389 0.951415 0.480527 0.946464 0.527065 0.944898 0.52751 0.948879 0.525086 0.955336 0.498108 0.955494 0.49227 0.955142 0.488211 0.954263 0.484425 0.949389 0.475505 0.954052 0.482326 0.94757 0.475109 0.945693 0.473082 0.943613 0.471998 0.950577 0.521636 0.949187 0.522238 0.951775 0.520708 0.950886 0.519379 0.952605 0.518141 0.95447 0.515316 0.952742 0.516616 0.878125 0.495997 0.943537 0.514246 0.944979 0.511457 0.945299 0.511731 0.944004 0.514141 0.946866 0.510467 0.945612 0.512005 0.946775 0.509925 0.944125 0.524447 0.943125 0.523168 0.943363 0.52176 0.944265 0.522893 0.943213 0.51865 0.9436 0.520352 0.942839 0.519741 0.942465 0.520831 0.942508 0.517563 0.943036 0.516979 0.944472 0.514036 0.943564 0.516394 0.946664 0.509365 0.948503 0.507957 0.948316 0.508687 0.949207 0.508705 0.948096 0.509397 0.949608 0.50791 0.950009 0.507096 0.951195 0.506751 0.950679 0.507606 0.951005 0.508659 0.950161 0.508443 0.951647 0.507843 0.952323 0.510866 0.951744 0.509448 0.952587 0.5089 0.953318 0.510638 0.952296 0.507042 0.953444 0.508317 0.954198 0.510416 0.954069 0.512878 0.953344 0.512779 0.95222 0.51488 0.952538 0.512757 0.952777 0.515115 0.953314 0.515413 0.952001 0.51802 0.951641 0.517475 0.949848 0.518868 0.951263 0.516984 0.950071 0.519673 0.950291 0.520481 0.948367 0.522605 0.94826 0.52146 0.946642 0.521256 0.948152 0.520315 0.946704 0.522693 0.946766 0.524131 0.94537 0.524785 0.945389 0.52319 0.944404 0.521338 0.945409 0.521595 0.948517 0.508521 0.947425 0.509189 0.946164 0.510225 0.943731 0.513771 0.942852 0.515989 0.942484 0.51808 0.944874 0.511783 0.950283 0.508511 0.949456 0.508269 0.942699 0.51973 0.943487 0.520694 0.951552 0.510694 0.95099 0.509314 0.944633 0.521012 0.946034 0.520645 0.951461 0.514432 0.951791 0.512457 0.947604 0.519694 0.949207 0.518265 0.95053 0.516413 0.954352 0.507334 0.955064 0.51004 0.953029 0.50566 0.954691 0.513093 0.953563 0.516187 0.942931 0.511155 0.945738 0.50837 0.941124 0.514785 0.948237 0.525023 0.946042 0.527051 0.950358 0.522206 0.940778 0.525984 0.939919 0.523165 0.942236 0.527579 0.940031 0.519157 0.94836 0.506655 0.95038 0.505668 0.951792 0.505283 0.952106 0.519194 0.94408 0.527997 0.955136 0.505085 0.955458 0.508799 0.953996 0.503048 0.954947 0.51289 0.953571 0.516724 0.940392 0.509704 0.943959 0.505926 0.937487 0.514053 0.946965 0.527152 0.943743 0.529685 0.949863 0.52392 0.936263 0.528363 0.934831 0.524989 0.938515 0.530358 0.93544 0.520327 0.947235 0.504116 0.949823 0.503295 0.952034 0.502955 0.951882 0.52041 0.941028 0.53079 0.956255 0.501869 0.956376 0.507194 0.955436 0.512282 0.95378 0.516679 0.954272 0.512902 0.953969 0.514386 0.955477 0.513065 0.955509 0.511632 0.956562 0.510151 0.957541 0.50583 0.957528 0.506237 0.957401 0.500104 0.957323 0.498901 0.956684 0.496896 0.956413 0.492938 0.956425 0.492794 0.955922 0.48933 0.955605 0.489791 0.952251 0.480529 0.95403 0.483685 0.955302 0.484788 0.955335 0.486204 0.955539 0.486154 0.954877 0.485325 0.956687 0.508947 0.956754 0.495687 0.955045 0.487387 0.877848 0.505182 0.877652 0.500582 0.87737 0.504506 0.877412 0.500243 0.876974 0.503437 0.877218 0.499703 0.87668 0.502023 0.877063 0.498994 0.876501 0.50033 0.876979 0.498142 0.876446 0.498438 0.87696 0.497191 0.876522 0.496436 0.877006 0.496186 0.876728 0.49442 0.877115 0.495174 0.877054 0.492488 0.877281 0.494204 0.877479 0.49073 0.877498 0.49332 0.877999 0.489197 0.877767 0.492546 0.878719 0.487808 0.878144 0.491879 0.879235 0.487423 0.878402 0.491725 0.878643 0.509686 0.877934 0.508686 0.877348 0.507101 0.876912 0.505005 0.876647 0.502497 0.876565 0.499694 0.876669 0.496727 0.876956 0.493734 0.877416 0.490859 0.878045 0.488251 0.878803 0.485988 0.879891 0.48389 0.880652 0.483253 0.880004 0.514038 0.879075 0.512727 0.878307 0.510649 0.877736 0.507903 0.877388 0.504616 0.87728 0.500942 0.877417 0.497054 0.877793 0.493132 0.878389 0.48936 0.879214 0.485947 0.880199 0.482989 0.881623 0.480314 0.882641 0.479405 0.881911 0.518172 0.880775 0.516569 0.879836 0.51403 0.879138 0.510673 0.878713 0.506655 0.878582 0.502165 0.878749 0.497412 0.879208 0.492618 0.879955 0.488021 0.881001 0.483899 0.88231 0.480367 0.883909 0.47731 0.885135 0.475926 0.884336 0.52203 0.883011 0.520159 0.881915 0.517195 0.8811 0.513276 0.880604 0.508586 0.88045 0.503344 0.880646 0.497795 0.881181 0.492199 0.882059 0.48684 0.883257 0.482017 0.884772 0.477872 0.886828 0.474331 0.888116 0.472377 0.887245 0.525554 0.885749 0.523442 0.884512 0.520096 0.883592 0.515673 0.883032 0.510379 0.882858 0.504462 0.883079 0.498199 0.883683 0.491882 0.884656 0.485819 0.885976 0.480334 0.887771 0.475644 0.888962 0.472096 0.890594 0.528694 0.888949 0.526372 0.887589 0.522693 0.886578 0.51783 0.885962 0.512009 0.885771 0.505504 0.886014 0.498617 0.886678 0.491672 0.887734 0.484992 0.889161 0.478945 0.891005 0.474124 0.894335 0.531403 0.892565 0.528905 0.891102 0.524947 0.890014 0.519714 0.889351 0.513452 0.889146 0.506453 0.889407 0.499043 0.890122 0.491571 0.891258 0.484384 0.892815 0.477978 0.894695 0.473363 0.898413 0.533643 0.896544 0.531004 0.894999 0.526825 0.89385 0.5213 0.893151 0.514687 0.892934 0.507295 0.893209 0.499472 0.893965 0.491581 0.895164 0.483992 0.89686 0.477387 0.898865 0.473076 0.902769 0.53538 0.900829 0.53264 0.899224 0.5283 0.898031 0.522562 0.897305 0.515695 0.897079 0.50802 0.897366 0.499895 0.89815 0.491701 0.899396 0.483821 0.901449 0.477074 0.903819 0.472976 0.909699 0.53692 0.907707 0.534109 0.906061 0.529655 0.904836 0.523767 0.904091 0.516721 0.90386 0.508844 0.904153 0.500507 0.904958 0.492099 0.906237 0.484012 0.908008 0.477129 0.910034 0.473198 0.916854 0.53736 0.91487 0.534559 0.91323 0.530122 0.914164 0.524465 0.913164 0.518196 0.913437 0.51134 0.91133 0.50108 0.912131 0.492703 0.913405 0.484646 0.91513 0.47783 0.916994 0.473623 0.92166 0.536911 0.919719 0.534172 0.91917 0.529284 0.917172 0.505296 0.919838 0.496406 0.920904 0.486229 0.92238 0.479225 0.924263 0.474614 0.926405 0.535913 0.924828 0.532245 0.931019 0.534378 0.929686 0.53188 0.92797 0.487724 0.927599 0.495894 0.929366 0.480734 0.931925 0.475167 0.935435 0.53233 0.934387 0.530379 0.933232 0.488977 0.932764 0.496065 0.934736 0.482159 0.937602 0.476887 0.93959 0.529799 0.938848 0.527798 0.937731 0.490249 0.936964 0.496523 0.939215 0.484123 0.942421 0.479379 0.943421 0.526821 0.942722 0.524593 0.94207 0.497013 0.942329 0.491435 0.943599 0.487511 0.946933 0.482758 0.949756 0.480976 0.945342 0.476815 0.940652 0.473783 0.947564 0.521395 0.9466 0.520277 0.951324 0.514898 0.949518 0.517928 0.928377 0.510114 0.926885 0.51291 0.927854 0.512845 0.929178 0.51043 0.92998 0.510746 0.931406 0.509225 0.930823 0.508639 0.92835 0.521984 0.930534 0.523359 0.930891 0.521821 0.928964 0.520607 0.929579 0.519229 0.928441 0.517467 0.927597 0.51852 0.926179 0.516255 0.926753 0.519573 0.927195 0.51571 0.928211 0.515165 0.928823 0.512781 0.932374 0.506682 0.930239 0.508053 0.932657 0.507439 0.93294 0.508196 0.934517 0.507536 0.93451 0.506707 0.936567 0.505592 0.934502 0.505878 0.936317 0.506456 0.936067 0.50732 0.937546 0.507578 0.93807 0.506748 0.938901 0.508422 0.940036 0.50988 0.941088 0.509726 0.939772 0.507879 0.940713 0.507314 0.938594 0.505926 0.942911 0.511998 0.942269 0.509491 0.941755 0.511888 0.940774 0.511818 0.940867 0.513981 0.941724 0.514237 0.941696 0.517149 0.942674 0.514592 0.940898 0.516619 0.940099 0.51609 0.938667 0.517973 0.939267 0.518807 0.937547 0.521739 0.939868 0.519641 0.937153 0.52057 0.936759 0.519402 0.934851 0.520311 0.935057 0.52176 0.932933 0.523788 0.935263 0.523209 0.932985 0.522196 0.933038 0.520604 0.931248 0.520284 0.932573 0.508007 0.934161 0.507367 0.930964 0.509008 0.927841 0.514787 0.928411 0.512543 0.928106 0.516928 0.929515 0.510546 0.935671 0.507169 0.937081 0.507438 0.929093 0.51864 0.93071 0.519671 0.938351 0.508298 0.9394 0.509723 0.932552 0.520045 0.934434 0.519715 0.940079 0.511519 0.940113 0.513519 0.936336 0.518792 0.938116 0.517377 0.939405 0.515521 0.943638 0.508965 0.941943 0.506311 0.939071 0.504531 0.94388 0.51543 0.944335 0.512165 0.927944 0.506963 0.925069 0.509715 0.923231 0.513349 0.935271 0.526189 0.938229 0.524222 0.940839 0.521447 0.923484 0.521848 0.925731 0.524779 0.928789 0.526502 0.922597 0.517761 0.93396 0.504385 0.931029 0.505302 0.936534 0.504088 0.942769 0.518413 0.932116 0.527039 0.945351 0.507568 0.943089 0.503744 0.939896 0.502018 0.945354 0.516015 0.946118 0.511811 0.925289 0.504712 0.920962 0.50815 0.918385 0.51252 0.934537 0.528948 0.938552 0.526478 0.941809 0.523283 0.918305 0.523665 0.921702 0.527196 0.925959 0.529352 0.917212 0.518867 0.933078 0.501722 0.929349 0.502508 0.936447 0.501609 0.943896 0.519878 0.930309 0.529931 0.948005 0.505607 0.944871 0.499392 0.947806 0.516062 0.9491 0.511191 0.953215 0.511264 0.952698 0.512701 0.951135 0.50884 0.950868 0.504414 0.946032 0.497811 0.946155 0.49879 0.9504 0.504692 0.944108 0.496015 0.944681 0.492183 0.945966 0.489086 0.945497 0.488606 0.944291 0.491984 0.951345 0.48426 0.948386 0.485293 0.952907 0.485943 0.952013 0.507755 0.944606 0.494766 0.94856 0.486751 0.889967 0.448966 0.879572 0.4873 0.878531 0.491695 0.881189 0.483034 0.883359 0.479059 0.88597 0.475436 0.826451 0.427416 0.889758 0.472115 0.881748 0.482959 0.884054 0.478968 0.886811 0.475429 0.942835 0.472365 0.877975 0.397658 0.883515 0.397651 0.873951 0.397664 0.870831 0.397671 0.867889 0.397674 0.918562 0.397639 0.925482 0.397634 0.901603 0.397646 0.909465 0.397642 0.891034 0.397645 0.929288 0.397637 0.894812 0.397645 0.931273 0.397662 0.86549 0.397668 0.931235 0.397655 0.882529 0.39765 0.877003 0.397658 0.871595 0.397671 0.868659 0.397671 0.868707 0.397667 0.925845 0.397644 0.918784 0.397657 0.909614 0.397666 0.901249 0.39767 0.890498 0.397656 0.92961 0.397643 0.894099 0.397656 0.867711 0.397671 0.900103 0.397679 0.595916 0.679782 0.593633 0.724091 0.587548 0.772055 0.579229 0.819401 0.570764 0.860428 0.56898 0.893979 0.055194 0.327681 0.056512 0.244825 0.056323 0.176259 0.056343 0.11532 0.057144 0.041836 0.468306 0.320445 0.459246 0.232082 0.470583 0.402538 0.456894 0.171519 0.044392 0.51728 0.04804 0.442488 0.039555 0.560029 0.472222 0.467543 0.655545 0.572596 0.685594 0.967391 0.590033 0.92387 0.595756 0.680499 0.590769 0.76975 0.682275 0.551691 0.647404 0.965201 0.571758 0.851938 0.600135 0.64164 0.623018 0.605621 0.617347 0.944413 0.720327 0.535205 + + + + + + + + + + + + + + + 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 4 4 4 5 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 4 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 4 4 4 5 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 4 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 +

89 0 23 243 1 26 90 2 28 6 3 29 91 4 30 243 1 26 89 0 23 5 5 31 92 6 33 244 7 35 91 4 30 5 5 31 299 8 36 244 7 35 92 6 33 218 9 37 7 10 39 95 11 41 93 12 42 8 13 57 93 12 42 95 11 41 94 14 61 9 15 62 96 16 65 245 17 66 89 0 23 6 3 29 89 0 23 245 17 66 97 18 67 5 5 31 97 18 67 245 17 66 98 19 68 11 20 69 98 19 68 245 17 66 96 16 65 10 21 70 97 18 67 246 22 71 92 6 33 5 5 31 92 6 33 246 22 71 300 23 72 218 9 37 300 23 72 246 22 71 99 24 84 219 25 85 99 24 84 246 22 71 97 18 67 11 20 69 12 26 86 247 27 89 93 12 42 9 15 62 93 12 42 247 27 89 100 28 90 8 13 57 13 29 135 102 30 137 101 31 138 14 32 139 101 31 138 102 30 137 7 10 39 8 13 57 103 33 140 248 34 141 98 19 68 10 21 70 98 19 68 248 34 141 104 35 142 11 20 69 104 35 142 248 34 141 105 36 200 16 37 246 105 36 200 248 34 141 103 33 140 15 38 249 100 28 90 107 39 252 101 31 138 8 13 57 101 31 138 107 39 252 106 40 253 14 32 139 108 41 254 109 42 256 13 29 135 14 32 139 18 43 259 109 42 256 108 41 254 17 44 260 106 40 253 111 45 262 108 41 254 14 32 139 108 41 254 111 45 262 110 46 265 17 44 260 20 47 266 112 48 283 113 49 285 19 50 286 113 49 285 112 48 283 18 43 259 17 44 260 110 46 265 115 51 289 113 49 285 17 44 260 113 49 285 115 51 289 114 52 290 19 50 286 22 53 291 116 54 292 117 55 293 21 56 294 117 55 293 116 54 292 20 47 266 19 50 286 114 52 290 119 57 295 117 55 293 19 50 286 117 55 293 119 57 295 118 58 296 21 56 294 23 59 297 249 60 298 120 61 300 24 62 303 120 61 300 249 60 298 22 53 291 21 56 294 118 58 296 122 63 304 120 61 300 21 56 294 120 61 300 122 63 304 121 64 884 24 62 303 26 65 885 339 66 886 340 67 887 123 68 888 123 68 888 340 67 887 341 69 889 28 70 890 341 69 889 340 67 887 124 71 891 27 72 892 124 71 891 340 67 887 339 66 886 25 73 893 125 74 894 250 75 895 307 76 896 29 77 897 307 76 896 250 75 895 126 78 898 227 79 899 126 78 898 250 75 895 123 68 888 28 70 890 123 68 888 250 75 895 125 74 894 26 65 885 126 78 898 127 80 900 45 81 901 227 79 899 126 78 898 28 70 890 30 82 902 127 80 900 128 83 0 251 84 1 308 85 2 31 86 3 308 85 74 251 84 75 129 87 76 228 88 77 129 87 76 251 84 75 130 89 78 33 90 79 130 89 4 251 84 1 128 83 0 32 91 12 131 92 13 252 93 14 309 94 15 34 95 16 309 94 15 252 93 14 128 83 0 31 86 3 128 83 0 252 93 14 132 96 17 32 91 12 132 96 17 252 93 14 131 92 13 35 97 18 133 98 82 253 99 83 132 96 17 35 97 18 132 96 17 253 99 83 134 100 91 32 91 12 134 100 91 253 99 83 156 101 92 36 102 93 156 101 92 253 99 83 133 98 82 38 103 94 135 104 96 254 105 97 136 106 98 39 107 101 136 106 98 254 105 97 137 108 102 37 109 105 137 108 102 254 105 97 133 98 82 35 97 18 133 98 82 254 105 97 135 104 96 38 103 94 104 35 142 255 110 903 99 24 84 11 20 69 99 24 84 255 110 903 310 111 904 219 25 85 310 111 904 255 110 903 138 112 905 1978 113 906 138 112 905 255 110 903 104 35 142 16 37 246 204 114 5 285 115 6 139 116 7 59 117 8 139 116 7 285 115 6 203 118 9 57 119 10 105 36 200 256 120 907 140 121 908 16 37 246 140 121 908 256 120 907 135 104 909 39 107 910 135 104 909 256 120 907 141 122 911 38 103 912 141 122 911 256 120 907 105 36 200 15 38 249 138 112 905 257 123 913 142 124 914 1978 113 906 142 124 914 257 123 913 154 125 915 229 126 916 154 125 915 257 123 913 140 121 908 39 107 910 140 121 908 257 123 913 138 112 905 16 37 246 143 127 11 284 128 19 202 129 20 60 130 21 203 118 9 284 128 19 143 127 11 57 119 10 144 131 917 56 132 918 2065 133 919 2066 134 920 311 135 921 258 136 922 125 74 894 29 77 897 125 74 894 258 136 922 145 137 923 26 65 885 145 137 80 258 136 81 146 138 95 40 139 99 146 138 95 258 136 81 311 135 100 41 140 103 43 141 924 147 142 925 148 143 926 42 144 927 148 143 926 147 142 925 23 59 297 24 62 303 149 145 928 259 146 929 124 71 891 25 73 893 124 71 891 259 146 929 150 147 976 27 72 892 150 147 976 259 146 929 147 142 925 43 141 924 147 142 925 259 146 929 149 145 928 23 59 297 121 64 884 152 148 978 148 143 926 24 62 303 148 143 926 152 148 978 151 149 980 42 144 927 231 150 981 30 82 902 28 70 890 341 69 889 231 150 981 341 69 889 27 72 892 44 151 982 153 152 104 260 153 106 129 87 76 33 90 79 129 87 76 260 153 106 312 154 107 228 88 77 312 154 107 260 153 106 146 138 95 41 140 103 146 138 95 260 153 106 153 152 104 40 139 99 154 125 110 261 155 111 313 156 112 229 126 113 313 156 112 261 155 111 155 157 114 230 158 115 155 157 114 261 155 111 136 106 98 37 109 105 136 106 98 261 155 111 154 125 110 39 107 101 153 152 104 262 159 108 181 160 109 40 139 99 181 160 116 262 159 117 134 100 91 36 102 93 134 100 91 262 159 117 130 89 4 32 91 12 130 89 78 262 159 108 153 152 104 33 90 79 137 108 102 263 161 118 155 157 114 37 109 105 155 157 114 263 161 118 314 162 119 230 158 115 314 162 119 263 161 118 131 92 13 34 95 16 131 92 13 263 161 118 137 108 102 35 97 18 151 149 980 241 163 983 157 164 985 42 144 927 157 164 985 241 163 983 242 165 987 83 166 1012 159 167 1013 264 168 1016 160 169 1017 44 151 982 160 169 1017 264 168 1016 239 170 1018 81 171 1019 239 170 1018 264 168 1016 238 172 1020 82 173 1023 238 172 1020 264 168 1016 159 167 1013 43 141 924 82 173 1023 238 172 1020 157 164 985 83 166 1012 157 164 985 238 172 1020 43 141 924 42 144 927 160 169 1017 265 174 1036 231 150 981 44 151 982 231 150 981 265 174 1036 232 175 1038 30 82 902 232 175 1038 265 174 1036 237 176 1039 80 177 1040 237 176 1039 265 174 1036 160 169 1017 81 171 1019 94 14 61 163 178 1041 164 179 1042 9 15 62 165 180 1043 266 181 1045 166 182 1046 46 183 1047 166 182 1046 266 181 1045 163 178 1041 94 14 61 90 2 28 288 184 1048 207 185 1049 6 3 29 164 179 1042 167 186 1050 12 26 86 9 15 62 166 182 1046 267 187 1051 168 188 1052 46 183 1047 168 188 1052 267 187 1051 169 189 1053 47 190 1054 169 189 1053 267 187 1051 95 11 41 7 10 39 95 11 41 267 187 1051 166 182 1046 94 14 61 207 185 1049 287 191 1055 96 16 65 6 3 29 96 16 65 287 191 1055 206 192 1056 10 21 70 170 193 22 268 194 2246 171 195 24 63 196 25 171 195 24 268 194 2246 172 197 2247 58 198 27 172 197 1057 268 194 1058 173 199 1059 64 200 1060 173 199 1059 268 194 1058 170 193 1061 62 201 1062 172 197 2247 269 202 2248 174 203 32 58 198 27 174 203 32 269 202 2248 175 204 2249 61 205 34 175 204 1063 269 202 1064 176 206 1065 65 207 1066 176 206 1065 269 202 1064 172 197 1057 64 200 1060 175 204 2249 270 208 2250 177 209 38 61 205 34 177 209 38 270 208 2250 178 210 2251 66 211 40 178 210 1067 270 208 1068 179 212 1069 67 213 1070 179 212 1069 270 208 1068 175 204 1063 65 207 1066 180 214 1071 271 215 1072 149 145 928 25 73 893 149 145 928 271 215 1072 249 60 298 23 59 297 249 60 298 271 215 1072 48 216 1073 22 53 291 150 147 976 159 167 1013 44 151 982 27 72 892 159 167 1013 150 147 976 43 141 924 48 216 1073 272 217 1074 116 54 292 22 53 291 116 54 292 272 217 1074 49 218 1075 20 47 266 49 218 1075 273 219 1076 112 48 283 20 47 266 112 48 283 273 219 1076 50 220 1077 18 43 259 50 220 1077 274 221 1078 109 42 256 18 43 259 109 42 256 274 221 1078 51 222 1079 13 29 135 169 189 1053 275 223 1080 52 224 1081 47 190 1054 51 222 1079 275 223 1080 102 30 137 13 29 135 102 30 137 275 223 1080 169 189 1053 7 10 39 206 192 1056 286 225 1082 103 33 140 10 21 70 103 33 140 286 225 1082 53 226 1083 15 38 249 53 226 1083 276 227 1084 141 122 911 15 38 249 141 122 911 276 227 1084 54 228 1085 38 103 912 156 101 1086 277 229 1087 55 230 1088 36 102 1089 54 228 1085 277 229 1087 156 101 1086 38 103 912 55 230 1088 182 231 1090 181 160 1091 36 102 1089 181 160 1091 182 231 1090 56 132 918 40 139 1092 202 129 20 283 232 43 183 233 44 60 130 21 201 234 45 68 235 46 183 233 44 283 232 43 56 132 918 144 131 917 145 137 923 40 139 1092 144 131 917 321 236 1093 339 66 886 26 65 885 145 137 923 276 227 1084 2069 237 1094 2070 238 1095 54 228 1085 290 239 47 208 240 48 184 241 49 278 242 50 210 243 51 290 239 47 278 242 50 185 244 52 2068 245 1096 2069 237 1094 276 227 1084 53 226 1083 277 229 1087 2071 246 1097 2073 247 1098 55 230 1088 289 248 53 209 249 54 186 250 55 279 251 56 208 240 48 289 248 53 279 251 56 184 241 49 2070 238 1095 2071 246 1097 277 229 1087 54 228 1085 275 223 1080 2075 252 1099 2076 253 1100 52 224 1081 294 254 2265 212 255 58 2053 256 59 280 257 60 214 258 1101 294 254 1102 280 257 1103 187 259 1104 2074 260 1105 2075 252 1099 275 223 1080 51 222 1079 286 225 1082 2072 261 1106 2068 245 1096 53 226 1083 292 262 63 210 243 51 185 244 52 2052 263 64 274 221 1078 2078 264 1107 2074 260 1105 51 222 1079 293 265 1108 214 258 1101 187 259 1104 2055 266 1109 213 267 1110 293 265 1108 2055 266 1109 188 268 1111 2079 269 1112 2078 264 1107 274 221 1078 50 220 1077 273 219 1076 2080 270 1113 2079 269 1112 50 220 1077 295 271 1114 213 267 1110 188 268 1111 2056 272 1115 215 273 1116 295 271 1114 2056 272 1115 189 274 1117 2081 275 1118 2080 270 1113 273 219 1076 49 218 1075 271 215 1072 2084 276 1119 2085 277 1120 48 216 1073 297 278 1121 216 279 1122 190 280 1123 281 281 1124 217 282 87 297 278 73 281 281 2271 191 283 88 2083 284 1125 2084 276 1119 271 215 1072 180 214 1071 272 217 1074 2082 285 1126 2081 275 1118 49 218 1075 296 286 1127 215 273 1116 189 274 1117 2057 287 1128 216 279 1122 296 286 1127 2057 287 1128 190 280 1123 2085 277 1120 2082 285 1126 272 217 1074 48 216 1073 182 231 1090 2064 288 1129 2065 133 919 56 132 918 291 289 120 211 290 121 2051 291 122 2050 292 123 209 249 54 291 289 120 2050 292 123 186 250 55 2073 247 1098 2064 288 1129 182 231 1090 55 230 1088 211 290 121 298 293 124 282 294 125 2051 291 122 298 293 124 323 295 126 322 296 127 282 294 125 70 297 128 192 298 129 139 116 7 57 119 10 59 117 8 139 116 7 192 298 129 71 299 130 69 300 131 193 301 132 143 127 11 60 130 21 70 297 128 57 119 10 143 127 11 193 301 132 73 302 133 194 303 134 170 193 22 63 196 25 62 201 1062 170 193 1061 194 303 1130 74 304 1131 59 117 8 71 299 130 205 305 136 204 114 5 62 201 1062 74 304 1131 195 306 1132 173 199 1059 64 200 1060 173 199 1059 195 306 1132 75 307 1133 64 200 1060 75 307 1133 196 308 1134 176 206 1065 65 207 1066 176 206 1065 196 308 1134 76 309 1135 77 310 1136 197 311 1137 178 210 1067 67 213 1070 66 211 40 178 210 2251 197 311 2267 78 312 143 65 207 1066 76 309 1135 198 313 1138 179 212 1069 77 310 1136 67 213 1070 179 212 1069 198 313 1138 72 314 201 199 315 202 183 233 44 68 235 46 69 300 131 60 130 21 183 233 44 199 315 202 200 316 203 72 314 201 68 235 46 201 234 45 338 317 204 200 316 203 201 234 45 337 318 205 338 317 204 337 318 205 66 211 40 78 312 143 283 232 43 336 319 206 337 318 205 201 234 45 177 209 38 336 319 206 335 320 207 61 205 34 284 128 19 334 321 208 335 320 207 202 129 20 174 203 32 334 321 208 333 322 209 58 198 27 285 115 6 332 323 210 333 322 209 203 118 9 171 195 24 332 323 210 331 324 232 63 196 25 331 324 232 204 114 5 205 305 136 330 325 233 331 324 232 330 325 233 73 302 133 63 196 25 329 326 234 292 262 63 2052 263 64 2054 327 235 2076 253 1100 2077 328 1139 328 329 1140 52 224 1081 52 224 1081 328 329 1140 327 330 1141 47 190 1054 287 191 1055 326 331 1142 327 330 1141 206 192 1056 168 188 1052 326 331 1142 325 332 1143 46 183 1047 288 184 1048 324 333 1144 325 332 1143 207 185 1049 193 301 132 289 248 53 208 240 48 70 297 128 209 249 54 289 248 53 193 301 132 69 300 131 210 243 51 292 262 63 205 305 136 71 299 130 208 240 48 290 239 47 192 298 129 70 297 128 192 298 129 290 239 47 210 243 51 71 299 130 199 315 202 291 289 120 209 249 54 69 300 131 211 290 121 291 289 120 199 315 202 72 314 201 292 262 63 329 326 234 330 325 233 205 305 136 2053 256 59 212 255 58 329 326 234 2054 327 235 195 306 1132 293 265 1108 213 267 1110 75 307 1133 214 258 1101 293 265 1108 195 306 1132 74 304 1131 212 255 58 294 254 2265 194 303 134 73 302 133 194 303 1130 294 254 1102 214 258 1101 74 304 1131 213 267 1110 295 271 1114 196 308 1134 75 307 1133 196 308 1134 295 271 1114 215 273 1116 76 309 1135 215 273 1116 296 286 1127 198 313 1138 76 309 1135 198 313 1138 296 286 1127 216 279 1122 77 310 1136 323 295 126 217 282 87 191 283 88 322 296 127 217 282 87 323 295 126 338 317 204 78 312 143 216 279 1122 297 278 1121 197 311 1137 77 310 1136 197 311 2267 297 278 73 217 282 87 78 312 143 200 316 203 298 293 124 211 290 121 72 314 201 247 27 89 301 334 1145 220 335 1146 100 28 90 221 336 1147 301 334 1145 247 27 89 12 26 86 107 39 252 302 337 1148 222 338 1149 106 40 253 220 335 1146 302 337 1148 107 39 252 100 28 90 111 45 262 303 339 1150 223 340 1151 110 46 265 222 338 1149 303 339 1150 111 45 262 106 40 253 115 51 289 304 341 1152 224 342 1153 114 52 290 223 340 1151 304 341 1152 115 51 289 110 46 265 119 57 295 305 343 1154 225 344 1155 118 58 296 224 342 1153 305 343 1154 119 57 295 114 52 290 122 63 304 306 345 1156 226 346 1157 121 64 884 225 344 1155 306 345 1156 122 63 304 118 58 296 152 148 978 346 347 1158 345 348 1159 151 149 980 152 148 978 121 64 884 226 346 1157 346 347 1158 241 163 983 344 349 1160 343 350 1161 242 165 987 241 163 983 151 149 980 345 348 1159 344 349 1160 167 186 1050 315 351 1162 221 336 1147 12 26 86 232 175 1038 316 352 1163 127 80 900 30 82 902 127 80 900 316 352 1163 162 353 1164 45 81 901 162 353 1164 316 352 1163 235 354 1165 79 355 1166 235 354 1165 316 352 1163 232 175 1038 80 177 1040 234 356 1167 317 357 1168 235 354 1165 80 177 1040 235 354 1165 317 357 1168 233 358 1169 79 355 1166 233 358 1169 317 357 1168 87 359 1170 3 360 1171 87 359 1170 317 357 1168 234 356 1167 2 361 1172 236 362 1173 318 363 1174 237 176 1039 81 171 1019 237 176 1039 318 363 1174 234 356 1167 80 177 1040 234 356 1167 318 363 1174 86 364 1175 2 361 1172 86 364 1175 318 363 1174 236 362 1173 1 365 1176 239 170 1018 319 366 1177 236 362 1173 81 171 1019 236 362 1173 319 366 1177 85 367 1178 1 365 1176 85 367 1178 319 366 1177 161 368 1179 0 369 1180 161 368 1179 319 366 1177 239 170 1018 82 173 1023 0 369 1180 161 368 1179 240 370 1181 4 371 1182 240 370 1181 161 368 1179 82 173 1023 83 166 1012 242 165 987 158 372 1183 240 370 1181 83 166 1012 240 370 1181 158 372 1183 84 373 1184 4 371 1182 343 350 1161 342 374 1185 158 372 1183 242 165 987 158 372 1183 342 374 1185 88 375 1186 84 373 1184 144 131 917 2066 134 920 2067 376 1187 321 236 1093 339 66 886 321 236 1093 180 214 1071 25 73 893 2067 376 1187 2083 284 1125 180 214 1071 321 236 1093 46 183 1047 325 332 1143 324 333 1144 165 180 1043 207 185 1049 325 332 1143 326 331 1142 287 191 1055 47 190 1054 327 330 1141 326 331 1142 168 188 1052 206 192 1056 327 330 1141 328 329 1140 286 225 1082 286 225 1082 328 329 1140 2077 328 1139 2072 261 1106 73 302 133 330 325 233 329 326 234 212 255 58 204 114 5 331 324 232 332 323 210 285 115 6 58 198 27 333 322 209 332 323 210 171 195 24 203 118 9 333 322 209 334 321 208 284 128 19 61 205 34 335 320 207 334 321 208 174 203 32 202 129 20 335 320 207 336 319 206 283 232 43 66 211 40 337 318 205 336 319 206 177 209 38 200 316 203 338 317 204 323 295 126 298 293 124 299 8 36 218 9 37 2022 377 1188 2017 378 1189 218 9 37 300 23 72 2021 379 1190 2022 377 1188 300 23 72 219 25 85 2023 380 1191 2021 379 1190 220 335 1146 301 334 1145 674 381 1192 592 382 1193 301 334 1145 221 336 1147 593 383 1194 674 381 1192 222 338 1149 302 337 1148 675 384 1195 594 385 1196 302 337 1148 220 335 1146 592 382 1193 675 384 1195 223 340 1151 303 339 1150 676 386 1197 595 387 1198 303 339 1150 222 338 1149 594 385 1196 676 386 1197 224 342 1153 304 341 1152 677 388 1199 596 389 1200 304 341 1152 223 340 1151 595 387 1198 677 388 1199 225 344 1155 305 343 1154 678 390 1201 597 391 1202 305 343 1154 224 342 1153 596 389 1200 678 390 1201 226 346 1157 306 345 1156 679 392 1203 598 393 1204 306 345 1156 225 344 1155 597 391 1202 679 392 1203 2036 394 1205 2037 395 1206 680 396 1207 599 397 1208 2037 395 1206 2038 398 1209 600 399 1210 680 396 1207 2038 398 1209 2039 400 1211 608 401 1212 600 399 1210 31 86 3 308 85 2 2019 402 144 2033 403 2261 602 404 148 681 405 149 2019 402 2264 2020 406 2259 34 95 16 309 94 15 2032 407 2262 2031 408 2252 309 94 15 31 86 3 2033 403 2261 2032 407 2262 219 25 85 310 111 904 2024 409 1213 2023 380 1191 684 410 1214 604 411 1215 2025 412 1216 2026 413 1217 2034 414 2258 2035 415 2260 685 416 158 605 417 159 2035 415 1218 2036 394 1205 599 397 1208 685 416 1219 345 348 1159 346 347 1158 1971 418 1220 1970 419 1221 346 347 1158 226 346 1157 598 393 1204 1971 418 1220 2020 406 2259 2016 420 2257 686 421 161 602 404 148 2016 420 2257 2034 414 2258 605 417 159 686 421 161 229 126 113 313 156 112 2028 422 2255 2027 423 2256 313 156 112 230 158 115 2029 424 2254 2028 422 2255 230 158 115 314 162 119 2030 425 2253 2029 424 2254 314 162 119 34 95 16 2031 408 2252 2030 425 2253 343 350 1161 344 349 1160 1969 426 1222 1968 427 1223 344 349 1160 345 348 1159 1970 419 1221 1969 426 1222 2039 400 1211 2040 428 1224 689 429 1225 608 401 1212 2040 428 1224 2041 430 1226 612 431 1227 689 429 1225 221 336 1147 315 351 1162 690 432 1228 593 383 1194 2041 430 1226 2042 433 1229 692 434 1230 612 431 1227 2042 433 1229 2043 435 1231 434 436 1232 692 434 1230 88 375 1186 342 374 1185 1967 437 1233 435 438 1234 342 374 1185 343 350 1161 1968 427 1223 1967 437 1233 436 439 1235 353 440 1236 437 441 1237 622 442 1238 438 443 1239 352 444 1240 436 439 1235 622 442 1238 439 445 1241 352 444 1240 438 443 1239 623 446 1242 440 447 1243 354 448 1244 439 445 1241 623 446 1242 355 449 1245 356 450 1246 441 451 1247 443 452 1248 441 451 1247 357 453 1249 442 454 1250 443 452 1248 444 455 1251 353 440 1236 436 439 1235 624 456 1252 436 439 1235 352 444 1240 445 457 1253 624 456 1252 445 457 1253 359 458 1254 446 459 1255 624 456 1252 446 459 1255 358 460 1256 444 455 1251 624 456 1252 445 457 1253 352 444 1240 439 445 1241 625 461 1257 439 445 1241 354 448 1244 447 462 1258 625 461 1257 447 462 1258 360 463 1259 448 464 1260 625 461 1257 448 464 1260 359 458 1254 445 457 1253 625 461 1257 361 465 1261 357 453 1249 441 451 1247 626 466 1262 441 451 1247 356 450 1246 449 467 1263 626 466 1262 362 468 1264 363 469 1265 450 470 1266 451 471 1267 450 470 1266 356 450 1246 355 449 1245 451 471 1267 452 472 1268 358 460 1256 446 459 1255 627 473 1269 446 459 1255 359 458 1254 453 474 1270 627 473 1269 453 474 1270 365 475 1271 454 476 1272 627 473 1269 454 476 1272 364 477 1273 452 472 1268 627 473 1269 449 467 1263 356 450 1246 450 470 1266 456 478 1274 450 470 1266 363 469 1265 455 479 1275 456 478 1274 457 480 1276 363 469 1265 362 468 1264 458 481 1277 367 482 1278 366 483 1279 457 480 1276 458 481 1277 455 479 1275 363 469 1265 457 480 1276 460 484 1280 457 480 1276 366 483 1279 459 485 1281 460 484 1280 369 486 1282 368 487 1283 462 488 1284 461 489 1285 462 488 1284 366 483 1279 367 482 1278 461 489 1285 459 485 1281 366 483 1279 462 488 1284 464 490 1286 462 488 1284 368 487 1283 463 491 1287 464 490 1286 371 492 1288 370 493 1289 466 494 1290 465 495 1291 466 494 1290 368 487 1283 369 486 1282 465 495 1291 463 491 1287 368 487 1283 466 494 1290 468 496 1292 466 494 1290 370 493 1289 467 497 1293 468 496 1292 372 498 1294 373 499 1295 469 500 1296 628 501 1297 469 500 1296 370 493 1289 371 492 1288 628 501 1297 467 497 1293 370 493 1289 469 500 1296 471 502 1298 469 500 1296 373 499 1295 470 503 1299 471 502 1298 375 504 1300 472 505 1301 1965 506 1302 1964 507 1303 472 505 1301 377 508 1304 1966 509 1305 1965 506 1302 1966 509 1305 376 510 1306 473 511 1307 1965 506 1302 473 511 1307 374 512 1308 1964 507 1303 1965 506 1302 474 513 1309 378 514 1310 475 515 1311 629 516 1312 475 515 1311 379 517 1313 476 518 1314 629 516 1312 476 518 1314 377 508 1304 472 505 1301 629 516 1312 472 505 1301 375 504 1300 474 513 1309 629 516 1312 476 518 1314 379 517 1313 399 519 1315 477 520 1316 476 518 1314 477 520 1316 380 521 1317 377 508 1304 478 522 162 381 523 163 479 524 164 630 525 165 479 524 174 382 526 175 480 527 176 630 525 177 480 527 176 384 528 178 481 529 179 630 525 177 481 529 166 383 530 167 478 522 162 630 525 165 482 531 168 385 532 169 483 533 170 631 534 171 483 533 170 381 523 163 478 522 162 631 534 171 478 522 162 383 530 167 484 535 172 631 534 171 484 535 172 386 536 173 482 531 168 631 534 171 485 537 180 386 536 173 484 535 172 632 538 181 484 535 172 383 530 167 486 539 182 632 538 181 486 539 182 387 540 183 511 541 184 632 538 181 511 541 184 390 542 185 485 537 180 632 538 181 487 543 186 391 544 187 488 545 188 633 546 189 488 545 188 388 547 190 489 548 191 633 546 189 489 548 191 386 536 173 485 537 180 633 546 189 485 537 180 390 542 185 487 543 186 633 546 189 453 474 1270 359 458 1254 448 464 1260 634 549 1318 448 464 1260 360 463 1259 490 550 1319 634 549 1318 490 550 1319 389 551 1320 491 552 1321 634 549 1318 491 552 1321 365 475 1271 453 474 1270 634 549 1318 575 553 236 405 554 237 492 555 238 659 556 239 492 555 238 403 557 240 574 558 241 659 556 239 454 476 1272 365 475 1271 493 559 1322 635 560 1323 493 559 1322 391 544 1324 487 543 1325 635 560 1323 487 543 1325 390 542 1326 494 561 1327 635 560 1323 494 561 1327 364 477 1273 454 476 1272 635 560 1323 491 552 1321 389 551 1320 495 562 1328 636 563 1329 495 562 1328 392 564 1330 508 565 1331 636 563 1329 508 565 1331 391 544 1324 493 559 1322 636 563 1329 493 559 1322 365 475 1271 491 552 1321 636 563 1329 496 566 242 406 567 243 573 568 244 658 569 245 574 558 241 403 557 240 496 566 242 658 569 245 651 570 1332 2087 571 1333 2088 572 1334 552 573 1335 497 574 1336 378 514 1310 474 513 1309 637 575 1337 474 513 1309 375 504 1300 498 576 1338 637 575 1337 498 576 211 394 577 212 499 578 213 637 575 214 499 578 213 395 579 215 497 574 216 637 575 214 397 580 1339 396 581 1340 501 582 1341 500 583 1342 501 582 1341 373 499 1295 372 498 1294 500 583 1342 502 584 1343 374 512 1308 473 511 1307 638 585 1344 473 511 1307 376 510 1306 503 586 1345 638 585 1344 503 586 1345 397 580 1339 500 583 1342 638 585 1344 500 583 1342 372 498 1294 502 584 1343 638 585 1344 470 503 1299 373 499 1295 501 582 1341 505 587 1346 501 582 1341 396 581 1340 504 588 1347 505 587 1346 609 589 1348 1966 509 1305 377 508 1304 380 521 1317 609 589 1348 398 590 1349 376 510 1306 1966 509 1305 506 591 217 384 528 178 480 527 176 639 592 218 480 527 176 382 526 175 507 593 219 639 592 218 507 593 219 395 579 215 499 578 213 639 592 218 499 578 213 394 577 212 506 591 217 639 592 218 508 565 192 392 564 193 509 594 194 640 595 195 509 594 194 400 596 196 510 597 197 640 595 195 510 597 197 388 547 190 488 545 188 640 595 195 488 545 188 391 544 187 508 565 192 640 595 195 506 591 217 394 577 212 538 598 226 641 599 227 538 598 198 387 540 183 486 539 182 641 599 199 486 539 182 383 530 167 481 529 166 641 599 199 481 529 179 384 528 178 506 591 217 641 599 227 489 548 191 388 547 190 510 597 197 642 600 220 510 597 197 400 596 196 512 601 221 642 600 220 512 601 221 385 532 169 482 531 168 642 600 220 482 531 168 386 536 173 489 548 191 642 600 220 504 588 1347 396 581 1340 513 602 1350 620 603 1351 513 602 1350 429 604 1352 621 605 1353 620 603 1351 515 606 1354 398 590 1349 516 607 1355 643 608 1356 516 607 1355 427 609 1357 618 610 1358 643 608 1356 618 610 1358 428 611 1359 617 612 1360 643 608 1356 617 612 1360 397 580 1339 515 606 1354 643 608 1356 428 611 1359 429 604 1352 513 602 1350 617 612 1360 513 602 1350 396 581 1340 397 580 1339 617 612 1360 516 607 1355 398 590 1349 609 589 1348 644 613 1361 609 589 1348 380 521 1317 610 614 1362 644 613 1361 610 614 1362 426 615 1363 616 616 1364 644 613 1361 616 616 1364 427 609 1357 516 607 1355 644 613 1361 442 454 1250 357 453 1249 520 617 1365 519 618 1366 521 619 1367 401 620 1368 522 621 1369 645 622 1370 522 621 1369 442 454 1250 519 618 1366 645 622 1370 437 441 1237 353 440 1236 579 623 1371 661 624 1372 520 617 1365 357 453 1249 361 465 1261 523 625 1373 522 621 1369 401 620 1368 524 626 1374 646 627 1375 524 626 1374 402 628 1376 525 629 1377 646 627 1375 525 629 1377 355 449 1245 443 452 1248 646 627 1375 443 452 1248 442 454 1250 522 621 1369 646 627 1375 579 623 1371 353 440 1236 444 455 1251 660 630 1378 444 455 1251 358 460 1256 578 631 1379 660 630 1378 526 632 2273 409 633 247 527 634 248 647 635 2268 527 634 248 404 636 250 528 637 251 647 635 2268 528 637 1380 410 638 1381 529 639 1382 647 635 1383 529 639 1382 408 640 1384 526 632 1385 647 635 1383 528 637 251 404 636 250 530 641 255 648 642 2269 530 641 255 407 643 257 531 644 258 648 642 2269 531 644 1386 411 645 1387 532 646 1388 648 642 1389 532 646 1388 410 638 1381 528 637 1380 648 642 1389 531 644 258 407 643 257 533 647 261 649 648 2272 533 647 261 412 649 263 534 650 264 649 648 2272 534 650 1390 413 651 1391 535 652 1392 649 648 1393 535 652 1392 411 645 1387 531 644 1386 649 648 1393 393 653 1394 374 512 1308 502 584 1343 537 654 1395 502 584 1343 372 498 1294 628 501 1297 537 654 1395 628 501 1297 371 492 1288 536 655 1396 537 654 1395 503 586 1345 376 510 1306 398 590 1349 515 606 1354 515 606 1354 397 580 1339 503 586 1345 536 655 1396 371 492 1288 465 495 1291 540 656 1397 465 495 1291 369 486 1282 539 657 1398 540 656 1397 539 657 1398 369 486 1282 461 489 1285 542 658 1399 461 489 1285 367 482 1278 541 659 1400 542 658 1399 541 659 1400 367 482 1278 458 481 1277 544 660 1401 458 481 1277 362 468 1264 543 661 1402 544 660 1401 525 629 1377 402 628 1376 545 662 1403 546 663 1404 543 661 1402 362 468 1264 451 471 1267 546 663 1404 451 471 1267 355 449 1245 525 629 1377 546 663 1404 578 631 1379 358 460 1256 452 472 1268 577 664 1405 452 472 1268 364 477 1273 547 665 1406 577 664 1405 547 665 1406 364 477 1273 494 561 1327 549 666 1407 494 561 1327 390 542 1326 548 667 1408 549 666 1407 511 541 1409 387 540 1410 550 668 1411 551 669 1412 548 667 1408 390 542 1326 511 541 1409 551 669 1412 550 668 1411 387 540 1410 538 598 1413 650 670 1414 538 598 1413 394 577 1415 552 573 1335 650 670 1414 573 568 244 406 567 243 553 671 267 657 672 268 572 673 269 657 672 268 553 671 267 414 674 270 552 573 1335 394 577 1415 498 576 1338 651 570 1332 651 570 1332 498 576 1338 375 504 1300 1964 507 1303 1945 675 1416 549 666 1407 548 667 1408 2091 676 1417 2092 677 1418 580 678 271 663 679 272 652 680 273 554 681 274 663 679 272 582 682 275 555 683 276 652 680 273 2093 684 1419 547 665 1406 549 666 1407 2092 677 1418 551 669 1412 550 668 1411 2095 685 1420 2090 686 1421 581 687 277 662 688 278 653 689 279 556 690 280 662 688 278 580 678 271 554 681 274 653 689 279 2091 676 1417 548 667 1408 551 669 1412 2090 686 1421 546 663 1404 545 662 1403 2097 691 1422 2098 692 1423 584 693 281 667 694 282 654 695 2270 557 696 284 667 694 1424 586 697 1425 558 698 1426 654 695 1427 2099 699 1428 543 661 1402 546 663 1404 2098 692 1423 577 664 1405 547 665 1406 2093 684 1419 2094 700 1429 582 682 275 665 701 287 2060 702 288 555 683 276 544 660 1401 543 661 1402 2099 699 1428 2100 703 1430 586 697 1425 666 704 1431 2061 705 1432 558 698 1426 666 704 1431 585 706 1433 559 707 1434 2061 705 1432 2101 708 1435 541 659 1400 544 660 1401 2100 703 1430 542 658 1399 541 659 1400 2101 708 1435 2102 709 1436 585 706 1433 668 710 1437 2062 711 1438 559 707 1434 668 710 1437 587 712 1439 560 713 1440 2062 711 1438 2103 714 1441 539 657 1398 542 658 1399 2102 709 1436 537 654 1395 536 655 1396 2105 715 1442 2106 716 1443 588 717 1444 670 718 1445 655 719 1446 561 720 1447 670 718 2275 589 721 301 562 722 302 655 719 299 2107 723 1448 393 653 1394 537 654 1395 2106 716 1443 540 656 1397 539 657 1398 2103 714 1441 2104 724 1449 587 712 1439 669 725 1450 2063 726 1451 560 713 1440 669 725 1450 588 717 1444 561 720 1447 2063 726 1451 2105 715 1442 536 655 1396 540 656 1397 2104 724 1449 650 670 1414 552 573 1335 2088 572 1334 2089 727 1452 583 728 305 664 729 306 2059 730 307 2058 731 308 664 729 306 581 687 277 556 690 280 2059 730 307 2095 685 1420 550 668 1411 650 670 1414 2089 727 1452 671 732 309 583 728 305 2058 731 308 656 733 310 1947 734 311 671 732 309 656 733 310 1946 735 970 563 736 971 416 737 972 403 557 240 492 555 238 563 736 971 492 555 238 405 554 237 417 738 973 564 739 974 415 740 975 406 567 243 496 566 242 564 739 974 496 566 242 403 557 240 416 737 972 565 741 2274 419 742 977 409 633 247 526 632 2273 565 741 1453 526 632 1385 408 640 1384 420 743 1454 576 744 979 417 738 973 405 554 237 575 553 236 566 745 1455 420 743 1454 408 640 1384 529 639 1382 566 745 1455 529 639 1382 410 638 1381 421 746 1456 567 747 1457 421 746 1456 410 638 1381 532 646 1388 567 747 1457 532 646 1388 411 645 1387 422 748 1458 568 749 1459 423 750 1460 413 651 1391 534 650 1390 568 749 984 534 650 264 412 649 263 424 751 986 569 752 1461 422 748 1458 411 645 1387 535 652 1392 569 752 1461 535 652 1392 413 651 1391 423 750 1460 570 753 988 418 754 989 414 674 270 553 671 267 570 753 988 553 671 267 406 567 243 415 740 975 414 674 270 418 754 989 571 755 990 572 673 269 572 673 269 571 755 990 1963 756 991 1962 757 992 424 751 986 412 649 263 1962 757 992 1963 756 991 657 672 268 572 673 269 1962 757 992 1961 758 993 533 647 261 407 643 257 1960 759 994 1961 758 993 658 569 245 573 568 244 1960 759 994 1959 760 995 530 641 255 404 636 250 1958 761 996 1959 760 995 659 556 239 574 558 241 1958 761 996 1957 762 997 527 634 248 409 633 247 1956 763 998 1957 762 997 576 744 979 575 553 236 1956 763 998 1955 764 999 409 633 247 419 742 977 1955 764 999 1956 763 998 2060 702 288 665 701 287 1954 765 1000 1953 766 1001 2097 691 1422 545 662 1403 1952 767 1462 2096 768 1463 545 662 1403 402 628 1376 1951 769 1464 1952 767 1462 660 630 1378 578 631 1379 1951 769 1464 1950 770 1465 524 626 1374 401 620 1368 1949 771 1466 1950 770 1465 661 624 1372 579 623 1371 1949 771 1466 1948 772 1467 564 739 974 416 737 972 580 678 271 662 688 278 581 687 277 415 740 975 564 739 974 662 688 278 582 682 275 417 738 973 576 744 979 665 701 287 580 678 271 416 737 972 563 736 971 663 679 272 563 736 971 417 738 973 582 682 275 663 679 272 570 753 988 415 740 975 581 687 277 664 729 306 583 728 305 418 754 989 570 753 988 664 729 306 665 701 287 576 744 979 1955 764 999 1954 765 1000 1954 765 1000 584 693 281 557 696 284 1953 766 1001 566 745 1455 421 746 1456 585 706 1433 666 704 1431 586 697 1425 420 743 1454 566 745 1455 666 704 1431 584 693 281 419 742 977 565 741 2274 667 694 282 565 741 1453 420 743 1454 586 697 1425 667 694 1424 585 706 1433 421 746 1456 567 747 1457 668 710 1437 567 747 1457 422 748 1458 587 712 1439 668 710 1437 587 712 1439 422 748 1458 569 752 1461 669 725 1450 569 752 1461 423 750 1460 588 717 1444 669 725 1450 589 721 301 1947 734 311 1946 735 970 562 722 302 589 721 301 424 751 986 1963 756 991 1947 734 311 588 717 1444 423 750 1460 568 749 1459 670 718 1445 568 749 984 424 751 986 589 721 301 670 718 2275 571 755 990 418 754 989 583 728 305 671 732 309 590 773 1468 354 448 1244 440 447 1243 672 774 1469 447 462 1258 354 448 1244 590 773 1468 673 775 1470 591 776 1471 360 463 1259 447 462 1258 673 775 1470 626 466 1262 449 467 1263 592 382 1193 674 381 1192 593 383 1194 361 465 1261 626 466 1262 674 381 1192 456 478 1274 455 479 1275 594 385 1196 675 384 1195 592 382 1193 449 467 1263 456 478 1274 675 384 1195 460 484 1280 459 485 1281 595 387 1198 676 386 1197 594 385 1196 455 479 1275 460 484 1280 676 386 1197 464 490 1286 463 491 1287 596 389 1200 677 388 1199 595 387 1198 459 485 1281 464 490 1286 677 388 1199 468 496 1292 467 497 1293 597 391 1202 678 390 1201 596 389 1200 463 491 1287 468 496 1292 678 390 1201 471 502 1298 470 503 1299 598 393 1204 679 392 1203 597 391 1202 467 497 1293 471 502 1298 679 392 1203 475 515 1311 378 514 1310 599 397 1208 680 396 1207 600 399 1210 379 517 1313 475 515 1311 680 396 1207 399 519 1315 379 517 1313 600 399 1210 608 401 1212 479 524 164 381 523 163 601 777 222 681 405 223 602 404 148 382 526 175 479 524 174 681 405 149 483 533 170 385 532 169 603 778 224 682 779 225 601 777 222 381 523 163 483 533 170 682 779 225 490 550 1319 360 463 1259 591 776 1471 683 780 1472 604 411 1215 389 551 1320 490 550 1319 683 780 1472 495 562 1328 389 551 1320 604 411 1215 684 410 1214 606 781 1473 392 564 1330 495 562 1328 684 410 1214 497 574 216 395 579 215 605 417 159 685 416 158 599 397 1208 378 514 1310 497 574 1336 685 416 1219 505 587 1346 504 588 1347 1970 419 1221 1971 418 1220 505 587 1346 1971 418 1220 598 393 1204 470 503 1299 507 593 219 382 526 175 602 404 148 686 421 161 605 417 159 395 579 215 507 593 219 686 421 161 509 594 194 392 564 193 606 781 228 687 782 229 607 783 230 400 596 196 509 594 194 687 782 229 512 601 221 400 596 196 607 783 230 688 784 231 603 778 224 385 532 169 512 601 221 688 784 231 620 603 1351 621 605 1353 1968 427 1223 1969 426 1222 620 603 1351 1969 426 1222 1970 419 1221 504 588 1347 518 785 1474 399 519 1315 608 401 1212 689 429 1225 612 431 1227 425 786 1475 518 785 1474 689 429 1225 523 625 1373 361 465 1261 593 383 1194 690 432 1228 610 614 1362 380 521 1317 477 520 1316 691 787 1476 477 520 1316 399 519 1315 518 785 1474 691 787 1476 518 785 1474 425 786 1475 614 788 1477 691 787 1476 614 788 1477 426 615 1363 610 614 1362 691 787 1476 611 789 1478 425 786 1475 612 431 1227 692 434 1230 434 436 1232 350 790 1479 611 789 1478 692 434 1230 613 791 1480 426 615 1363 614 788 1477 693 792 1481 614 788 1477 425 786 1475 611 789 1478 693 792 1481 611 789 1478 350 790 1479 433 793 1482 693 792 1481 433 793 1482 349 794 1483 613 791 1480 693 792 1481 615 795 1484 427 609 1357 616 616 1364 694 796 1485 616 616 1364 426 615 1363 613 791 1480 694 796 1485 613 791 1480 349 794 1483 432 797 1486 694 796 1485 432 797 1486 348 798 1487 615 795 1484 694 796 1485 618 610 1358 427 609 1357 615 795 1484 695 799 1488 615 795 1484 348 798 1487 431 800 1489 695 799 1488 431 800 1489 347 801 1490 517 802 1491 695 799 1488 517 802 1491 428 611 1359 618 610 1358 695 799 1488 347 801 1490 351 803 1492 619 804 1493 517 802 1491 619 804 1493 429 604 1352 428 611 1359 517 802 1491 621 605 1353 429 604 1352 619 804 1493 514 805 1494 619 804 1493 351 803 1492 430 806 1495 514 805 1494 1968 427 1223 621 605 1353 514 805 1494 1967 437 1233 514 805 1494 430 806 1495 435 438 1234 1967 437 1233 696 807 1496 697 808 1497 710 809 1498 709 810 1499 697 808 1497 698 811 1500 711 812 1501 710 809 1498 698 811 1500 699 813 1502 712 814 1503 711 812 1501 699 813 1502 700 815 1504 713 816 1505 712 814 1503 700 815 1504 701 817 1506 714 818 1507 713 816 1505 701 817 1506 702 819 1508 715 820 1509 714 818 1507 702 819 1508 703 821 1510 716 822 1511 715 820 1509 703 821 1510 704 823 1512 717 824 1513 716 822 1511 704 823 1512 705 825 1514 718 826 1515 717 824 1513 705 825 1514 706 827 1516 719 828 1517 718 826 1515 706 827 1516 707 829 1518 720 830 1519 719 828 1517 707 829 1518 1331 831 1520 721 832 1521 720 830 1519 708 833 1522 722 834 1523 1979 835 1524 1980 836 1525 709 810 1499 710 809 1498 724 837 1526 723 838 1527 710 809 1498 711 812 1501 725 839 1528 724 837 1526 711 812 1501 712 814 1503 726 840 1529 725 839 1528 712 814 1503 713 816 1505 727 841 1530 726 840 1529 713 816 1505 714 818 1507 728 842 1531 727 841 1530 714 818 1507 715 820 1509 729 843 1532 728 842 1531 715 820 1509 716 822 1511 730 844 1533 729 843 1532 716 822 1511 717 824 1513 731 845 1534 730 844 1533 717 824 1513 718 826 1515 732 846 1535 731 845 1534 718 826 1515 719 828 1517 733 847 1536 732 846 1535 719 828 1517 720 830 1519 734 848 1537 733 847 1536 1333 849 1538 721 832 1521 1979 835 1524 1982 850 1539 723 838 1527 724 837 1526 737 851 1540 736 852 1541 724 837 1526 725 839 1528 738 853 1542 737 851 1540 725 839 1528 726 840 1529 739 854 1543 738 853 1542 726 840 1529 727 841 1530 740 855 1544 739 854 1543 727 841 1530 728 842 1531 741 856 1545 740 855 1544 728 842 1531 729 843 1532 742 857 1546 741 856 1545 729 843 1532 730 844 1533 743 858 1547 742 857 1546 730 844 1533 731 845 1534 744 859 1548 743 858 1547 731 845 1534 732 846 1535 745 860 1549 744 859 1548 732 846 1535 733 847 1536 746 861 1550 745 860 1549 733 847 1536 734 848 1537 747 862 1551 746 861 1550 1334 863 1552 1333 849 1538 1982 850 1539 1983 864 1553 736 852 1541 737 851 1540 750 865 1554 749 866 1555 737 851 1540 738 853 1542 751 867 1556 750 865 1554 738 853 1542 739 854 1543 752 868 1557 751 867 1556 739 854 1543 740 855 1544 753 869 1558 752 868 1557 740 855 1544 741 856 1545 754 870 1559 753 869 1558 741 856 1545 742 857 1546 755 871 1560 754 870 1559 742 857 1546 743 858 1547 756 872 1561 755 871 1560 743 858 1547 744 859 1548 757 873 1562 756 872 1561 744 859 1548 745 860 1549 758 874 1563 757 873 1562 745 860 1549 746 861 1550 759 875 1564 758 874 1563 746 861 1550 747 862 1551 760 876 1565 759 875 1564 1335 877 1566 1334 863 1552 1983 864 1553 1984 878 1567 749 866 1555 750 865 1554 763 879 1568 762 880 1569 750 865 1554 751 867 1556 764 881 1570 763 879 1568 751 867 1556 752 868 1557 765 882 1571 764 881 1570 752 868 1557 753 869 1558 766 883 1572 765 882 1571 753 869 1558 754 870 1559 767 884 1573 766 883 1572 754 870 1559 755 871 1560 768 885 1574 767 884 1573 755 871 1560 756 872 1561 769 886 1575 768 885 1574 756 872 1561 757 873 1562 770 887 1576 769 886 1575 757 873 1562 758 874 1563 771 888 1577 770 887 1576 758 874 1563 759 875 1564 772 889 1578 771 888 1577 759 875 1564 760 876 1565 773 890 1579 772 889 1578 1336 891 1580 1335 877 1566 1984 878 1567 1981 892 1581 762 880 1569 763 879 1568 776 893 1582 775 894 1583 763 879 1568 764 881 1570 777 895 1584 776 893 1582 764 881 1570 765 882 1571 778 896 1585 777 895 1584 765 882 1571 766 883 1572 779 897 1586 778 896 1585 766 883 1572 767 884 1573 780 898 1587 779 897 1586 767 884 1573 768 885 1574 781 899 1588 780 898 1587 768 885 1574 769 886 1575 782 900 1589 781 899 1588 769 886 1575 770 887 1576 783 901 1590 782 900 1589 770 887 1576 771 888 1577 784 902 1591 783 901 1590 771 888 1577 772 889 1578 785 903 1592 784 902 1591 772 889 1578 773 890 1579 786 904 1593 785 903 1592 2 361 1172 1336 891 1580 1981 892 1581 87 359 1170 775 894 1583 776 893 1582 788 905 1594 787 906 1595 776 893 1582 777 895 1584 789 907 1596 788 905 1594 777 895 1584 778 896 1585 790 908 1597 789 907 1596 778 896 1585 779 897 1586 791 909 1598 790 908 1597 779 897 1586 780 898 1587 792 910 1599 791 909 1598 780 898 1587 781 899 1588 793 911 1600 792 910 1599 781 899 1588 782 900 1589 794 912 1601 793 911 1600 782 900 1589 783 901 1590 795 913 1602 794 912 1601 783 901 1590 784 902 1591 796 914 1603 795 913 1602 784 902 1591 785 903 1592 797 915 1604 796 914 1603 785 903 1592 786 904 1593 798 916 1605 797 915 1604 787 906 1595 788 905 1594 800 917 1606 799 918 1607 788 905 1594 789 907 1596 801 919 1608 800 917 1606 789 907 1596 790 908 1597 802 920 1609 801 919 1608 790 908 1597 791 909 1598 803 921 1610 802 920 1609 791 909 1598 792 910 1599 804 922 1611 803 921 1610 792 910 1599 793 911 1600 805 923 1612 804 922 1611 793 911 1600 794 912 1601 806 924 1613 805 923 1612 794 912 1601 795 913 1602 807 925 1614 806 924 1613 795 913 1602 796 914 1603 808 926 1615 807 925 1614 796 914 1603 797 915 1604 809 927 1616 808 926 1615 797 915 1604 798 916 1605 810 928 1617 809 927 1616 799 918 1607 800 917 1606 812 929 1618 811 930 1619 800 917 1606 801 919 1608 813 931 1620 812 929 1618 801 919 1608 802 920 1609 814 932 1621 813 931 1620 802 920 1609 803 921 1610 815 933 1622 814 932 1621 803 921 1610 804 922 1611 816 934 1623 815 933 1622 804 922 1611 805 923 1612 817 935 1624 816 934 1623 805 923 1612 806 924 1613 818 936 1625 817 935 1624 806 924 1613 807 925 1614 819 937 1626 818 936 1625 807 925 1614 808 926 1615 820 938 1627 819 937 1626 808 926 1615 809 927 1616 821 939 1628 820 938 1627 809 927 1616 810 928 1617 822 940 1629 821 939 1628 811 930 1619 812 929 1618 824 941 1630 823 942 1631 812 929 1618 813 931 1620 825 943 1632 824 941 1630 813 931 1620 814 932 1621 826 944 1633 825 943 1632 814 932 1621 815 933 1622 827 945 1634 826 944 1633 815 933 1622 816 934 1623 828 946 1635 827 945 1634 816 934 1623 817 935 1624 829 947 1636 828 946 1635 817 935 1624 818 936 1625 830 948 1637 829 947 1636 818 936 1625 819 937 1626 831 949 1638 830 948 1637 819 937 1626 820 938 1627 832 950 1639 831 949 1638 820 938 1627 821 939 1628 833 951 1640 832 950 1639 821 939 1628 822 940 1629 834 952 1641 833 951 1640 823 942 1631 824 941 1630 835 953 1642 846 954 1643 824 941 1630 825 943 1632 836 955 1644 835 953 1642 825 943 1632 826 944 1633 837 956 1645 836 955 1644 826 944 1633 827 945 1634 838 957 1646 837 956 1645 827 945 1634 828 946 1635 839 958 1647 838 957 1646 828 946 1635 829 947 1636 840 959 1648 839 958 1647 829 947 1636 830 948 1637 841 960 1649 840 959 1648 830 948 1637 831 949 1638 842 961 1650 841 960 1649 831 949 1638 832 950 1639 843 962 1651 842 961 1650 832 950 1639 833 951 1640 844 963 1652 843 962 1651 833 951 1640 834 952 1641 845 964 1653 844 963 1652 846 954 1643 835 953 1642 848 965 1654 847 966 1655 835 953 1642 836 955 1644 849 967 1656 848 965 1654 836 955 1644 837 956 1645 850 968 1657 849 967 1656 837 956 1645 838 957 1646 851 969 1658 850 968 1657 838 957 1646 839 958 1647 852 970 1659 851 969 1658 839 958 1647 840 959 1648 853 971 1660 852 970 1659 840 959 1648 841 960 1649 854 972 1661 853 971 1660 841 960 1649 842 961 1650 855 973 1662 854 972 1661 842 961 1650 843 962 1651 856 974 1663 855 973 1662 843 962 1651 844 963 1652 857 975 1664 856 974 1663 844 963 1652 845 964 1653 858 976 1665 857 975 1664 847 966 1655 848 965 1654 860 977 1666 859 978 1667 848 965 1654 849 967 1656 861 979 1668 860 977 1666 849 967 1656 850 968 1657 862 980 1669 861 979 1668 853 971 1660 854 972 1661 863 981 1670 854 972 1661 855 973 1662 864 982 1671 863 981 1670 855 973 1662 856 974 1663 865 983 1672 864 982 1671 856 974 1663 857 975 1664 866 984 1673 865 983 1672 857 975 1664 858 976 1665 867 985 1674 866 984 1673 859 978 1667 860 977 1666 869 986 1675 868 987 1676 860 977 1666 861 979 1668 870 988 1677 869 986 1675 868 987 1676 869 986 1675 872 989 1678 871 990 1679 869 986 1675 870 988 1677 873 991 1680 872 989 1678 875 992 1681 874 993 1682 864 982 1671 865 983 1672 865 983 1672 866 984 1673 876 994 1683 875 992 1681 866 984 1673 867 985 1674 877 995 1684 876 994 1683 871 990 1679 872 989 1678 879 996 1685 878 997 1686 872 989 1678 873 991 1680 880 998 1687 879 996 1685 882 999 1688 881 1000 1689 874 993 1682 875 992 1681 875 992 1681 876 994 1683 883 1001 1690 882 999 1688 876 994 1683 877 995 1684 884 1002 1691 883 1001 1690 878 997 1686 879 996 1685 886 1003 1692 885 1004 1693 879 996 1685 880 998 1687 887 1005 1694 886 1003 1692 889 1006 1695 888 1007 1696 881 1000 1689 882 999 1688 882 999 1688 883 1001 1690 890 1008 1697 889 1006 1695 883 1001 1690 884 1002 1691 891 1009 1698 890 1008 1697 885 1004 1693 886 1003 1692 893 1010 1699 892 1011 1700 886 1003 1692 887 1005 1694 894 1012 1701 893 1010 1699 1313 1013 1702 888 1007 1696 889 1006 1695 895 1014 1703 889 1006 1695 890 1008 1697 896 1015 1704 895 1014 1703 890 1008 1697 891 1009 1698 1314 1016 1705 896 1015 1704 891 1009 1698 1337 1017 1706 897 1018 1707 1314 1016 1705 1985 1019 1708 1337 1017 1706 320 1020 1709 1986 1021 1710 892 1011 1700 893 1010 1699 899 1022 1711 898 1023 1712 893 1010 1699 894 1012 1701 900 1024 1713 899 1022 1711 1312 1025 1714 1311 1026 1715 906 1027 1716 905 1028 1717 697 808 1497 696 807 1496 907 1029 1718 698 811 1500 697 808 1497 907 1029 1718 699 813 1502 698 811 1500 907 1029 1718 700 815 1504 699 813 1502 907 1029 1718 701 817 1506 700 815 1504 907 1029 1718 702 819 1508 701 817 1506 907 1029 1718 703 821 1510 702 819 1508 907 1029 1718 704 823 1512 703 821 1510 907 1029 1718 705 825 1514 704 823 1512 907 1029 1718 706 827 1516 705 825 1514 907 1029 1718 707 829 1518 706 827 1516 907 1029 1718 707 829 1518 907 1029 1718 1331 831 1520 708 833 1522 1980 836 1525 907 1029 1718 941 1030 312 980 1031 313 1044 1032 314 1007 1033 315 1007 1033 315 1028 1034 316 956 1035 317 941 1030 312 942 1036 318 958 1037 319 1028 1034 316 1007 1033 315 1007 1033 315 1044 1032 314 981 1038 320 942 1036 318 943 1039 321 979 1040 322 1043 1041 323 1008 1042 324 1008 1042 324 1029 1043 325 955 1044 326 943 1039 321 941 1030 312 956 1035 317 1029 1043 325 1008 1042 324 1008 1042 324 1043 1041 323 980 1031 313 941 1030 312 944 1045 327 978 1046 328 1042 1047 329 1009 1048 330 1009 1048 330 1027 1049 331 953 1050 332 944 1045 327 943 1039 321 955 1044 326 1027 1049 331 1009 1048 330 1009 1048 330 1042 1047 329 979 1040 322 943 1039 321 945 1051 333 977 1052 334 1041 1053 335 1010 1054 336 1010 1054 336 1030 1055 337 960 1056 338 945 1051 333 944 1045 327 953 1050 332 1030 1055 337 1010 1054 336 1010 1054 336 1041 1053 335 978 1046 328 944 1045 327 1011 1057 339 1032 1058 340 964 1059 341 946 1060 342 945 1051 333 960 1056 338 1032 1058 340 1011 1057 339 1011 1057 339 946 1060 342 1066 1061 343 1067 1062 344 947 1063 345 976 1064 346 1040 1065 347 1012 1066 348 1012 1066 348 1034 1067 349 968 1068 350 947 1063 345 946 1060 342 964 1059 341 1034 1067 349 1012 1066 348 1012 1066 348 1040 1065 347 1066 1061 343 946 1060 342 948 1069 351 975 1070 352 1039 1071 353 1013 1072 354 1013 1072 354 1036 1073 355 971 1074 356 948 1069 351 947 1063 345 968 1068 350 1036 1073 355 1013 1072 354 1013 1072 354 1039 1071 353 976 1064 346 947 1063 345 949 1075 357 973 1076 358 1038 1077 359 1014 1078 360 1014 1078 360 1035 1079 361 967 1080 362 949 1075 357 948 1069 351 971 1074 356 1035 1079 361 1014 1078 360 1014 1078 360 1038 1077 359 975 1070 352 948 1069 351 950 1081 363 974 1082 364 1037 1083 365 1015 1084 366 1015 1084 366 1033 1085 367 963 1086 368 950 1081 363 949 1075 357 967 1080 362 1033 1085 367 1015 1084 366 1015 1084 366 1037 1083 365 973 1076 358 949 1075 357 942 1036 318 981 1038 320 1045 1087 369 1016 1088 370 1016 1088 370 1031 1089 371 958 1037 319 942 1036 318 950 1081 363 963 1086 368 1031 1089 371 1016 1088 370 1016 1088 370 1045 1087 369 974 1082 364 950 1081 363 1044 1032 314 1038 1077 359 973 1076 358 981 1038 320 986 1090 1719 1048 1091 1720 1907 1092 1721 1906 1093 1722 923 1094 1723 1017 1095 1724 1907 1092 1721 1908 1096 1725 990 1097 1726 1050 1098 1727 1911 1099 1728 1913 1100 1729 925 1101 1730 1018 1102 1731 1911 1099 1728 1909 1103 1732 909 1104 1733 1051 1105 1734 1905 1106 1735 1909 1103 1732 951 1107 1736 1019 1108 1737 1905 1106 1735 1906 1093 1722 908 1109 1738 1052 1110 1739 1910 1111 1740 1908 1096 1725 924 1112 1741 1020 1113 1742 1910 1111 1740 1912 1114 1743 910 1115 1744 1053 1116 1745 1914 1117 1746 1912 1114 1743 926 1118 1747 1021 1119 1748 1914 1117 1746 1916 1120 1749 927 1121 1750 1022 1122 1751 1918 1123 1752 1920 1124 1753 982 1125 1754 1046 1126 1755 1918 1123 1752 1916 1120 1749 984 1127 1756 1047 1128 1757 1922 1129 1758 1920 1124 1753 929 1130 1759 1023 1131 1760 1922 1129 1758 1924 1132 1761 911 1133 1762 1054 1134 1763 1923 1135 1764 1924 1132 1761 930 1136 1765 1024 1137 1766 1923 1135 1764 1921 1138 1767 988 1139 1768 1049 1140 1769 1919 1141 1770 1921 1138 1767 928 1142 1771 1025 1143 1772 1919 1141 1770 1917 1144 1773 912 1145 1774 1055 1146 1775 1915 1147 1776 1917 1144 1773 952 1148 1777 1026 1149 1778 1915 1147 1776 1913 1100 1729 953 1050 332 1027 1049 331 954 1150 969 914 1151 963 954 1152 969 1027 1049 331 955 1044 326 913 1153 967 956 1035 317 1028 1034 316 957 1154 968 916 1155 965 957 1156 968 1028 1034 316 958 1037 319 915 1157 962 955 1044 326 1029 1043 325 959 1158 966 913 1159 967 959 1160 966 1029 1043 325 956 1035 317 916 1161 965 960 1056 338 1030 1055 337 961 1162 964 917 1163 959 961 1164 964 1030 1055 337 953 1050 332 914 1165 963 958 1037 319 1031 1089 371 962 1166 961 915 1167 962 962 1168 961 1031 1089 371 963 1086 368 918 1169 958 964 1059 341 1032 1058 340 965 1170 960 919 1171 955 965 1172 960 1032 1058 340 960 1056 338 917 1173 959 963 1086 368 1033 1085 367 966 1174 957 918 1175 958 966 1176 957 1033 1085 367 967 1080 362 920 1177 954 968 1068 350 1034 1067 349 969 1178 956 921 1179 950 969 1180 956 1034 1067 349 964 1059 341 919 1181 955 967 1080 362 1035 1079 361 970 1182 953 920 1183 954 970 1184 953 1035 1079 361 971 1074 356 922 1185 952 971 1074 356 1036 1073 355 972 1186 951 922 1187 952 972 1188 951 1036 1073 355 968 1068 350 921 1189 950 914 1190 1779 954 1191 1780 1020 1113 1742 924 1112 1741 923 1094 1723 1020 1113 1742 954 1192 1780 913 1193 1781 916 1194 1782 957 1195 1783 1019 1108 1737 951 1107 1736 925 1101 1730 1019 1108 1737 957 1196 1783 915 1197 1784 923 1094 1723 913 1198 1781 959 1199 1785 1017 1095 1724 916 1200 1782 951 1107 1736 1017 1095 1724 959 1201 1785 917 1202 1786 961 1203 1787 1021 1119 1748 926 1118 1747 914 1204 1779 924 1112 1741 1021 1119 1748 961 1205 1787 925 1101 1730 915 1206 1784 962 1207 1788 1018 1102 1731 952 1148 1777 1018 1102 1731 962 1208 1788 918 1209 1789 919 1210 1790 965 1211 1791 1022 1122 1751 927 1121 1750 917 1212 1786 926 1118 1747 1022 1122 1751 965 1213 1791 952 1148 1777 918 1214 1789 966 1215 1792 1026 1149 1778 928 1142 1771 1026 1149 1778 966 1216 1792 920 1217 1793 921 1218 1794 969 1219 1795 1023 1131 1760 929 1130 1759 919 1220 1790 927 1121 1750 1023 1131 1760 969 1221 1795 928 1142 1771 920 1222 1793 970 1223 1796 1025 1143 1772 930 1136 1765 1025 1143 1772 970 1224 1796 922 1225 1797 930 1136 1765 922 1226 1797 972 1227 1798 1024 1137 1766 921 1228 1794 929 1130 1759 1024 1137 1766 972 1229 1798 984 1127 1756 1046 1126 1755 996 1230 1799 932 1231 1800 996 1230 1799 1046 1126 1755 982 1125 1754 931 1232 1801 911 1133 1762 1047 1128 1757 983 1233 1802 933 1234 1803 983 1233 1802 1047 1128 1757 984 1127 1756 932 1231 1800 908 1109 1738 1048 1091 1720 985 1235 1804 935 1236 1805 985 1235 1804 1048 1091 1720 986 1090 1719 934 1237 1806 912 1145 1774 1049 1140 1769 987 1238 1807 937 1239 1808 987 1238 1807 1049 1140 1769 988 1139 1768 936 1240 1809 909 1104 1733 1050 1098 1727 989 1241 1810 939 1242 1811 989 1241 1810 1050 1098 1727 990 1097 1726 938 1243 1812 986 1090 1719 1051 1105 1734 991 1244 1813 934 1237 1806 991 1244 1813 1051 1105 1734 909 1104 1733 939 1242 1811 910 1115 1744 1052 1110 1739 992 1245 1814 940 1246 1815 992 1245 1814 1052 1110 1739 908 1109 1738 935 1236 1805 982 1125 1754 1053 1116 1745 993 1247 1816 931 1232 1801 993 1247 1816 1053 1116 1745 910 1115 1744 940 1246 1815 988 1139 1768 1054 1134 1763 994 1248 1817 936 1240 1809 994 1248 1817 1054 1134 1763 911 1133 1762 933 1234 1803 990 1097 1726 1055 1146 1775 995 1249 1818 938 1243 1812 995 1249 1818 1055 1146 1775 912 1145 1774 937 1239 1808 996 1230 1799 1056 1250 1819 997 1251 1820 932 1231 1800 998 1252 1821 1056 1250 1819 996 1230 1799 931 1232 1801 983 1233 1802 1057 1253 1822 999 1254 1823 933 1234 1803 997 1251 1820 1057 1253 1822 983 1233 1802 932 1231 1800 985 1235 1804 1058 1255 1824 1000 1256 1825 935 1236 1805 1001 1257 1826 1058 1255 1824 985 1235 1804 934 1237 1806 987 1238 1807 1059 1258 1827 1002 1259 1828 937 1239 1808 1003 1260 1829 1059 1258 1827 987 1238 1807 936 1240 1809 989 1241 1810 1060 1261 1830 1004 1262 1831 939 1242 1811 1005 1263 1832 1060 1261 1830 989 1241 1810 938 1243 1812 991 1244 1813 1061 1264 1833 1001 1257 1826 934 1237 1806 1004 1262 1831 1061 1264 1833 991 1244 1813 939 1242 1811 992 1245 1814 1062 1265 1834 1006 1266 1835 940 1246 1815 1000 1256 1825 1062 1265 1834 992 1245 1814 935 1236 1805 993 1247 1816 1063 1267 1836 998 1252 1821 931 1232 1801 1006 1266 1835 1063 1267 1836 993 1247 1816 940 1246 1815 994 1248 1817 1064 1268 1837 1003 1260 1829 936 1240 1809 999 1254 1823 1064 1268 1837 994 1248 1817 933 1234 1803 995 1249 1818 1065 1269 1838 1005 1263 1832 938 1243 1812 1002 1259 1828 1065 1269 1838 995 1249 1818 937 1239 1808 973 1076 358 1037 1083 365 974 1082 364 1045 1087 369 981 1038 320 980 1031 313 1043 1041 323 1039 1071 353 975 1070 352 1044 1032 314 980 1031 313 975 1070 352 1038 1077 359 1043 1041 323 979 1040 322 976 1064 346 1039 1071 353 978 1046 328 1041 1053 335 977 1052 334 1067 1062 344 1066 1061 343 979 1040 322 1042 1047 329 1040 1065 347 976 1064 346 1011 1057 339 1067 1062 344 977 1052 334 945 1051 333 978 1046 328 1066 1061 343 1040 1065 347 1042 1047 329 997 1251 1820 1056 1250 1819 904 1270 1839 903 1271 1840 1056 1250 1819 998 1252 1821 1313 1013 1702 904 1270 1839 999 1254 1823 1057 1253 1822 902 1272 1841 901 1273 1842 1000 1256 1825 1058 1255 1824 863 981 1670 864 982 1671 1058 1255 1824 1001 1257 1826 853 971 1660 863 981 1670 1002 1259 1828 1059 1258 1827 887 1005 1694 880 998 1687 1059 1258 1827 1003 1260 1829 894 1012 1701 887 1005 1694 1004 1262 1831 1060 1261 1830 862 980 1669 851 969 1658 1060 1261 1830 1005 1263 1832 870 988 1677 862 980 1669 1001 1257 1826 1061 1264 1833 852 970 1659 853 971 1660 1061 1264 1833 1004 1262 1831 851 969 1658 852 970 1659 1006 1266 1835 1062 1265 1834 874 993 1682 881 1000 1689 1062 1265 1834 1000 1256 1825 864 982 1671 874 993 1682 1063 1267 1836 1006 1266 1835 881 1000 1689 888 1007 1696 1003 1260 1829 1064 1268 1837 900 1024 1713 894 1012 1701 1064 1268 1837 999 1254 1823 901 1273 1842 900 1024 1713 1005 1263 1832 1065 1269 1838 873 991 1680 870 988 1677 1065 1269 1838 1002 1259 1828 880 998 1687 873 991 1680 1057 1253 1822 997 1251 1820 903 1271 1840 902 1272 1841 870 988 1677 861 979 1668 862 980 1669 862 980 1669 850 968 1657 851 969 1658 1063 1267 1836 888 1007 1696 1313 1013 1702 998 1252 1821 1116 1274 372 1237 1275 373 1117 1276 374 1151 1277 375 1237 1275 373 1152 1278 376 1117 1276 374 1153 1279 377 1238 1280 378 1092 1281 379 1070 1282 380 1308 1283 381 1238 1280 378 1153 1279 377 1309 1284 382 1153 1279 377 1239 1285 383 1310 1286 384 1309 1284 382 1110 1287 385 1287 1288 386 1239 1285 383 1093 1289 387 1093 1289 387 1239 1285 383 1153 1279 377 1070 1282 380 1219 1290 388 1118 1291 389 1154 1292 390 1297 1293 391 1113 1294 392 1115 1295 393 1297 1293 391 1154 1292 390 1120 1296 394 1112 1297 395 1150 1298 396 1155 1299 397 1071 1300 398 1155 1299 397 1150 1301 396 1069 1302 399 1154 1292 390 1240 1303 400 1156 1304 401 1113 1305 392 1156 1306 401 1240 1303 400 1277 1307 402 1114 1308 403 1277 1307 402 1240 1303 400 1157 1309 404 1222 1310 405 1157 1309 404 1240 1303 400 1154 1292 390 1118 1291 389 1218 1311 406 1121 1312 407 1158 1313 408 1274 1314 409 1219 1290 388 1274 1314 409 1158 1313 408 1118 1291 389 1159 1315 410 1241 1316 411 1160 1317 412 1123 1318 413 1160 1317 412 1241 1316 411 1245 1319 414 1124 1320 415 1245 1319 414 1241 1316 411 1161 1321 416 1161 1321 416 1241 1316 411 1159 1315 410 1122 1322 417 1162 1323 418 1242 1324 419 1119 1325 420 1120 1296 394 1220 1326 421 1242 1324 419 1162 1323 418 1125 1327 422 1162 1323 418 1243 1328 423 1163 1329 424 1125 1327 422 1163 1329 424 1243 1328 423 1094 1330 425 1072 1331 426 1094 1330 425 1243 1328 423 1155 1299 397 1071 1300 398 1155 1299 397 1243 1328 423 1162 1323 418 1120 1296 394 1278 1332 427 1244 1333 428 1164 1334 429 1223 1335 430 1164 1334 429 1244 1333 428 1158 1313 408 1121 1312 407 1158 1313 408 1244 1333 428 1157 1309 404 1118 1291 389 1157 1309 404 1244 1333 428 1278 1332 427 1222 1310 405 1124 1320 415 1245 1319 414 1165 1336 431 1126 1337 432 1165 1336 431 1245 1319 414 1166 1338 433 1208 1339 434 1129 1340 435 1167 1341 436 1128 1342 437 1167 1341 436 1129 1340 435 1296 1343 438 1209 1344 439 1168 1345 440 1246 1346 441 1095 1347 442 1073 1348 443 1095 1347 442 1246 1346 441 1266 1349 444 1074 1350 445 1266 1349 444 1246 1346 441 1167 1341 436 1209 1344 439 1167 1341 436 1246 1346 441 1168 1345 440 1128 1342 437 1228 1351 446 1247 1352 447 1170 1353 448 1131 1354 449 1170 1353 448 1247 1352 447 1169 1355 450 1130 1356 451 1171 1357 452 1248 1358 453 1172 1359 454 1132 1360 455 1172 1359 454 1248 1358 453 1237 1275 373 1116 1274 372 1171 1357 452 1301 1361 456 1174 1362 457 1248 1358 453 1237 1275 373 1248 1358 453 1173 1363 458 1152 1278 376 1173 1363 458 1248 1358 453 1174 1362 457 1133 1364 459 1175 1365 460 1249 1366 461 1307 1367 462 1306 1368 463 1307 1367 462 1249 1366 461 1238 1280 378 1308 1283 381 1238 1280 378 1249 1366 461 1096 1369 464 1092 1281 379 1096 1369 464 1249 1366 461 1175 1365 460 1075 1370 465 1218 1311 406 1273 1371 466 1176 1372 467 1121 1312 407 1134 1373 468 1135 1374 469 1176 1372 467 1273 1371 466 1177 1375 470 1250 1376 471 1178 1377 472 1136 1378 473 1178 1377 472 1250 1376 471 1179 1379 474 1137 1380 475 1179 1379 474 1250 1376 471 1171 1357 452 1132 1360 455 1180 1381 476 1251 1382 477 1177 1375 470 1136 1378 473 1181 1383 478 1235 1384 479 1174 1362 457 1301 1361 456 1181 1383 478 1251 1382 477 1182 1385 480 1126 1337 432 1182 1385 480 1251 1382 477 1180 1381 476 1138 1386 481 1183 1387 482 1252 1388 483 1179 1379 474 1132 1360 455 1179 1379 474 1252 1388 483 1184 1389 484 1137 1380 475 1184 1389 484 1252 1388 483 1286 1390 485 1232 1391 486 1286 1390 485 1252 1388 483 1183 1387 482 1233 1392 487 1139 1393 488 1217 1394 489 1272 1395 490 1185 1396 491 1216 1397 492 1140 1398 493 1185 1396 491 1272 1395 490 1186 1399 494 1253 1400 495 1187 1401 496 1142 1402 497 1187 1401 496 1253 1400 495 1188 1403 498 1144 1404 499 1188 1403 498 1253 1400 495 1189 1405 500 1143 1406 501 1189 1405 500 1253 1400 495 1186 1399 494 1141 1407 502 1190 1408 503 1254 1409 504 1191 1410 505 1145 1411 506 1191 1410 505 1254 1409 504 1192 1412 507 1130 1356 451 1192 1412 507 1254 1409 504 1186 1399 494 1142 1402 497 1186 1399 494 1254 1409 504 1190 1408 503 1141 1407 502 1193 1413 508 1255 1414 509 1281 1415 510 1225 1416 511 1281 1415 510 1255 1414 509 1194 1417 512 1226 1418 513 1194 1417 512 1255 1414 509 1185 1396 491 1140 1398 493 1185 1396 491 1255 1414 509 1193 1413 508 1139 1393 488 1195 1419 514 1256 1420 515 1188 1403 498 1143 1406 501 1188 1403 498 1256 1420 515 1196 1421 516 1144 1404 499 1196 1421 516 1256 1420 515 1284 1422 517 1230 1423 518 1284 1422 517 1256 1420 515 1195 1419 514 1231 1424 519 1216 1397 492 1271 1425 520 1194 1417 512 1140 1398 493 1227 1426 521 1226 1418 513 1194 1417 512 1271 1425 520 1197 1427 522 1257 1428 523 1283 1429 524 1229 1430 525 1283 1429 524 1257 1428 523 1196 1421 516 1230 1423 518 1196 1421 516 1257 1428 523 1187 1401 496 1144 1404 499 1187 1401 496 1257 1428 523 1197 1427 522 1142 1402 497 1198 1431 526 1258 1432 527 1220 1326 421 1125 1327 422 1221 1433 528 1258 1432 527 1198 1431 526 1146 1434 529 1200 1435 530 1259 1436 531 1199 1437 532 1147 1438 533 1174 1362 457 1260 1439 534 1201 1440 535 1133 1364 459 1302 1441 536 1304 1442 537 1305 1443 538 1201 1440 535 1198 1431 526 1261 1444 539 1203 1445 540 1146 1434 529 1203 1445 540 1261 1444 539 1097 1446 541 1076 1447 542 1097 1446 541 1261 1444 539 1163 1329 424 1072 1331 426 1163 1329 424 1261 1444 539 1198 1431 526 1125 1327 422 1305 1443 538 1262 1448 543 1175 1365 460 1306 1368 463 1175 1365 460 1262 1448 543 1098 1449 544 1075 1370 465 1098 1449 544 1262 1448 543 1204 1450 545 1077 1451 546 1204 1450 545 1262 1448 543 1305 1443 538 1304 1442 537 1148 1452 547 1276 1453 548 1221 1433 528 1146 1434 529 1199 1437 532 1206 1454 549 1205 1455 550 1147 1438 533 1265 1456 551 1303 1457 552 1304 1442 537 1302 1441 536 1078 1458 553 1263 1459 554 1203 1445 540 1076 1447 542 1203 1445 540 1263 1459 554 1148 1452 547 1146 1434 529 1204 1450 545 1264 1460 555 1099 1461 556 1077 1451 546 1303 1457 552 1264 1460 555 1204 1450 545 1304 1442 537 1206 1454 549 1129 1340 435 1208 1339 434 1205 1455 550 1074 1350 445 1266 1349 444 1263 1459 554 1078 1458 553 1263 1459 554 1266 1349 444 1209 1344 439 1148 1452 547 1279 1462 557 1267 1463 558 1210 1464 559 1224 1465 560 1210 1464 559 1267 1463 558 1176 1372 467 1135 1374 469 1176 1372 467 1267 1463 558 1164 1334 429 1121 1312 407 1164 1334 429 1267 1463 558 1279 1462 557 1223 1335 430 1285 1466 561 1268 1467 562 1184 1389 484 1232 1391 486 1184 1389 484 1268 1467 562 1211 1468 563 1137 1380 475 1211 1468 563 1268 1467 562 1195 1419 514 1143 1406 501 1195 1419 514 1268 1467 562 1285 1466 561 1231 1424 519 1149 1469 564 1269 1470 565 1212 1471 566 1145 1411 506 1212 1471 566 1269 1470 565 1213 1472 567 1138 1386 481 1134 1373 468 1300 1473 568 1214 1474 569 1135 1374 469 1139 1393 488 1214 1474 569 1300 1473 568 1217 1394 489 1215 1475 570 1270 1476 571 1189 1405 500 1141 1407 502 1189 1405 500 1270 1476 571 1211 1468 563 1143 1406 501 1211 1468 563 1270 1476 571 1178 1377 472 1137 1380 475 1178 1377 472 1270 1476 571 1215 1475 570 1136 1378 473 1227 1426 521 1271 1425 520 1247 1352 447 1228 1351 446 1247 1352 447 1271 1425 520 1216 1397 492 1169 1355 450 1216 1397 492 1272 1395 490 1293 1477 572 1169 1355 450 1293 1477 572 1272 1395 490 1217 1394 489 1149 1469 564 1134 1373 468 1273 1371 466 1290 1478 573 1213 1472 567 1290 1478 573 1273 1371 466 1218 1311 406 1124 1320 415 1218 1311 406 1274 1314 409 1160 1317 412 1124 1320 415 1160 1317 412 1274 1314 409 1219 1290 388 1123 1318 413 1115 1479 393 1275 1480 574 1159 1315 410 1123 1318 413 1330 1481 575 1161 1321 416 1122 1322 417 1259 1436 531 1258 1432 527 1221 1433 528 1199 1437 532 1221 1433 528 1276 1453 548 1206 1454 549 1199 1437 532 1276 1453 548 1296 1343 438 1129 1340 435 1206 1454 549 1114 1482 403 1277 1307 402 1100 1483 576 1068 1484 577 1100 1483 576 1277 1307 402 1222 1310 405 1079 1485 578 1222 1310 405 1278 1332 427 1101 1486 579 1079 1485 578 1101 1486 579 1278 1332 427 1223 1335 430 1080 1487 580 1223 1335 430 1279 1462 557 1102 1488 581 1080 1487 580 1102 1488 581 1279 1462 557 1224 1465 560 1081 1489 582 1224 1465 560 1280 1490 583 1103 1491 584 1081 1489 582 1103 1491 584 1280 1490 583 1225 1416 511 1082 1492 585 1225 1416 511 1281 1415 510 1104 1493 586 1082 1492 585 1104 1493 586 1281 1415 510 1226 1418 513 1083 1494 587 1083 1494 587 1226 1418 513 1227 1426 521 1084 1495 588 1084 1495 588 1227 1426 521 1228 1351 446 1085 1496 589 1131 1354 449 1282 1497 590 1105 1498 591 1087 1499 592 1105 1498 591 1282 1497 590 1229 1430 525 1086 1500 593 1106 1501 594 1283 1429 524 1230 1423 518 1088 1502 595 1229 1430 525 1283 1429 524 1106 1501 594 1086 1500 593 1230 1423 518 1284 1422 517 1107 1503 596 1088 1502 595 1107 1503 596 1284 1422 517 1231 1424 519 1089 1504 597 1108 1505 598 1285 1466 561 1232 1391 486 1090 1506 599 1231 1424 519 1285 1466 561 1108 1505 598 1089 1504 597 1232 1391 486 1286 1390 485 1109 1507 600 1090 1506 599 1109 1507 600 1286 1390 485 1233 1392 487 1091 1508 601 1233 1392 487 1287 1288 386 1110 1287 385 1091 1508 601 1168 1345 440 1288 1509 602 1234 1510 603 1128 1342 437 1234 1510 603 1288 1509 602 1264 1460 555 1303 1457 552 1264 1460 555 1288 1509 602 1111 1511 604 1099 1461 556 1111 1511 604 1288 1509 602 1168 1345 440 1073 1348 443 1085 1496 589 1228 1351 446 1131 1354 449 1087 1499 592 1200 1435 530 1289 1512 605 1235 1384 479 1127 1513 606 1235 1384 479 1289 1512 605 1260 1439 534 1174 1362 457 1260 1439 534 1289 1512 605 1236 1514 607 1202 1515 608 1236 1514 607 1289 1512 605 1200 1435 530 1147 1438 533 1213 1472 567 1290 1478 573 1182 1385 480 1138 1386 481 1126 1337 432 1182 1385 480 1290 1478 573 1124 1320 415 1205 1455 550 1291 1516 609 1236 1514 607 1147 1438 533 1236 1514 607 1291 1516 609 1207 1517 610 1202 1515 608 1215 1475 570 1292 1518 611 1180 1381 476 1136 1378 473 1180 1381 476 1292 1518 611 1212 1471 566 1138 1386 481 1212 1471 566 1292 1518 611 1190 1408 503 1145 1411 506 1190 1408 503 1292 1518 611 1215 1475 570 1141 1407 502 1208 1339 434 1294 1519 612 1291 1516 609 1205 1455 550 1291 1516 609 1294 1519 612 1265 1456 551 1207 1517 610 1169 1355 450 1293 1477 572 1191 1410 505 1130 1356 451 1191 1410 505 1293 1477 572 1149 1469 564 1145 1411 506 1234 1510 603 1294 1519 612 1208 1339 434 1128 1342 437 1282 1497 590 1295 1520 613 1197 1427 522 1229 1430 525 1197 1427 522 1295 1520 613 1192 1412 507 1142 1402 497 1192 1412 507 1295 1520 613 1170 1353 448 1130 1356 451 1170 1353 448 1295 1520 613 1282 1497 590 1131 1354 449 1209 1344 439 1296 1343 438 1276 1453 548 1148 1452 547 1219 1290 388 1297 1293 391 1115 1521 393 1123 1318 413 1235 1384 479 1181 1383 478 1126 1337 432 1165 1336 431 1127 1513 606 1183 1387 482 1298 1522 614 1287 1288 386 1233 1392 487 1287 1288 386 1298 1522 614 1239 1285 383 1239 1285 383 1298 1522 614 1310 1286 384 1172 1359 454 1298 1522 614 1183 1387 482 1132 1360 455 1210 1464 559 1299 1523 615 1280 1490 583 1224 1465 560 1280 1490 583 1299 1523 615 1193 1413 508 1225 1416 511 1193 1413 508 1299 1523 615 1214 1474 569 1139 1393 488 1214 1474 569 1299 1523 615 1210 1464 559 1135 1374 469 1217 1394 489 1300 1473 568 1269 1470 565 1149 1469 564 1269 1470 565 1300 1473 568 1134 1373 468 1213 1472 567 1301 1361 456 1177 1375 470 1251 1382 477 1181 1383 478 1171 1357 452 1250 1376 471 1177 1375 470 1301 1361 456 1202 1515 608 1207 1517 610 1265 1456 551 1302 1441 536 1201 1440 535 1260 1439 534 1202 1515 608 1302 1441 536 1265 1456 551 1294 1519 612 1234 1510 603 1303 1457 552 1201 1440 535 1305 1443 538 1306 1368 463 1133 1364 459 1307 1367 462 1173 1363 458 1133 1364 459 1306 1368 463 1173 1363 458 1307 1367 462 1308 1283 381 1152 1278 376 1152 1278 376 1308 1283 381 1309 1284 382 1117 1276 374 1310 1286 384 1116 1274 372 1117 1276 374 1309 1284 382 1298 1522 614 1172 1359 454 1116 1274 372 1310 1286 384 1068 1524 1843 1319 1525 1844 1318 1526 1845 1114 1527 1846 902 1272 1841 1321 1528 1847 1318 1526 1845 906 1027 1716 902 1272 1841 906 1027 1716 1311 1026 1715 901 1273 1842 1311 1026 1715 899 1022 1711 900 1024 1713 901 1273 1842 898 1023 1712 899 1022 1711 1311 1026 1715 1312 1025 1714 1113 1529 1848 1322 1530 1849 1323 1531 1850 1115 1532 1851 1313 1013 1702 1324 1533 1852 1323 1531 1850 904 1270 1839 1316 1534 1853 1325 1535 1854 1326 1536 1855 1317 1537 1856 1315 1538 1857 1320 1539 1858 1332 1540 1859 897 1018 1707 903 1271 1840 1322 1530 1849 1321 1528 1847 902 1272 1841 895 1014 1703 1325 1535 1854 1324 1533 1852 1313 1013 1702 1159 1315 410 1275 1541 574 1316 1542 616 1122 1322 417 1120 1296 394 1119 1325 420 1317 1543 617 1112 1544 395 1314 1016 1705 1327 1545 1860 1326 1536 1855 896 1015 1704 1317 1546 617 1119 1325 420 1122 1322 417 1316 1547 616 906 1027 1716 1318 1526 1845 1319 1525 1844 905 1028 1717 1150 1548 1861 1332 1540 1859 1320 1539 1858 1069 1549 1862 1114 1550 1846 1318 1526 1845 1321 1528 1847 1156 1551 1863 1156 1552 1863 1321 1528 1847 1322 1530 1849 1113 1553 1848 904 1270 1839 1323 1531 1850 1322 1530 1849 903 1271 1840 1115 1554 1851 1323 1531 1850 1324 1533 1852 1275 1555 1864 1275 1556 1864 1324 1533 1852 1325 1535 1854 1316 1557 1853 896 1015 1704 1326 1536 1855 1325 1535 1854 895 1014 1703 1317 1558 1856 1326 1536 1855 1327 1545 1860 1112 1559 1865 1112 1560 1865 1327 1545 1860 1332 1540 1859 1150 1561 1861 1328 1562 618 1259 1436 531 1200 1435 530 1127 1513 606 1220 1326 421 1258 1432 527 1259 1436 531 1328 1562 618 1329 1563 619 1242 1324 419 1220 1326 421 1328 1562 618 1166 1338 433 1328 1562 618 1127 1513 606 1165 1336 431 1330 1481 575 1329 1563 619 1328 1562 618 1166 1338 433 1119 1325 420 1329 1563 619 1330 1481 575 1122 1322 417 1119 1325 420 1242 1324 419 1329 1563 619 1161 1321 416 1330 1481 575 1166 1338 433 1245 1319 414 1314 1016 1705 897 1018 1707 1332 1540 1859 1327 1545 1860 720 830 1519 721 832 1521 1333 849 1538 734 848 1537 734 848 1537 1333 849 1538 1334 863 1552 747 862 1551 747 862 1551 1334 863 1552 1335 877 1566 760 876 1565 760 876 1565 1335 877 1566 1336 891 1580 773 890 1579 773 890 1579 1336 891 1580 2 361 1172 786 904 1593 786 904 1593 2 361 1172 86 364 1175 798 916 1605 884 1002 1691 320 1020 1709 1337 1017 1706 891 1009 1698 696 807 1496 709 810 1499 1349 1564 1866 1338 1565 1867 1338 1565 1867 1349 1564 1866 1350 1566 1868 1339 1567 1869 1339 1567 1869 1350 1566 1868 1351 1568 1870 1340 1569 1871 1340 1569 1871 1351 1568 1870 1352 1570 1872 1341 1571 1873 1341 1571 1873 1352 1570 1872 1353 1572 1874 1342 1573 1875 1342 1573 1875 1353 1572 1874 1354 1574 1876 1343 1575 1877 1343 1575 1877 1354 1574 1876 1355 1576 1878 1344 1577 1879 1344 1577 1879 1355 1576 1878 1356 1578 1880 1345 1579 1881 1345 1579 1881 1356 1578 1880 1357 1580 1882 1346 1581 1883 1346 1581 1883 1357 1580 1882 1358 1582 1884 1347 1583 1885 1347 1583 1885 1358 1582 1884 1359 1584 1886 1348 1585 1887 1348 1585 1887 1359 1584 1886 1360 1586 1888 1897 1587 1889 1897 1587 1889 1360 1586 1888 1972 1588 1890 1973 1589 1891 709 810 1499 723 838 1527 1361 1590 1892 1349 1564 1866 1349 1564 1866 1361 1590 1892 1362 1591 1893 1350 1566 1868 1350 1566 1868 1362 1591 1893 1363 1592 1894 1351 1568 1870 1351 1568 1870 1363 1592 1894 1364 1593 1895 1352 1570 1872 1352 1570 1872 1364 1593 1895 1365 1594 1896 1353 1572 1874 1353 1572 1874 1365 1594 1896 1366 1595 1897 1354 1574 1876 1354 1574 1876 1366 1595 1897 1367 1596 1898 1355 1576 1878 1355 1576 1878 1367 1596 1898 1368 1597 1899 1356 1578 1880 1356 1578 1880 1368 1597 1899 1369 1598 1900 1357 1580 1882 1357 1580 1882 1369 1598 1900 1370 1599 1901 1358 1582 1884 1358 1582 1884 1370 1599 1901 1371 1600 1902 1359 1584 1886 1360 1586 1888 1899 1601 1903 1975 1602 1904 1972 1588 1890 723 838 1527 736 852 1541 1372 1603 1905 1361 1590 1892 1361 1590 1892 1372 1603 1905 1373 1604 1906 1362 1591 1893 1362 1591 1893 1373 1604 1906 1374 1605 1907 1363 1592 1894 1363 1592 1894 1374 1605 1907 1375 1606 1908 1364 1593 1895 1364 1593 1895 1375 1606 1908 1376 1607 1909 1365 1594 1896 1365 1594 1896 1376 1607 1909 1377 1608 1910 1366 1595 1897 1366 1595 1897 1377 1608 1910 1378 1609 1911 1367 1596 1898 1367 1596 1898 1378 1609 1911 1379 1610 1912 1368 1597 1899 1368 1597 1899 1379 1610 1912 1380 1611 1913 1369 1598 1900 1369 1598 1900 1380 1611 1913 1381 1612 1914 1370 1599 1901 1370 1599 1901 1381 1612 1914 1382 1613 1915 1371 1600 1902 1899 1601 1903 1900 1614 1916 1976 1615 1917 1975 1602 1904 736 852 1541 749 866 1555 1383 1616 1918 1372 1603 1905 1372 1603 1905 1383 1616 1918 1384 1617 1919 1373 1604 1906 1373 1604 1906 1384 1617 1919 1385 1618 1920 1374 1605 1907 1374 1605 1907 1385 1618 1920 1386 1619 1921 1375 1606 1908 1375 1606 1908 1386 1619 1921 1387 1620 1922 1376 1607 1909 1376 1607 1909 1387 1620 1922 1388 1621 1923 1377 1608 1910 1377 1608 1910 1388 1621 1923 1389 1622 1924 1378 1609 1911 1378 1609 1911 1389 1622 1924 1390 1623 1925 1379 1610 1912 1379 1610 1912 1390 1623 1925 1391 1624 1926 1380 1611 1913 1380 1611 1913 1391 1624 1926 1392 1625 1927 1381 1612 1914 1381 1612 1914 1392 1625 1927 1393 1626 1928 1382 1613 1915 1900 1614 1916 1901 1627 1929 1977 1628 1930 1976 1615 1917 749 866 1555 762 880 1569 1394 1629 1931 1383 1616 1918 1383 1616 1918 1394 1629 1931 1395 1630 1932 1384 1617 1919 1384 1617 1919 1395 1630 1932 1396 1631 1933 1385 1618 1920 1385 1618 1920 1396 1631 1933 1397 1632 1934 1386 1619 1921 1386 1619 1921 1397 1632 1934 1398 1633 1935 1387 1620 1922 1387 1620 1922 1398 1633 1935 1399 1634 1936 1388 1621 1923 1388 1621 1923 1399 1634 1936 1400 1635 1937 1389 1622 1924 1389 1622 1924 1400 1635 1937 1401 1636 1938 1390 1623 1925 1390 1623 1925 1401 1636 1938 1402 1637 1939 1391 1624 1926 1391 1624 1926 1402 1637 1939 1403 1638 1940 1392 1625 1927 1392 1625 1927 1403 1638 1940 1404 1639 1941 1393 1626 1928 1901 1627 1929 1902 1640 1942 1974 1641 1943 1977 1628 1930 762 880 1569 775 894 1583 1405 1642 1944 1394 1629 1931 1394 1629 1931 1405 1642 1944 1406 1643 1945 1395 1630 1932 1395 1630 1932 1406 1643 1945 1407 1644 1946 1396 1631 1933 1396 1631 1933 1407 1644 1946 1408 1645 1947 1397 1632 1934 1397 1632 1934 1408 1645 1947 1409 1646 1948 1398 1633 1935 1398 1633 1935 1409 1646 1948 1410 1647 1949 1399 1634 1936 1399 1634 1936 1410 1647 1949 1411 1648 1950 1400 1635 1937 1400 1635 1937 1411 1648 1950 1412 1649 1951 1401 1636 1938 1401 1636 1938 1412 1649 1951 1413 1650 1952 1402 1637 1939 1402 1637 1939 1413 1650 1952 1414 1651 1953 1403 1638 1940 1403 1638 1940 1414 1651 1953 1415 1652 1954 1404 1639 1941 2043 435 1231 2044 1653 1955 1974 1641 1943 434 436 1232 775 894 1583 787 906 1595 1416 1654 1956 1405 1642 1944 1405 1642 1944 1416 1654 1956 1417 1655 1957 1406 1643 1945 1406 1643 1945 1417 1655 1957 1418 1656 1958 1407 1644 1946 1407 1644 1946 1418 1656 1958 1419 1657 1959 1408 1645 1947 1408 1645 1947 1419 1657 1959 1420 1658 1960 1409 1646 1948 1409 1646 1948 1420 1658 1960 1421 1659 1961 1410 1647 1949 1410 1647 1949 1421 1659 1961 1422 1660 1962 1411 1648 1950 1411 1648 1950 1422 1660 1962 1423 1661 1963 1412 1649 1951 1412 1649 1951 1423 1661 1963 1424 1662 1964 1413 1650 1952 1413 1650 1952 1424 1662 1964 1425 1663 1965 1414 1651 1953 1414 1651 1953 1425 1663 1965 1426 1664 1966 1415 1652 1954 787 906 1595 799 918 1607 1427 1665 1967 1416 1654 1956 1416 1654 1956 1427 1665 1967 1428 1666 1968 1417 1655 1957 1417 1655 1957 1428 1666 1968 1429 1667 1969 1418 1656 1958 1418 1656 1958 1429 1667 1969 1430 1668 1970 1419 1657 1959 1419 1657 1959 1430 1668 1970 1431 1669 1971 1420 1658 1960 1420 1658 1960 1431 1669 1971 1432 1670 1972 1421 1659 1961 1421 1659 1961 1432 1670 1972 1433 1671 1973 1422 1660 1962 1422 1660 1962 1433 1671 1973 1434 1672 1974 1423 1661 1963 1423 1661 1963 1434 1672 1974 1435 1673 1975 1424 1662 1964 1424 1662 1964 1435 1673 1975 1436 1674 1976 1425 1663 1965 1425 1663 1965 1436 1674 1976 1437 1675 1977 1426 1664 1966 799 918 1607 811 930 1619 1438 1676 1978 1427 1665 1967 1427 1665 1967 1438 1676 1978 1439 1677 1979 1428 1666 1968 1428 1666 1968 1439 1677 1979 1440 1678 1980 1429 1667 1969 1429 1667 1969 1440 1678 1980 1441 1679 1981 1430 1668 1970 1430 1668 1970 1441 1679 1981 1442 1680 1982 1431 1669 1971 1431 1669 1971 1442 1680 1982 1443 1681 1983 1432 1670 1972 1432 1670 1972 1443 1681 1983 1444 1682 1984 1433 1671 1973 1433 1671 1973 1444 1682 1984 1445 1683 1985 1434 1672 1974 1434 1672 1974 1445 1683 1985 1446 1684 1986 1435 1673 1975 1435 1673 1975 1446 1684 1986 1447 1685 1987 1436 1674 1976 1436 1674 1976 1447 1685 1987 1448 1686 1988 1437 1675 1977 811 930 1619 823 942 1631 1449 1687 1989 1438 1676 1978 1438 1676 1978 1449 1687 1989 1450 1688 1990 1439 1677 1979 1439 1677 1979 1450 1688 1990 1451 1689 1991 1440 1678 1980 1440 1678 1980 1451 1689 1991 1452 1690 1992 1441 1679 1981 1441 1679 1981 1452 1690 1992 1453 1691 1993 1442 1680 1982 1442 1680 1982 1453 1691 1993 1454 1692 1994 1443 1681 1983 1443 1681 1983 1454 1692 1994 1455 1693 1995 1444 1682 1984 1444 1682 1984 1455 1693 1995 1456 1694 1996 1445 1683 1985 1445 1683 1985 1456 1694 1996 1457 1695 1997 1446 1684 1986 1446 1684 1986 1457 1695 1997 1458 1696 1998 1447 1685 1987 1447 1685 1987 1458 1696 1998 1459 1697 1999 1448 1686 1988 823 942 1631 846 954 1643 1460 1698 2000 1449 1687 1989 1449 1687 1989 1460 1698 2000 1461 1699 2001 1450 1688 1990 1450 1688 1990 1461 1699 2001 1462 1700 2002 1451 1689 1991 1451 1689 1991 1462 1700 2002 1463 1701 2003 1452 1690 1992 1452 1690 1992 1463 1701 2003 1464 1702 2004 1453 1691 1993 1453 1691 1993 1464 1702 2004 1465 1703 2005 1454 1692 1994 1454 1692 1994 1465 1703 2005 1466 1704 2006 1455 1693 1995 1455 1693 1995 1466 1704 2006 1467 1705 2007 1456 1694 1996 1456 1694 1996 1467 1705 2007 1468 1706 2008 1457 1695 1997 1457 1695 1997 1468 1706 2008 1469 1707 2009 1458 1696 1998 1458 1696 1998 1469 1707 2009 1470 1708 2010 1459 1697 1999 846 954 1643 847 966 1655 1471 1709 2011 1460 1698 2000 1460 1698 2000 1471 1709 2011 1472 1710 2012 1461 1699 2001 1461 1699 2001 1472 1710 2012 1473 1711 2013 1462 1700 2002 1462 1700 2002 1473 1711 2013 1474 1712 2014 1463 1701 2003 1463 1701 2003 1474 1712 2014 1475 1713 2015 1464 1702 2004 1464 1702 2004 1475 1713 2015 1476 1714 2016 1465 1703 2005 1465 1703 2005 1476 1714 2016 1477 1715 2017 1466 1704 2006 1466 1704 2006 1477 1715 2017 1478 1716 2018 1467 1705 2007 1467 1705 2007 1478 1716 2018 1479 1717 2019 1468 1706 2008 1468 1706 2008 1479 1717 2019 1480 1718 2020 1469 1707 2009 1469 1707 2009 1480 1718 2020 1481 1719 2021 1470 1708 2010 847 966 1655 859 978 1667 1482 1720 2022 1471 1709 2011 1471 1709 2011 1482 1720 2022 1483 1721 2023 1472 1710 2012 1472 1710 2012 1483 1721 2023 1484 1722 2024 1473 1711 2013 1476 1714 2016 1485 1723 2025 1477 1715 2017 1477 1715 2017 1485 1723 2025 1488 1724 2026 1478 1716 2018 1478 1716 2018 1488 1724 2026 1489 1725 2027 1479 1717 2019 1479 1717 2019 1489 1725 2027 1490 1726 2028 1480 1718 2020 1480 1718 2020 1490 1726 2028 1491 1727 2029 1481 1719 2021 859 978 1667 868 987 1676 1486 1728 2030 1482 1720 2022 1482 1720 2022 1486 1728 2030 1487 1729 2031 1483 1721 2023 868 987 1676 871 990 1679 1492 1730 2032 1486 1728 2030 1486 1728 2030 1492 1730 2032 1493 1731 2033 1487 1729 2031 1495 1732 2034 1489 1725 2027 1488 1724 2026 1494 1733 2035 1489 1725 2027 1495 1732 2034 1496 1734 2036 1490 1726 2028 1490 1726 2028 1496 1734 2036 1497 1735 2037 1491 1727 2029 871 990 1679 878 997 1686 1498 1736 2038 1492 1730 2032 1492 1730 2032 1498 1736 2038 1499 1737 2039 1493 1731 2033 1501 1738 2040 1495 1732 2034 1494 1733 2035 1500 1739 2041 1495 1732 2034 1501 1738 2040 1502 1740 2042 1496 1734 2036 1496 1734 2036 1502 1740 2042 1503 1741 2043 1497 1735 2037 878 997 1686 885 1004 1693 1504 1742 2044 1498 1736 2038 1498 1736 2038 1504 1742 2044 1505 1743 2045 1499 1737 2039 1507 1744 2046 1501 1738 2040 1500 1739 2041 1506 1745 2047 1501 1738 2040 1507 1744 2046 1508 1746 2048 1502 1740 2042 1502 1740 2042 1508 1746 2048 1509 1747 2049 1503 1741 2043 885 1004 1693 892 1011 1700 1510 1748 2050 1504 1742 2044 1504 1742 2044 1510 1748 2050 1511 1749 2051 1505 1743 2045 1882 1750 2052 1512 1751 2053 1507 1744 2046 1506 1745 2047 1507 1744 2046 1512 1751 2053 1513 1752 2054 1508 1746 2048 1508 1746 2048 1513 1752 2054 1883 1753 2055 1509 1747 2049 1509 1747 2049 1883 1753 2055 1514 1754 2056 1904 1755 2057 1904 1755 2057 1985 1019 1708 1986 1021 1710 1903 1756 2058 892 1011 1700 898 1023 1712 1515 1757 2059 1510 1748 2050 1510 1748 2050 1515 1757 2059 1516 1758 2060 1511 1749 2051 1312 1025 1714 905 1028 1717 1521 1759 2061 1881 1760 2062 1338 1565 1867 907 1029 1718 696 807 1496 1339 1567 1869 907 1029 1718 1338 1565 1867 1340 1569 1871 907 1029 1718 1339 1567 1869 1341 1571 1873 907 1029 1718 1340 1569 1871 1342 1573 1875 907 1029 1718 1341 1571 1873 1343 1575 1877 907 1029 1718 1342 1573 1875 1344 1577 1879 907 1029 1718 1343 1575 1877 1345 1579 1881 907 1029 1718 1344 1577 1879 1346 1581 1883 907 1029 1718 1345 1579 1881 1347 1583 1885 907 1029 1718 1346 1581 1883 1348 1585 1887 907 1029 1718 1347 1583 1885 1348 1585 1887 1897 1587 1889 907 1029 1718 1973 1589 1891 907 1029 1718 1897 1587 1889 1555 1761 692 1621 1762 693 1658 1763 694 1594 1764 695 1621 1762 693 1555 1761 692 1570 1765 696 1642 1766 697 1556 1767 698 1621 1762 693 1642 1766 697 1572 1768 699 1621 1762 693 1556 1767 698 1595 1769 700 1658 1763 694 1557 1770 701 1622 1771 702 1657 1772 703 1593 1773 704 1622 1771 702 1557 1770 701 1569 1774 705 1643 1775 706 1555 1761 692 1622 1771 702 1643 1775 706 1570 1765 696 1622 1771 702 1555 1761 692 1594 1764 695 1657 1772 703 1558 1776 707 1623 1777 708 1656 1778 709 1592 1779 710 1623 1777 708 1558 1776 707 1567 1780 711 1641 1781 712 1557 1770 701 1623 1777 708 1641 1781 712 1569 1774 705 1623 1777 708 1557 1770 701 1593 1773 704 1656 1778 709 1559 1782 713 1624 1783 714 1655 1784 715 1591 1785 716 1624 1783 714 1559 1782 713 1574 1786 717 1644 1787 718 1558 1776 707 1624 1783 714 1644 1787 718 1567 1780 711 1624 1783 714 1558 1776 707 1592 1779 710 1655 1784 715 1625 1788 719 1560 1789 720 1578 1790 721 1646 1791 722 1559 1782 713 1625 1788 719 1646 1791 722 1574 1786 717 1625 1788 719 1681 1792 723 1680 1793 724 1560 1789 720 1561 1794 725 1626 1795 726 1654 1796 727 1590 1797 728 1626 1795 726 1561 1794 725 1582 1798 729 1648 1799 730 1560 1789 720 1626 1795 726 1648 1799 730 1578 1790 721 1626 1795 726 1560 1789 720 1680 1793 724 1654 1796 727 1562 1800 731 1627 1801 732 1653 1802 733 1589 1803 734 1627 1801 732 1562 1800 731 1585 1804 735 1650 1805 736 1561 1794 725 1627 1801 732 1650 1805 736 1582 1798 729 1627 1801 732 1561 1794 725 1590 1797 728 1653 1802 733 1563 1806 737 1628 1807 738 1652 1808 739 1587 1809 740 1628 1807 738 1563 1806 737 1581 1810 741 1649 1811 742 1562 1800 731 1628 1807 738 1649 1811 742 1585 1804 735 1628 1807 738 1562 1800 731 1589 1803 734 1652 1808 739 1564 1812 743 1629 1813 744 1651 1814 745 1588 1815 746 1629 1813 744 1564 1812 743 1577 1816 747 1647 1817 748 1563 1806 737 1629 1813 744 1647 1817 748 1581 1810 741 1629 1813 744 1563 1806 737 1587 1809 740 1651 1814 745 1556 1767 698 1630 1818 749 1659 1819 750 1595 1769 700 1630 1818 749 1556 1767 698 1572 1768 699 1645 1820 752 1564 1812 743 1630 1818 749 1645 1820 752 1577 1816 747 1630 1818 749 1564 1812 743 1588 1815 746 1659 1819 750 1658 1763 694 1595 1769 700 1587 1809 740 1652 1808 739 1662 1821 2063 1600 1822 2064 1927 1823 2065 1926 1824 2066 1631 1825 2067 1537 1826 2068 1925 1827 2069 1926 1824 2066 1664 1828 2070 1604 1829 2071 1934 1830 2072 1932 1831 2073 1632 1832 2074 1539 1833 2075 1930 1834 2076 1932 1831 2073 1665 1835 2077 1523 1836 2078 1930 1834 2076 1928 1837 2079 1633 1838 2080 1565 1839 2081 1927 1823 2065 1928 1837 2079 1666 1840 2082 1522 1841 2083 1925 1827 2069 1929 1842 2084 1634 1843 2085 1538 1844 2086 1931 1845 2087 1929 1842 2084 1667 1846 2088 1524 1847 2089 1931 1845 2087 1933 1848 2090 1635 1849 2091 1540 1850 2092 1935 1851 2093 1933 1848 2090 1636 1852 2094 1541 1853 2095 1939 1854 2096 1937 1855 2097 1660 1856 2098 1596 1857 2099 1935 1851 2093 1937 1855 2097 1661 1858 2100 1598 1859 2101 1939 1854 2096 1941 1860 2102 1637 1861 2103 1543 1862 2104 1943 1863 2105 1941 1860 2102 1668 1864 2106 1525 1865 2107 1943 1863 2105 1944 1866 2108 1638 1867 2109 1544 1868 2110 1942 1869 2111 1944 1866 2108 1663 1870 2112 1602 1871 2113 1942 1869 2111 1940 1872 2114 1639 1873 2115 1542 1874 2116 1938 1875 2117 1940 1872 2114 1669 1876 2118 1526 1877 2119 1938 1875 2117 1936 1878 2120 1640 1879 2121 1566 1880 2122 1934 1830 2072 1936 1878 2120 1567 1780 711 1528 1881 944 1568 1882 949 1641 1781 712 1568 1883 949 1527 1884 947 1569 1774 705 1641 1781 712 1570 1765 696 1530 1885 946 1571 1886 948 1642 1766 697 1571 1887 948 1529 1888 942 1572 1768 699 1642 1766 697 1569 1774 705 1527 1889 947 1573 1890 945 1643 1775 706 1573 1891 945 1530 1892 946 1570 1765 696 1643 1775 706 1574 1786 717 1531 1893 940 1575 1894 943 1644 1787 718 1575 1895 943 1528 1896 944 1567 1780 711 1644 1787 718 1572 1768 699 1529 1897 942 1576 1898 941 1645 1820 752 1576 1899 941 1532 1900 938 1577 1816 747 1645 1820 752 1578 1790 721 1533 1901 936 1579 1902 939 1646 1791 722 1579 1903 939 1531 1904 940 1574 1786 717 1646 1791 722 1577 1816 747 1532 1905 938 1580 1906 937 1647 1817 748 1580 1907 937 1534 1908 934 1581 1810 741 1647 1817 748 1582 1798 729 1535 1909 931 1583 1910 935 1648 1799 730 1583 1911 935 1533 1912 936 1578 1790 721 1648 1799 730 1581 1810 741 1534 1913 934 1584 1914 933 1649 1811 742 1584 1915 933 1536 1916 932 1585 1804 735 1649 1811 742 1585 1804 735 1536 1917 932 1586 1918 930 1650 1805 736 1586 1919 930 1535 1920 931 1582 1798 729 1650 1805 736 1568 1921 2123 1528 1922 2124 1538 1844 2086 1634 1843 2085 1568 1923 2123 1634 1843 2085 1537 1826 2068 1527 1924 2125 1571 1925 2126 1530 1926 2127 1565 1839 2081 1633 1838 2080 1571 1927 2126 1633 1838 2080 1539 1833 2075 1529 1928 2128 1573 1929 2129 1527 1930 2125 1537 1826 2068 1631 1825 2067 1573 1931 2129 1631 1825 2067 1565 1839 2081 1530 1932 2127 1575 1933 2130 1531 1934 2131 1540 1850 2092 1635 1849 2091 1575 1935 2130 1635 1849 2091 1538 1844 2086 1528 1936 2124 1576 1937 2132 1529 1938 2128 1539 1833 2075 1632 1832 2074 1576 1939 2132 1632 1832 2074 1566 1880 2122 1532 1940 2133 1579 1941 2134 1533 1942 2135 1541 1853 2095 1636 1852 2094 1579 1943 2134 1636 1852 2094 1540 1850 2092 1531 1944 2131 1580 1945 2136 1532 1946 2133 1566 1880 2122 1640 1879 2121 1580 1947 2136 1640 1879 2121 1542 1874 2116 1534 1948 2137 1583 1949 2138 1535 1950 2139 1543 1862 2104 1637 1861 2103 1583 1951 2138 1637 1861 2103 1541 1853 2095 1533 1952 2135 1584 1953 2140 1534 1954 2137 1542 1874 2116 1639 1873 2115 1584 1955 2140 1639 1873 2115 1544 1868 2110 1536 1956 2141 1586 1957 2142 1536 1958 2141 1544 1868 2110 1638 1867 2109 1586 1959 2142 1638 1867 2109 1543 1862 2104 1535 1960 2139 1598 1859 2101 1546 1961 2143 1610 1962 2144 1660 1856 2098 1610 1962 2144 1545 1963 2145 1596 1857 2099 1660 1856 2098 1525 1865 2107 1547 1964 2146 1597 1965 2147 1661 1858 2100 1597 1965 2147 1546 1961 2143 1598 1859 2101 1661 1858 2100 1522 1841 2083 1549 1966 2148 1599 1967 2149 1662 1821 2063 1599 1967 2149 1548 1968 2150 1600 1822 2064 1662 1821 2063 1526 1877 2119 1551 1969 2151 1601 1970 2152 1663 1870 2112 1601 1970 2152 1550 1971 2153 1602 1871 2113 1663 1870 2112 1523 1836 2078 1553 1972 2154 1603 1973 2155 1664 1828 2070 1603 1973 2155 1552 1974 2156 1604 1829 2071 1664 1828 2070 1600 1822 2064 1548 1968 2150 1605 1975 2157 1665 1835 2077 1605 1975 2157 1553 1972 2154 1523 1836 2078 1665 1835 2077 1524 1847 2089 1554 1976 2158 1606 1977 2159 1666 1840 2082 1606 1977 2159 1549 1966 2148 1522 1841 2083 1666 1840 2082 1596 1857 2099 1545 1963 2145 1607 1978 2160 1667 1846 2088 1607 1978 2160 1554 1976 2158 1524 1847 2089 1667 1846 2088 1602 1871 2113 1550 1971 2153 1608 1979 2161 1668 1864 2106 1608 1979 2161 1547 1964 2146 1525 1865 2107 1668 1864 2106 1604 1829 2071 1552 1974 2156 1609 1980 2162 1669 1876 2118 1609 1980 2162 1551 1969 2151 1526 1877 2119 1669 1876 2118 1610 1962 2144 1546 1961 2143 1611 1981 2163 1670 1982 2164 1612 1983 2165 1545 1963 2145 1610 1962 2144 1670 1982 2164 1597 1965 2147 1547 1964 2146 1613 1984 2166 1671 1985 2167 1611 1981 2163 1546 1961 2143 1597 1965 2147 1671 1985 2167 1599 1967 2149 1549 1966 2148 1614 1986 2168 1672 1987 2169 1615 1988 2170 1548 1968 2150 1599 1967 2149 1672 1987 2169 1601 1970 2152 1551 1969 2151 1616 1989 2171 1673 1990 2172 1617 1991 2173 1550 1971 2153 1601 1970 2152 1673 1990 2172 1603 1973 2155 1553 1972 2154 1618 1992 2174 1674 1993 2175 1619 1994 2176 1552 1974 2156 1603 1973 2155 1674 1993 2175 1605 1975 2157 1548 1968 2150 1615 1988 2170 1675 1995 2177 1618 1992 2174 1553 1972 2154 1605 1975 2157 1675 1995 2177 1606 1977 2159 1554 1976 2158 1620 1996 2178 1676 1997 2179 1614 1986 2168 1549 1966 2148 1606 1977 2159 1676 1997 2179 1607 1978 2160 1545 1963 2145 1612 1983 2165 1677 1998 2180 1620 1996 2178 1554 1976 2158 1607 1978 2160 1677 1998 2180 1608 1979 2161 1550 1971 2153 1617 1991 2173 1678 1999 2181 1613 1984 2166 1547 1964 2146 1608 1979 2161 1678 1999 2181 1609 1980 2162 1552 1974 2156 1619 1994 2176 1679 2000 2182 1616 1989 2171 1551 1969 2151 1609 1980 2162 1679 2000 2182 1587 1809 740 1595 1769 700 1659 1819 750 1588 1815 746 1651 1814 745 1594 1764 695 1589 1803 734 1653 1802 733 1657 1772 703 1658 1763 694 1652 1808 739 1589 1803 734 1594 1764 695 1657 1772 703 1653 1802 733 1590 1797 728 1593 1773 704 1592 1779 710 1680 1793 724 1681 1792 723 1591 1785 716 1655 1784 715 1593 1773 704 1590 1797 728 1654 1796 727 1656 1778 709 1625 1788 719 1559 1782 713 1591 1785 716 1681 1792 723 1592 1779 710 1656 1778 709 1654 1796 727 1680 1793 724 1611 1981 2163 1519 2001 2183 1520 2002 2184 1670 1982 2164 1670 1982 2164 1520 2002 2184 1882 1750 2052 1612 1983 2165 1613 1984 2166 1517 2003 2185 1518 2004 2186 1671 1985 2167 1614 1986 2168 1488 1724 2026 1485 1723 2025 1672 1987 2169 1672 1987 2169 1485 1723 2025 1476 1714 2016 1615 1988 2170 1616 1989 2171 1499 1737 2039 1505 1743 2045 1673 1990 2172 1673 1990 2172 1505 1743 2045 1511 1749 2051 1617 1991 2173 1618 1992 2174 1474 1712 2014 1484 1722 2024 1674 1993 2175 1674 1993 2175 1484 1722 2024 1487 1729 2031 1619 1994 2176 1615 1988 2170 1476 1714 2016 1475 1713 2015 1675 1995 2177 1675 1995 2177 1475 1713 2015 1474 1712 2014 1618 1992 2174 1620 1996 2178 1500 1739 2041 1494 1733 2035 1676 1997 2179 1676 1997 2179 1494 1733 2035 1488 1724 2026 1614 1986 2168 1677 1998 2180 1506 1745 2047 1500 1739 2041 1620 1996 2178 1617 1991 2173 1511 1749 2051 1516 1758 2060 1678 1999 2181 1678 1999 2181 1516 1758 2060 1517 2003 2185 1613 1984 2166 1619 1994 2176 1487 1729 2031 1493 1731 2033 1679 2000 2182 1679 2000 2182 1493 1731 2033 1499 1737 2039 1616 1989 2171 1671 1985 2167 1518 2004 2186 1519 2001 2183 1611 1981 2163 1487 1729 2031 1484 1722 2024 1483 1721 2023 1484 1722 2024 1474 1712 2014 1473 1711 2013 1677 1998 2180 1612 1983 2165 1882 1750 2052 1506 1745 2047 1807 2005 620 1687 2006 621 1721 2007 622 1721 2007 622 1687 2006 621 1722 2008 623 1807 2005 620 1723 2009 624 1070 1282 380 1092 1281 379 1808 2010 625 1878 2011 626 1879 2012 627 1723 2009 624 1808 2010 625 1723 2009 624 1879 2012 627 1880 2013 628 1809 2014 629 1110 1287 385 1093 1289 387 1809 2014 629 1857 2015 630 1093 1289 387 1070 1282 380 1723 2009 624 1809 2014 629 1789 2016 631 1867 2017 632 1724 2018 633 1688 2019 634 1683 2020 635 1724 2018 633 1867 2017 632 1685 2021 636 1690 2022 637 1725 2023 638 1720 2024 639 1682 2025 640 1071 1300 398 1069 2026 399 1720 2027 639 1725 2023 638 1724 2018 633 1683 2028 635 1726 2029 641 1810 2030 642 1726 2031 641 1684 2032 643 1847 2033 644 1810 2030 642 1847 2033 644 1792 2034 645 1727 2035 646 1810 2030 642 1727 2035 646 1688 2019 634 1724 2018 633 1810 2030 642 1788 2036 647 1844 2037 648 1728 2038 649 1691 2039 650 1789 2016 631 1688 2019 634 1728 2038 649 1844 2037 648 1729 2040 651 1693 2041 652 1730 2042 653 1811 2043 654 1730 2042 653 1694 2044 655 1815 2045 656 1811 2043 654 1815 2045 656 1731 2046 657 1811 2043 654 1731 2046 657 1692 2047 658 1729 2040 651 1811 2043 654 1732 2048 659 1690 2022 637 1689 2049 660 1812 2050 661 1790 2051 662 1695 2052 663 1732 2048 659 1812 2050 661 1732 2048 659 1695 2052 663 1733 2053 664 1813 2054 665 1733 2053 664 1072 1331 426 1094 1330 425 1813 2054 665 1094 1330 425 1071 1300 398 1725 2023 638 1813 2054 665 1725 2023 638 1690 2022 637 1732 2048 659 1813 2054 665 1848 2055 666 1793 2056 667 1734 2057 668 1814 2058 669 1734 2057 668 1691 2039 650 1728 2038 649 1814 2058 669 1728 2038 649 1688 2019 634 1727 2035 646 1814 2058 669 1727 2035 646 1792 2034 645 1848 2055 666 1814 2058 669 1694 2044 655 1696 2059 670 1735 2060 671 1815 2045 656 1735 2060 671 1736 2061 672 1815 2045 656 1778 2062 673 1698 2063 674 1737 2064 675 1699 2065 676 1737 2064 675 1779 2066 677 1866 2067 678 1699 2065 676 1738 2068 679 1073 1348 443 1095 1347 442 1816 2069 680 1095 1347 442 1074 1350 445 1836 2070 681 1816 2069 680 1836 2070 681 1779 2066 677 1737 2064 675 1816 2069 680 1737 2064 675 1698 2063 674 1738 2068 679 1816 2069 680 1798 2071 682 1701 2072 683 1740 2073 684 1817 2074 685 1740 2073 684 1700 2075 686 1739 2076 687 1817 2074 685 1741 2077 688 1702 2078 689 1742 2079 690 1818 2080 691 1742 2079 690 1686 2081 751 1807 2005 620 1818 2080 691 1741 2077 688 1818 2080 691 1744 2082 753 1871 2083 754 1807 2005 620 1722 2008 623 1743 2084 755 1818 2080 691 1743 2084 755 1703 2085 756 1744 2082 753 1818 2080 691 1745 2086 757 1876 2087 758 1877 2088 759 1819 2089 760 1877 2088 759 1878 2011 626 1808 2010 625 1819 2089 760 1808 2010 625 1092 1281 379 1096 1369 464 1819 2089 760 1096 1369 464 1075 1370 465 1745 2086 757 1819 2089 760 1788 2036 647 1691 2039 650 1746 2090 761 1843 2091 762 1704 2092 763 1843 2091 762 1746 2090 761 1705 2093 764 1747 2094 765 1706 2095 766 1748 2096 767 1820 2097 768 1748 2096 767 1707 2098 769 1749 2099 770 1820 2097 768 1749 2099 770 1702 2078 689 1741 2077 688 1820 2097 768 1750 2100 771 1706 2095 766 1747 2094 765 1821 2101 772 1751 2102 773 1871 2083 754 1744 2082 753 1805 2103 774 1751 2102 773 1696 2059 670 1752 2104 775 1821 2101 772 1752 2104 775 1708 2105 776 1750 2100 771 1821 2101 772 1753 2106 777 1702 2078 689 1749 2099 770 1822 2107 778 1749 2099 770 1707 2098 769 1754 2108 779 1822 2107 778 1754 2108 779 1802 2109 780 1856 2110 781 1822 2107 778 1856 2110 781 1803 2111 782 1753 2106 777 1822 2107 778 1709 2112 783 1755 2113 784 1842 2114 785 1787 2115 786 1786 2116 787 1842 2114 785 1755 2113 784 1710 2117 788 1756 2118 789 1712 2119 790 1757 2120 791 1823 2121 792 1757 2120 791 1714 2122 793 1758 2123 794 1823 2121 792 1758 2123 794 1713 2124 795 1759 2125 796 1823 2121 792 1759 2125 796 1711 2126 797 1756 2118 789 1823 2121 792 1760 2127 798 1715 2128 799 1761 2129 800 1824 2130 801 1761 2129 800 1700 2075 686 1762 2131 802 1824 2130 801 1762 2131 802 1712 2119 790 1756 2118 789 1824 2130 801 1756 2118 789 1711 2126 797 1760 2127 798 1824 2130 801 1763 2132 803 1795 2133 804 1851 2134 805 1825 2135 806 1851 2134 805 1796 2136 807 1764 2137 808 1825 2135 806 1764 2137 808 1710 2117 788 1755 2113 784 1825 2135 806 1755 2113 784 1709 2112 783 1763 2132 803 1825 2135 806 1765 2138 809 1713 2124 795 1758 2123 794 1826 2139 810 1758 2123 794 1714 2122 793 1766 2140 811 1826 2139 810 1766 2140 811 1800 2141 812 1854 2142 813 1826 2139 810 1854 2142 813 1801 2143 814 1765 2138 809 1826 2139 810 1786 2116 787 1710 2117 788 1764 2137 808 1841 2144 815 1797 2145 816 1841 2144 815 1764 2137 808 1796 2136 807 1767 2146 817 1799 2147 818 1853 2148 819 1827 2149 820 1853 2148 819 1800 2141 812 1766 2140 811 1827 2149 820 1766 2140 811 1714 2122 793 1757 2120 791 1827 2149 820 1757 2120 791 1712 2119 790 1767 2146 817 1827 2149 820 1768 2150 821 1695 2052 663 1790 2051 662 1828 2151 822 1791 2152 823 1716 2153 824 1768 2150 821 1828 2151 822 1770 2154 825 1717 2155 826 1769 2156 827 1829 2157 828 1744 2082 753 1703 2085 756 1771 2158 829 1830 2159 830 1872 2160 831 1771 2158 829 1875 2161 832 1874 2162 833 1768 2150 821 1716 2153 824 1773 2163 834 1831 2164 835 1773 2163 834 1076 1447 542 1097 1446 541 1831 2164 835 1097 1446 541 1072 1331 426 1733 2053 664 1831 2164 835 1733 2053 664 1695 2052 663 1768 2150 821 1831 2164 835 1875 2161 832 1876 2087 758 1745 2086 757 1832 2165 836 1745 2086 757 1075 1370 465 1098 1449 544 1832 2165 836 1098 1449 544 1077 1451 546 1774 2166 837 1832 2165 836 1774 2166 837 1874 2162 833 1875 2161 832 1832 2165 836 1718 2167 838 1716 2153 824 1791 2152 823 1846 2168 839 1769 2156 827 1717 2155 826 1775 2169 840 1776 2170 841 1835 2171 842 1872 2160 831 1874 2162 833 1873 2172 843 1078 1458 553 1076 1447 542 1773 2163 834 1833 2173 844 1773 2163 834 1716 2153 824 1718 2167 838 1833 2173 844 1774 2166 837 1077 1451 546 1099 1461 556 1834 2174 845 1873 2172 843 1874 2162 833 1774 2166 837 1834 2174 845 1776 2170 841 1775 2169 840 1778 2062 673 1699 2065 676 1074 1350 445 1078 1458 553 1833 2173 844 1836 2070 681 1833 2173 844 1718 2167 838 1779 2066 677 1836 2070 681 1849 2175 846 1794 2176 847 1780 2177 848 1837 2178 849 1780 2177 848 1705 2093 764 1746 2090 761 1837 2178 849 1746 2090 761 1691 2039 650 1734 2057 668 1837 2178 849 1734 2057 668 1793 2056 667 1849 2175 846 1837 2178 849 1855 2179 850 1802 2109 780 1754 2108 779 1838 2180 851 1754 2108 779 1707 2098 769 1781 2181 852 1838 2180 851 1781 2181 852 1713 2124 795 1765 2138 809 1838 2180 851 1765 2138 809 1801 2143 814 1855 2179 850 1838 2180 851 1719 2182 853 1715 2128 799 1782 2183 854 1839 2184 855 1782 2183 854 1708 2105 776 1783 2185 856 1839 2184 855 1704 2092 763 1705 2093 764 1784 2186 857 1870 2187 858 1709 2112 783 1787 2115 786 1870 2187 858 1784 2186 857 1785 2188 859 1711 2126 797 1759 2125 796 1840 2189 860 1759 2125 796 1713 2124 795 1781 2181 852 1840 2189 860 1781 2181 852 1707 2098 769 1748 2096 767 1840 2189 860 1748 2096 767 1706 2095 766 1785 2188 859 1840 2189 860 1797 2145 816 1798 2071 682 1817 2074 685 1841 2144 815 1817 2074 685 1739 2076 687 1786 2116 787 1841 2144 815 1786 2116 787 1739 2076 687 1863 2190 861 1842 2114 785 1863 2190 861 1719 2182 853 1787 2115 786 1842 2114 785 1704 2092 763 1783 2185 856 1860 2191 862 1843 2091 762 1860 2191 862 1694 2044 655 1788 2036 647 1843 2091 762 1788 2036 647 1694 2044 655 1730 2042 653 1844 2037 648 1730 2042 653 1693 2041 652 1789 2016 631 1844 2037 648 1685 2192 636 1693 2041 652 1729 2040 651 1845 2193 863 1896 2194 864 1692 2047 658 1731 2046 657 1829 2157 828 1769 2156 827 1791 2152 823 1828 2151 822 1791 2152 823 1769 2156 827 1776 2170 841 1846 2168 839 1846 2168 839 1776 2170 841 1699 2065 676 1866 2067 678 1684 2195 643 1068 2196 577 1100 1483 576 1847 2033 644 1100 1483 576 1079 1485 578 1792 2034 645 1847 2033 644 1792 2034 645 1079 1485 578 1101 1486 579 1848 2055 666 1101 1486 579 1080 1487 580 1793 2056 667 1848 2055 666 1793 2056 667 1080 1487 580 1102 1488 581 1849 2175 846 1102 1488 581 1081 1489 582 1794 2176 847 1849 2175 846 1794 2176 847 1081 1489 582 1103 1491 584 1850 2197 865 1103 1491 584 1082 1492 585 1795 2133 804 1850 2197 865 1795 2133 804 1082 1492 585 1104 1493 586 1851 2134 805 1104 1493 586 1083 1494 587 1796 2136 807 1851 2134 805 1083 1494 587 1084 1495 588 1797 2145 816 1796 2136 807 1084 1495 588 1085 1496 589 1798 2071 682 1797 2145 816 1701 2072 683 1087 1499 592 1105 1498 591 1852 2198 866 1105 1498 591 1086 1500 593 1799 2147 818 1852 2198 866 1106 1501 594 1088 1502 595 1800 2141 812 1853 2148 819 1799 2147 818 1086 1500 593 1106 1501 594 1853 2148 819 1800 2141 812 1088 1502 595 1107 1503 596 1854 2142 813 1107 1503 596 1089 1504 597 1801 2143 814 1854 2142 813 1108 1505 598 1090 1506 599 1802 2109 780 1855 2179 850 1801 2143 814 1089 1504 597 1108 1505 598 1855 2179 850 1802 2109 780 1090 1506 599 1109 1507 600 1856 2110 781 1109 1507 600 1091 1508 601 1803 2111 782 1856 2110 781 1803 2111 782 1091 1508 601 1110 1287 385 1857 2015 630 1738 2068 679 1698 2063 674 1804 2199 867 1858 2200 868 1804 2199 867 1873 2172 843 1834 2174 845 1858 2200 868 1834 2174 845 1099 1461 556 1111 1511 604 1858 2200 868 1111 1511 604 1073 1348 443 1738 2068 679 1858 2200 868 1085 1496 589 1087 1499 592 1701 2072 683 1798 2071 682 1770 2154 825 1697 2201 869 1805 2103 774 1859 2202 870 1805 2103 774 1744 2082 753 1830 2159 830 1859 2202 870 1830 2159 830 1772 2203 871 1806 2204 872 1859 2202 870 1806 2204 872 1717 2155 826 1770 2154 825 1859 2202 870 1783 2185 856 1708 2105 776 1752 2104 775 1860 2191 862 1696 2059 670 1694 2044 655 1860 2191 862 1752 2104 775 1775 2169 840 1717 2155 826 1806 2204 872 1861 2205 873 1806 2204 872 1772 2203 871 1777 2206 874 1861 2205 873 1785 2188 859 1706 2095 766 1750 2100 771 1862 2207 875 1750 2100 771 1708 2105 776 1782 2183 854 1862 2207 875 1782 2183 854 1715 2128 799 1760 2127 798 1862 2207 875 1760 2127 798 1711 2126 797 1785 2188 859 1862 2207 875 1778 2062 673 1775 2169 840 1861 2205 873 1864 2208 876 1861 2205 873 1777 2206 874 1835 2171 842 1864 2208 876 1739 2076 687 1700 2075 686 1761 2129 800 1863 2190 861 1761 2129 800 1715 2128 799 1719 2182 853 1863 2190 861 1804 2199 867 1698 2063 674 1778 2062 673 1864 2208 876 1852 2198 866 1799 2147 818 1767 2146 817 1865 2209 877 1767 2146 817 1712 2119 790 1762 2131 802 1865 2209 877 1762 2131 802 1700 2075 686 1740 2073 684 1865 2209 877 1740 2073 684 1701 2072 683 1852 2198 866 1865 2209 877 1779 2066 677 1718 2167 838 1846 2168 839 1866 2067 678 1789 2016 631 1693 2041 652 1685 2210 636 1867 2017 632 1805 2103 774 1697 2201 869 1735 2060 671 1696 2059 670 1751 2102 773 1753 2106 777 1803 2111 782 1857 2015 630 1868 2211 878 1857 2015 630 1809 2014 629 1868 2211 878 1809 2014 629 1880 2013 628 1868 2211 878 1742 2079 690 1702 2078 689 1753 2106 777 1868 2211 878 1780 2177 848 1794 2176 847 1850 2197 865 1869 2212 879 1850 2197 865 1795 2133 804 1763 2132 803 1869 2212 879 1763 2132 803 1709 2112 783 1784 2186 857 1869 2212 879 1784 2186 857 1705 2093 764 1780 2177 848 1869 2212 879 1787 2115 786 1719 2182 853 1839 2184 855 1870 2187 858 1839 2184 855 1783 2185 856 1704 2092 763 1870 2187 858 1871 2083 754 1751 2102 773 1821 2101 772 1747 2094 765 1741 2077 688 1871 2083 754 1747 2094 765 1820 2097 768 1772 2203 871 1872 2160 831 1835 2171 842 1777 2206 874 1771 2158 829 1872 2160 831 1772 2203 871 1830 2159 830 1835 2171 842 1873 2172 843 1804 2199 867 1864 2208 876 1771 2158 829 1703 2085 756 1876 2087 758 1875 2161 832 1877 2088 759 1876 2087 758 1703 2085 756 1743 2084 755 1743 2084 755 1722 2008 623 1878 2011 626 1877 2088 759 1722 2008 623 1687 2006 621 1879 2012 627 1878 2011 626 1880 2013 628 1879 2012 627 1687 2006 621 1686 2081 751 1868 2211 878 1880 2013 628 1686 2081 751 1742 2079 690 1068 2213 1843 1684 2214 2187 1886 2215 2188 1319 1525 1844 1518 2004 2186 1521 1759 2061 1886 2215 2188 1887 2216 2189 1518 2004 2186 1517 2003 2185 1881 1760 2062 1521 1759 2061 1881 1760 2062 1517 2003 2185 1516 1758 2060 1515 1757 2059 898 1023 1712 1312 1025 1714 1881 1760 2062 1515 1757 2059 1683 2217 2190 1685 2218 2191 1889 2219 2192 1888 2220 2193 1882 1750 2052 1520 2002 2184 1889 2219 2192 1890 2221 2194 1884 2222 2195 1885 2223 2196 1892 2224 2197 1891 2225 2198 1315 1538 1857 1514 1754 2056 1898 2226 2199 1320 1539 1858 1519 2001 2183 1518 2004 2186 1887 2216 2189 1888 2220 2193 1512 1751 2053 1882 1750 2052 1890 2221 2194 1891 2225 2198 1729 2040 651 1692 2047 658 1884 2227 880 1845 2228 863 1690 2022 637 1682 2229 640 1885 2230 881 1689 2049 660 1883 1753 2055 1513 1752 2054 1892 2224 2197 1893 2231 2200 1885 2232 881 1884 2233 880 1692 2047 658 1689 2049 660 1521 1759 2061 905 1028 1717 1319 1525 1844 1886 2215 2188 1720 2234 2201 1069 2235 1862 1320 1539 1858 1898 2226 2199 1684 2236 2187 1726 2237 2202 1887 2216 2189 1886 2215 2188 1726 2238 2202 1683 2239 2190 1888 2220 2193 1887 2216 2189 1520 2002 2184 1519 2001 2183 1888 2220 2193 1889 2219 2192 1685 2240 2191 1845 2241 2203 1890 2221 2194 1889 2219 2192 1845 2242 2203 1884 2243 2195 1891 2225 2198 1890 2221 2194 1513 1752 2054 1512 1751 2053 1891 2225 2198 1892 2224 2197 1885 2244 2196 1682 2245 2204 1893 2231 2200 1892 2224 2197 1682 2246 2204 1720 2247 2201 1898 2226 2199 1893 2231 2200 1894 2248 882 1697 2201 869 1770 2154 825 1829 2157 828 1790 2051 662 1894 2248 882 1829 2157 828 1828 2151 822 1895 2249 883 1894 2248 882 1790 2051 662 1812 2050 661 1736 2061 672 1735 2060 671 1697 2201 869 1894 2248 882 1896 2194 864 1736 2061 672 1894 2248 882 1895 2249 883 1689 2049 660 1692 2047 658 1896 2194 864 1895 2249 883 1689 2049 660 1895 2249 883 1812 2050 661 1731 2046 657 1815 2045 656 1736 2061 672 1896 2194 864 1883 1753 2055 1893 2231 2200 1898 2226 2199 1514 1754 2056 1359 1584 1886 1371 1600 1902 1899 1601 1903 1360 1586 1888 1371 1600 1902 1382 1613 1915 1900 1614 1916 1899 1601 1903 1382 1613 1915 1393 1626 1928 1901 1627 1929 1900 1614 1916 1393 1626 1928 1404 1639 1941 1902 1640 1942 1901 1627 1929 1404 1639 1941 1415 1652 1954 350 790 1479 1902 1640 1942 1415 1652 1954 1426 1664 1966 433 793 1482 350 790 1479 1497 1735 2037 1903 1756 2058 430 806 1495 1503 1741 2043 1509 1747 2049 1904 1755 2057 1903 1756 2058 1051 1105 1734 986 1090 1719 1906 1093 1722 1905 1106 1735 1048 1091 1720 908 1109 1738 1908 1096 1725 1907 1092 1721 1017 1095 1724 951 1107 1736 1906 1093 1722 1907 1092 1721 1019 1108 1737 925 1101 1730 1909 1103 1732 1905 1106 1735 1020 1113 1742 923 1094 1723 1908 1096 1725 1910 1111 1740 1050 1098 1727 909 1104 1733 1909 1103 1732 1911 1099 1728 1052 1110 1739 910 1115 1744 1912 1114 1743 1910 1111 1740 1018 1102 1731 952 1148 1777 1913 1100 1729 1911 1099 1728 1021 1119 1748 924 1112 1741 1912 1114 1743 1914 1117 1746 1055 1146 1775 990 1097 1726 1913 1100 1729 1915 1147 1776 1053 1116 1745 982 1125 1754 1916 1120 1749 1914 1117 1746 1026 1149 1778 928 1142 1771 1917 1144 1773 1915 1147 1776 1022 1122 1751 926 1118 1747 1916 1120 1749 1918 1123 1752 1049 1140 1769 912 1145 1774 1917 1144 1773 1919 1141 1770 1046 1126 1755 984 1127 1756 1920 1124 1753 1918 1123 1752 1025 1143 1772 930 1136 1765 1921 1138 1767 1919 1141 1770 1023 1131 1760 927 1121 1750 1920 1124 1753 1922 1129 1758 1054 1134 1763 988 1139 1768 1921 1138 1767 1923 1135 1764 1047 1128 1757 911 1133 1762 1924 1132 1761 1922 1129 1758 1024 1137 1766 929 1130 1759 1924 1132 1761 1923 1135 1764 1522 1841 2083 1662 1821 2063 1926 1824 2066 1925 1827 2069 1600 1822 2064 1665 1835 2077 1928 1837 2079 1927 1823 2065 1565 1839 2081 1631 1825 2067 1926 1824 2066 1927 1823 2065 1537 1826 2068 1634 1843 2085 1929 1842 2084 1925 1827 2069 1539 1833 2075 1633 1838 2080 1928 1837 2079 1930 1834 2076 1524 1847 2089 1666 1840 2082 1929 1842 2084 1931 1845 2087 1523 1836 2078 1664 1828 2070 1932 1831 2073 1930 1834 2076 1538 1844 2086 1635 1849 2091 1933 1848 2090 1931 1845 2087 1566 1880 2122 1632 1832 2074 1932 1831 2073 1934 1830 2072 1596 1857 2099 1667 1846 2088 1933 1848 2090 1935 1851 2093 1604 1829 2071 1669 1876 2118 1936 1878 2120 1934 1830 2072 1540 1850 2092 1636 1852 2094 1937 1855 2097 1935 1851 2093 1542 1874 2116 1640 1879 2121 1936 1878 2120 1938 1875 2117 1598 1859 2101 1660 1856 2098 1937 1855 2097 1939 1854 2096 1526 1877 2119 1663 1870 2112 1940 1872 2114 1938 1875 2117 1541 1853 2095 1637 1861 2103 1941 1860 2102 1939 1854 2096 1544 1868 2110 1639 1873 2115 1940 1872 2114 1942 1869 2111 1525 1865 2107 1661 1858 2100 1941 1860 2102 1943 1863 2105 1602 1871 2113 1668 1864 2106 1944 1866 2108 1942 1869 2111 1543 1862 2104 1638 1867 2109 1944 1866 2108 1943 1863 2105 651 570 1332 1945 675 1416 2086 2250 2205 2087 571 1333 1964 507 1303 374 512 1308 393 653 1394 1945 675 1416 2086 2250 2205 1945 675 1416 393 653 1394 2107 723 1448 401 620 1368 521 619 1367 1948 772 1467 1949 771 1466 579 623 1371 660 630 1378 1950 770 1465 1949 771 1466 402 628 1376 524 626 1374 1950 770 1465 1951 769 1464 578 631 1379 577 664 1405 1952 767 1462 1951 769 1464 577 664 1405 2094 700 1429 2096 768 1463 1952 767 1462 419 742 977 584 693 281 1954 765 1000 1955 764 999 575 553 236 659 556 239 1957 762 997 1956 763 998 404 636 250 527 634 248 1957 762 997 1958 761 996 574 558 241 658 569 245 1959 760 995 1958 761 996 407 643 257 530 641 255 1959 760 995 1960 759 994 573 568 244 657 672 268 1961 758 993 1960 759 994 412 649 263 533 647 261 1961 758 993 1962 757 992 571 755 990 671 732 309 1947 734 311 1963 756 991 1470 1708 2010 1481 1719 2021 347 801 1490 431 800 1489 1459 1697 1999 1470 1708 2010 431 800 1489 348 798 1487 1448 1686 1988 1459 1697 1999 348 798 1487 432 797 1486 1437 1675 1977 1448 1686 1988 432 797 1486 349 794 1483 1491 1727 2029 351 803 1492 347 801 1490 1481 1719 2021 1497 1735 2037 430 806 1495 351 803 1492 1491 1727 2029 435 438 1234 430 806 1495 1903 1756 2058 1986 1021 1710 435 438 1234 1986 1021 1710 320 1020 1709 88 375 1186 433 793 1482 1426 1664 1966 1437 1675 1977 349 794 1483 2048 2251 2206 2049 2252 2207 1973 1589 1891 1972 1588 1890 1902 1640 1942 350 790 1479 434 436 1232 1974 1641 1943 2047 2253 2208 2048 2251 2206 1972 1588 1890 1975 1602 1904 2046 2254 2209 2047 2253 2208 1975 1602 1904 1976 1615 1917 2045 2255 2210 2046 2254 2209 1976 1615 1917 1977 1628 1930 2044 1653 1955 2045 2255 2210 1977 1628 1930 1974 1641 1943 606 781 1473 684 410 1214 2026 413 1217 2027 423 2211 310 111 904 1978 113 906 2025 412 1216 2024 409 1213 867 985 1674 858 976 1665 4 371 1182 84 373 1184 858 976 1665 845 964 1653 0 369 1180 4 371 1182 721 832 1521 1331 831 1520 1980 836 1525 1979 835 1524 774 2256 2212 3 360 1171 87 359 1170 1981 892 1581 722 834 1523 735 2257 2213 1982 850 1539 1979 835 1524 735 2257 2213 748 2258 2214 1983 864 1553 1982 850 1539 748 2258 2214 761 2259 2215 1984 878 1567 1983 864 1553 761 2259 2215 774 2256 2212 1981 892 1581 1984 878 1567 810 928 1617 798 916 1605 86 364 1175 1 365 1176 1 365 1176 85 367 1178 822 940 1629 810 928 1617 834 952 1641 822 940 1629 85 367 1178 0 369 1180 845 964 1653 834 952 1641 0 369 1180 88 375 1186 320 1020 1709 2015 2260 2216 2015 2260 2216 84 373 1184 88 375 1186 1904 1755 2057 1514 1754 2056 1315 1538 1857 1985 1019 1708 1337 1017 1706 1985 1019 1708 1315 1538 1857 897 1018 1707 90 2 28 243 1 26 1987 2261 2217 1988 2262 2218 243 1 26 91 4 30 1989 2263 2219 1987 2261 2217 91 4 30 244 7 35 1990 2264 2220 1989 2263 2219 244 7 35 299 8 36 1991 2265 2221 1990 2264 2220 164 179 1042 163 178 1041 1992 2266 2222 1993 2267 2223 266 181 1045 165 180 1043 1994 2268 2224 1995 2269 2225 163 178 1041 266 181 1045 1995 2269 2225 1992 2266 2222 288 184 1048 90 2 28 1988 2262 2218 1996 2270 2226 167 186 1050 164 179 1042 1993 2267 2223 1997 2271 2227 324 333 1144 288 184 1048 1996 2270 2226 1998 2272 2228 315 351 1162 167 186 1050 1997 2271 2227 1999 2273 2229 165 180 1043 324 333 1144 1998 2272 2228 1994 2268 2224 1991 2265 2221 299 8 36 2017 378 1189 2018 2274 2230 690 432 1228 315 351 1162 1999 2273 2229 2001 2275 2231 622 442 1238 437 441 1237 2002 2276 2232 2003 2277 2233 438 443 1239 622 442 1238 2003 2277 2233 2004 2278 2234 623 446 1242 438 443 1239 2004 2278 2234 2005 2279 2235 440 447 1243 623 446 1242 2005 2279 2235 2006 2280 2236 519 618 1366 520 617 1365 2007 2281 2237 2008 2282 2238 521 619 1367 645 622 1370 2009 2283 2239 2010 2284 2240 645 622 1370 519 618 1366 2008 2282 2238 2009 2283 2239 437 441 1237 661 624 1372 2011 2285 2241 2002 2276 2232 520 617 1365 523 625 1373 2012 2286 2242 2007 2281 2237 661 624 1372 1948 772 1467 2013 2287 2243 2011 2285 2241 672 774 1469 440 447 1243 2006 2280 2236 2000 2288 2244 523 625 1373 690 432 1228 2001 2275 2231 2012 2286 2242 1948 772 1467 521 619 1367 2010 2284 2240 2013 2287 2243 1988 2262 2218 1987 2261 2217 2014 2289 2245 1987 2261 2217 1989 2263 2219 2014 2289 2245 1989 2263 2219 1990 2264 2220 2014 2289 2245 1990 2264 2220 1991 2265 2221 2014 2289 2245 1993 2267 2223 1992 2266 2222 2014 2289 2245 1995 2269 2225 1994 2268 2224 2014 2289 2245 1992 2266 2222 1995 2269 2225 2014 2289 2245 1996 2270 2226 1988 2262 2218 2014 2289 2245 1997 2271 2227 1993 2267 2223 2014 2289 2245 1998 2272 2228 1996 2270 2226 2014 2289 2245 1999 2273 2229 1997 2271 2227 2014 2289 2245 1994 2268 2224 1998 2272 2228 2014 2289 2245 1991 2265 2221 2018 2274 2230 2000 2288 2244 2014 2289 2245 2001 2275 2231 1999 2273 2229 2014 2289 2245 2003 2277 2233 2002 2276 2232 2014 2289 2245 2004 2278 2234 2003 2277 2233 2014 2289 2245 2005 2279 2235 2004 2278 2234 2014 2289 2245 2006 2280 2236 2005 2279 2235 2014 2289 2245 2008 2282 2238 2007 2281 2237 2014 2289 2245 2010 2284 2240 2009 2283 2239 2014 2289 2245 2009 2283 2239 2008 2282 2238 2014 2289 2245 2002 2276 2232 2011 2285 2241 2014 2289 2245 2007 2281 2237 2012 2286 2242 2014 2289 2245 2011 2285 2241 2013 2287 2243 2014 2289 2245 2000 2288 2244 2006 2280 2236 2014 2289 2245 2012 2286 2242 2001 2275 2231 2014 2289 2245 2013 2287 2243 2010 2284 2240 2014 2289 2245 2015 2260 2216 320 1020 1709 884 1002 1691 877 995 1684 877 995 1684 867 985 1674 84 373 1184 2015 2260 2216 1497 1735 2037 1503 1741 2043 1903 1756 2058 672 774 1469 2000 2288 2244 2018 2274 2230 2017 378 1189 308 85 74 228 88 77 2020 406 151 2019 402 150 673 775 1470 590 773 1468 2022 377 1188 2021 379 1190 590 773 1468 672 774 1469 2017 378 1189 2022 377 1188 591 776 1471 673 775 1470 2021 379 1190 2023 380 1191 683 780 1472 591 776 1471 2023 380 1191 2024 409 1213 604 411 1215 683 780 1472 2024 409 1213 2025 412 1216 1978 113 906 142 124 914 2026 413 1217 2025 412 1216 142 124 914 229 126 916 2027 423 2211 2026 413 1217 687 782 229 606 781 228 2027 423 153 2028 422 152 607 783 230 687 782 229 2028 422 152 2029 424 154 688 784 231 607 783 230 2029 424 154 2030 425 155 603 778 224 688 784 231 2030 425 155 2031 408 147 682 779 225 603 778 224 2031 408 147 2032 407 146 601 777 222 682 779 225 2032 407 146 2033 403 145 681 405 223 601 777 222 2033 403 145 2019 402 2263 2020 406 151 228 88 77 312 154 107 2016 420 160 312 154 107 41 140 103 2034 414 156 2016 420 160 41 140 103 311 135 100 2035 415 157 2034 414 156 311 135 921 29 77 897 2036 394 1205 2035 415 1218 29 77 897 307 76 896 2037 395 1206 2036 394 1205 307 76 896 227 79 899 2038 398 1209 2037 395 1206 227 79 899 45 81 901 2039 400 1211 2038 398 1209 45 81 901 162 353 1164 2040 428 1224 2039 400 1211 162 353 1164 79 355 1166 2041 430 1226 2040 428 1224 79 355 1166 233 358 1169 2042 433 1229 2041 430 1226 233 358 1169 3 360 1171 2043 435 1231 2042 433 1229 3 360 1171 774 2256 2212 2044 1653 1955 2043 435 1231 774 2256 2212 761 2259 2215 2045 2255 2210 2044 1653 1955 761 2259 2215 748 2258 2214 2046 2254 2209 2045 2255 2210 748 2258 2214 735 2257 2213 2047 2253 2208 2046 2254 2209 735 2257 2213 722 834 1523 2048 2251 2206 2047 2253 2208 722 834 1523 708 833 1522 2049 2252 2207 2048 2251 2206 907 1029 1718 2049 2252 2207 708 833 1522 1973 1589 1891 2049 2252 2207 907 1029 1718 907 1029 1718 1980 836 1525 1331 831 1520 2050 292 123 2051 291 122 2065 133 1002 2064 288 1003 282 294 125 322 296 127 2067 376 1004 2066 134 1005 2051 291 122 282 294 125 2066 134 1005 2065 133 1002 185 244 52 278 242 50 2069 237 1006 2068 245 1007 184 241 49 279 251 56 2071 246 1008 2070 238 1009 278 242 50 184 241 49 2070 238 1009 2069 237 1006 2052 263 64 185 244 52 2068 245 1007 2072 261 1010 186 250 55 2050 292 123 2064 288 1003 2073 247 1011 279 251 56 186 250 55 2073 247 1011 2071 246 1008 187 259 1104 280 257 1103 2075 252 1099 2074 260 1105 2053 256 59 2054 327 235 2077 328 1014 2076 253 1015 280 257 60 2053 256 59 2076 253 1015 2075 252 2276 2055 266 1109 187 259 1104 2074 260 1105 2078 264 1107 2054 327 235 2052 263 64 2072 261 1010 2077 328 1014 188 268 1111 2055 266 1109 2078 264 1107 2079 269 1112 2056 272 1115 188 268 1111 2079 269 1112 2080 270 1113 189 274 1117 2056 272 1115 2080 270 1113 2081 275 1118 2057 287 1128 189 274 1117 2081 275 1118 2082 285 1126 191 283 88 281 281 2271 2084 276 1021 2083 284 1022 190 280 1123 2057 287 1128 2082 285 1126 2085 277 1120 281 281 1124 190 280 1123 2085 277 1120 2084 276 1119 322 296 127 191 283 88 2083 284 1022 2067 376 1004 1946 735 970 656 733 310 2087 571 1024 2086 2250 1025 2058 731 308 2059 730 307 2089 727 1026 2088 572 1027 656 733 310 2058 731 308 2088 572 1027 2087 571 1024 653 689 279 554 681 274 2091 676 1028 2090 686 1029 652 680 273 555 683 276 2093 684 1030 2092 677 1031 554 681 274 652 680 273 2092 677 1031 2091 676 1028 555 683 276 2060 702 288 2094 700 1032 2093 684 1030 2059 730 307 556 690 280 2095 685 1033 2089 727 1026 556 690 280 653 689 279 2090 686 1029 2095 685 1033 1953 766 1001 557 696 284 2097 691 1034 2096 768 1035 654 695 1427 558 698 1426 2099 699 1428 2098 692 1423 557 696 284 654 695 2270 2098 692 1037 2097 691 1034 558 698 1426 2061 705 1432 2100 703 1430 2099 699 1428 2060 702 288 1953 766 1001 2096 768 1035 2094 700 1032 2061 705 1432 559 707 1434 2101 708 1435 2100 703 1430 559 707 1434 2062 711 1438 2102 709 1436 2101 708 1435 2062 711 1438 560 713 1440 2103 714 1441 2102 709 1436 560 713 1440 2063 726 1451 2104 724 1449 2103 714 1441 2063 726 1451 561 720 1447 2105 715 1442 2104 724 1449 655 719 299 562 722 302 2107 723 1044 2106 716 2266 561 720 1447 655 719 1446 2106 716 1443 2105 715 1442 562 722 302 1946 735 970 2086 2250 1025 2107 723 1044 1686 2081 751 1687 2006 621 1807 2005 620 1117 1276 374 1237 1275 373 1151 1277 375

+
+
+
+
+ + + + 0 0 1 0 + 0 1 0 0 + 1 0 0 0 + + + + + + + + + + + + 400.113 463.264 -431.078 + 0 0 1 0 + 0 1 0 -223.2 + 1 0 0 -38.4 + + + + 148.654 183.672 -292.179 + 0 0 1 -12.8709 + 0 1 0 -191.679 + 1 0 0 -45.6358 + + + + + + + +
diff --git a/data/client/mesh/animal_wolf.png b/data/client/mesh/animal_wolf.png new file mode 100644 index 000000000..af1baffc1 Binary files /dev/null and b/data/client/mesh/animal_wolf.png differ diff --git a/data/client/shaders/mesh.frag b/data/client/shaders/mesh.frag new file mode 100644 index 000000000..e7877844c --- /dev/null +++ b/data/client/shaders/mesh.frag @@ -0,0 +1,57 @@ +in vec3 v_pos; +in vec3 v_norm; +in vec2 v_texcoords; +in vec3 v_diffusecolor; +in vec3 v_specularcolor; +in vec3 v_lightpos; +out vec4 o_color; +uniform sampler2D u_texture; + +vec3 getMaterialColor() { + return texture(u_texture, v_texcoords).rgb; +} + +vec3 getAmbientColor(vec3 materialcolor) { + const float ambientstrength = 1.0; + return ambientstrength * materialcolor; +} + +vec3 getDiffuseColor(vec3 lightdir, vec3 normal) { + float diffuse = max(dot(lightdir, normal), 0.0); + return diffuse * v_diffusecolor; +} + +vec3 getSpecularColor(vec3 lightdir, vec3 normal) { + const float specularstrength = 0.5; + vec3 viewdir = normalize(-v_pos); + vec3 reflectdir = reflect(-lightdir, normal); + float specangle = max(dot(reflectdir, viewdir), 0.0); + float spec = pow(specangle, 32); + return specularstrength * spec * v_specularcolor; +} + +vec3 getFogColor() { + return vec3(0.04, 0.29, 0.94); +} + +float getFog() { + const float density = 0.05; + const float endfog = 1500.0; + const float startfog = 500.0; + float fogdistance = gl_FragCoord.z / gl_FragCoord.w; + float d = density * fogdistance; + float fogval = (endfog - fogdistance) / (endfog - startfog); + return 1.0 - clamp(fogval, 0.0, 1.0); +} + +void main(void) { + vec3 lightdir = normalize(v_lightpos - v_pos); + + vec3 materialcolor = getMaterialColor(); + vec3 ambientcolor = getAmbientColor(materialcolor); + vec3 diffusecolor = getDiffuseColor(lightdir, v_norm); + vec3 specularcolor = getSpecularColor(lightdir, v_norm); + vec3 fogcolor = getFogColor(); + vec3 finalcolor = (ambientcolor + diffusecolor + specularcolor) * materialcolor; + o_color = vec4(mix(finalcolor, fogcolor, getFog()), 1.0); +} diff --git a/data/client/shaders/mesh.vert b/data/client/shaders/mesh.vert new file mode 100644 index 000000000..ebf2e9b72 --- /dev/null +++ b/data/client/shaders/mesh.vert @@ -0,0 +1,30 @@ +// attributes from the VAOs +in vec3 a_pos; +in vec3 a_norm; +in vec2 a_texcoords; + +uniform mat4 u_projection; +uniform mat4 u_model; +uniform mat4 u_view; +uniform vec3 u_diffusecolor; +uniform vec3 u_specularcolor; +uniform vec3 u_lightpos; + +out vec3 v_pos; +out vec3 v_norm; +out vec2 v_texcoords; +out vec3 v_diffusecolor; +out vec3 v_specularcolor; +out vec3 v_lightpos; + +void main(void) { + mat4 modelview = u_view * u_model; + vec4 pos4 = modelview * vec4(a_pos, 1.0); + v_pos = vec3(pos4) / pos4.w; + v_norm = a_norm; + v_texcoords = a_texcoords; + v_diffusecolor = u_diffusecolor; + v_specularcolor = u_specularcolor; + v_lightpos = u_lightpos; + gl_Position = u_projection * modelview * vec4(a_pos, 1.0); +} diff --git a/data/client/shaders/ui.frag b/data/client/shaders/ui.frag new file mode 100644 index 000000000..08626db60 --- /dev/null +++ b/data/client/shaders/ui.frag @@ -0,0 +1,10 @@ +uniform sampler2D u_texture; +in vec2 v_texcoord; +in vec4 v_color; +out vec4 o_color; + +void main(void) { + vec4 color = texture2D(u_texture, v_texcoord); + vec4 fcolor = v_color / 255.0; + o_color = color * fcolor * 255.0; +} diff --git a/data/client/shaders/ui.vert b/data/client/shaders/ui.vert new file mode 100644 index 000000000..97a0738d2 --- /dev/null +++ b/data/client/shaders/ui.vert @@ -0,0 +1,15 @@ +// attributes from the VAOs +in vec2 a_pos; +in vec2 a_texcoord; +in vec4 a_color; + +uniform mat4 u_projection; + +out vec2 v_texcoord; +out vec4 v_color; + +void main(void) { + v_color = a_color; + v_texcoord = a_texcoord; + gl_Position = u_projection * vec4(a_pos.x, a_pos.y, 0.0, 1.0); +} diff --git a/data/client/shaders/water.frag b/data/client/shaders/water.frag new file mode 100644 index 000000000..e7877844c --- /dev/null +++ b/data/client/shaders/water.frag @@ -0,0 +1,57 @@ +in vec3 v_pos; +in vec3 v_norm; +in vec2 v_texcoords; +in vec3 v_diffusecolor; +in vec3 v_specularcolor; +in vec3 v_lightpos; +out vec4 o_color; +uniform sampler2D u_texture; + +vec3 getMaterialColor() { + return texture(u_texture, v_texcoords).rgb; +} + +vec3 getAmbientColor(vec3 materialcolor) { + const float ambientstrength = 1.0; + return ambientstrength * materialcolor; +} + +vec3 getDiffuseColor(vec3 lightdir, vec3 normal) { + float diffuse = max(dot(lightdir, normal), 0.0); + return diffuse * v_diffusecolor; +} + +vec3 getSpecularColor(vec3 lightdir, vec3 normal) { + const float specularstrength = 0.5; + vec3 viewdir = normalize(-v_pos); + vec3 reflectdir = reflect(-lightdir, normal); + float specangle = max(dot(reflectdir, viewdir), 0.0); + float spec = pow(specangle, 32); + return specularstrength * spec * v_specularcolor; +} + +vec3 getFogColor() { + return vec3(0.04, 0.29, 0.94); +} + +float getFog() { + const float density = 0.05; + const float endfog = 1500.0; + const float startfog = 500.0; + float fogdistance = gl_FragCoord.z / gl_FragCoord.w; + float d = density * fogdistance; + float fogval = (endfog - fogdistance) / (endfog - startfog); + return 1.0 - clamp(fogval, 0.0, 1.0); +} + +void main(void) { + vec3 lightdir = normalize(v_lightpos - v_pos); + + vec3 materialcolor = getMaterialColor(); + vec3 ambientcolor = getAmbientColor(materialcolor); + vec3 diffusecolor = getDiffuseColor(lightdir, v_norm); + vec3 specularcolor = getSpecularColor(lightdir, v_norm); + vec3 fogcolor = getFogColor(); + vec3 finalcolor = (ambientcolor + diffusecolor + specularcolor) * materialcolor; + o_color = vec4(mix(finalcolor, fogcolor, getFog()), 1.0); +} diff --git a/data/client/shaders/water.vert b/data/client/shaders/water.vert new file mode 100644 index 000000000..fbba3ab10 --- /dev/null +++ b/data/client/shaders/water.vert @@ -0,0 +1,34 @@ +// attributes from the VAOs +in vec3 a_pos; +in vec3 a_norm; +in vec2 a_texcoords; + +uniform float u_wavetime; +uniform float u_wavewidth; +uniform float u_waveheight; +uniform mat4 u_projection; +uniform mat4 u_model; +uniform mat4 u_view; +uniform vec3 u_diffusecolor; +uniform vec3 u_specularcolor; +uniform vec3 u_lightpos; + +out vec3 v_pos; +out vec3 v_norm; +out vec2 v_texcoords; +out vec3 v_diffusecolor; +out vec3 v_specularcolor; +out vec3 v_lightpos; + +void main(void) { + mat4 modelview = u_view * u_model; + vec4 pos4 = modelview * vec4(a_pos, 1.0); + v_pos = vec3(pos4) / pos4.w; + v_norm = a_norm; + v_texcoords = a_texcoords; + v_diffusecolor = u_diffusecolor; + v_specularcolor = u_specularcolor; + v_lightpos = u_lightpos; + float posw = sin(u_wavewidth * a_pos.x + u_wavetime) * cos(u_wavewidth * a_pos.y + u_wavetime) * u_waveheight; + gl_Position = u_projection * modelview * vec4(a_pos, posw); +} diff --git a/data/client/shaders/world.frag b/data/client/shaders/world.frag new file mode 100644 index 000000000..27ff1cbb7 --- /dev/null +++ b/data/client/shaders/world.frag @@ -0,0 +1,90 @@ +flat in int v_material; +flat in int v_density; +in vec3 v_pos; +in vec3 v_diffusecolor; +in vec3 v_specularcolor; +in vec3 v_lightpos; +out vec4 o_color; + +// the different material types +const int AIR = 0; +const int DIRT = 1; +const int GRASS = 2; +const int CLOUD = 3; +const int WATER = 4; +const int LEAVES = 5; +const int TRUNK = 6; +const int CLOUDS = 7; + +const float MAX_MATERIAL = 16.0; + +vec3 getMaterialColor() { + if (v_material == DIRT) { + return vec3(0.97, 0.67, 0.39); + } + if (v_material == GRASS) { + return vec3(0.24, 0.67, 0.24); + } + if (v_material == CLOUD) { + return vec3(0.75, 0.75, 0.9); + } + if (v_material == TRUNK) { + return vec3(0.4, 0.2, 0.0); + } + if (v_material == LEAVES) { + return vec3(0.4, 0.6, 0.4); + } + if (v_material == CLOUDS) { + return vec3(0.4, 0.6, 0.9); + } + // error + return vec3(1.0, float(v_material) / (MAX_MATERIAL * 255.0), float(v_density) / (MAX_MATERIAL * 255.0)); +} + +vec3 getAmbientColor(vec3 materialcolor) { + const float ambientstrength = 1.0; + return ambientstrength * materialcolor; +} + +vec3 getDiffuseColor(vec3 lightdir, vec3 normal) { + float diffuse = max(dot(lightdir, normal), 0.0); + return diffuse * v_diffusecolor; +} + +vec3 getSpecularColor(vec3 lightdir, vec3 normal) { + const float specularstrength = 0.5; + vec3 viewdir = normalize(-v_pos); + vec3 reflectdir = reflect(-lightdir, normal); + float specangle = max(dot(reflectdir, viewdir), 0.0); + float spec = pow(specangle, 32); + return specularstrength * spec * v_specularcolor; +} + +vec3 getFogColor() { + return vec3(0.04, 0.29, 0.94); +} + +float getFog() { + const float density = 0.05; + const float endfog = 1500.0; + const float startfog = 500.0; + float fogdistance = gl_FragCoord.z / gl_FragCoord.w; + float d = density * fogdistance; + float fogval = (endfog - fogdistance) / (endfog - startfog); + return 1.0 - clamp(fogval, 0.0, 1.0); +} + +void main(void) { + vec3 fdx = vec3(dFdx(v_pos.x), dFdx(v_pos.y), dFdx(v_pos.z)); + vec3 fdy = vec3(dFdy(v_pos.x), dFdy(v_pos.y), dFdy(v_pos.z)); + vec3 normal = normalize(cross(fdx, fdy)); + vec3 lightdir = normalize(v_lightpos - v_pos); + + vec3 materialcolor = getMaterialColor(); + vec3 ambientcolor = getAmbientColor(materialcolor); + vec3 diffusecolor = getDiffuseColor(lightdir, normal); + vec3 specularcolor = getSpecularColor(lightdir, normal); + vec3 fogcolor = getFogColor(); + vec3 finalcolor = (ambientcolor + diffusecolor + specularcolor) * materialcolor; + o_color = vec4(mix(finalcolor, fogcolor, getFog()), 1.0); +} diff --git a/data/client/shaders/world.vert b/data/client/shaders/world.vert new file mode 100644 index 000000000..9418e72be --- /dev/null +++ b/data/client/shaders/world.vert @@ -0,0 +1,29 @@ +// attributes from the VAOs +in vec3 a_pos; +in ivec2 a_materialdensity; + +uniform mat4 u_projection; +uniform mat4 u_model; +uniform mat4 u_view; +uniform vec3 u_diffusecolor; +uniform vec3 u_specularcolor; +uniform vec3 u_lightpos; + +flat out int v_material; +flat out int v_density; +out vec3 v_pos; +out vec3 v_diffusecolor; +out vec3 v_specularcolor; +out vec3 v_lightpos; + +void main(void) { + mat4 modelview = u_view * u_model; + vec4 pos4 = modelview * vec4(a_pos, 1.0); + v_pos = vec3(pos4) / pos4.w; + v_material = a_materialdensity.x; + v_density = a_materialdensity.y; + v_diffusecolor = u_diffusecolor; + v_specularcolor = u_specularcolor; + v_lightpos = u_lightpos; + gl_Position = u_projection * modelview * vec4(a_pos, 1.0); +} diff --git a/data/client/texture/water.png b/data/client/texture/water.png new file mode 100644 index 000000000..2bb9e8217 Binary files /dev/null and b/data/client/texture/water.png differ diff --git a/data/client/ui/font/font.tb.txt b/data/client/ui/font/font.tb.txt new file mode 100644 index 000000000..b15c81f81 --- /dev/null +++ b/data/client/ui/font/font.tb.txt @@ -0,0 +1,15 @@ +info + glyph_str !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + name Segoe +size 14 + bitmap font_14.png + ascent 15 + descent 5 + advance_delta -3 + space_advance 5 +size 28 + bitmap font_28.png + ascent 31 + descent 10 + advance_delta -7 + space_advance 10 diff --git a/data/client/ui/font/font_14.png b/data/client/ui/font/font_14.png new file mode 100644 index 000000000..95f90947d Binary files /dev/null and b/data/client/ui/font/font_14.png differ diff --git a/data/client/ui/font/font_28.png b/data/client/ui/font/font_28.png new file mode 100644 index 000000000..ff7c56c8e Binary files /dev/null and b/data/client/ui/font/font_28.png differ diff --git a/data/client/ui/keybindings.cfg b/data/client/ui/keybindings.cfg new file mode 100644 index 000000000..385024633 --- /dev/null +++ b/data/client/ui/keybindings.cfg @@ -0,0 +1,5 @@ +w +move_forward +a +move_left +s +move_backward +d +move_right +ctrl+w quit diff --git a/data/client/ui/lang/en.tb.txt b/data/client/ui/lang/en.tb.txt new file mode 100644 index 000000000..8d7191b71 --- /dev/null +++ b/data/client/ui/lang/en.tb.txt @@ -0,0 +1,14 @@ +TBMessageWindow.ok Ok +TBMessageWindow.cancel Cancel +TBMessageWindow.yes Yes +TBMessageWindow.no No +TBList.header Showing %d of %d +connect Connect +password Password +login Login +email Email +ok Ok +disconnect Disconnect +disconnecttext You either got disconnected or the connect attempt failed +authfailed Authentication failed +authfailedtext Authentication failed diff --git a/data/client/ui/skin/arrow_down.png b/data/client/ui/skin/arrow_down.png new file mode 100644 index 000000000..589c9fc10 Binary files /dev/null and b/data/client/ui/skin/arrow_down.png differ diff --git a/data/client/ui/skin/arrow_left.png b/data/client/ui/skin/arrow_left.png new file mode 100644 index 000000000..7f5447b68 Binary files /dev/null and b/data/client/ui/skin/arrow_left.png differ diff --git a/data/client/ui/skin/arrow_right.png b/data/client/ui/skin/arrow_right.png new file mode 100644 index 000000000..fce7cf397 Binary files /dev/null and b/data/client/ui/skin/arrow_right.png differ diff --git a/data/client/ui/skin/arrow_up.png b/data/client/ui/skin/arrow_up.png new file mode 100644 index 000000000..a07789fc7 Binary files /dev/null and b/data/client/ui/skin/arrow_up.png differ diff --git a/data/client/ui/skin/button.png b/data/client/ui/skin/button.png new file mode 100644 index 000000000..6516534fc Binary files /dev/null and b/data/client/ui/skin/button.png differ diff --git a/data/client/ui/skin/button_flat_outline.png b/data/client/ui/skin/button_flat_outline.png new file mode 100644 index 000000000..ba3e2b704 Binary files /dev/null and b/data/client/ui/skin/button_flat_outline.png differ diff --git a/data/client/ui/skin/button_flat_pressed.png b/data/client/ui/skin/button_flat_pressed.png new file mode 100644 index 000000000..ee7e65677 Binary files /dev/null and b/data/client/ui/skin/button_flat_pressed.png differ diff --git a/data/client/ui/skin/button_grouped_x_first_down.png b/data/client/ui/skin/button_grouped_x_first_down.png new file mode 100644 index 000000000..ace624e01 Binary files /dev/null and b/data/client/ui/skin/button_grouped_x_first_down.png differ diff --git a/data/client/ui/skin/button_grouped_x_first_up.png b/data/client/ui/skin/button_grouped_x_first_up.png new file mode 100644 index 000000000..525841117 Binary files /dev/null and b/data/client/ui/skin/button_grouped_x_first_up.png differ diff --git a/data/client/ui/skin/button_grouped_x_last_down.png b/data/client/ui/skin/button_grouped_x_last_down.png new file mode 100644 index 000000000..b12dc5b23 Binary files /dev/null and b/data/client/ui/skin/button_grouped_x_last_down.png differ diff --git a/data/client/ui/skin/button_grouped_x_last_up.png b/data/client/ui/skin/button_grouped_x_last_up.png new file mode 100644 index 000000000..f9ea08f34 Binary files /dev/null and b/data/client/ui/skin/button_grouped_x_last_up.png differ diff --git a/data/client/ui/skin/button_grouped_x_middle_down.png b/data/client/ui/skin/button_grouped_x_middle_down.png new file mode 100644 index 000000000..922d1dd30 Binary files /dev/null and b/data/client/ui/skin/button_grouped_x_middle_down.png differ diff --git a/data/client/ui/skin/button_grouped_x_middle_up.png b/data/client/ui/skin/button_grouped_x_middle_up.png new file mode 100644 index 000000000..acac147d7 Binary files /dev/null and b/data/client/ui/skin/button_grouped_x_middle_up.png differ diff --git a/data/client/ui/skin/button_pressed.png b/data/client/ui/skin/button_pressed.png new file mode 100644 index 000000000..56cecfb3e Binary files /dev/null and b/data/client/ui/skin/button_pressed.png differ diff --git a/data/client/ui/skin/checkbox.png b/data/client/ui/skin/checkbox.png new file mode 100644 index 000000000..532d647c8 Binary files /dev/null and b/data/client/ui/skin/checkbox.png differ diff --git a/data/client/ui/skin/checkbox_mark.png b/data/client/ui/skin/checkbox_mark.png new file mode 100644 index 000000000..ed217d582 Binary files /dev/null and b/data/client/ui/skin/checkbox_mark.png differ diff --git a/data/client/ui/skin/checkbox_pressed.png b/data/client/ui/skin/checkbox_pressed.png new file mode 100644 index 000000000..a490b9004 Binary files /dev/null and b/data/client/ui/skin/checkbox_pressed.png differ diff --git a/data/client/ui/skin/container.png b/data/client/ui/skin/container.png new file mode 100644 index 000000000..b37f936b6 Binary files /dev/null and b/data/client/ui/skin/container.png differ diff --git a/data/client/ui/skin/editfield.png b/data/client/ui/skin/editfield.png new file mode 100644 index 000000000..09e6be55a Binary files /dev/null and b/data/client/ui/skin/editfield.png differ diff --git a/data/client/ui/skin/fadeout_x.png b/data/client/ui/skin/fadeout_x.png new file mode 100644 index 000000000..830c6db0b Binary files /dev/null and b/data/client/ui/skin/fadeout_x.png differ diff --git a/data/client/ui/skin/fadeout_y.png b/data/client/ui/skin/fadeout_y.png new file mode 100644 index 000000000..085b6a2a8 Binary files /dev/null and b/data/client/ui/skin/fadeout_y.png differ diff --git a/data/client/ui/skin/focus_r4.png b/data/client/ui/skin/focus_r4.png new file mode 100644 index 000000000..82c1e63e1 Binary files /dev/null and b/data/client/ui/skin/focus_r4.png differ diff --git a/data/client/ui/skin/focus_tabbutton_left.png b/data/client/ui/skin/focus_tabbutton_left.png new file mode 100644 index 000000000..1b445fec6 Binary files /dev/null and b/data/client/ui/skin/focus_tabbutton_left.png differ diff --git a/data/client/ui/skin/focus_tabbutton_top.png b/data/client/ui/skin/focus_tabbutton_top.png new file mode 100644 index 000000000..db015e236 Binary files /dev/null and b/data/client/ui/skin/focus_tabbutton_top.png differ diff --git a/data/client/ui/skin/item_hover.png b/data/client/ui/skin/item_hover.png new file mode 100644 index 000000000..90a6e723c Binary files /dev/null and b/data/client/ui/skin/item_hover.png differ diff --git a/data/client/ui/skin/item_selected.png b/data/client/ui/skin/item_selected.png new file mode 100644 index 000000000..cf5dd472d Binary files /dev/null and b/data/client/ui/skin/item_selected.png differ diff --git a/data/client/ui/skin/item_separator_x.png b/data/client/ui/skin/item_separator_x.png new file mode 100644 index 000000000..19073e907 Binary files /dev/null and b/data/client/ui/skin/item_separator_x.png differ diff --git a/data/client/ui/skin/item_separator_y.png b/data/client/ui/skin/item_separator_y.png new file mode 100644 index 000000000..baf7f51bf Binary files /dev/null and b/data/client/ui/skin/item_separator_y.png differ diff --git a/data/client/ui/skin/progress_spinner_strip.png b/data/client/ui/skin/progress_spinner_strip.png new file mode 100644 index 000000000..212a10629 Binary files /dev/null and b/data/client/ui/skin/progress_spinner_strip.png differ diff --git a/data/client/ui/skin/radio.png b/data/client/ui/skin/radio.png new file mode 100644 index 000000000..bfff79668 Binary files /dev/null and b/data/client/ui/skin/radio.png differ diff --git a/data/client/ui/skin/radio_mark.png b/data/client/ui/skin/radio_mark.png new file mode 100644 index 000000000..570f48ad8 Binary files /dev/null and b/data/client/ui/skin/radio_mark.png differ diff --git a/data/client/ui/skin/radio_pressed.png b/data/client/ui/skin/radio_pressed.png new file mode 100644 index 000000000..a9836185e Binary files /dev/null and b/data/client/ui/skin/radio_pressed.png differ diff --git a/data/client/ui/skin/resizer.png b/data/client/ui/skin/resizer.png new file mode 100644 index 000000000..5918a7b20 Binary files /dev/null and b/data/client/ui/skin/resizer.png differ diff --git a/data/client/ui/skin/scroll_bg_x.png b/data/client/ui/skin/scroll_bg_x.png new file mode 100644 index 000000000..fc2eb5df9 Binary files /dev/null and b/data/client/ui/skin/scroll_bg_x.png differ diff --git a/data/client/ui/skin/scroll_bg_y.png b/data/client/ui/skin/scroll_bg_y.png new file mode 100644 index 000000000..2775e3b43 Binary files /dev/null and b/data/client/ui/skin/scroll_bg_y.png differ diff --git a/data/client/ui/skin/scroll_fg_x.png b/data/client/ui/skin/scroll_fg_x.png new file mode 100644 index 000000000..6bc8a5a10 Binary files /dev/null and b/data/client/ui/skin/scroll_fg_x.png differ diff --git a/data/client/ui/skin/scroll_fg_y.png b/data/client/ui/skin/scroll_fg_y.png new file mode 100644 index 000000000..861e1bdf0 Binary files /dev/null and b/data/client/ui/skin/scroll_fg_y.png differ diff --git a/data/client/ui/skin/search.png b/data/client/ui/skin/search.png new file mode 100644 index 000000000..79cd11f14 Binary files /dev/null and b/data/client/ui/skin/search.png differ diff --git a/data/client/ui/skin/section_container.png b/data/client/ui/skin/section_container.png new file mode 100644 index 000000000..331a3f555 Binary files /dev/null and b/data/client/ui/skin/section_container.png differ diff --git a/data/client/ui/skin/selection.png b/data/client/ui/skin/selection.png new file mode 100644 index 000000000..541c02a23 Binary files /dev/null and b/data/client/ui/skin/selection.png differ diff --git a/data/client/ui/skin/skin.tb.txt b/data/client/ui/skin/skin.tb.txt new file mode 100644 index 000000000..99283b0ae --- /dev/null +++ b/data/client/ui/skin/skin.tb.txt @@ -0,0 +1,464 @@ +# This is the default skin of Turbo Badger +# The license of the skin is Public Domain. +# +# For more information about Turbo Badger and its license, +# see tb_core.h. +description + name Turbo Badger Default skin + # Dimensions in dp (the default unit for padding and such) and bitmaps are specified for this DPI. + base-dpi 96 + # The skin also has graphics available in these DPI modes + supported-dpi 96 +defaults + spacing 5 + text-color #fefefe + placeholder + opacity 0.2 + disabled + opacity 0.3 +elements + TBButton + text-color #fefefe + bitmap button.png + cut 17 + expand 7 + padding 6 8 + overrides + element TBButtonInGroup + condition: target: parent, property: skin, value: button_group + condition: target: parent, property: axis, value: x + element TBButton.pressed + state pressed + TBButton.pressed + text-color #fefefe + bitmap button_pressed.png + cut 17 + expand 7 + content-ofs-x 1 + content-ofs-y 1 + + TBButton.flat + text-color #fefefe + padding 6 8 + children + element TBButton.flat.hovered + state hovered + element TBButton.flat.pressed + state pressed + TBButton.flat.hovered + bitmap button_flat_outline.png + cut 15 + expand 6 + TBButton.flat.pressed + bitmap button_flat_pressed.png + cut 8 + + # == TBButtonInGroup is not a widget. It's only used as override for TBButton under a "button_group" ==== + TBButtonInGroup + bitmap button_grouped_x_middle_up.png + cut 17 + expand 7 + padding 6 8 + overrides + element TBButtonInGroup.first + condition: target: prev sibling, property: skin, value: TBButton, test: != + element TBButtonInGroup.last + condition: target: next sibling, property: skin, value: TBButton, test: != + element TBButtonInGroup.pressed + state pressed + TBButtonInGroup.pressed + clone TBButtonInGroup + bitmap button_grouped_x_middle_down.png + content-ofs-x 1 + content-ofs-y 1 + overrides + TBButtonInGroup.first + clone TBButtonInGroup + bitmap button_grouped_x_first_up.png + overrides + element TBButtonInGroup.first.pressed + state pressed + TBButtonInGroup.first.pressed + clone TBButtonInGroup.pressed + bitmap button_grouped_x_first_down.png + overrides + TBButtonInGroup.last + clone TBButtonInGroup + bitmap button_grouped_x_last_up.png + overrides + element TBButtonInGroup.last.pressed + state pressed + TBButtonInGroup.last.pressed + clone TBButtonInGroup.pressed + bitmap button_grouped_x_last_down.png + overrides + + # == button_group is not a widget. It's specified on widgets that should group TBButton ======= + button_group + spacing -1px + + # == TBSection skins ========================================================================== + TBSection.layout + spacing -1px + TBSection.container + bitmap section_container.png + type StretchBorder + cut 11 + expand 6 + padding 10 + TBSectionHeader + bitmap window_mover_bg_tile.png + type Tile + expand -1 + padding 3 16 + children + element TBSectionHeader.icon_0 + condition: target: this, property: value, value: 0 + condition: target: this, property: capture, test: != + element TBSectionHeader.icon_1 + condition: target: this, property: value, value: 1 + condition: target: this, property: capture, test: != + element TBSectionHeader.icon_pressed + condition: target: this, property: capture + overlays + element TBSectionHeader.overlay + state all + TBSectionHeader.overlay + bitmap window_mover_overlay.png + type StretchBorder + cut 16 + expand 3 + TBSectionHeader.icon_0 + bitmap toggle_section_icon_up.png + type Image + img-position-x 0 + img-ofs-x 4 + TBSectionHeader.icon_1 + bitmap toggle_section_icon_down.png + type Image + img-position-x 0 + img-ofs-x 4 + TBSectionHeader.icon_pressed + bitmap toggle_section_icon_middle.png + type Image + img-position-x 0 + img-ofs-x 4 + + # == TBTabContainer skins - Create strong overrides for the tab buttons four alignments ============ + TBTabContainer.rootlayout + spacing -1px + TBTabContainer.tablayout_x + padding 0 10 + TBTabContainer.tablayout_y + padding 10 0 + TBTabContainer.container + clone TBContainer + TBTabContainer.tab + strong-overrides + element TBTabContainer.tab_top + condition: target: ancestors, property: align, value: top + element TBTabContainer.tab_bottom + condition: target: ancestors, property: align, value: bottom + element TBTabContainer.tab_left + condition: target: ancestors, property: align, value: left + element TBTabContainer.tab_right + condition: target: ancestors, property: align, value: right + # == Top tab button ============================= + TBTabContainer.tab_top + bitmap tab_button_top_inactive.png + cut 12 + expand 6 + padding 6 6 3 6 + min-width 50 + overrides + element TBTabContainer.tab_top.pressed + state pressed + children + element tab_top_focus + state focused + tab_top_focus + type StretchBorder + bitmap focus_tabbutton_top.png + cut 12 + expand 6 + TBTabContainer.tab_top.pressed + bitmap tab_button_top_active.png + cut 13 + expand 6 + # == Bottom tab button ============================= + TBTabContainer.tab_bottom + bitmap tab_button_bottom_inactive.png + cut 12 + expand 6 + padding 3 6 6 6 + min-width 50 + overrides + element TBTabContainer.tab_bottom.pressed + state pressed + children + element tab_bottom_focus + state focused + tab_bottom_focus + clone tab_top_focus + flip-y 1 + TBTabContainer.tab_bottom.pressed + bitmap tab_button_bottom_active.png + cut 13 + expand 6 + # == Left tab button ============================= + TBTabContainer.tab_left + bitmap tab_button_left_inactive.png + cut 12 + expand 6 + padding 6 3 6 6 + min-width 50 + overrides + element TBTabContainer.tab_left.pressed + state pressed + children + element tab_left_focus + state focused + tab_left_focus + type StretchBorder + bitmap focus_tabbutton_left.png + cut 12 + expand 6 + TBTabContainer.tab_left.pressed + bitmap tab_button_left_active.png + cut 13 + expand 6 + # == Right tab button ============================= + TBTabContainer.tab_right + bitmap tab_button_right_inactive.png + cut 12 + expand 6 + padding 6 6 6 3 + min-width 50 + overrides + element TBTabContainer.tab_right.pressed + state pressed + children + element tab_right_focus + state focused + tab_right_focus + clone tab_left_focus + flip-x 1 + TBTabContainer.tab_right.pressed + bitmap tab_button_right_active.png + cut 13 + expand 6 + + # == TBEditField skin. Create strong overrides for the search type to add magnifier glass icon ===== + TBEditField.selection + cut 2 + bitmap selection.png + TBEditField + bitmap editfield.png + cut 12 + expand 4 + padding 4 + strong-overrides + element TBEditField.search + condition: target: this, property: edit-type, value: "search" + + TBEditField.search + clone TBEditField + padding 4 4 4 24 + min-width 50 + children + element TBEditField.search.icon + TBEditField.search.icon + bitmap search.png + type Image + img-position-x 0 + img-ofs-x 5 + + # == TBWindow skin ================================================================================= + TBWindow + bitmap window.png + cut 16 + expand 12 + padding 10 + overrides + element TBWindow.selected + state selected + TBWindow.selected + bitmap window_active.png + cut 16 + expand 12 + TBWindow.close + bitmap window_close.png + type Image + children + element TBWindow.close.pressed + state pressed + TBWindow.close.pressed + bitmap window_close_pressed.png + type Image + TBWindow.mover + text-color #b8b8b8 + bitmap window_mover_bg_tile.png + type Tile + expand -1 + padding 4 + overrides + element TBWindow.mover.active + state selected + children + element TBWindow.mover.overlay + state all + TBWindow.mover.overlay + bitmap window_mover_overlay.png + cut 12 + expand 3 + TBWindow.mover.active + clone TBWindow.mover + text-color #fefefe + overrides + overlays + children + + # == Misc skins ==================================================================================== + TBContainer + bitmap container.png + type StretchBorder + cut 12 + expand 6 + padding 10 + TBCheckBox + bitmap checkbox.png + cut 19 + expand 7 + children + element TBCheckBox.selected + state selected + element TBCheckBox.pressed + state pressed + TBCheckBox.selected + bitmap checkbox_mark.png + type Image + expand 7 + TBCheckBox.pressed + bitmap checkbox_pressed.png + type Image + TBRadioButton + bitmap radio.png + cut 19 + expand 7 + children + element TBRadioButton.selected + state selected + element TBRadioButton.pressed + state pressed + TBRadioButton.selected + bitmap radio_mark.png + type Image + expand 7 + TBRadioButton.pressed + bitmap radio_pressed.png + type Image + expand 7 + TBLayout.fadeout_x + bitmap fadeout_x.png + TBLayout.fadeout_y + bitmap fadeout_y.png + TBSelectList + clone TBEditField + padding 2 + TBSelectDropdown + clone TBButton + TBSelectDropdown.arrow + clone arrow.down + TBSelectDropdown.window + clone TBPopupWindow + TBPopupWindow + clone TBWindow + padding 2 + TBMenuWindow + clone TBPopupWindow + TBSelectItem + padding 4 10 + children + element TBSelectItem.hovered + state hovered + element TBSelectItem.selected + state selected + TBSelectItem.selected + cut 7 + bitmap item_selected.png + TBSelectItem.hovered + cut 7 + bitmap item_hover.png + TBSelectItem.separator + clone TBSeparator + + TBSeparator + bitmap item_separator_x.png + type Stretch Image + overrides + element TBSeparator.y + condition: target: parent, property: axis, value: x + TBSeparator.y + bitmap item_separator_y.png + type Stretch Image + + TBScrollBarBgX + bitmap scroll_bg_x.png + cut 11 + expand 5 + TBScrollBarFgX + bitmap scroll_fg_x.png + cut 11 + expand 5 + TBScrollBarBgY + bitmap scroll_bg_y.png + cut 11 + expand 5 + TBScrollBarFgY + bitmap scroll_fg_y.png + cut 11 + expand 5 + + TBSliderBgX + bitmap slider_bg_x.png + cut 9 + min-height 19 + max-height 19 + min-width 50 + TBSliderFgX + bitmap slider_handle.png + expand 5 + + TBSliderBgY + bitmap slider_bg_y.png + cut 9 + min-width 19 + max-width 19 + min-height 50 + TBSliderFgY + clone TBSliderFgX + + TBResizer + bitmap resizer.png + TBInlineSelect + max-width 110 + TBDimmer + background-color #00000088 + + TBProgressSpinner + min-width 28 + min-height 28 + TBProgressSpinner.fg + bitmap progress_spinner_strip.png + + # The TBList header is always disabled, thus gets slightly less opacity default. + TBList.header + + arrow.left: type: Image, bitmap: arrow_left.png, min-width: 5, min-height: 10 + arrow.right: type: Image, bitmap: arrow_right.png, min-width: 5, min-height: 10 + arrow.up: type: Image, bitmap: arrow_up.png, min-width: 10, min-height: 5 + arrow.down: type: Image, bitmap: arrow_down.png, min-width: 10, min-height: 5 + generic_focus + bitmap focus_r4.png + cut 11 + expand 4 diff --git a/data/client/ui/skin/slider_bg_x.png b/data/client/ui/skin/slider_bg_x.png new file mode 100644 index 000000000..71c31634b Binary files /dev/null and b/data/client/ui/skin/slider_bg_x.png differ diff --git a/data/client/ui/skin/slider_bg_y.png b/data/client/ui/skin/slider_bg_y.png new file mode 100644 index 000000000..d756e841a Binary files /dev/null and b/data/client/ui/skin/slider_bg_y.png differ diff --git a/data/client/ui/skin/slider_handle.png b/data/client/ui/skin/slider_handle.png new file mode 100644 index 000000000..94489a013 Binary files /dev/null and b/data/client/ui/skin/slider_handle.png differ diff --git a/data/client/ui/skin/tab_button_bottom_active.png b/data/client/ui/skin/tab_button_bottom_active.png new file mode 100644 index 000000000..77ee097db Binary files /dev/null and b/data/client/ui/skin/tab_button_bottom_active.png differ diff --git a/data/client/ui/skin/tab_button_bottom_inactive.png b/data/client/ui/skin/tab_button_bottom_inactive.png new file mode 100644 index 000000000..99d3c9062 Binary files /dev/null and b/data/client/ui/skin/tab_button_bottom_inactive.png differ diff --git a/data/client/ui/skin/tab_button_left_active.png b/data/client/ui/skin/tab_button_left_active.png new file mode 100644 index 000000000..ed6f4620c Binary files /dev/null and b/data/client/ui/skin/tab_button_left_active.png differ diff --git a/data/client/ui/skin/tab_button_left_inactive.png b/data/client/ui/skin/tab_button_left_inactive.png new file mode 100644 index 000000000..d2e207909 Binary files /dev/null and b/data/client/ui/skin/tab_button_left_inactive.png differ diff --git a/data/client/ui/skin/tab_button_right_active.png b/data/client/ui/skin/tab_button_right_active.png new file mode 100644 index 000000000..276d23f79 Binary files /dev/null and b/data/client/ui/skin/tab_button_right_active.png differ diff --git a/data/client/ui/skin/tab_button_right_inactive.png b/data/client/ui/skin/tab_button_right_inactive.png new file mode 100644 index 000000000..47f4def72 Binary files /dev/null and b/data/client/ui/skin/tab_button_right_inactive.png differ diff --git a/data/client/ui/skin/tab_button_top_active.png b/data/client/ui/skin/tab_button_top_active.png new file mode 100644 index 000000000..271b679f0 Binary files /dev/null and b/data/client/ui/skin/tab_button_top_active.png differ diff --git a/data/client/ui/skin/tab_button_top_inactive.png b/data/client/ui/skin/tab_button_top_inactive.png new file mode 100644 index 000000000..16023b187 Binary files /dev/null and b/data/client/ui/skin/tab_button_top_inactive.png differ diff --git a/data/client/ui/skin/toggle_section_icon_down.png b/data/client/ui/skin/toggle_section_icon_down.png new file mode 100644 index 000000000..23bb510d6 Binary files /dev/null and b/data/client/ui/skin/toggle_section_icon_down.png differ diff --git a/data/client/ui/skin/toggle_section_icon_middle.png b/data/client/ui/skin/toggle_section_icon_middle.png new file mode 100644 index 000000000..919848274 Binary files /dev/null and b/data/client/ui/skin/toggle_section_icon_middle.png differ diff --git a/data/client/ui/skin/toggle_section_icon_up.png b/data/client/ui/skin/toggle_section_icon_up.png new file mode 100644 index 000000000..e9bdf693a Binary files /dev/null and b/data/client/ui/skin/toggle_section_icon_up.png differ diff --git a/data/client/ui/skin/window.png b/data/client/ui/skin/window.png new file mode 100644 index 000000000..93ffeccaf Binary files /dev/null and b/data/client/ui/skin/window.png differ diff --git a/data/client/ui/skin/window_active.png b/data/client/ui/skin/window_active.png new file mode 100644 index 000000000..20232c3fd Binary files /dev/null and b/data/client/ui/skin/window_active.png differ diff --git a/data/client/ui/skin/window_close.png b/data/client/ui/skin/window_close.png new file mode 100644 index 000000000..810045118 Binary files /dev/null and b/data/client/ui/skin/window_close.png differ diff --git a/data/client/ui/skin/window_close_pressed.png b/data/client/ui/skin/window_close_pressed.png new file mode 100644 index 000000000..91e2166cf Binary files /dev/null and b/data/client/ui/skin/window_close_pressed.png differ diff --git a/data/client/ui/skin/window_mover_bg_tile.png b/data/client/ui/skin/window_mover_bg_tile.png new file mode 100644 index 000000000..5d00a2562 Binary files /dev/null and b/data/client/ui/skin/window_mover_bg_tile.png differ diff --git a/data/client/ui/skin/window_mover_overlay.png b/data/client/ui/skin/window_mover_overlay.png new file mode 100644 index 000000000..2490d5c13 Binary files /dev/null and b/data/client/ui/skin/window_mover_overlay.png differ diff --git a/data/client/ui/window/authfailed.tb.txt b/data/client/ui/window/authfailed.tb.txt new file mode 100644 index 000000000..e7b82d9e0 --- /dev/null +++ b/data/client/ui/window/authfailed.tb.txt @@ -0,0 +1,10 @@ +WindowInfo + title @authfailed +TBLayout + axis y + distribution gravity + TBTextField + text @authfailedtext + TBButton + text @ok + id ok diff --git a/data/client/ui/window/disconnect.tb.txt b/data/client/ui/window/disconnect.tb.txt new file mode 100644 index 000000000..0a24f7c71 --- /dev/null +++ b/data/client/ui/window/disconnect.tb.txt @@ -0,0 +1,10 @@ +WindowInfo + title @disconnect +TBLayout + axis y + distribution gravity + TBTextField + text @disconnecttext + TBButton + text @ok + id ok diff --git a/data/client/ui/window/hud.tb.txt b/data/client/ui/window/hud.tb.txt new file mode 100644 index 000000000..159171ff7 --- /dev/null +++ b/data/client/ui/window/hud.tb.txt @@ -0,0 +1,10 @@ +WindowInfo + position: 0 0 +TBLayout + axis y + distribution gravity + TBTextField + text @disconnecttext + TBButton + text @disconnect + id disconnect diff --git a/data/client/ui/window/login.tb.txt b/data/client/ui/window/login.tb.txt new file mode 100644 index 000000000..f5873a1b8 --- /dev/null +++ b/data/client/ui/window/login.tb.txt @@ -0,0 +1,36 @@ +WindowInfo + title @connect +TBLayout + axis y + distribution gravity + TBLayout + axis x + gravity left right + distribution-position right + TBTextField + text @email + TBEditField + placeholder @email + id email + type email + lp + width 400 + TBLayout + axis x + gravity left right + distribution-position right + TBTextField + text @password + TBEditField + placeholder @password + id password + type password + lp + width 400 + TBLayout + axis x + gravity right + distribution-position right bottom + TBButton + text @login + id login diff --git a/data/server/ai/constants.lua b/data/server/ai/constants.lua new file mode 100644 index 000000000..e074c689f --- /dev/null +++ b/data/server/ai/constants.lua @@ -0,0 +1,2 @@ +INCREASE_COOLDOWNID = 1 +HUNT_COOLDOWNID = 2 diff --git a/data/server/ai/rabbit.lua b/data/server/ai/rabbit.lua new file mode 100644 index 000000000..92bc77c1f --- /dev/null +++ b/data/server/ai/rabbit.lua @@ -0,0 +1,14 @@ +require "ai.shared" + +function rabbitStayAlive (parentnode) + parentnode:addNode("Steer(SelectionFlee)", "fleefromhunter"):setCondition("And(Filter(SelectNpcsOfTypes{ANIMAL_WOLF}),IsCloseToSelection{10})") +end + +function rabbit () + local name = "ANIMAL_RABBIT" + local rootNode = AI.createTree(name):createRoot("PrioritySelector", name) + rabbitStayAlive(rootNode) + increasePopulation(rootNode) + idle(rootNode) + die(rootNode) +end diff --git a/data/server/ai/shared.lua b/data/server/ai/shared.lua new file mode 100644 index 000000000..e824d8e46 --- /dev/null +++ b/data/server/ai/shared.lua @@ -0,0 +1,37 @@ +require "ai.constants" + +function increasePopulation (parentnode) + local parallel = parentnode:addNode("Parallel", "increasepopulation") + parallel:setCondition("And(Not(IsOnCooldown{".. INCREASE_COOLDOWNID .."}),Filter(SelectIncreasePartner{".. INCREASE_COOLDOWNID .."}))") + + parallel:addNode("Steer(SelectionSeek)", "followincreasepartner") + local spawn = parallel:addNode("Parallel", "spawn") + spawn:setCondition("IsCloseToSelection{1}") + + spawn:addNode("Spawn", "spawn") + spawn:addNode("TriggerCooldown{".. INCREASE_COOLDOWNID .."}", "increasecooldown") + spawn:addNode("TriggerCooldownOnSelection{".. INCREASE_COOLDOWNID .."}", "increasecooldownonpartner") +end + +function hunt (parentnode) + local parallel = parentnode:addNode("Parallel", "hunt") + parallel:setCondition("Not(IsOnCooldown{".. HUNT_COOLDOWNID .."})") + + parallel:addNode("Steer(SelectionSeek)", "follow"):setCondition("Filter(SelectPrey{ANIMAL_RABBIT})") + parallel:addNode("AttackOnSelection", "attack"):setCondition("IsCloseToSelection{1}") + parallel:addNode("SetPointOfInterest", "setpoi"):setCondition("IsCloseToSelection{1}") + parallel:addNode("TriggerCooldown{".. HUNT_COOLDOWNID .."}", "increasecooldown"):setCondition("Not(IsSelectionAlive)") +end + +function idle (parentnode) + local prio = parentnode:addNode("PrioritySelector", "walkuncrowded") + + -- if there are too many objects (see parameter) visible of either the same npc type or the max count, leave the area + -- otherwise walk randomly around in the area around your home position + --prio:addNode("Steer(WanderAroundHome{100})", "wanderathome"):addCondition("Not(IsCrowded{10, 100})") + -- if we can't walk in our home base area, we are wandering freely around to find another not crowded area + prio:addNode("Steer(Wander)", "wanderfreely") +end + +function die (parentnode) +end diff --git a/data/server/ai/wolf.lua b/data/server/ai/wolf.lua new file mode 100644 index 000000000..b311575ff --- /dev/null +++ b/data/server/ai/wolf.lua @@ -0,0 +1,14 @@ +require "ai.shared" + +function wolfStayAlive (parentnode) +end + +function wolf () + local name = "ANIMAL_WOLF" + local rootNode = AI.createTree(name):createRoot("PrioritySelector", name) + wolfStayAlive(rootNode) + hunt(rootNode) + increasePopulation(rootNode) + idle(rootNode) + die(rootNode) +end diff --git a/data/server/attributes.lua b/data/server/attributes.lua new file mode 100644 index 000000000..3a09a4784 --- /dev/null +++ b/data/server/attributes.lua @@ -0,0 +1,18 @@ +function animalDefault(container) + container:absolute("SPEED", 10.0) + container:absolute("HEALTH", 100.0) + container:absolute("ATTACKRANGE", 0.0) + container:absolute("STRENGTH", 5.0) +end + +function init() + local wolf = attrib.createContainer("ANIMAL_WOLF") + animalDefault(wolf) + wolf:absolute("ATTACKRANGE", 2.0) + wolf:register() + + local rabbit = attrib.createContainer("ANIMAL_RABBIT") + animalDefault(rabbit) + rabbit:absolute("SPEED", 9.0) + rabbit:register() +end diff --git a/data/server/behaviourtrees.lua b/data/server/behaviourtrees.lua new file mode 100644 index 000000000..4427f8827 --- /dev/null +++ b/data/server/behaviourtrees.lua @@ -0,0 +1,7 @@ +require "ai.wolf" +require "ai.rabbit" + +function init () + wolf() + rabbit() +end diff --git a/data/shared/world-1.wld b/data/shared/world-1.wld new file mode 100644 index 000000000..5fe76befe Binary files /dev/null and b/data/shared/world-1.wld differ diff --git a/docs/MILESTONES.md b/docs/MILESTONES.md new file mode 100644 index 000000000..6a4e8a096 --- /dev/null +++ b/docs/MILESTONES.md @@ -0,0 +1,47 @@ +Project Voxel +------------------- + +# Milestone #1 +* VoxelVolume on Server [done] +* Network message to connect and send the server seed to create the client side world [done] +* VoxelVolume on Client [done] +* Render VoxelVolume on the client side [done] +* Camera movement without clipping [done] + +# Milestone #2 +* Network handlers for user/irrlicht movement [done] +* Irrlich movement (clipping on the Voxels) and send movement messages to the server and back to the client [done] +** lerping between the messages +* Server needs some user representation [done] + +# Milestone #3 +* NPCs [done] +* Network messages for spawning npcs [done] +* Network messages for npc movement [done] +* Network handlers for spawning npcs [done] +* Network handlers for npc movement [done] +* Take over NPCs + +# Milestone #4 +* Behaviour trees for a simple NPC chain (Shephard => Trader) +* Visibility (QuadTree in the EntityStorage::update method) [done] + +# Milestone #5 +* Login (Authentification and Authorization - see EntityStorage::login) +* Logout -> NPC falls asleep for some time, NPC will follow BehaviourTree again after some time + +# Milestone #6 +* Bigger worlds +* Some sort of AMS [done] +* Persist user data +* Persist world data on server shutdown + + +Voxel AMS +------------------- + +* Buffs/Debuffs +* AreaEffects +* Spells/Dispells +* Skills +* Cooldowns [done] diff --git a/fips b/fips new file mode 100755 index 000000000..8f8a21cd9 --- /dev/null +++ b/fips @@ -0,0 +1,17 @@ +#!/usr/bin/env python +"""fips main entry""" +import os +import sys +import subprocess +proj_path = os.path.dirname(os.path.abspath(__file__)) +fips_path = os.path.dirname(proj_path) + '/fips' +if not os.path.isdir(fips_path) : + print("\033[93m=== cloning fips build system to '{}':\033[0m".format(fips_path)) + subprocess.call(['git', 'clone', 'https://github.com/floooh/fips.git', fips_path]) +sys.path.insert(0,fips_path) +try : + from mod import fips +except ImportError : + print("\033[91m[ERROR]\033[0m failed to initialize fips build system in '{}'".format(proj_path)) + sys.exit(10) +fips.run(fips_path, proj_path, sys.argv) diff --git a/fips.cmd b/fips.cmd new file mode 100644 index 000000000..6780a0d68 --- /dev/null +++ b/fips.cmd @@ -0,0 +1,3 @@ +@python fips %* + + diff --git a/fips.yml b/fips.yml new file mode 100644 index 000000000..f059e219a --- /dev/null +++ b/fips.yml @@ -0,0 +1,54 @@ +imports: + fips-glm: + git: https://github.com/floooh/fips-glm.git + fips-accidentalnoise: + git: https://github.com/mgerhardy/fips-accidentalnoise.git + fips-enet: + git: https://github.com/mgerhardy/fips-enet.git + fips-polyvox: + git: https://github.com/mgerhardy/fips-polyvox.git + fips-simpleai: + git: https://github.com/mgerhardy/fips-simpleai.git + fips-flatbuffers: + git: https://github.com/mgerhardy/fips-flatbuffers.git + fips-sauce: + git: https://github.com/mgerhardy/fips-sauce.git + fips-googletest: + git: https://github.com/mgerhardy/fips-googletest.git + fips-turbobadger: + git: https://github.com/fungos/fips-turbobadger.git + fips-stb: + git: https://github.com/fungos/fips-stb.git + fips-assimp: + git: https://github.com/fungos/fips-assimp.git + fips-lua: + git: https://github.com/mgerhardy/fips-lua.git + fips-zlib: + git: https://github.com/floooh/fips-zlib.git + fips-noisepp: + git: https://github.com/mgerhardy/fips-noisepp.git + +exports: + header-dirs: + - src/client + - src/server + - src/worldgenerator + - src/modules + - src/modules/ui + modules: + core: src/modules/core + io: src/modules/io + video: src/modules/video + ui: src/modules/ui + util: src/modules/util + network: src/modules/network + voxel: src/modules/voxel + attrib: src/modules/attrib + noise: src/modules/noise + backend: src/modules/backend + frontend: src/modules/frontend + client: src/client + server: src/server + rcon: src/rcon + worldgenerator: src/worldgenerator + commonlua: src/modules/commonlua diff --git a/screenshots/2015-04-24.png b/screenshots/2015-04-24.png new file mode 100644 index 000000000..950f88c51 Binary files /dev/null and b/screenshots/2015-04-24.png differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 000000000..975d5fc9c --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,5 @@ +fips_add_subdirectory(modules) +fips_add_subdirectory(client) +fips_add_subdirectory(server) +fips_add_subdirectory(rcon) +fips_add_subdirectory(worldgenerator) diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt new file mode 100644 index 000000000..da04cec76 --- /dev/null +++ b/src/client/CMakeLists.txt @@ -0,0 +1,26 @@ +fips_begin_app(client windowed) + fips_files( + Client.h Client.cpp + ) + + fips_dir(sauce) + fips_files( + ClientModule.h + ClientInjector.h + ) + + fips_dir(network) + fips_files( + AuthFailedHandler.h + ClientNetworkModule.h + NpcSpawnHandler.h + SeedHandler.cpp SeedHandler.h + UserSpawnHandler.h + UserUpdateHandler.h + NpcRemoveHandler.h + ) + find_package(SDL2 REQUIRED) + include_directories(${SDL2_INCLUDE_DIRS} .) + fips_deps(frontend util ${SDL2_LIBRARIES}) + copy_data_files(client) +fips_end_app() diff --git a/src/client/Client.cpp b/src/client/Client.cpp new file mode 100644 index 000000000..3183ad1b4 --- /dev/null +++ b/src/client/Client.cpp @@ -0,0 +1,446 @@ +#include "Client.h" +#include "voxel/Spiral.h" +#include "network/messages/ClientMessages.h" +#include "frontend/ui/LoginWindow.h" +#include "frontend/ui/DisconnectWindow.h" +#include "frontend/ui/AuthFailedWindow.h" +#include "frontend/ui/HudWindow.h" +#include +#include +#include "core/Command.h" +#include "sauce/ClientInjector.h" +#include "video/GLDebug.h" + +#define registerMoveCmd(name, flag) \ + core::Command::registerCommand(name, [&] (const core::CmdArgs& args) { \ + if (args.empty()) \ + return; \ + if (args[0] == "true") \ + _moveMask |= MoveDirection_##flag; \ + else \ + _moveMask &= ~MoveDirection_##flag; \ + }); + +Client::Client(video::MeshPoolPtr meshPool, network::NetworkPtr network, voxel::WorldPtr world, network::MessageSenderPtr messageSender, + core::EventBusPtr eventBus, core::TimeProviderPtr timeProvider, io::FilesystemPtr filesystem) : + UIApp(filesystem, eventBus), _meshPool(meshPool), _network(network), _world(world), _messageSender(messageSender), _timeProvider( + timeProvider), _worldShader(), _meshShader(new frontend::MeshShader()), _waterShader(new frontend::WaterShader()), _userId(-1), _peer(nullptr), _moveMask(0), _lastMovement( + 0L) { + init("engine", "client"); +} + +Client::~Client() { + core::Command::unregisterCommand("+move_right"); + core::Command::unregisterCommand("+move_left"); + core::Command::unregisterCommand("+move_upt"); + core::Command::unregisterCommand("+move_down"); +} + +void Client::sendMovement() { + if (_peer == nullptr) + return; + + if (_now - _lastMovement <= 100L) + return; + + _lastMovement = _now; + flatbuffers::FlatBufferBuilder fbb; + const MoveDirection md = (MoveDirection) _moveMask; + _messageSender->sendClientMessage(_peer, fbb, Type_Move, CreateMove(fbb, md, _camera.pitch(), _camera.yaw()).Union(), 0); +} + +void Client::onMouseMotion(int32_t x, int32_t y, int32_t relX, int32_t relY) { + UIApp::onMouseMotion(x, y, relX, relY); + _camera.onMotion(x, y, relX, relY); +} + +void Client::onEvent(const network::DisconnectEvent& event) { + ui::Window* main = new frontend::LoginWindow(this); + new frontend::DisconnectWindow(main); +} + +void Client::onEvent(const network::NewConnectionEvent& event) { + flatbuffers::FlatBufferBuilder fbb; + const std::string& email = core::Var::get("cl_email")->strVal(); + const std::string& password = core::Var::get("cl_password")->strVal(); + Log::info("Trying to log into the server"); + _messageSender->sendClientMessage(_peer, fbb, Type_UserConnect, + CreateUserConnect(fbb, fbb.CreateString(email), fbb.CreateString(password)).Union()); +} + +void Client::onEvent(const voxel::WorldCreatedEvent& event) { + Log::info("world created"); + const int size = core::Var::get("cl_chunksize")->intVal(); + glm::ivec2 pos = _lastCameraPosition; + voxel::Spiral o; + for (int i = 0; i < 10000; ++i) { + event.world()->scheduleMeshExtraction(pos); + o.next(); + pos.x = _lastCameraPosition.x + o.x() * size; + pos.y = _lastCameraPosition.y + o.y() * size; + } + new frontend::HudWindow(this, _width, _height); +} + +// TODO: generate bigger buffers and use glBufferSubData +video::GLMeshData Client::createMesh(voxel::DecodedMesh& surfaceMesh, const glm::ivec2& translation, float scale) { + // Convenient access to the vertices and indices + const uint32_t* vecIndices = surfaceMesh.getRawIndexData(); + const uint32_t numIndices = surfaceMesh.getNoOfIndices(); + const voxel::VoxelVertexDecoded* vecVertices = surfaceMesh.getRawVertexData(); + const uint32_t numVertices = surfaceMesh.getNoOfVertices(); + + // This struct holds the OpenGL properties (buffer handles, etc) which will be used + // to render our mesh. We copy the data from the PolyVox mesh into this structure. + video::GLMeshData meshData; + + // Create the VAO for the mesh + glGenVertexArrays(1, &meshData.vertexArrayObject); + core_assert(meshData.vertexArrayObject > 0); + glBindVertexArray(meshData.vertexArrayObject); + + // The GL_ARRAY_BUFFER will contain the list of vertex positions + glGenBuffers(1, &meshData.vertexBuffer); + core_assert(meshData.vertexBuffer > 0); + glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(voxel::VoxelVertexDecoded), vecVertices, GL_STATIC_DRAW); + + // and GL_ELEMENT_ARRAY_BUFFER will contain the indices + glGenBuffers(1, &meshData.indexBuffer); + core_assert(meshData.indexBuffer > 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshData.indexBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof(uint32_t), vecIndices, GL_STATIC_DRAW); + + const int posLoc = _worldShader.enableVertexAttribute("a_pos"); + glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(voxel::VoxelVertexDecoded), + GL_OFFSET(offsetof(voxel::VoxelVertexDecoded, position))); + + const int matLoc = _worldShader.enableVertexAttribute("a_materialdensity"); + // our material and density is encoded as 8 bits material and 8 bits density + core_assert(sizeof(voxel::Voxel) == sizeof(uint16_t)); + glVertexAttribIPointer(matLoc, sizeof(voxel::Voxel), GL_UNSIGNED_BYTE, sizeof(voxel::VoxelVertexDecoded), + GL_OFFSET(offsetof(voxel::VoxelVertexDecoded, data))); + + glBindVertexArray(0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + Log::trace("mesh information:\n- mesh indices: %i, vertices: %i\n- position: %i:%i", numIndices, numVertices, translation.x, + translation.y); + + meshData.noOfIndices = numIndices; + meshData.translation = translation; + meshData.scale = scale; + meshData.indexType = GL_UNSIGNED_INT; + return meshData; +} + +core::AppState Client::onInit() { + eventBus()->subscribe(*this); + eventBus()->subscribe(*this); + eventBus()->subscribe(*this); + + GLDebug::enable(GLDebug::Medium); + + core::AppState state = UIApp::onInit(); + if (state != core::Running) + return state; + + if (!_network->start()) + return core::Cleanup; + + core::Var::get("cl_name", "noname"); + core::Var::get("cl_password", "nopassword"); + + if (!_worldShader.init()) { + return core::Cleanup; + } + if (!_meshShader->init()) { + return core::Cleanup; + } + if (!_waterShader->init()) { + return core::Cleanup; + } + + _waterTexture = video::TexturePtr(new video::Texture("texture/water.png")); + _waterTexture->load(); + const glm::vec3 vertices[4] = { glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(1.0f, + 1.0f, 0.0f) }; + const glm::ivec3 indices[2] = { glm::ivec3( 0, 1, 2 ), glm::ivec3( 1, 3, 2 ) }; + glGenVertexArrays(1, &_waterData.vertexArrayObject); + core_assert(_waterData.vertexArrayObject > 0); + glBindVertexArray(_waterData.vertexArrayObject); + + glGenBuffers(1, &_waterData.vertexBuffer); + core_assert(_waterData.vertexBuffer > 0); + glBindBuffer(GL_ARRAY_BUFFER, _waterData.vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(glm::vec3), vertices, GL_STATIC_DRAW); + + glGenBuffers(1, &_waterData.indexBuffer); + core_assert(_waterData.indexBuffer > 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _waterData.indexBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, 2 * sizeof(glm::ivec2), indices, GL_STATIC_DRAW); + + const int posLoc = _waterShader->enableVertexAttribute("a_pos"); + glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(voxel::VoxelVertexDecoded), + GL_OFFSET(offsetof(voxel::VoxelVertexDecoded, position))); + + glBindVertexArray(0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + _waterData.noOfIndices = 2; + _waterData.scale = 1.0f; + _waterData.indexType = GL_UNSIGNED_INT; + + GL_checkError(); + + _camera.init(_width, _height); + + registerMoveCmd("+move_right", MOVERIGHT); + registerMoveCmd("+move_left", MOVELEFT); + registerMoveCmd("+move_forward", MOVEFORWARD); + registerMoveCmd("+move_backward", MOVEBACKWARD); + + _clearColor = glm::vec3(0.04, 0.29, 0.94); + + _root.SetSkinBg(tb::TBIDC("background")); + new frontend::LoginWindow(this); + + SDL_GL_SetSwapInterval(core::Var::get("cl_vsync", "true")->boolVal()); + + return state; +} + +void Client::renderBackground() { + _camera.setAngles(-M_PI_2, M_PI); + _camera.setPosition(glm::vec3(0.0f, 100.0f, 0.0f)); + _camera.update(); + const glm::mat4& view = _camera.getViewMatrix(); + const glm::mat4& projection = glm::perspective(45.0f, _aspect, 0.1f, 1000.0f); + + _meshShader->activate(); + _meshShader->setUniformMatrix("u_view", view, false); + _meshShader->setUniformMatrix("u_projection", projection, false); + _meshShader->setUniformVec3("u_lightpos", _lightPos); + _meshShader->setUniformVec3("u_diffusecolor", _diffuseColor); + _meshShader->setUniformVec3("u_specularcolor", _specularColor); + _meshShader->setUniformi("u_texture", 0); + const video::MeshPtr& mesh = _meshPool->getMesh("animal_rabbit"); + if (mesh->initMesh(_meshShader)) { + const glm::mat4& translate = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 20.0f)); + const glm::mat4& scale = glm::scale(translate, glm::vec3(0.01f)); + const glm::mat4& model = glm::rotate(scale, (float) glm::sin(_now / 100L), glm::vec3(0.0, 1.0, 0.0)); + _meshShader->setUniformMatrix("u_model", model, false); + mesh->render(); + } + _meshShader->deactivate(); + glBindVertexArray(0); + glBindTexture(GL_TEXTURE_2D, 0); + GL_checkError(); +} + +void Client::renderMap() { + voxel::DecodedMeshData mesh; + while (_world->pop(mesh)) { + // Now add the mesh to the list of meshes to render. + addMeshData(createMesh(mesh.mesh, mesh.translation, 1.0f)); + } + + // TODO: use polyvox VolumeResampler to create a minimap of your volume + + const bool left = _moveMask & MoveDirection_MOVELEFT; + const bool right = _moveMask & MoveDirection_MOVERIGHT; + const bool forward = _moveMask & MoveDirection_MOVEFORWARD; + const bool backward = _moveMask & MoveDirection_MOVEBACKWARD; + _camera.updatePosition(_deltaFrame, left, right, forward, backward); + _camera.updateViewMatrix(); + glClear(GL_DEPTH_BUFFER_BIT); + + glEnable(GL_DEPTH_TEST); + //glEnable(GL_CULL_FACE); + //glCullFace(GL_BACK); + + GL_checkError(); + + const glm::mat4& view = _camera.getViewMatrix(); + const glm::mat4& projection = glm::perspective(45.0f, _aspect, 0.1f, 1000.0f); + + _waterShader->activate(); + _waterShader->setUniformMatrix("u_model", glm::mat4(1.0f), false); + _waterShader->setUniformMatrix("u_view", view, false); + _waterShader->setUniformMatrix("u_projection", projection, false); + _waterShader->setUniformVec3("u_lightpos", _lightPos); + _waterShader->setUniformVec3("u_diffusecolor", _diffuseColor); + _waterShader->setUniformVec3("u_specularcolor", _specularColor); + _waterShader->setUniformi("u_texture", 0); + _waterShader->setUniformf("u_wavetime", 0.5f); + _waterShader->setUniformf("u_wavewidth", 0.6f); + _waterShader->setUniformf("u_waveheight", 1.0f); + _waterTexture->bind(); + glBindVertexArray(_waterData.vertexArrayObject); + glDrawElements(GL_TRIANGLES, _waterData.noOfIndices, _waterData.indexType, 0); + glBindVertexArray(0); + _waterTexture->unbind(); + _waterShader->deactivate(); + GL_checkError(); + + _worldShader.activate(); + _worldShader.setUniformMatrix("u_view", view, false); + _worldShader.setUniformMatrix("u_projection", projection, false); + _worldShader.setUniformVec3("u_lightpos", _lightPos); + _worldShader.setUniformVec3("u_diffusecolor", _diffuseColor); + _worldShader.setUniformVec3("u_specularcolor", _specularColor); + // TODO: add culling + for (const video::GLMeshData& meshData : _meshData) { + const glm::mat4& model = glm::translate(glm::mat4(1.0f), glm::vec3(meshData.translation.x, 0, meshData.translation.y)); + _worldShader.setUniformMatrix("u_model", model, false); + glBindVertexArray(meshData.vertexArrayObject); + glDrawElements(GL_TRIANGLES, meshData.noOfIndices, meshData.indexType, 0); + } + _worldShader.deactivate(); + GL_checkError(); + + _meshShader->activate(); + _meshShader->setUniformMatrix("u_view", view, false); + _meshShader->setUniformMatrix("u_projection", projection, false); + _meshShader->setUniformVec3("u_lightpos", _lightPos); + _meshShader->setUniformVec3("u_diffusecolor", _diffuseColor); + _meshShader->setUniformVec3("u_specularcolor", _specularColor); + _meshShader->setUniformi("u_texture", 0); + for (const auto& e : _entities) { + const frontend::ClientEntityPtr& ent = e.second; + ent->update(_now); + const video::MeshPtr& mesh = ent->mesh(); + if (!mesh->initMesh(_meshShader)) + continue; + const glm::mat4& translate = glm::translate(glm::mat4(1.0f), ent->position()); + const glm::mat4& scale = glm::scale(translate, glm::vec3(0.01f)); + const glm::mat4& model = glm::rotate(scale, ent->orientation(), glm::vec3(0.0, 1.0, 0.0)); + _meshShader->setUniformMatrix("u_model", model, false); + mesh->render(); + } + _meshShader->deactivate(); + glBindVertexArray(0); + glBindTexture(GL_TEXTURE_2D, 0); + GL_checkError(); + + // TODO: iterate over meshdata again and remove too far away chunks + + const glm::ivec2& camXZ = _world->getGridPos(_camera.getPosition()); + const glm::vec2 diff = _lastCameraPosition - camXZ; + if (glm::length(diff.x) >= 1 || glm::length(diff.y) >= 1) { + _lastCameraPosition = camXZ; + _world->scheduleMeshExtraction(camXZ); + } + + glBindVertexArray(0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisable(GL_DEPTH_TEST); + //glDisable(GL_CULL_FACE); + + GL_checkError(); +} + +void Client::beforeUI() { + UIApp::beforeUI(); + + if (_world->isCreated()) + renderMap(); + else + renderBackground(); +} + +core::AppState Client::onCleanup() { + core::AppState state = UIApp::onCleanup(); + // TODO: destroy the gl buffers + _world->destroy(); + return state; +} + +core::AppState Client::onRunning() { + _timeProvider->update(_now); + core::AppState state = UIApp::onRunning(); + sendMovement(); + if (state == core::AppState::Running) { + _posLerp.update(_now); + _camera.setPosition(_posLerp.position()); + _network->update(); + _world->onFrame(_deltaFrame); + } + + return state; +} + +void Client::authFailed() { + ui::Window* main = new frontend::LoginWindow(this); + new frontend::AuthFailedWindow(main); +} + +void Client::disconnect() { + flatbuffers::FlatBufferBuilder fbb; + _messageSender->sendClientMessage(_peer, fbb, Type_UserDisconnect, CreateUserDisconnect(fbb).Union()); +} + +void Client::npcUpdate(frontend::ClientEntityId id, const glm::vec3& pos, float orientation) { + auto i = _entities.find(id); + if (i == _entities.end()) { + Log::error("could not find entity with id %li", id); + return; + } + Log::trace("NPC %li updated at pos %f:%f:%f with orientation %f", id, pos.x, pos.y, pos.z, orientation); + i->second->lerpPosition(_now, pos, orientation); +} + +void Client::npcSpawn(frontend::ClientEntityId id, network::messages::NpcType type, const glm::vec3& pos) { + auto i = _entities.find(id); + if (i != _entities.end()) { + Log::error("NPC %li already spawned", id); + return; + } + Log::info("NPC %li spawned at pos %f:%f:%f (type %i)", id, pos.x, pos.y, pos.z, type); + const std::string& meshName = core::string::toLower(network::messages::EnumNameNpcType(type)); + _entities[id] = frontend::ClientEntityPtr(new frontend::ClientEntity(id, type, _now, pos, 0.0f, _meshPool->getMesh(meshName))); +} + +void Client::userUpdate(const glm::vec3& position) { + _posLerp.lerpPosition(_now, position); +} + +void Client::npcRemove(frontend::ClientEntityId id) { + auto i = _entities.find(id); + if (i == _entities.end()) { + Log::error("NPC %li not found", id); + return; + } + Log::info("NPC %li removed", id); + _entities.erase(i); +} + +void Client::spawn(frontend::ClientEntityId id, const char *name, const glm::vec3& pos) { + Log::info("User %li (%s) logged in at pos %f:%f:%f", id, name, pos.x, pos.y, pos.z); + _userId = id; + _posLerp.setPosition(_now, pos); +} +; + +bool Client::connect(uint16_t port, const std::string& hostname) { + ENetPeer* peer = _network->connect(port, hostname); + if (!peer) { + Log::error("Failed to connect to server %s:%i", hostname.c_str(), port); + return false; + } + + peer->data = this; + + _peer = peer; + Log::error("Connected to server %s:%i", hostname.c_str(), port); + return true; +} + +int main(int argc, char *argv[]) { + getInjector()->get()->startMainLoop(argc, argv); + return EXIT_SUCCESS; +} diff --git a/src/client/Client.h b/src/client/Client.h new file mode 100644 index 000000000..c130b565f --- /dev/null +++ b/src/client/Client.h @@ -0,0 +1,112 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "network/messages/ServerMessages.h" +#include "frontend/WorldShader.h" +#include "frontend/MeshShader.h" +#include "frontend/WaterShader.h" +#include "frontend/ClientEntity.h" +#include "util/PosLerp.h" +#include "core/Var.h" +#include "core/Common.h" +#include "core/EventBus.h" +#include "core/TimeProvider.h" +#include "voxel/World.h" +#include "network/Network.h" +#include "network/MessageSender.h" +#include "network/NetworkEvents.h" +#include "ui/UIApp.h" +#include "video/GLMeshData.h" +#include "video/MeshPool.h" +#include "video/GLFunc.h" +#include "video/Shader.h" +#include "video/VertexBuffer.h" +#include "video/Camera.h" + +class Client: public ui::UIApp, public core::IEventBusHandler, public core::IEventBusHandler< + network::DisconnectEvent>, public core::IEventBusHandler { +protected: + video::MeshPoolPtr _meshPool; + network::NetworkPtr _network; + voxel::WorldPtr _world; + network::MessageSenderPtr _messageSender; + core::TimeProviderPtr _timeProvider; + frontend::WorldShader _worldShader; + frontend::MeshShaderPtr _meshShader; + frontend::WaterShaderPtr _waterShader; + video::TexturePtr _waterTexture; + video::GLMeshData _waterData; + video::Camera _camera; + glm::vec3 _lightPos = glm::vec3(1.0, 1.0, 1.0); + glm::vec3 _diffuseColor = glm::vec3(0.1, 0.1, 0.1); + glm::vec3 _specularColor = glm::vec3(0.0, 0.0, 0.0); + // the position of the last extraction - we only care for x and z here + // moving along the y axis should not arise the need to extract new meshes + glm::ivec2 _lastCameraPosition; + // Index/vertex buffer data + std::vector _meshData; + frontend::ClientEntityId _userId; + ENetPeer* _peer; + uint8_t _moveMask; + typedef std::unordered_map Entities; + Entities _entities; + + util::PosLerp _posLerp; + long _lastMovement; + + inline frontend::ClientEntityId id() const { + return _userId; + } + + // Convert a PolyVox mesh to OpenGL index/vertex buffers. + video::GLMeshData createMesh(voxel::DecodedMesh& surfaceMesh, const glm::ivec2& translation, float scale); + + void addMeshData(video::GLMeshData meshData); + void sendMovement(); + + void renderBackground(); + void renderMap(); +public: + Client(video::MeshPoolPtr meshPool, network::NetworkPtr network, voxel::WorldPtr world, network::MessageSenderPtr messageSender, + core::EventBusPtr eventBus, core::TimeProviderPtr timeProvider, io::FilesystemPtr filesystem); + ~Client(); + + core::AppState onInit() override; + core::AppState onRunning() override; + core::AppState onCleanup() override; + void beforeUI() override; + + void onEvent(const voxel::WorldCreatedEvent& event); + void onEvent(const network::DisconnectEvent& event); + /** + * @brief We send the user connect message to the server and we get the seed and a user spawn message back. + * + * @note If auth failed, we get an auth failed message + */ + void onEvent(const network::NewConnectionEvent& event); + void onMouseMotion(int32_t x, int32_t y, int32_t relX, int32_t relY) override; + bool connect(uint16_t port, const std::string& hostname); + void authFailed(); + void npcSpawn(frontend::ClientEntityId id, network::messages::NpcType type, const glm::vec3& pos); + void npcUpdate(frontend::ClientEntityId id, const glm::vec3& pos, float orientation); + void npcRemove(frontend::ClientEntityId id); + void userUpdate(const glm::vec3& position); + void disconnect(); + // spawns our own player + void spawn(frontend::ClientEntityId id, const char *name, const glm::vec3& pos); +}; + +typedef std::shared_ptr ClientPtr; + +inline void Client::addMeshData(video::GLMeshData meshData) { + _meshData.push_back(meshData); +} diff --git a/src/client/network/AuthFailedHandler.h b/src/client/network/AuthFailedHandler.h new file mode 100644 index 000000000..b05defe32 --- /dev/null +++ b/src/client/network/AuthFailedHandler.h @@ -0,0 +1,10 @@ +#pragma once + +#include "IClientProtocolHandler.h" + +/** + * Looks like the username password combination is wrong + */ +CLIENTPROTOHANDLERIMPL(AuthFailed) { + client->authFailed(); +} diff --git a/src/client/network/ClientNetworkModule.h b/src/client/network/ClientNetworkModule.h new file mode 100644 index 000000000..986119dd9 --- /dev/null +++ b/src/client/network/ClientNetworkModule.h @@ -0,0 +1,24 @@ +#pragma once + +#include "Client.h" +#include "network/NetworkModule.h" +#include "network/messages/ServerMessages.h" +#include "SeedHandler.h" +#include "AuthFailedHandler.h" +#include "UserSpawnHandler.h" +#include "UserUpdateHandler.h" +#include "NpcSpawnHandler.h" +#include "NpcUpdateHandler.h" +#include "NpcRemoveHandler.h" + +class ClientNetworkModule: public NetworkModule { + void configureHandlers() const override { + configureHandler(Type_NpcSpawn, NpcSpawnHandler); + configureHandler(Type_NpcRemove, NpcRemoveHandler); + configureHandler(Type_NpcUpdate, NpcUpdateHandler); + configureHandler(Type_UserSpawn, UserSpawnHandler); + configureHandler(Type_UserUpdate, UserUpdateHandler); + configureHandler(Type_Seed, SeedHandler(voxel::World &)); + configureHandler(Type_AuthFailed, AuthFailedHandler); + } +}; diff --git a/src/client/network/IClientProtocolHandler.h b/src/client/network/IClientProtocolHandler.h new file mode 100644 index 000000000..926a9f7ac --- /dev/null +++ b/src/client/network/IClientProtocolHandler.h @@ -0,0 +1,30 @@ +#pragma once + +#include "network/Network.h" +#include "network/IMsgProtocolHandler.h" +#include "network/messages/ServerMessages.h" +#include "network/messages/ClientMessages.h" +#include "Client.h" + +template +class IClientProtocolHandler: public network::IMsgProtocolHandler { +public: + IClientProtocolHandler() : + network::IMsgProtocolHandler(true) { + } + + virtual ~IClientProtocolHandler() { + } + + virtual void execute(Client* attachment, const MSGTYPE* message) override = 0; +}; + +#define CLIENTPROTOHANDLER(msgType) \ +struct msgType##Handler: public IClientProtocolHandler { \ + msgType##Handler() : IClientProtocolHandler() {} \ + void execute(Client* attachment, const msgType* message) override; \ +} + +#define CLIENTPROTOHANDLERIMPL(msgType) \ +CLIENTPROTOHANDLER(msgType); \ +inline void msgType##Handler::execute(Client* client, const msgType* message) diff --git a/src/client/network/NpcRemoveHandler.h b/src/client/network/NpcRemoveHandler.h new file mode 100644 index 000000000..fbd5c9bd2 --- /dev/null +++ b/src/client/network/NpcRemoveHandler.h @@ -0,0 +1,7 @@ +#pragma once + +#include "IClientProtocolHandler.h" + +CLIENTPROTOHANDLERIMPL(NpcRemove) { + client->npcRemove(message->id()); +} diff --git a/src/client/network/NpcSpawnHandler.h b/src/client/network/NpcSpawnHandler.h new file mode 100644 index 000000000..9403870c1 --- /dev/null +++ b/src/client/network/NpcSpawnHandler.h @@ -0,0 +1,11 @@ +#pragma once + +#include "IClientProtocolHandler.h" + +/** + * Spawn handler that announces a new npc appearance to your client. + */ +CLIENTPROTOHANDLERIMPL(NpcSpawn) { + const network::messages::Vec3 *pos = message->pos(); + client->npcSpawn(message->id(), message->type(), glm::vec3(pos->x(), pos->y(), pos->z())); +} diff --git a/src/client/network/NpcUpdateHandler.h b/src/client/network/NpcUpdateHandler.h new file mode 100644 index 000000000..c0c40cc85 --- /dev/null +++ b/src/client/network/NpcUpdateHandler.h @@ -0,0 +1,12 @@ +#pragma once + +#include "IClientProtocolHandler.h" + +/** + * Handler that updates a particular entity on the client side + */ +CLIENTPROTOHANDLERIMPL(NpcUpdate) { + const network::messages::Vec3 *pos = message->pos(); + const glm::vec3 npcPos(pos->x(), pos->y(), pos->z()); + client->npcUpdate(message->id(), npcPos, message->rotation()); +} diff --git a/src/client/network/SeedHandler.cpp b/src/client/network/SeedHandler.cpp new file mode 100644 index 000000000..887a65a26 --- /dev/null +++ b/src/client/network/SeedHandler.cpp @@ -0,0 +1,11 @@ +#include "SeedHandler.h" +#include "core/Var.h" +#include "network/messages/ServerMessages.h" +#include "voxel/World.h" + +void SeedHandler::execute(ENetPeer* peer, const void* raw) { + const network::messages::server::Seed* message = static_cast(raw); + const long seed = message->seed(); + Log::info("Seed is: %li", seed); + _world->load(seed); +} diff --git a/src/client/network/SeedHandler.h b/src/client/network/SeedHandler.h new file mode 100644 index 000000000..aec89e088 --- /dev/null +++ b/src/client/network/SeedHandler.h @@ -0,0 +1,19 @@ +#pragma once + +#include "network/Network.h" +namespace voxel { +class World; +typedef std::shared_ptr WorldPtr; +} + +/** + * Handler that forwards the server seed to your world in order to recreate the same world + */ +class SeedHandler: public network::IProtocolHandler { +private: + voxel::WorldPtr _world; +public: + SeedHandler(voxel::WorldPtr world) : _world(world) {} + + void execute(ENetPeer* peer, const void* message) override; +}; diff --git a/src/client/network/UserSpawnHandler.h b/src/client/network/UserSpawnHandler.h new file mode 100644 index 000000000..dcb5f363e --- /dev/null +++ b/src/client/network/UserSpawnHandler.h @@ -0,0 +1,8 @@ +#pragma once + +#include "IClientProtocolHandler.h" + +CLIENTPROTOHANDLERIMPL(UserSpawn) { + const network::messages::Vec3 *pos = message->pos(); + client->spawn(message->id(), message->name()->c_str(), glm::vec3(pos->x(), pos->y(), pos->z())); +} diff --git a/src/client/network/UserUpdateHandler.h b/src/client/network/UserUpdateHandler.h new file mode 100644 index 000000000..b55aa38d5 --- /dev/null +++ b/src/client/network/UserUpdateHandler.h @@ -0,0 +1,13 @@ +#pragma once + +#include "IClientProtocolHandler.h" + +/** + * Updates your own client + */ +CLIENTPROTOHANDLERIMPL(UserUpdate) { + const network::messages::Vec3 *pos = message->pos(); + if (pos == nullptr) + return; + client->userUpdate(glm::vec3(pos->x(), pos->y(), pos->z())); +} diff --git a/src/client/sauce/ClientInjector.h b/src/client/sauce/ClientInjector.h new file mode 100644 index 000000000..4fccf7978 --- /dev/null +++ b/src/client/sauce/ClientInjector.h @@ -0,0 +1,11 @@ +#pragma once + +#include "ClientModule.h" +#include "network/ClientNetworkModule.h" + +inline sauce::shared_ptr getInjector() { + sauce::Modules modules; + modules.add(); + modules.add(); + return modules.createInjector(); +} diff --git a/src/client/sauce/ClientModule.h b/src/client/sauce/ClientModule.h new file mode 100644 index 000000000..aab2b9207 --- /dev/null +++ b/src/client/sauce/ClientModule.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +#include "core/AbstractModule.h" +#include "voxel/World.h" +#include "video/MeshPool.h" +#include "network/Network.h" +#include "network/MessageSender.h" + +class ClientModule: public core::AbstractModule { + void configure() const override { + core::AbstractModule::configure(); + bind().in().to(); + bind().in().to(); + bind().in().to(); + } +}; diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt new file mode 100644 index 000000000..ff73de940 --- /dev/null +++ b/src/modules/CMakeLists.txt @@ -0,0 +1,15 @@ +fips_ide_group(Modules) +fips_add_subdirectory(core) +fips_add_subdirectory(io) +fips_add_subdirectory(video) +fips_add_subdirectory(ui) +fips_add_subdirectory(network) +fips_add_subdirectory(noise) +fips_add_subdirectory(voxel) +fips_add_subdirectory(util) +fips_add_subdirectory(attrib) +fips_add_subdirectory(cooldown) +fips_add_subdirectory(backend) +fips_add_subdirectory(frontend) +fips_add_subdirectory(commonlua) +fips_add_subdirectory(dbpost) diff --git a/src/modules/attrib/Attributes.cpp b/src/modules/attrib/Attributes.cpp new file mode 100644 index 000000000..e0440c235 --- /dev/null +++ b/src/modules/attrib/Attributes.cpp @@ -0,0 +1,96 @@ +#include "Attributes.h" + +namespace attrib { + +Attributes::Attributes() : + _dirty(false), _lock("Attributes"), _attribLock("Attributes2") { +} + +bool Attributes::onFrame(long /*dt*/) { + if (!_dirty.exchange(false)) + return false; + Containers containers; + { + core::ScopedReadLock scopedLock(_lock); + containers = _containers; + } + Values max; + for (const Container& c : containers) { + const Values& abs = c.absolute(); + for (ValuesConstIter i = abs.begin(); i != abs.end(); ++i) { + max[i->first] += i->second; + } + } + for (const Container& c : containers) { + const Values& abs = c.percentage(); + for (ValuesConstIter i = abs.begin(); i != abs.end(); ++i) { + max[i->first] *= 1.0 + (i->second * 0.01); + } + } + core::ScopedReadLock scopedLock(_attribLock); + _max = max; + + for (ValuesIter i = _current.begin(); i != _current.end(); ++i) { + ValuesIter mi = _max.find(i->first); + if (mi == _max.end()) + continue; + i->second = std::min(mi->second, i->second); + } + return true; +} + +void Attributes::add(const Container& container) { + core::ScopedWriteLock scopedLock(_lock); + _containers.insert(container); + _dirty = true; +} + +void Attributes::remove(const Container& container) { + core::ScopedWriteLock scopedLock(_lock); + _containers.erase(container); + _dirty = true; +} + +void Attributes::add(Container&& container) { + core::ScopedWriteLock scopedLock(_lock); + _containers.insert(container); + _dirty = true; +} + +void Attributes::add(const ContainerPtr& container) { + if (!container) + return; + core::ScopedWriteLock scopedLock(_lock); + _containerPtrs.insert(container); + _containers.insert(*container.get()); + _dirty = true; +} + +void Attributes::remove(const ContainerPtr& container) { + if (!container) + return; + core::ScopedWriteLock scopedLock(_lock); + _containers.erase(*container.get()); + _containerPtrs.erase(container); + _dirty = true; +} + +void Attributes::remove(Container&& container) { + core::ScopedWriteLock scopedLock(_lock); + _containers.erase(container); + _dirty = true; +} + +double Attributes::setCurrent(Types type, double value) { + core::ScopedWriteLock scopedLock(_attribLock); + auto i = _max.find(type); + if (i == _max.end()) { + _current[type] = value; + return value; + } + const double max = std::min(i->second, value); + _current[type] = max; + return max; +} + +} diff --git a/src/modules/attrib/Attributes.h b/src/modules/attrib/Attributes.h new file mode 100644 index 000000000..9a5442e0b --- /dev/null +++ b/src/modules/attrib/Attributes.h @@ -0,0 +1,69 @@ +#pragma once + +#include "Container.h" +#include "core/ReadWriteLock.h" + +namespace attrib { + +class Attributes { +protected: + std::atomic_bool _dirty; + Values _current; + Values _max; + Containers _containers; + // keep them here for ref counting + std::unordered_set _containerPtrs; + core::ReadWriteLock _lock; + core::ReadWriteLock _attribLock; + +public: + Attributes(); + + /** + * @brief Calculates the new max values for the currently assigned @c Container's + */ + bool onFrame(long dt); + + void add(const Container& container); + void add(Container&& container); + void add(const ContainerPtr& container); + void remove(const Container& container); + void remove(Container&& container); + void remove(const ContainerPtr& container); + + /** + * @brief Set the current value for a particular type. The current value is always capped + * by the max value (if there is one set) for that particular type. + * + * @param[in] type The attribute type + * @param[in] value The value to assign to the specified type + */ + double setCurrent(Types type, double value); + /** + * @return The capped current value for the specified type + */ + double getCurrent(Types type) const; + /** + * @return The current calculated max value for the specified type. This value is computed by the + * @c Container's that were added before the last @c update() call happened. + */ + double getMax(Types type) const; +}; + +inline double Attributes::getCurrent(Types type) const { + core::ScopedReadLock scopedLock(_attribLock); + auto i = _current.find(type); + if (i == _current.end()) + return 0.0; + return i->second; +} + +inline double Attributes::getMax(Types type) const { + core::ScopedReadLock scopedLock(_attribLock); + auto i = _max.find(type); + if (i == _max.end()) + return 0.0; + return i->second; +} + +} diff --git a/src/modules/attrib/CMakeLists.txt b/src/modules/attrib/CMakeLists.txt new file mode 100644 index 000000000..0ac7ea218 --- /dev/null +++ b/src/modules/attrib/CMakeLists.txt @@ -0,0 +1,17 @@ +fips_begin_module(attrib) + fips_files( + Attributes.h Attributes.cpp + Types.h + Container.h Container.cpp + ContainerProvider.h ContainerProvider.cpp + ) + fips_deps(core commonlua) +fips_end_module() + +begin_googleunittest(attrib) + fips_dir(tests) + fips_files( + AttributesTest.cpp + ) + fips_deps(attrib) +end_googleunittest() diff --git a/src/modules/attrib/Container.cpp b/src/modules/attrib/Container.cpp new file mode 100644 index 000000000..42a8337d6 --- /dev/null +++ b/src/modules/attrib/Container.cpp @@ -0,0 +1,23 @@ +#include "Container.h" + +namespace attrib { + +ContainerBuilder::ContainerBuilder(const std::string& name) : + _name(name) { +} + +ContainerBuilder& ContainerBuilder::addPercentage(Types type, double value) { + _percentage[type] = value; + return *this; +} + +ContainerBuilder& ContainerBuilder::addAbsolute(Types type, double value) { + _absolute[type] = value; + return *this; +} + +Container ContainerBuilder::create() { + return Container(_name, _percentage, _absolute); +} + +} diff --git a/src/modules/attrib/Container.h b/src/modules/attrib/Container.h new file mode 100644 index 000000000..7b71fa9e3 --- /dev/null +++ b/src/modules/attrib/Container.h @@ -0,0 +1,76 @@ +#pragma once + +#include +#include +#include +#include +#include +#include "Types.h" + +namespace attrib { + +class Container; + +typedef std::unordered_set Containers; +typedef std::unordered_map Values; +typedef Values::const_iterator ValuesConstIter; +typedef Values::iterator ValuesIter; + +class Container { +protected: + std::string _name; + Values _percentage; + Values _absolute; +public: + Container(const std::string& name, const Values& percentage, const Values& absolute) : + _name(name), _percentage(percentage), _absolute(absolute) { + } + + Container(std::string&& name, Values&& percentage, Values&& absolute) : + _name(std::move(name)), _percentage(std::move(percentage)), _absolute(std::move(absolute)) { + } + + /** + * @brief Each container must have a unique name set. + */ + inline const std::string& name() const { + return _name; + } + + inline const Values& percentage() const { + return _percentage; + } + + inline const Values& absolute() const { + return _absolute; + } + + inline bool operator==(const Container& rhs) const { + return rhs._name == _name; + } +}; + +class ContainerBuilder { +private: + Values _percentage; + Values _absolute; + const std::string _name; +public: + ContainerBuilder(const std::string& name); + ContainerBuilder& addPercentage(Types type, double value); + ContainerBuilder& addAbsolute(Types type, double value); + + Container create(); +}; + +typedef std::shared_ptr ContainerPtr; + +} + +namespace std { +template<> struct hash { + inline size_t operator()(const attrib::Container &c) const { + return std::hash()(c.name()); + } +}; +} diff --git a/src/modules/attrib/ContainerProvider.cpp b/src/modules/attrib/ContainerProvider.cpp new file mode 100644 index 000000000..321edcf61 --- /dev/null +++ b/src/modules/attrib/ContainerProvider.cpp @@ -0,0 +1,67 @@ +#include "ContainerProvider.h" +#include "commonlua/LUA.h" +#include "LUAFunctions.h" +#include "core/Log.h" +#include "core/App.h" +#include "io/Filesystem.h" + +namespace attrib { + +ContainerProvider::ContainerProvider() { +} + +bool ContainerProvider::init() { + lua::LUA lua; + luaL_Reg createContainer = { "createContainer", luaCreateContainer }; + luaL_Reg eof = { nullptr, nullptr }; + luaL_Reg funcs[] = { createContainer, eof }; + + lua::LUAType container = lua.registerType("Container"); + container.addFunction("getName", luaContainerGetName); + container.addFunction("absolute", luaContainerAddAbsolute); + container.addFunction("percentage", luaContainerAddPercentage); + container.addFunction("register", luaContainerRegister); + container.addFunction("__gc", luaContainerGC); + container.addFunction("__tostring", luaContainerToString); + + lua.reg("attrib", funcs); + + const std::string& attributes = core::App::getInstance()->filesystem()->load("attributes.lua"); + if (attributes.empty()) + return false; + + if (!lua.load(attributes)) { + _error = lua.getError(); + return false; + } + + // loads all the attributes + lua.newGlobalData("Provider", this); + if (!lua.execute("init")) { + _error = lua.getError(); + return false; + } + + Log::info("loaded %i containers", (int)_containers.size()); + + return true; +} + +void ContainerProvider::addContainer(const ContainerPtr& container) { + if (!container) + return; + Log::trace("register container %s", container->name().c_str()); + if (_containers.find(container->name()) != _containers.end()) + Log::warn("overriding already existing container for %s", container->name().c_str()); + _containers[container->name()] = container; +} + +ContainerPtr ContainerProvider::getContainer(const std::string& name) const { + auto i = _containers.find(name); + if (i == _containers.end()) + return ContainerPtr(); + + return i->second; +} + +} diff --git a/src/modules/attrib/ContainerProvider.h b/src/modules/attrib/ContainerProvider.h new file mode 100644 index 000000000..eb1edb729 --- /dev/null +++ b/src/modules/attrib/ContainerProvider.h @@ -0,0 +1,30 @@ +#pragma once + +#include "Container.h" +#include +#include +#include + +namespace attrib { + +class ContainerProvider { +private: + typedef std::unordered_map Containers; + Containers _containers; + std::string _error; +public: + ContainerProvider(); + + bool init(); + + void addContainer(const ContainerPtr& container); + ContainerPtr getContainer(const std::string& name) const; + + inline const std::string& error() const { + return _error; + } +}; + +typedef std::shared_ptr ContainerProviderPtr; + +} diff --git a/src/modules/attrib/LUAContainer.h b/src/modules/attrib/LUAContainer.h new file mode 100644 index 000000000..0107f756d --- /dev/null +++ b/src/modules/attrib/LUAContainer.h @@ -0,0 +1,37 @@ +#pragma once + +#include + +namespace attrib { + +class ContainerProvider; + +class LUAContainer { +private: + std::string _name; + ContainerProvider* _ctx; + Values _percentage; + Values _absolute; +public: + LUAContainer(const std::string& name, ContainerProvider* ctx) : + _name(name), _ctx(ctx) { + } + + void addPercentage(Types type, double value) { + _percentage.insert(std::make_pair(type, value)); + } + + void addAbsolute(Types type, double value) { + _absolute.insert(std::make_pair(type, value)); + } + + void createContainer() const { + _ctx->addContainer(ContainerPtr(new Container(_name, _percentage, _absolute))); + } + + inline const std::string& getName() const { + return _name; + } +}; + +} diff --git a/src/modules/attrib/LUAFunctions.h b/src/modules/attrib/LUAFunctions.h new file mode 100644 index 000000000..bc71db55f --- /dev/null +++ b/src/modules/attrib/LUAFunctions.h @@ -0,0 +1,64 @@ +#pragma once + +#include "ContainerProvider.h" +#include "LUAContainer.h" + +namespace attrib { + +static ContainerProvider* luaGetContext(lua_State * l) { + return lua::LUA::getGlobalData(l, "Provider"); +} + +static LUAContainer* luaGetContainerContext(lua_State * l, int n) { + return lua::LUA::getUserData(l, n, "Container"); +} + +static int luaCreateContainer(lua_State * l) { + ContainerProvider *ctx = luaGetContext(l); + const std::string name = luaL_checkstring(l, 1); + LUAContainer** udata = lua::LUA::newUserdata(l, "Container"); + *udata = new LUAContainer(name, ctx); + return 1; +} + +static int luaContainerGC(lua_State * l) { + LUAContainer *container = luaGetContainerContext(l, 1); + delete container; + return 0; +} + +static int luaContainerToString(lua_State * l) { + const LUAContainer *ctx = luaGetContainerContext(l, 1); + lua_pushfstring(l, "container: %s", ctx->getName().c_str()); + return 1; +} + +static int luaContainerAddAbsolute(lua_State * l) { + LUAContainer *ctx = luaGetContainerContext(l, 1); + const char* type = luaL_checkstring(l, 2); + const double value = luaL_checknumber(l, 3); + ctx->addAbsolute(getType(type), value); + return 0; +} + +static int luaContainerAddPercentage(lua_State * l) { + LUAContainer *ctx = luaGetContainerContext(l, 1); + const char* type = luaL_checkstring(l, 2); + const double value = luaL_checknumber(l, 3); + ctx->addPercentage(getType(type), value); + return 0; +} + +static int luaContainerRegister(lua_State * l) { + LUAContainer *ctx = luaGetContainerContext(l, 1); + ctx->createContainer(); + return 0; +} + +static int luaContainerGetName(lua_State * l) { + const LUAContainer *ctx = luaGetContainerContext(l, 1); + lua_pushstring(l, ctx->getName().c_str()); + return 1; +} + +} diff --git a/src/modules/attrib/Types.h b/src/modules/attrib/Types.h new file mode 100644 index 000000000..4e319e961 --- /dev/null +++ b/src/modules/attrib/Types.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include +#include "core/Common.h" + +namespace attrib { + +enum class Types { + NONE, + HEALTH, + SPEED, + ATTACKRANGE, + STRENGTH, + MAX +}; + +static const char* typeNames[] = { + "NONE", + "HEALTH", + "SPEED", + "ATTACKRANGE", + "STRENGTH" +}; +CASSERT(lengthof(typeNames) == (size_t)Types::MAX); + +inline Types getType(const char* name) { + for (int i = 0; i < (int)Types::MAX; ++i) { + if (!strcmp(typeNames[i], name)) + return (Types)i; + } + return Types::NONE; +} + +} + +namespace std { +template<> struct hash { + inline size_t operator()(const attrib::Types &s) const { + return static_cast(s); + } +}; +} diff --git a/src/modules/attrib/tests/AttributesTest.cpp b/src/modules/attrib/tests/AttributesTest.cpp new file mode 100644 index 000000000..41907a1f5 --- /dev/null +++ b/src/modules/attrib/tests/AttributesTest.cpp @@ -0,0 +1,37 @@ +#include +#include "attrib/Attributes.h" + +namespace attrib { + +TEST(Attributes, testCurrents) { + Attributes attributes; + ContainerBuilder t("test"); + t.addPercentage(Types::HEALTH, 100).addAbsolute(Types::HEALTH, 10); + ASSERT_FALSE(attributes.onFrame(1L)); + attributes.add(t.create()); + ASSERT_TRUE(attributes.onFrame(1L)); + ASSERT_EQ(20, attributes.getMax(Types::HEALTH)); + ASSERT_EQ(20, attributes.setCurrent(Types::HEALTH, 100)); +} + +TEST(Attributes, testAddRemove) { + Attributes attributes; + ContainerBuilder test1("test1"); + test1.addAbsolute(Types::HEALTH, 1); + attributes.add(test1.create()); + ASSERT_TRUE(attributes.onFrame(1L)); + ASSERT_EQ(1, attributes.getMax(Types::HEALTH)); + + ContainerBuilder test2("test2"); + test2.addAbsolute(Types::HEALTH, 1); + attributes.add(test2.create()); + ASSERT_TRUE(attributes.onFrame(1L)); + ASSERT_EQ(2, attributes.getMax(Types::HEALTH)); + + ContainerBuilder test1Remove("test1"); + attributes.remove(test1Remove.create()); + ASSERT_TRUE(attributes.onFrame(1L)); + ASSERT_EQ(1, attributes.getMax(Types::HEALTH)); +} + +} diff --git a/src/modules/backend/CMakeLists.txt b/src/modules/backend/CMakeLists.txt new file mode 100644 index 000000000..3703dafda --- /dev/null +++ b/src/modules/backend/CMakeLists.txt @@ -0,0 +1,89 @@ +fips_begin_module(backend) + fips_dir(spawn) + fips_files( + SpawnMgr.cpp SpawnMgr.h + ) + + fips_dir(loop) + fips_files( + ServerLoop.cpp ServerLoop.h + ) + + fips_dir(entity/ai) + fips_files( + AICharacter.cpp AICharacter.h + AIRegistry.cpp AIRegistry.h + AILoader.h + ) + + fips_dir(network) + fips_files( + UserConnectHandler.cpp UserConnectHandler.h + UserDisconnectHandler.h + AttackHandler.h + ServerNetworkModule.h + MoveHandler.h + IUserProtocolHandler.h + ) + + fips_dir(entity/ai/condition) + fips_files( + IsCloseToSelection.h + IsSelectionAlive.h + IsOnCooldown.h + ) + + fips_dir(entity/ai/action) + fips_files( + Task.h + GoHome.h + Spawn.h + Die.h + SetPointOfInterest.h + AttackOnSelection.h + TriggerCooldown.cpp TriggerCooldown.h + TriggerCooldownOnSelection.cpp TriggerCooldownOnSelection.h + ) + + fips_dir(entity/ai/filter) + fips_files( + SelectPrey.cpp SelectPrey.h + SelectVisible.cpp SelectVisible.h + SelectIncreasePartner.cpp SelectIncreasePartner.h + SelectNpcsOfTypes.h + ) + + fips_dir(storage) + fips_files( + UserStore.cpp UserStore.h + PQHandle.cpp PQHandle.h + StoreCmd.cpp StoreCmd.h + ) + + fips_dir(poi) + fips_files( + PoiProvider.cpp PoiProvider.h + ) + + fips_dir(entity) + fips_files( + Npc.cpp Npc.h + User.cpp User.h + EntityId.h + EntityStorage.cpp EntityStorage.h + Entity.cpp Entity.h + ) + find_package(SDL2 REQUIRED) + include_directories(${SDL2_INCLUDE_DIRS} .) + fips_deps(network io core util voxel attrib cooldown dbpost simpleai ${SDL2_LIBRARIES}) +fips_end_module() + +begin_googleunittest(backend) + fips_dir(tests) + fips_files( + SpawnMgrTest.cpp + PoiProviderTest.cpp + StorageTest.cpp + ) + fips_deps(network io core util voxel attrib cooldown dbpost simpleai backend) +end_googleunittest() diff --git a/src/modules/backend/entity/Entity.cpp b/src/modules/backend/entity/Entity.cpp new file mode 100644 index 000000000..e3e9788f5 --- /dev/null +++ b/src/modules/backend/entity/Entity.cpp @@ -0,0 +1,80 @@ +#include "Entity.h" +#include "core/Set.h" +#include "core/Common.h" + +namespace backend { + +void Entity::visibleAdd(const EntitySet& entities) { + for (const EntityPtr& e : entities) { + Log::trace("entity %i is visible for %i", (int)e->id(), (int)id()); + } +} + +void Entity::visibleRemove(const EntitySet& entities) { + for (const EntityPtr& e : entities) { + Log::trace("entity %i is no longer visible for %i", (int)e->id(), (int)id()); + } +} + +void Entity::initAttribs() { + _attribs.onFrame(0L); + + static const attrib::Types types[] = {attrib::Types::HEALTH}; + + for (size_t i = 0; i < lengthof(types); ++i) { + const attrib::Types type = static_cast(types[i]); + const double max = _attribs.getMax(type); + _attribs.setCurrent(type, max); + } +} + +void Entity::addContainer(const std::string& id) { + const attrib::ContainerPtr& c = _containerProvider->getContainer(id); + if (!c) { + Log::error("could not add attribute container for %s", id.c_str()); + return; + } + _attribs.add(c); +} + +void Entity::removeContainer(const std::string& id) { + const attrib::ContainerPtr& c = _containerProvider->getContainer(id); + if (!c) { + Log::error("could not remove attribute container for %s", id.c_str()); + return; + } + _attribs.remove(c); +} + +bool Entity::update(long dt) { + _attribs.onFrame(dt); + _cooldowns.update(); + return true; +} + +void Entity::updateVisible(const EntitySet& set) { + _visibleLock.lockWrite(); + const auto& stillVisible = core::setIntersection(set, _visible); + const EntitySet remove = std::move(core::setDifference(stillVisible, _visible)); + const EntitySet add = std::move(core::setDifference(set, stillVisible)); + _visible = std::move(core::setUnion(stillVisible, add)); + core_assert(stillVisible.size() + add.size() == _visible.size()); + _visibleLock.unlockWrite(); + + ENetPeer* p = peer(); + if (p != nullptr) { + for (const auto& e : stillVisible) { + const glm::vec3 _pos = e->pos(); + const network::messages::Vec3 posBuf {_pos.x, _pos.y, _pos.z}; + flatbuffers::FlatBufferBuilder fbb; + _messageSender->sendServerMessage(p, fbb, Type_NpcUpdate, CreateNpcUpdate(fbb, e->id(), &posBuf, e->orientation()).Union()); + } + } + + if (!add.empty()) + visibleAdd(add); + if (!remove.empty()) + visibleRemove(remove); +} + +} diff --git a/src/modules/backend/entity/Entity.h b/src/modules/backend/entity/Entity.h new file mode 100644 index 000000000..4c6eecd05 --- /dev/null +++ b/src/modules/backend/entity/Entity.h @@ -0,0 +1,167 @@ +#pragma once + +#include +#include +#include +#include "core/Rect.h" +#include "core/ReadWriteLock.h" +#include "attrib/Attributes.h" +#include "attrib/ContainerProvider.h" +#include "cooldown/CooldownMgr.h" +#include "network/MessageSender.h" +#include "EntityId.h" + +namespace backend { + +class Entity; +typedef std::shared_ptr EntityPtr; +typedef std::unordered_set EntitySet; + +class Entity { +private: + core::ReadWriteLock _visibleLock; + EntitySet _visible; + +protected: + EntityId _entityId; + network::MessageSenderPtr _messageSender; + attrib::ContainerProviderPtr _containerProvider; + attrib::Attributes _attribs; + cooldown::CooldownMgr _cooldowns; + + /** + * @brief Called with the set of entities that just get visible for this entity + */ + virtual void visibleAdd(const EntitySet& entities); + /** + * @brief Called with the set of entities that just get invisible for this entity + */ + virtual void visibleRemove(const EntitySet& entities); + void initAttribs(); +public: + + Entity(EntityId id, const network::MessageSenderPtr& messageSender, const core::TimeProviderPtr& timeProvider, const attrib::ContainerProviderPtr& containerProvider) : + _visibleLock("Entity"), _entityId(id), _messageSender(messageSender), _containerProvider(containerProvider), _cooldowns(timeProvider) { + } + + void addContainer(const std::string& id); + void removeContainer(const std::string& id); + + virtual ~Entity() { + } + + inline cooldown::CooldownMgr& cooldownMgr() { + return _cooldowns; + } + + inline EntityId id() const { + return _entityId; + } + + inline bool dead() const { + return _attribs.getCurrent(attrib::Types::HEALTH) < 0.00001; + } + + virtual ENetPeer* peer() const { + return nullptr; + } + + /** + * @note The implementation behind this must ensure thread safety + * @return the current position in world coordinates + */ + virtual glm::vec3 pos() const = 0; + virtual float orientation() const = 0; + virtual network::messages::NpcType npcType() const = 0; + + inline double current(attrib::Types type) const { + return _attribs.getCurrent(type); + } + + inline double max(attrib::Types type) const { + return _attribs.getMax(type); + } + + /** + * @brief Allows to execute a functor/lambda on the visible objects + * + * @note This is thread safe + */ + template + void visitVisible(Func& func) { + core::ScopedReadLock lock(_visibleLock); + for (EntityPtr& e : _visible) { + func(e); + } + } + + /** + * @brief Allows to execute a functor/lambda on the visible objects + * + * @note This is thread safe + */ + template + void visitVisible(const Func& func) const { + const EntitySet& copy = visibleCopy(); + for (const EntityPtr& e : copy) { + func(e); + } + } + + /** + * @brief Creates a copy of the currently visible objects. If you don't need a copy, use the @c Entity::visibleVisible method. + * + * @note This is thread safe + */ + inline EntitySet visibleCopy() const { + core::ScopedReadLock lock(_visibleLock); + const EntitySet set(_visible); + return set; + } + + /** + * @brief This will inform the entity about all the other entities that it can see. + * @param[in] set The entities that are currently visible + * @note All entities have the same view range - see @c Entity::regionRect + * @note This is thread safe + */ + void updateVisible(const EntitySet& set); + + /** + * @brief The tick of the entity + * @param[in] dt The delta time (in millis) since the last tick was executed + * @return @c false if the entity should be removed from the world + */ + virtual bool update(long dt); + + /** + * @return the size of this entity + */ + inline float size() const { + return 1.0f; + } + + /** + * @brief Calculates the two dimensional rect that defines the size of the entity. + * @note The position is in the center of this rectangle. + * @note This is in world coordinates. + */ + inline core::RectFloat rect() const { + const glm::vec3 p = pos(); + const float halfSize = size() / 2.0f; + return core::RectFloat(p.x - halfSize, p.z - halfSize, p.x + halfSize, p.z + halfSize); + } + + /** + * @brief the region rect is where the player currently is - surrounded by 9 other fields. + * this is used e.g. for visibility calculation + */ + core::RectFloat regionRect() const { + const glm::vec3 p = pos(); + static const float regionSize = 1000.0f; + static const float regionHalf = regionSize / 2.0; + return core::RectFloat(p.x - regionHalf, p.z - regionHalf, p.x + regionHalf, p.z + regionHalf); + } +}; + +} diff --git a/src/modules/backend/entity/EntityId.h b/src/modules/backend/entity/EntityId.h new file mode 100644 index 000000000..8f5b2d14a --- /dev/null +++ b/src/modules/backend/entity/EntityId.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace backend { + +typedef int32_t EntityId; + +} diff --git a/src/modules/backend/entity/EntityStorage.cpp b/src/modules/backend/entity/EntityStorage.cpp new file mode 100644 index 000000000..ca27b71c3 --- /dev/null +++ b/src/modules/backend/entity/EntityStorage.cpp @@ -0,0 +1,167 @@ +#include "EntityStorage.h" +#include "core/Var.h" +#include "User.h" +#include "backend/storage/PQHandle.h" +#include "backend/storage/UserStore.h" + +#define broadcastMsg(msg, type) _messageSender->broadcastServerMessage(fbb, network::messages::server::type, network::messages::server::msg.Union()); + +namespace backend { + +EntityStorage::EntityStorage(network::MessageSenderPtr messageSender, voxel::WorldPtr world, core::TimeProviderPtr timeProvider, + attrib::ContainerProviderPtr containerProvider, PoiProviderPtr poiProvider) : + _quadTree(core::RectFloat::getMaxRect(), 100.0f), _quadTreeCache(_quadTree), _messageSender(messageSender), _world(world), _timeProvider( + timeProvider), _containerProvider(containerProvider), _poiProvider(poiProvider), _time(0L) { +} + +core::RectFloat EntityStorage::Node::getRect() const { + if (user) + return user->rect(); + return npc->rect(); +} + +bool EntityStorage::Node::operator==(const Node& rhs) const { + return rhs.user == user && rhs.npc == rhs.npc; +} + +void EntityStorage::registerUser(const UserPtr& user) { + _users[user->id()] = user; +} + +EntityId EntityStorage::getUserId(const std::string& user, const std::string& passwd) const { + std::string tmUid = "0"; + PQHandle pq; + pq.init(); + int checkId = pq.loadUser(user, passwd, tmUid); + + if (checkId == 0) { + const core::VarPtr& autoReg = core::Var::get("user_auto_register", "no"); + if (autoReg->strVal() == "yes") { + pq.storeUser(user, passwd, tmUid); + checkId = pq.loadUser(user, passwd, tmUid); + } + } + return checkId; +} + +UserPtr EntityStorage::login(ENetPeer* peer, const std::string& email, const std::string& passwd) { + EntityId id = getUserId(email, passwd); + Log::info("getting userid: %i", (int) id); + if (id <= 0) + return UserPtr(); + auto i = _users.find(id); + if (i == _users.end()) { + static const std::string name = "NONAME"; + UserPtr u(new User(peer, id, name, _messageSender, _world, _timeProvider, _containerProvider, _poiProvider)); + registerUser(u); + return u; + } + const UserPtr& u = i->second; + if (u->host() == peer->address.host) { + Log::info("user %i reconnects with host %i on port %i", (int) id, peer->address.host, peer->address.port); + i->second->setPeer(peer); + return i->second; + } + + Log::info("skip connection attempt for client %i - the hosts don't match", (int) id); + return UserPtr(); +} + +bool EntityStorage::logout(EntityId userId) { + auto i = _users.find(userId); + if (i == _users.end()) + return false; + _users.erase(i); + return true; +} + +void EntityStorage::addNpc(const NpcPtr& npc) { + _npcs.insert(std::make_pair(npc->id(), std::move(npc))); +} + +bool EntityStorage::removeNpc(ai::CharacterId id) { + NpcsIter i = _npcs.find(id); + if (i == _npcs.end()) { + return false; + } + _quadTree.remove(Node { UserPtr(), i->second }); + _npcs.erase(id); + return true; +} + +NpcPtr EntityStorage::getNpc(ai::CharacterId id) { + NpcsIter i = _npcs.find(id); + if (i == _npcs.end()) { + Log::trace("Could not find npc with id %i", id); + return NpcPtr(); + } + return i->second; +} + +void EntityStorage::onFrame(long dt) { + static long lastFrame = _time; + _time += dt; + + // let this run at 4 frames per second + const long deltaLastTick = _time - lastFrame; + const long delayBetweenTicks = 250L; + if (deltaLastTick >= delayBetweenTicks) { + lastFrame = _time - (deltaLastTick - delayBetweenTicks); + } else { + return; + } + + _quadTreeCache.clear(); + updateQuadTree(); + // first update the users - to e.g. remove dead npc controls + for (auto i : _users) { + updateEntity(i.second, deltaLastTick); + } + for (auto i = _npcs.begin(); i != _npcs.end();) { + NpcPtr npc = i->second; + if (!updateEntity(npc, deltaLastTick)) { + Log::info("remove npc %i", npc->id()); + _quadTree.remove(Node { UserPtr(), npc }); + i = _npcs.erase(i); + } else { + ++i; + } + } +} + +void EntityStorage::updateQuadTree() { + // TODO: a full rebuild is not needed every frame + _quadTree.clear(); + static const UserPtr EMPTYUSER; + static const NpcPtr EMPTYNPC; + for (auto i : _npcs) { + _quadTree.insert(Node { EMPTYUSER, i.second }); + } + for (auto i : _users) { + const UserPtr& user = i.second; + // users that have taken over a npc are indirectly updated with the npc already + if (user->hasTakenOverNpc()) + continue; + // this user is an ghost light + _quadTree.insert(Node { user, EMPTYNPC }); + } +} + +bool EntityStorage::updateEntity(const EntityPtr& entity, long dt) { + if (!entity->update(dt)) + return false; + const core::RectFloat& rect = entity->regionRect(); + const auto& contents = _quadTreeCache.query(rect); + EntitySet set; + for (const Node& node : contents) { + if (node.npc) + set.insert(node.npc); + else if (node.user && !node.user->hasTakenOverNpc()) + set.insert(node.user); + } + set.erase(entity); + entity->updateVisible(set); + return true; +} + +} diff --git a/src/modules/backend/entity/EntityStorage.h b/src/modules/backend/entity/EntityStorage.h new file mode 100644 index 000000000..d395319a4 --- /dev/null +++ b/src/modules/backend/entity/EntityStorage.h @@ -0,0 +1,71 @@ +#pragma once + +#include "EntityId.h" +#include "Npc.h" +#include "network/Network.h" +#include "network/MessageSender.h" +#include "core/QuadTree.h" +#include + +namespace backend { + +class User; +typedef std::shared_ptr UserPtr; + +class EntityStorage { +private: + typedef std::unordered_map Users; + typedef Users::iterator UsersIter; + Users _users; + + typedef std::unordered_map Npcs; + typedef Npcs::iterator NpcsIter; + Npcs _npcs; + + /** + * this node contains either a user or a npc - but never both + * this is used for the quadtree + */ + struct Node { + UserPtr user; + NpcPtr npc; + + core::RectFloat getRect() const; + bool operator==(const Node& rhs) const; + }; + + core::QuadTree _quadTree; + core::QuadTreeCache _quadTreeCache; + + network::MessageSenderPtr _messageSender; + voxel::WorldPtr _world; + core::TimeProviderPtr _timeProvider; + attrib::ContainerProviderPtr _containerProvider; + PoiProviderPtr _poiProvider; + long _time; + + void registerUser(const UserPtr& user); + // users are controlling npcs - and here we update them and send the messages to + // the users that are seeing this npc entity. + // users itself are not visible until they have taken over a npc + bool updateEntity(const EntityPtr& entity, long dt); + void updateQuadTree(); + + EntityId getUserId(const std::string& user, const std::string& passwd) const; +public: + EntityStorage(network::MessageSenderPtr messageSender, voxel::WorldPtr world, core::TimeProviderPtr timeProvider, + attrib::ContainerProviderPtr containerProvider, PoiProviderPtr poiProvider); + + UserPtr login(ENetPeer* peer, const std::string& email, const std::string& passwd); + bool logout(EntityId userId); + + void addNpc(const NpcPtr& npc); + bool removeNpc(ai::CharacterId id); + NpcPtr getNpc(ai::CharacterId id); + + void onFrame(long dt); +}; + +typedef std::shared_ptr EntityStoragePtr; + +} diff --git a/src/modules/backend/entity/Npc.cpp b/src/modules/backend/entity/Npc.cpp new file mode 100644 index 000000000..1487f0f85 --- /dev/null +++ b/src/modules/backend/entity/Npc.cpp @@ -0,0 +1,101 @@ +#include "Npc.h" +#include "EntityStorage.h" +#include "backend/poi/PoiProvider.h" +#include "voxel/World.h" +#include + +namespace backend { + +std::atomic Npc::_nextNpcId(5000000); + +Npc::Npc(network::messages::NpcType type, const EntityStoragePtr& entityStorage, const ai::TreeNodePtr& behaviour, const voxel::WorldPtr& world, const network::MessageSenderPtr& messageSender, + const core::TimeProviderPtr& timeProvider, const attrib::ContainerProviderPtr& containerProvider, const PoiProviderPtr& poiProvider) : + Entity(_nextNpcId++, messageSender, timeProvider, containerProvider), _type(type), _humanControlled(false), _world(world), _poiProvider(poiProvider) { + _ai = ai::AIPtr(new ai::AI(behaviour)); + _ai->setCharacter(ai::ICharacterPtr(new AICharacter(_entityId, *this))); +} + +Npc::~Npc() { + ai::Zone* zone = _ai->getZone(); + if (zone == nullptr) + return; + zone->scheduleDestroy(id()); + _ai->setZone(nullptr); +} + +void Npc::init(const glm::ivec3* pos) { + const glm::ivec3& randomPos = pos ? *pos : _world->randomPos(); + const int material = _world->getMaterial(randomPos.x, randomPos.y, randomPos.z); + Log::info("spawn character %i with behaviour tree %s at position %i:%i:%i (material: %i)", + ai()->getId(), ai()->getBehaviour()->getName().c_str(), randomPos.x, randomPos.y, randomPos.z, material); + setHomePosition(randomPos); + _ai->getCharacter()->setPosition(ai::Vector3f(randomPos.x, randomPos.y, randomPos.z)); + const char *typeName = network::messages::EnumNameNpcType(_type); + addContainer(typeName); + initAttribs(); +} + +std::string Npc::name() const { + return network::messages::EnumNameNpcType(_type); +} + +void Npc::setPointOfInterest() { + _poiProvider->addPointOfInterest(pos()); +} + +float Npc::orientation() const { + return _ai->getCharacter()->getOrientation(); +} + +double Npc::applyDamage(Npc* attacker, double damage) { + double health = _attribs.getCurrent(attrib::Types::HEALTH); + if (health > 0.0) { + health = std::max(0.0, health - damage); + if (attacker != nullptr) + _ai->getAggroMgr().addAggro(attacker->ai(), damage); + _attribs.setCurrent(attrib::Types::HEALTH, health); + return damage; + } + return 0.0; +} + +bool Npc::die() { + return applyDamage(nullptr, _attribs.getCurrent(attrib::Types::HEALTH)) > 0.0; +} + +bool Npc::attack(ai::CharacterId id) { + const double strength = _attribs.getCurrent(attrib::Types::STRENGTH); + if (strength <= 0.0) + return false; + return _ai->getZone()->execute(id, [&] (const ai::AIPtr & targetAi) { + AICharacter& targetChr = ai::character_cast(targetAi->getCharacter()); + targetChr.getNpc().applyDamage(this, strength); + }); +} + +glm::vec3 Npc::pos() const { + const ai::Vector3f pos = _ai->getCharacter()->getPosition(); + return glm::vec3(pos.x, pos.y, pos.z); +} + +bool Npc::update(long dt) { + if (!Entity::update(dt)) + return false; + _ai->getCharacter()->setSpeed(_attribs.getCurrent(attrib::Types::SPEED)); + return !dead(); +} + +bool Npc::route(const glm::ivec3& target) { + std::list result; + const ai::Vector3f pos = _ai->getCharacter()->getPosition(); + const PolyVox::Vector3DInt32 start(pos.x, pos.y, pos.z); + const PolyVox::Vector3DInt32 end(target.x, target.y, target.z); + return _world->findPath(start, end, result); +} + +void Npc::moveToGround() { + const ai::Vector3f pos = _ai->getCharacter()->getPosition(); + _ai->getCharacter()->setPosition(ai::Vector3f(pos.x, _world->findFloor(pos.x, pos.z), pos.z)); +} + +} diff --git a/src/modules/backend/entity/Npc.h b/src/modules/backend/entity/Npc.h new file mode 100644 index 000000000..14aa76b45 --- /dev/null +++ b/src/modules/backend/entity/Npc.h @@ -0,0 +1,111 @@ +#pragma once + +#include +#include +#include "Entity.h" +#include "ai/AICharacter.h" +#include "backend/poi/PoiProvider.h" + +namespace voxel { +class World; +typedef std::shared_ptr WorldPtr; +} + +namespace backend { + +class EntityStorage; +typedef std::shared_ptr EntityStoragePtr; + +class Npc: public Entity { +private: + friend class AICharacter; + static std::atomic _nextNpcId; + network::messages::NpcType _type; + std::atomic_bool _humanControlled; + voxel::WorldPtr _world; + EntityStoragePtr _entityStorage; + PoiProviderPtr _poiProvider; + glm::ivec3 _homePosition; + ai::AIPtr _ai; + + void moveToGround(); + +public: + Npc(network::messages::NpcType type, const EntityStoragePtr& entityStorage, const ai::TreeNodePtr& behaviour, const voxel::WorldPtr& world, const network::MessageSenderPtr& messageSender, + const core::TimeProviderPtr& timeProvider, const attrib::ContainerProviderPtr& containerProvider, const PoiProviderPtr& poiProvider); + ~Npc(); + + void init(const glm::ivec3* pos = nullptr); + + voxel::WorldPtr world() const; + void setHomePosition(const glm::ivec3& pos); + /** + * @brief Sets a points of interest at the current npc position. + */ + void setPointOfInterest(); + const glm::ivec3& homePosition() const; + void releaseHumanControlled(); + bool aquireHumanControlled(); + bool humanControlled() const; + bool route(const glm::ivec3& target); + const ai::AIPtr& ai(); + + bool die(); + bool attack(ai::CharacterId id); + /** + * @brief Applies damage to the entity + * @param attacker The attacking @c Npc. This might be @c nullptr + * @param[in] damage The damage that the attacker tries to apply to the victim. + * @return The amount of applied damage. + * @note The amount of the applied damage might be less that the indended damage + * @note The victim gets aggro on the attacker + */ + double applyDamage(Npc* attacker, double damage); + + bool update(long dt) override; + + glm::vec3 pos() const override; + float orientation() const override; + std::string name() const; + + network::messages::NpcType npcType() const override; +}; + +inline void Npc::setHomePosition(const glm::ivec3& pos) { + _homePosition = pos; +} + +inline voxel::WorldPtr Npc::world() const { + return _world; +} + +inline const glm::ivec3& Npc::homePosition() const { + return _homePosition; +} + +inline void Npc::releaseHumanControlled() { + _humanControlled = false; +} + +inline bool Npc::aquireHumanControlled() { + bool expected = false; + if (!_humanControlled.compare_exchange_strong(expected, true)) + return false; + return true; +} + +inline network::messages::NpcType Npc::npcType() const { + return _type; +} + +inline const ai::AIPtr& Npc::ai() { + return _ai; +} + +inline bool Npc::humanControlled() const { + return _humanControlled; +} + +typedef std::shared_ptr NpcPtr; + +} diff --git a/src/modules/backend/entity/User.cpp b/src/modules/backend/entity/User.cpp new file mode 100644 index 000000000..71e2883c5 --- /dev/null +++ b/src/modules/backend/entity/User.cpp @@ -0,0 +1,182 @@ +#include "User.h" +#include "util/Velocity.h" +#include "core/Var.h" +#include "voxel/World.h" + +namespace backend { + +User::User(ENetPeer* peer, EntityId id, const std::string& name, const network::MessageSenderPtr& messageSender, + const voxel::WorldPtr& world, const core::TimeProviderPtr& timeProvider, const attrib::ContainerProviderPtr& containerProvider, + const PoiProviderPtr& poiProvider) : + Entity(id, messageSender, timeProvider, containerProvider), _peer(nullptr), _name(name), _world(world), _poiProvider(poiProvider), _moveMask( + (MoveDirection) 0), _pitch(0.0f), _yaw(0.0f), _lastAction(0ul), _time(0ul) { + setPeer(peer); + const glm::vec3& poi = _poiProvider->getPointOfInterest(); + _pos = poi; + _attribs.setCurrent(attrib::Types::SPEED, 20.0); + _userTimeout = core::Var::get("sv_usertimeout", "60000"); +} + +void User::visibleAdd(const EntitySet& entities) { + Entity::visibleAdd(entities); + for (const EntityPtr& e : entities) { + sendEntitySpawn(e); + } +} + +void User::visibleRemove(const EntitySet& entities) { + Entity::visibleRemove(entities); + for (const EntityPtr& e : entities) { + sendEntityRemove(e); + } +} + +void User::setPos(const glm::vec3& pos) { + const int floor = _world->findFloor(pos.x, pos.z); + _pos = pos; + if (_pos.y < floor) + _pos.y = floor; +} + +ENetPeer* User::setPeer(ENetPeer* peer) { + ENetPeer* old = _peer; + _peer = peer; + if (_peer) { + _host = _peer->address.host; + _peer->data = this; + } else { + _host = 0u; + } + return old; +} + +void User::attack(EntityId id) { + const NpcPtr& npc = takenOverNpc(); + if (!npc) + return; + npc->attack(id); +} + +void User::disconnect() { + Log::trace("disconnect user"); +} + +bool User::update(long dt) { + _time += dt; + if (!Entity::update(dt)) + return false; + + if (_time - _lastAction > _userTimeout->ulongVal()) { + disconnect(); + return false; + } + + // invalid id means spectator + if (id() == -1) { + // TODO: if a certain time has passed, get another point of interest + //const glm::vec3& poi = _poiProvider->getPointOfInterest(); + //_pos = poi; + _lastAction = _time; + return true; + } + + NpcPtr npc = takenOverNpc(); + if (npc && npc->dead()) { + // if the controlled npc died, reset it + _npc = NpcPtr(); + } + if (_moveMask == (MoveDirection) 0) + return true; + + _lastAction = _time; + + const float speedVal = current(attrib::Types::SPEED); + const float deltaTime = static_cast(dt) / 1000.0f; + if (_moveMask & (MoveDirection_MOVEFORWARD | MoveDirection_MOVEBACKWARD)) { + const glm::vec3& direction = util::getDirection(_pitch, _yaw); + const glm::vec3 velocity(direction * speedVal); + if (_moveMask & MoveDirection_MOVEFORWARD) { + setPos(pos() + velocity * deltaTime); + Log::trace("move forward: dt %f, speed: %f p(%f:%f:%f), pitch: %f, yaw: %f", deltaTime, speedVal, _pos.x, _pos.y, _pos.z, _pitch, _yaw); + } else if (_moveMask & MoveDirection_MOVEBACKWARD) { + setPos(pos() - velocity * deltaTime); + Log::trace("move backward: dt %f, speed: %f p(%f:%f:%f), pitch: %f, yaw: %f", deltaTime, speedVal, _pos.x, _pos.y, _pos.z, _pitch, _yaw); + } + } + if (_moveMask & (MoveDirection_MOVERIGHT | MoveDirection_MOVELEFT)) { + const glm::vec3& direction = util::getDirection(_yaw); + const glm::vec3 velocity(direction * speedVal); + if (_moveMask & MoveDirection_MOVELEFT) { + setPos(pos() - velocity * deltaTime); + Log::trace("move left: dt %f, speed: %f p(%f:%f:%f)", deltaTime, speedVal, _pos.x, _pos.y, _pos.z); + } else if (_moveMask & MoveDirection_MOVERIGHT) { + setPos(pos() + velocity * deltaTime); + Log::trace("move right: dt %f, speed: %f p(%f:%f:%f)", deltaTime, speedVal, _pos.x, _pos.y, _pos.z); + } + } + sendUserUpdate(); + + return true; +} + +void User::sendUserUpdate() const { + // update is send with the npc - and also broadcasted to all the others - we + // don't see the users until they have taken over an npc + if (hasTakenOverNpc()) + return; + + flatbuffers::FlatBufferBuilder fbb; + const glm::vec3& newPos = pos(); + const network::messages::Vec3 posBuf { newPos.x, newPos.y, newPos.z }; + sendServerMsg(UserUpdate(fbb, &posBuf), UserUpdate); +} + +void User::sendSeed(long seed) const { + flatbuffers::FlatBufferBuilder fbb; + sendServerMsg(Seed(fbb, seed), Seed); +} + +void User::sendUserSpawn() const { + flatbuffers::FlatBufferBuilder fbb; + const network::messages::Vec3 pos { _pos.x, _pos.y, _pos.z }; + broadcastServerMsg(UserSpawn(fbb, id(), fbb.CreateString(_name), &pos), UserSpawn); +} + +void User::sendEntityUpdate(const EntityPtr& entity) const { + flatbuffers::FlatBufferBuilder fbb; + const glm::vec3& _pos = entity->pos(); + const network::messages::Vec3 pos { _pos.x, _pos.y, _pos.z }; + sendServerMsg(NpcUpdate(fbb, entity->id(), &pos, entity->orientation()), NpcUpdate); +} + +void User::sendEntitySpawn(const EntityPtr& entity) const { + flatbuffers::FlatBufferBuilder fbb; + const glm::vec3& pos = entity->pos(); + const network::messages::Vec3 vec3 { pos.x, pos.y, pos.z }; + const long humanId = id(); // -1; + sendServerMsg(NpcSpawn(fbb, entity->id(), entity->npcType(), &vec3, humanId), NpcSpawn); +} + +void User::sendEntityRemove(const EntityPtr& entity) const { + flatbuffers::FlatBufferBuilder fbb; + sendServerMsg(NpcRemove(fbb, entity->id()), NpcRemove); +} + +bool User::takeOverNpc(const NpcPtr& character) { + // if the user already has control over a character, don't allow + // a switch to another character - only a reset + if (_npc && character) + return false; + if (_npc) + _npc->releaseHumanControlled(); + _npc = NpcPtr(); + if (character->aquireHumanControlled()) { + _npc = character; + flatbuffers::FlatBufferBuilder fbb; + broadcastServerMsg(NpcTakeOver(fbb, _npc->id(), id()), NpcTakeOver); + return true; + } + return false; +} + +} diff --git a/src/modules/backend/entity/User.h b/src/modules/backend/entity/User.h new file mode 100644 index 000000000..5d3685cc2 --- /dev/null +++ b/src/modules/backend/entity/User.h @@ -0,0 +1,128 @@ +#pragma once + +#include "network/MessageSender.h" +#include "Npc.h" + +namespace backend { + +class User : public Entity { +private: + ENetPeer* _peer; + std::string _name; + std::string _password; + std::string _email; + glm::vec3 _pos; + NpcPtr _npc; + uint32_t _host; + voxel::WorldPtr _world; + PoiProviderPtr _poiProvider; + MoveDirection _moveMask; + float _pitch; + float _yaw; + uint64_t _lastAction; + uint64_t _time; + core::VarPtr _userTimeout; + +protected: + void visibleAdd(const EntitySet& entities) override; + void visibleRemove(const EntitySet& entities) override; + +public: + User(ENetPeer* peer, EntityId id, const std::string& name, const network::MessageSenderPtr& messageSender, const voxel::WorldPtr& world, + const core::TimeProviderPtr& timeProvider, const attrib::ContainerProviderPtr& containerProvider, const PoiProviderPtr& poiProvider); + + void setEntityId(EntityId id) { + _entityId = id; + } + + void setPassword(const std::string& pw){ + _password = pw; + } + + void setEmail(const std::string& mail){ + _email = mail; + } + + inline const std::string& name() const { + return _name; + } + + inline const std::string& password() const { + return _password; + } + + inline const std::string& email() const { + return _email; + } + + void changeMovement(MoveDirection bitmask, float pitch, float yaw) { + _moveMask = bitmask; + _pitch = pitch; + _yaw = yaw; + } + + void attack(EntityId id); + + /** + * @brief The client closed the connection - the user object itself will stay in the server until + * a logout cooldown was hit + */ + void disconnect(); + + bool update(long dt) override; + + ENetPeer* peer() const override { + if (_peer->state == ENET_PEER_STATE_DISCONNECTED) + return nullptr; + return _peer; + } + + /** + * @brief Sets a new ENetPeer and returns the old one. + */ + ENetPeer* setPeer(ENetPeer* peer); + + uint32_t host() const { + return _host; + } + + glm::vec3 pos() const override { + return _pos; + } + + void setPos(const glm::vec3& pos); + + float orientation() const override { + return _pitch; + } + + network::messages::NpcType npcType() const override { + if (!_npc) + return network::messages::NpcType_NONE; + return _npc->npcType(); + } + + inline bool hasTakenOverNpc() const { + const bool val = _npc.get() != nullptr; + return val; + } + + inline NpcPtr takenOverNpc() const { + return _npc; + } + + bool takeOverNpc(const NpcPtr& character); + /** + * @brief Informs the user that the login was successful + */ + void sendUserSpawn() const; + void sendUserUpdate() const; + void sendEntityUpdate(const EntityPtr& entity) const; + void sendEntitySpawn(const EntityPtr& entity) const; + void sendEntityRemove(const EntityPtr& entity) const; + void sendSeed(long seed) const; +}; + +typedef std::shared_ptr UserPtr; + +} diff --git a/src/modules/backend/entity/ai/AICharacter.cpp b/src/modules/backend/entity/ai/AICharacter.cpp new file mode 100644 index 000000000..d15586a92 --- /dev/null +++ b/src/modules/backend/entity/ai/AICharacter.cpp @@ -0,0 +1,34 @@ +#include "AICharacter.h" +#include "backend/entity/Npc.h" + +namespace backend { + +AICharacter::AICharacter(ai::CharacterId id, Npc& npc) : + ai::ICharacter(id), _npc(npc) { + setOrientation(ai::randomf(ai::M_2PI)); + setAttribute(ai::attributes::NAME, npc.name() + " " + std::to_string(id)); + setAttribute(ai::attributes::ID, std::to_string(id)); +} + +AICharacter::~AICharacter() { +} + +void AICharacter::update(long dt, bool debuggingActive) { + if (_npc._humanControlled) + return; + _npc.moveToGround(); + + if (debuggingActive) { + setAttribute(ai::attributes::POSITION, std::to_string(getPosition())); + setAttribute(ai::attributes::ORIENTATION, std::to_string(ai::toDegrees(getOrientation()))); + setAttribute("Human", std::to_string(_npc._humanControlled)); + for (int i = 0; i < (int)attrib::Types::MAX; ++i) { + const double current = _npc._attribs.getCurrent((attrib::Types)i); + const double max = _npc._attribs.getMax((attrib::Types)i); + setAttribute("Attrib " + std::to_string(i), std::to_string(current) + "/" + std::to_string(max)); + } + } + ai::ICharacter::update(dt, debuggingActive); +} + +} diff --git a/src/modules/backend/entity/ai/AICharacter.h b/src/modules/backend/entity/ai/AICharacter.h new file mode 100644 index 000000000..d2af2926e --- /dev/null +++ b/src/modules/backend/entity/ai/AICharacter.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +namespace backend { + +class Npc; + +class AICharacter : public ai::ICharacter { +private: + Npc& _npc; +public: + AICharacter(ai::CharacterId id, Npc& npc); + ~AICharacter(); + void update(long dt, bool debuggingActive) override; + + inline Npc& getNpc() const { + return _npc; + } +}; + +} diff --git a/src/modules/backend/entity/ai/AILoader.h b/src/modules/backend/entity/ai/AILoader.h new file mode 100644 index 000000000..20c33974f --- /dev/null +++ b/src/modules/backend/entity/ai/AILoader.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include + +#include "AIRegistry.h" + +namespace backend { + +class AILoader: public ai::LUATreeLoader { +private: + AIRegistryPtr _registry; +public: + AILoader(AIRegistryPtr registry) : + ai::LUATreeLoader(*registry.get()), _registry(registry) { + } +}; + +typedef std::shared_ptr AILoaderPtr; + +} diff --git a/src/modules/backend/entity/ai/AIRegistry.cpp b/src/modules/backend/entity/ai/AIRegistry.cpp new file mode 100644 index 000000000..ffdd615f4 --- /dev/null +++ b/src/modules/backend/entity/ai/AIRegistry.cpp @@ -0,0 +1,43 @@ +#include "AIRegistry.h" + +#include "backend/entity/EntityStorage.h" +#include "backend/spawn/SpawnMgr.h" +#include "core/Singleton.h" + +#include "action/Die.h" +#include "action/GoHome.h" +#include "action/Spawn.h" +#include "action/AttackOnSelection.h" +#include "action/SetPointOfInterest.h" +#include "action/TriggerCooldown.h" +#include "action/TriggerCooldownOnSelection.h" + +#include "condition/IsCloseToSelection.h" +#include "condition/IsSelectionAlive.h" +#include "condition/IsOnCooldown.h" + +#include "filter/SelectVisible.h" +#include "filter/SelectNpcsOfTypes.h" +#include "filter/SelectIncreasePartner.h" +#include "filter/SelectPrey.h" + +namespace backend { + +void AIRegistry::init(const backend::SpawnMgrPtr& spawnMgr) { + registerNodeFactory("GoHome", core::Singleton::getInstance()); + registerNodeFactory("AttackOnSelection", core::Singleton::getInstance()); + registerFilterFactory("SelectVisible", SelectVisible::FACTORY); + registerFilterFactory("SelectIncreasePartner", SelectIncreasePartner::FACTORY); + registerFilterFactory("SelectPrey", SelectPrey::FACTORY); + registerFilterFactory("SelectNpcsOfTypes", SelectNpcsOfTypes::FACTORY); + registerConditionFactory("IsCloseToSelection", IsCloseToSelection::FACTORY); + registerConditionFactory("IsOnCooldown", IsOnCooldown::FACTORY); + registerConditionFactory("IsSelectionAlive", IsSelectionAlive::FACTORY); + registerNodeFactory("SetPointOfInterest", SetPointOfInterest::FACTORY); + registerNodeFactory("Spawn", Spawn::getInstance(spawnMgr)); + registerNodeFactory("Die", core::Singleton::getInstance()); + registerNodeFactory("TriggerCooldown", TriggerCooldown::FACTORY); + registerNodeFactory("TriggerCooldownOnSelection", TriggerCooldownOnSelection::FACTORY); +} + +} diff --git a/src/modules/backend/entity/ai/AIRegistry.h b/src/modules/backend/entity/ai/AIRegistry.h new file mode 100644 index 000000000..6553f182a --- /dev/null +++ b/src/modules/backend/entity/ai/AIRegistry.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +#include "backend/entity/EntityStorage.h" + +namespace backend { + +class SpawnMgr; +typedef std::shared_ptr SpawnMgrPtr; + +class AIRegistry: public ai::AIRegistry { +public: + void init(const backend::SpawnMgrPtr& spawnMgr); +}; + +typedef std::shared_ptr AIRegistryPtr; + +} diff --git a/src/modules/backend/entity/ai/action/AttackOnSelection.h b/src/modules/backend/entity/ai/action/AttackOnSelection.h new file mode 100644 index 000000000..29420d5ab --- /dev/null +++ b/src/modules/backend/entity/ai/action/AttackOnSelection.h @@ -0,0 +1,20 @@ +#pragma once + +#include "Task.h" + +using namespace ai; + +namespace backend { + +AI_TASK(AttackOnSelection) { + backend::Npc& npc = chr.getNpc(); + const FilteredEntities& selection = npc.ai()->getFilteredEntities(); + if (selection.empty()) + return FAILED; + if (npc.attack(selection[0])) + return FINISHED; + return FAILED; +} + +} + diff --git a/src/modules/backend/entity/ai/action/Die.h b/src/modules/backend/entity/ai/action/Die.h new file mode 100644 index 000000000..137afe668 --- /dev/null +++ b/src/modules/backend/entity/ai/action/Die.h @@ -0,0 +1,17 @@ +#pragma once + +#include "Task.h" + +using namespace ai; + +namespace backend { + +AI_TASK(Die) { + backend::Npc& npc = chr.getNpc(); + if (npc.die()) + return FINISHED; + return FAILED; +} + +} + diff --git a/src/modules/backend/entity/ai/action/GoHome.h b/src/modules/backend/entity/ai/action/GoHome.h new file mode 100644 index 000000000..1e2de63a5 --- /dev/null +++ b/src/modules/backend/entity/ai/action/GoHome.h @@ -0,0 +1,17 @@ +#pragma once + +#include "Task.h" + +using namespace ai; + +namespace backend { + +AI_TASK(GoHome) { + backend::Npc& npc = chr.getNpc(); + if (npc.route(npc.homePosition())) + return FINISHED; + return FAILED; +} + +} + diff --git a/src/modules/backend/entity/ai/action/SetPointOfInterest.h b/src/modules/backend/entity/ai/action/SetPointOfInterest.h new file mode 100644 index 000000000..624a3d880 --- /dev/null +++ b/src/modules/backend/entity/ai/action/SetPointOfInterest.h @@ -0,0 +1,16 @@ +#pragma once + +#include "Task.h" + +using namespace ai; + +namespace backend { + +AI_TASK(SetPointOfInterest) { + backend::Npc& npc = chr.getNpc(); + npc.setPointOfInterest(); + return FINISHED; +} + +} + diff --git a/src/modules/backend/entity/ai/action/Spawn.h b/src/modules/backend/entity/ai/action/Spawn.h new file mode 100644 index 000000000..ab7612d25 --- /dev/null +++ b/src/modules/backend/entity/ai/action/Spawn.h @@ -0,0 +1,47 @@ +#pragma once + +#include "Task.h" +#include "core/Common.h" +#include "backend/spawn/SpawnMgr.h" + +using namespace ai; + +namespace backend { + +class Spawn: public Task { +private: + backend::SpawnMgrPtr _spawnMgr; +public: + class Factory: public ITreeNodeFactory { + private: + backend::SpawnMgrPtr _spawnMgr; + public: + Factory(const backend::SpawnMgrPtr& spawnMgr) : + _spawnMgr(spawnMgr) { + } + + TreeNodePtr create(const TreeNodeFactoryContext *ctx) const { + return TreeNodePtr(new Spawn(ctx->name, ctx->parameters, ctx->condition, _spawnMgr)); + } + }; + + static Factory& getInstance(const backend::SpawnMgrPtr& spawnMgr) { + thread_local Factory FACTORY(spawnMgr); + return FACTORY; + } + + Spawn(const std::string& name, const std::string& parameters, const ConditionPtr& condition, const backend::SpawnMgrPtr& spawnMgr) : + Task(name, parameters, condition), _spawnMgr(spawnMgr) { + } + + TreeNodeStatus doAction(backend::AICharacter& chr, long deltaMillis) override { + backend::Npc& npc = chr.getNpc(); + const glm::ivec3 pos = glm::ivec3(npc.pos()); + if (_spawnMgr->spawn(*npc.ai()->getZone(), npc.npcType(), 1, &pos) == 1) + return FINISHED; + return FAILED; + } +}; + +} + diff --git a/src/modules/backend/entity/ai/action/Task.h b/src/modules/backend/entity/ai/action/Task.h new file mode 100644 index 000000000..97e7ed0bd --- /dev/null +++ b/src/modules/backend/entity/ai/action/Task.h @@ -0,0 +1,34 @@ +#pragma once + +#include +#include "backend/entity/ai/AICharacter.h" +#include "core/String.h" + +using namespace ai; + +namespace backend { + +class Task: public ITask { +public: + TASK_CLASS(Task) + + TreeNodeStatus doAction(const AIPtr& entity, long deltaMillis) override { + return doAction(ai::character_cast(entity->getCharacter()), deltaMillis); + } + + virtual TreeNodeStatus doAction(backend::AICharacter& chr, long deltaMillis) = 0; +}; + +#define AI_TASK(TaskName) \ +struct TaskName: public Task { \ + TaskName(const std::string& name, const std::string& parameters, const ConditionPtr& condition) : \ + Task(name, parameters, condition) {} \ + virtual ~TaskName() {} \ + NODE_FACTORY \ + TreeNodeStatus doAction(backend::AICharacter& chr, long deltaMillis) override; \ +}; \ +NODE_FACTORY_IMPL(TaskName) \ +inline TreeNodeStatus TaskName::doAction(backend::AICharacter& chr, long deltaMillis) + +} + diff --git a/src/modules/backend/entity/ai/action/TriggerCooldown.cpp b/src/modules/backend/entity/ai/action/TriggerCooldown.cpp new file mode 100644 index 000000000..dfb2b5213 --- /dev/null +++ b/src/modules/backend/entity/ai/action/TriggerCooldown.cpp @@ -0,0 +1,24 @@ +#include "TriggerCooldown.h" +#include "core/Common.h" +#include "entity/Npc.h" + +namespace backend { + +TriggerCooldown::TriggerCooldown(const std::string& name, const std::string& parameters, const ConditionPtr& condition) : + Task(name, parameters, condition) { + _cooldownId = static_cast(core::string::toInt(parameters)); + core_assert(_cooldownId > cooldown::NONE); + core_assert(_cooldownId < cooldown::MAX); +} + +TreeNodeStatus TriggerCooldown::doAction(backend::AICharacter& chr, long deltaMillis) { + backend::Npc& npc = chr.getNpc(); + if (npc.cooldownMgr().triggerCooldown(_cooldownId) == cooldown::CooldownTriggerState::SUCCESS) { + return FINISHED; + } + return FAILED; +} + +NODE_FACTORY_IMPL(TriggerCooldown) + +} diff --git a/src/modules/backend/entity/ai/action/TriggerCooldown.h b/src/modules/backend/entity/ai/action/TriggerCooldown.h new file mode 100644 index 000000000..1b3c10947 --- /dev/null +++ b/src/modules/backend/entity/ai/action/TriggerCooldown.h @@ -0,0 +1,21 @@ +#pragma once + +#include "Task.h" +#include "cooldown/CooldownType.h" + +using namespace ai; + +namespace backend { + +class TriggerCooldown: public Task { +private: + cooldown::CooldownType _cooldownId; +public: + TriggerCooldown(const std::string& name, const std::string& parameters, const ConditionPtr& condition); + NODE_FACTORY + + TreeNodeStatus doAction(backend::AICharacter& chr, long deltaMillis) override; +}; + +} + diff --git a/src/modules/backend/entity/ai/action/TriggerCooldownOnSelection.cpp b/src/modules/backend/entity/ai/action/TriggerCooldownOnSelection.cpp new file mode 100644 index 000000000..79521c2f7 --- /dev/null +++ b/src/modules/backend/entity/ai/action/TriggerCooldownOnSelection.cpp @@ -0,0 +1,33 @@ +#include "TriggerCooldownOnSelection.h" +#include "core/Common.h" +#include "entity/Npc.h" + +namespace backend { + +TriggerCooldownOnSelection::TriggerCooldownOnSelection(const std::string& name, const std::string& parameters, const ConditionPtr& condition) : + Task(name, parameters, condition) { + _cooldownId = static_cast(core::string::toInt(parameters)); + core_assert(_cooldownId > cooldown::NONE); + core_assert(_cooldownId < cooldown::MAX); +} + +TreeNodeStatus TriggerCooldownOnSelection::doAction(backend::AICharacter& chr, long deltaMillis) { + const FilteredEntities& selection = chr.getNpc().ai()->getFilteredEntities(); + if (selection.empty()) + return FAILED; + ai::Zone* zone = chr.getNpc().ai()->getZone(); + if (zone == nullptr) + return FAILED; + for (CharacterId id : selection) { + auto func = [=] (const ai::AIPtr& ai) { + Npc& npc = ai->getCharacterCast().getNpc(); + npc.cooldownMgr().triggerCooldown(_cooldownId); + }; + zone->execute(id, func); + } + return FINISHED; +} + +NODE_FACTORY_IMPL(TriggerCooldownOnSelection) + +} diff --git a/src/modules/backend/entity/ai/action/TriggerCooldownOnSelection.h b/src/modules/backend/entity/ai/action/TriggerCooldownOnSelection.h new file mode 100644 index 000000000..803c5cb32 --- /dev/null +++ b/src/modules/backend/entity/ai/action/TriggerCooldownOnSelection.h @@ -0,0 +1,22 @@ +#pragma once + +#include "Task.h" +#include "cooldown/CooldownType.h" +#include "entity/EntityStorage.h" + +using namespace ai; + +namespace backend { + +class TriggerCooldownOnSelection: public Task { +private: + cooldown::CooldownType _cooldownId; + TriggerCooldownOnSelection(const std::string& name, const std::string& parameters, const ConditionPtr& condition); +public: + NODE_FACTORY + + TreeNodeStatus doAction(backend::AICharacter& chr, long deltaMillis) override; +}; + +} + diff --git a/src/modules/backend/entity/ai/condition/IsCloseToSelection.h b/src/modules/backend/entity/ai/condition/IsCloseToSelection.h new file mode 100644 index 000000000..5a1c89e02 --- /dev/null +++ b/src/modules/backend/entity/ai/condition/IsCloseToSelection.h @@ -0,0 +1,52 @@ +#pragma once + +#include +#include +#include "backend/entity/EntityStorage.h" + +using namespace ai; + +namespace backend { + +class IsCloseToSelection: public ICondition { +protected: + int _distance; + + IsCloseToSelection(const std::string& parameters) : + ICondition("IsCloseToSelection", parameters) { + if (_parameters.empty()) + _distance = 1; + else + _distance = std::stoi(_parameters); + } +public: + CONDITION_FACTORY + + bool evaluate(const AIPtr& entity) override { + ai::Zone* zone = entity->getZone(); + if (zone == nullptr) + return false; + + const FilteredEntities& selection = entity->getFilteredEntities(); + if (selection.empty()) + return false; + + bool closeEnough = false; + auto func = [&] (const ai::AIPtr& ai) { + const Npc& npc = ai->getCharacterCast().getNpc(); + const glm::vec3& pos = npc.pos(); + const ai::Vector3f& ownPos = entity->getCharacter()->getPosition(); + const int distance = ownPos.distance(ai::Vector3f(pos.x, pos.y, pos.z)); + if (distance <= _distance) + closeEnough = true; + }; + + if (!zone->execute(selection[0], func)) + return false; + return closeEnough; + } +}; + +CONDITION_FACTORY_IMPL(IsCloseToSelection) + +} diff --git a/src/modules/backend/entity/ai/condition/IsOnCooldown.h b/src/modules/backend/entity/ai/condition/IsOnCooldown.h new file mode 100644 index 000000000..abc13d5b0 --- /dev/null +++ b/src/modules/backend/entity/ai/condition/IsOnCooldown.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include "cooldown/CooldownType.h" +#include "core/Common.h" +#include "core/String.h" +#include "entity/ai/AICharacter.h" +#include "entity/Npc.h" + +using namespace ai; + +namespace backend { + +class IsOnCooldown: public ICondition { +private: + cooldown::CooldownType _cooldownId; + IsOnCooldown(const std::string& parameters) : + ICondition("IsOnCooldown", parameters) { + _cooldownId = static_cast(core::string::toInt(parameters)); + core_assert(_cooldownId > cooldown::NONE); + core_assert(_cooldownId < cooldown::MAX); + } +public: + CONDITION_FACTORY + + bool evaluate(const AIPtr& entity) override { + const AICharacter& chr = ai::character_cast(entity->getCharacter()); + return chr.getNpc().cooldownMgr().isCooldown(_cooldownId); + } + +}; + +CONDITION_FACTORY_IMPL(IsOnCooldown) + +} diff --git a/src/modules/backend/entity/ai/condition/IsSelectionAlive.h b/src/modules/backend/entity/ai/condition/IsSelectionAlive.h new file mode 100644 index 000000000..6a3dd48d0 --- /dev/null +++ b/src/modules/backend/entity/ai/condition/IsSelectionAlive.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +using namespace ai; + +namespace backend { + +class IsSelectionAlive: public ICondition { +protected: + CONDITION_CLASS(IsSelectionAlive) +public: + CONDITION_FACTORY + + bool evaluate(const AIPtr& entity) override { + const FilteredEntities& selection = entity->getFilteredEntities(); + if (selection.empty()) + return true; + bool alive = false; + auto func = [&] (const AIPtr& ai) { + AICharacter& chr = ai->getCharacterCast(); + alive = !chr.getNpc().dead(); + }; + if (!entity->getZone()->execute(selection[0], func)) + return false; + return alive; + } +}; + +CONDITION_FACTORY_IMPL(IsSelectionAlive); + +} diff --git a/src/modules/backend/entity/ai/filter/SelectIncreasePartner.cpp b/src/modules/backend/entity/ai/filter/SelectIncreasePartner.cpp new file mode 100644 index 000000000..5d02673c0 --- /dev/null +++ b/src/modules/backend/entity/ai/filter/SelectIncreasePartner.cpp @@ -0,0 +1,22 @@ +#include "SelectIncreasePartner.h" +#include "backend/entity/Npc.h" +#include "core/Log.h" + +namespace backend { + +void SelectIncreasePartner::filter(const AIPtr& entity) { + FilteredEntities& entities = getFilteredEntities(entity); + entities.clear(); + backend::Npc& chr = ai::character_cast(entity->getCharacter()).getNpc(); + chr.visitVisible([&] (const backend::EntityPtr& e) { + if (chr.npcType() != e->npcType()) + return; + if (e->cooldownMgr().isCooldown(_cooldownId)) + return; + entities.push_back(e->id()); + }); +} + +FILTER_FACTORY_IMPL(SelectIncreasePartner) + +} diff --git a/src/modules/backend/entity/ai/filter/SelectIncreasePartner.h b/src/modules/backend/entity/ai/filter/SelectIncreasePartner.h new file mode 100644 index 000000000..1b4a7209e --- /dev/null +++ b/src/modules/backend/entity/ai/filter/SelectIncreasePartner.h @@ -0,0 +1,28 @@ +#pragma once + +#include "core/String.h" +#include "core/Common.h" +#include "cooldown/CooldownType.h" +#include + +using namespace ai; + +namespace backend { + +class SelectIncreasePartner: public IFilter { +private: + cooldown::CooldownType _cooldownId; +public: + FILTER_FACTORY + + SelectIncreasePartner(const std::string& parameters = "") : + IFilter("SelectIncreasePartner", parameters) { + _cooldownId = static_cast(core::string::toInt(parameters)); + core_assert(_cooldownId > cooldown::NONE); + core_assert(_cooldownId < cooldown::MAX); + } + + void filter(const AIPtr& entity) override; +}; + +} diff --git a/src/modules/backend/entity/ai/filter/SelectNpcsOfTypes.h b/src/modules/backend/entity/ai/filter/SelectNpcsOfTypes.h new file mode 100644 index 000000000..61ac71817 --- /dev/null +++ b/src/modules/backend/entity/ai/filter/SelectNpcsOfTypes.h @@ -0,0 +1,50 @@ +#pragma once + +#include +#include "core/String.h" +#include "core/Common.h" +#include "network/messages/Shared_generated.h" +#include + +using namespace ai; + +namespace backend { + +class SelectNpcsOfTypes: public IFilter { +private: + std::bitset _npcTypes; +public: + FILTER_FACTORY + + SelectNpcsOfTypes(const std::string& parameters) : + IFilter("SelectNpcsOfTypes", parameters) { + const char **names = network::messages::EnumNamesNpcType(); + std::vector types; + core::string::splitString(parameters, types, ","); + for (const std::string& type : types) { + int i = 0; + while (*names) { + if (!strcmp(*names, type.c_str())) { + _npcTypes[i] = true; + break; + } + ++i; + ++names; + } + } + } + + void filter(const AIPtr& entity) override { + FilteredEntities& entities = getFilteredEntities(entity); + backend::Npc& chr = ai::character_cast(entity->getCharacter()).getNpc(); + chr.visitVisible([&] (const backend::EntityPtr& e) { + if (!_npcTypes[e->npcType()]) + return; + entities.push_back(e->id()); + }); + } +}; + +FILTER_FACTORY_IMPL(SelectNpcsOfTypes) + +} diff --git a/src/modules/backend/entity/ai/filter/SelectPrey.cpp b/src/modules/backend/entity/ai/filter/SelectPrey.cpp new file mode 100644 index 000000000..b733d1b3c --- /dev/null +++ b/src/modules/backend/entity/ai/filter/SelectPrey.cpp @@ -0,0 +1,33 @@ +#include "SelectPrey.h" +#include "entity/Npc.h" + +namespace backend { + +SelectPrey::SelectPrey(const std::string& parameters) : + IFilter("SelectPrey", parameters), _npcType(network::messages::NpcType_NONE) { + const char **names = network::messages::EnumNamesNpcType(); + int i = 0; + while (*names) { + if (!strcmp(*names, parameters.c_str())) { + _npcType = static_cast(i); + break; + } + ++i; + ++names; + } + core_assert(_npcType > network::messages::NpcType_NONE); + core_assert(_npcType < network::messages::NpcType_MAX); +} + +void SelectPrey::filter(const AIPtr& entity) { + FilteredEntities& entities = getFilteredEntities(entity); + backend::Npc& chr = ai::character_cast(entity->getCharacter()).getNpc(); + chr.visitVisible([&] (const backend::EntityPtr& e) { + if (e->npcType() == _npcType) + entities.push_back(e->id()); + }); +} + +FILTER_FACTORY_IMPL(SelectPrey) + +} diff --git a/src/modules/backend/entity/ai/filter/SelectPrey.h b/src/modules/backend/entity/ai/filter/SelectPrey.h new file mode 100644 index 000000000..464c416bd --- /dev/null +++ b/src/modules/backend/entity/ai/filter/SelectPrey.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include "core/String.h" +#include "core/Common.h" +#include "network/messages/Shared_generated.h" + +using namespace ai; + +namespace backend { + +class SelectPrey: public IFilter { +private: + network::messages::NpcType _npcType; +public: + FILTER_FACTORY + + SelectPrey(const std::string& parameters = ""); + + void filter(const AIPtr& entity) override; +}; + +} diff --git a/src/modules/backend/entity/ai/filter/SelectVisible.cpp b/src/modules/backend/entity/ai/filter/SelectVisible.cpp new file mode 100644 index 000000000..ab77c9ed0 --- /dev/null +++ b/src/modules/backend/entity/ai/filter/SelectVisible.cpp @@ -0,0 +1,16 @@ +#include "SelectVisible.h" +#include "entity/Npc.h" + +namespace backend { + +void SelectVisible::filter(const AIPtr& entity) { + FilteredEntities& entities = getFilteredEntities(entity); + backend::Npc& chr = ai::character_cast(entity->getCharacter()).getNpc(); + chr.visitVisible([&] (const backend::EntityPtr& e) { + entities.push_back(e->id()); + }); +} + +FILTER_FACTORY_IMPL(SelectVisible) + +} diff --git a/src/modules/backend/entity/ai/filter/SelectVisible.h b/src/modules/backend/entity/ai/filter/SelectVisible.h new file mode 100644 index 000000000..3c14ddd0b --- /dev/null +++ b/src/modules/backend/entity/ai/filter/SelectVisible.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +using namespace ai; + +namespace backend { + +class SelectVisible: public IFilter { +public: + FILTER_FACTORY + + SelectVisible(const std::string& parameters = "") : + IFilter("SelectVisible", parameters) { + } + + void filter (const AIPtr& entity) override; +}; + +} diff --git a/src/modules/backend/loop/ServerLoop.cpp b/src/modules/backend/loop/ServerLoop.cpp new file mode 100644 index 000000000..6199d4a17 --- /dev/null +++ b/src/modules/backend/loop/ServerLoop.cpp @@ -0,0 +1,105 @@ +#include "ServerLoop.h" +#include "core/Command.h" +#include "core/Tokenizer.h" + +namespace backend { + +ServerLoop::ServerLoop(network::NetworkPtr network, SpawnMgrPtr spawnMgr, voxel::WorldPtr world, EntityStoragePtr entityStorage, core::EventBusPtr eventBus, AIRegistryPtr registry, + attrib::ContainerProviderPtr containerProvider, PoiProviderPtr poiProvider) : + _network(network), _spawnMgr(spawnMgr), _world(world), _zone("Zone"), _aiServer(*registry, 11338, "127.0.0.1"), _entityStorage(entityStorage), _eventBus(eventBus), _registry( + registry), _containerProvider(containerProvider), _poiProvider(poiProvider) { + _eventBus->subscribe(*this); + _eventBus->subscribe(*this); +} + +bool ServerLoop::onInit() { + if (!_containerProvider->init()) { + Log::error("Failed to load the attributes: %s", _containerProvider->error().c_str()); + return false; + } + _registry->init(_spawnMgr); + if (!_spawnMgr->init()) + return false; + const core::VarPtr& seed = core::Var::get("sv_seed", "1"); + + class ProgressMonitor: public util::IProgressMonitor { + public: + void step(int steps = 1) override { + IProgressMonitor::step(steps); + Log::info("max: %i, steps: %i => %f\r", _max, _steps, progress()); + } + void done() override { + Log::info("\ndone"); + } + } monitor; + + if (!_world->load(seed->longVal(), &monitor)) + return false; + if (_aiServer.start()) { + Log::info("Start the ai debug server on 127.0.0.1:11338"); + _aiServer.addZone(&_zone); + } else { + Log::error("Could not start the ai debug server"); + } + return true; +} + +void ServerLoop::readInput() { + const char *input = _input.read(); + if (input == nullptr) + return; + if (core::Command::execute(input) != 0) + return; + core::Tokenizer t(input); + while (t.hasNext()) { + const std::string& var = t.next(); + const core::VarPtr& varPtr = core::Var::get(var, "", core::CV_NOTCREATEEMPTY); + if (!t.hasNext()) { + if (varPtr) { + Log::info("%s = %s", varPtr->name().c_str(), varPtr->strVal().c_str()); + } else { + Log::error("unknown command"); + } + break; + } + const std::string& value = t.next(); + varPtr->setVal(value); + } +} + +void ServerLoop::onFrame(long dt) { + readInput(); + core_trace_scoped("ServerLoop"); + _network->update(); + { // TODO: move into own thread + core_trace_scoped("PoiUpdate"); + _poiProvider->update(dt); + } + { // TODO: move into own thread + core_trace_scoped("WorldUpdate"); + _world->onFrame(dt); + } + { // TODO: move into own thread + core_trace_scoped("AIServerUpdate"); + _zone.update(dt); + _aiServer.update(dt); + } + { // TODO: move into own thread + core_trace_scoped("SpawnMgrUpdate"); + _spawnMgr->onFrame(_zone, dt); + } + { + core_trace_scoped("EntityStorage"); + _entityStorage->onFrame(dt); + } +} + +void ServerLoop::onEvent(const network::DisconnectEvent& event) { + Log::info("disconnect peer: %i", event.peer()->connectID); +} + +void ServerLoop::onEvent(const network::NewConnectionEvent& event) { + Log::info("new connection - waiting for login request from %i", event.peer()->connectID); +} + +} diff --git a/src/modules/backend/loop/ServerLoop.h b/src/modules/backend/loop/ServerLoop.h new file mode 100644 index 000000000..b76b6577f --- /dev/null +++ b/src/modules/backend/loop/ServerLoop.h @@ -0,0 +1,49 @@ +#pragma once + +#include "core/EventBus.h" +#include "core/Trace.h" +#include "network/Network.h" +#include "network/NetworkEvents.h" +#include "voxel/World.h" +#include "backend/spawn/SpawnMgr.h" +#include "core/Input.h" +#include "network/ProtocolHandlerRegistry.h" +#include "backend/entity/EntityStorage.h" +#include "backend/entity/ai/AIRegistry.h" +#include "core/EventBus.h" + +#include +#include +#include +#include + +namespace backend { + +class ServerLoop: public core::IEventBusHandler, core::IEventBusHandler { +private: + network::NetworkPtr _network; + SpawnMgrPtr _spawnMgr; + voxel::WorldPtr _world; + ai::Zone _zone; + ai::Server _aiServer; + EntityStoragePtr _entityStorage; + core::EventBusPtr _eventBus; + AIRegistryPtr _registry; + attrib::ContainerProviderPtr _containerProvider; + PoiProviderPtr _poiProvider; + core::Input _input; + + void readInput(); +public: + ServerLoop(network::NetworkPtr network, SpawnMgrPtr spawnMgr, voxel::WorldPtr world, EntityStoragePtr entityStorage, core::EventBusPtr eventBus, AIRegistryPtr registry, + attrib::ContainerProviderPtr containerProvider, PoiProviderPtr poiProvider); + + bool onInit(); + void onFrame(long dt); + void onEvent(const network::DisconnectEvent& event); + void onEvent(const network::NewConnectionEvent& event); +}; + +typedef std::shared_ptr ServerLoopPtr; + +} diff --git a/src/modules/backend/network/AttackHandler.h b/src/modules/backend/network/AttackHandler.h new file mode 100644 index 000000000..f4b53dccd --- /dev/null +++ b/src/modules/backend/network/AttackHandler.h @@ -0,0 +1,12 @@ +#pragma once + +#include "network/Network.h" +#include "IUserProtocolHandler.h" + +namespace backend { + +USERPROTOHANDLERIMPL(Attack) { + user->attack(message->targetId()); +} + +} diff --git a/src/modules/backend/network/IUserProtocolHandler.h b/src/modules/backend/network/IUserProtocolHandler.h new file mode 100644 index 000000000..47121aa8a --- /dev/null +++ b/src/modules/backend/network/IUserProtocolHandler.h @@ -0,0 +1,36 @@ +#pragma once + +#include "network/IMsgProtocolHandler.h" +#include "backend/entity/User.h" +#include "network/messages/ServerMessages.h" +#include "network/messages/ClientMessages.h" + +using namespace network::messages::server; +using namespace network::messages::client; + +namespace backend { + +template +class IUserProtocolHandler: public network::IMsgProtocolHandler { +public: + IUserProtocolHandler() : + network::IMsgProtocolHandler(true) { + } + + virtual ~IUserProtocolHandler() { + } + + virtual void execute(User* attachment, const MSGTYPE* message) override = 0; +}; + +#define USERPROTOHANDLER(msgType) \ +struct msgType##Handler: public IUserProtocolHandler { \ + msgType##Handler() : IUserProtocolHandler() {} \ + void execute(User* attachment, const msgType* message) override; \ +} + +#define USERPROTOHANDLERIMPL(msgType) \ +USERPROTOHANDLER(msgType); \ +inline void msgType##Handler::execute(User* user, const msgType* message) + +} diff --git a/src/modules/backend/network/MoveHandler.h b/src/modules/backend/network/MoveHandler.h new file mode 100644 index 000000000..bc5b9295d --- /dev/null +++ b/src/modules/backend/network/MoveHandler.h @@ -0,0 +1,12 @@ +#pragma once + +#include "network/Network.h" +#include "IUserProtocolHandler.h" + +namespace backend { + +USERPROTOHANDLERIMPL(Move) { + user->changeMovement(message->direction(), message->pitch(), message->yaw()); +} + +} diff --git a/src/modules/backend/network/ServerNetworkModule.h b/src/modules/backend/network/ServerNetworkModule.h new file mode 100644 index 000000000..c2e3c3627 --- /dev/null +++ b/src/modules/backend/network/ServerNetworkModule.h @@ -0,0 +1,22 @@ +#pragma once + +#include "network/NetworkModule.h" +#include "network/messages/ClientMessages.h" + +#include "UserConnectHandler.h" +#include "UserDisconnectHandler.h" +#include "AttackHandler.h" +#include "MoveHandler.h" + +namespace backend { + +class ServerNetworkModule: public NetworkModule { + void configureHandlers() const override { + configureHandler(Type_UserConnect, UserConnectHandler(network::Network &, backend::EntityStorage &)); + configureHandler(Type_UserDisconnect, UserDisconnectHandler()); + configureHandler(Type_Attack, AttackHandler()); + configureHandler(Type_Move, MoveHandler()); + } +}; + +} diff --git a/src/modules/backend/network/UserConnectHandler.cpp b/src/modules/backend/network/UserConnectHandler.cpp new file mode 100644 index 000000000..fccdb06b2 --- /dev/null +++ b/src/modules/backend/network/UserConnectHandler.cpp @@ -0,0 +1,40 @@ +#include "UserConnectHandler.h" +#include "network/messages/ClientMessages.h" +#include "network/messages/ServerMessages.h" +#include "backend/entity/User.h" +#include "core/Var.h" + +namespace backend { + +UserConnectHandler::UserConnectHandler(network::NetworkPtr network, backend::EntityStoragePtr entityStorage) : + _network(network), _entityStorage(entityStorage) { + auto data = CreateAuthFailed(_authFailed); + auto msg = CreateServerMessage(_authFailed, Type_AuthFailed, data.Union()); + FinishServerMessageBuffer(_authFailed, msg); +} + +void UserConnectHandler::sendAuthFailed(ENetPeer* peer) { + ENetPacket* packet = enet_packet_create(_authFailed.GetBufferPointer(), _authFailed.GetSize(), ENET_PACKET_FLAG_RELIABLE); + _network->sendMessage(peer, packet); +} + +void UserConnectHandler::execute(ENetPeer* peer, const void* raw) { + const auto* message = getMsg(raw); + + const char *email = message->email()->c_str(); + const char *password = message->password()->c_str(); + Log::info("User %s tries to log into the gameserver", email); + + UserPtr user = _entityStorage->login(peer, email, password); + if (!user) { + sendAuthFailed(peer); + return; + } + + // TODO: use the current seed from the world, not from a config var that can be changed during runtime + const long seed = core::Var::get("sv_seed")->longVal(); + user->sendSeed(seed); + user->sendUserSpawn(); +} + +} diff --git a/src/modules/backend/network/UserConnectHandler.h b/src/modules/backend/network/UserConnectHandler.h new file mode 100644 index 000000000..bd0efda9f --- /dev/null +++ b/src/modules/backend/network/UserConnectHandler.h @@ -0,0 +1,24 @@ +#pragma once + +#include "network/Network.h" +#include "backend/entity/EntityStorage.h" + +#include + +namespace backend { + +class UserConnectHandler: public network::IProtocolHandler { +private: + network::NetworkPtr _network; + backend::EntityStoragePtr _entityStorage; + flatbuffers::FlatBufferBuilder _authFailed; + + void sendAuthFailed(ENetPeer* peer); + +public: + UserConnectHandler(network::NetworkPtr network, backend::EntityStoragePtr entityStorage); + + void execute(ENetPeer* peer, const void* message) override; +}; + +} diff --git a/src/modules/backend/network/UserDisconnectHandler.h b/src/modules/backend/network/UserDisconnectHandler.h new file mode 100644 index 000000000..f072231f2 --- /dev/null +++ b/src/modules/backend/network/UserDisconnectHandler.h @@ -0,0 +1,12 @@ +#pragma once + +#include "network/Network.h" +#include "IUserProtocolHandler.h" + +namespace backend { + +USERPROTOHANDLERIMPL(UserDisconnect) { + user->disconnect(); +} + +} diff --git a/src/modules/backend/poi/PoiProvider.cpp b/src/modules/backend/poi/PoiProvider.cpp new file mode 100644 index 000000000..5efc03c5d --- /dev/null +++ b/src/modules/backend/poi/PoiProvider.cpp @@ -0,0 +1,55 @@ +#include "PoiProvider.h" +#include "core/Random.h" +#include "voxel/World.h" +#include "core/Var.h" + +namespace backend { + +PoiProvider::PoiProvider(voxel::WorldPtr world, core::TimeProviderPtr timeProvider) : + _world(world), _timeProvider(timeProvider), _lock("PoiProvider") { +} + +void PoiProvider::update(long /*dt*/) { + constexpr unsigned long seconds = 60L * 1000L; + for (;;) { + _lock.lockWrite(); + auto i = _pois.begin(); + if (i == _pois.end()) { + _lock.unlockWrite(); + break; + } + Poi poi = *i; + if (poi.time + seconds > _timeProvider->tickTime()) { + _lock.unlockWrite(); + break; + } + _pois.erase(i); + _lock.unlockWrite(); + } +} + +void PoiProvider::addPointOfInterest(const glm::vec3& pos) { + _lock.lockWrite(); + _pois.push_back(Poi { pos, _timeProvider->tickTime() }); + + struct PoiComparatorLess: public std::binary_function { + inline bool operator()(const Poi& x, const Poi& y) const { + return std::less()(x.time, y.time); + } + }; + + std::sort(_pois.begin(), _pois.end(), PoiComparatorLess()); + _lock.unlockWrite(); +} + +size_t PoiProvider::getPoisCount() const { + return _pois.size(); +} + +glm::vec3 PoiProvider::getPointOfInterest() const { + if (_pois.empty()) + return _world->randomPos(); + return core::randomElement(_pois.begin(), _pois.end())->pos; +} + +} diff --git a/src/modules/backend/poi/PoiProvider.h b/src/modules/backend/poi/PoiProvider.h new file mode 100644 index 000000000..5fce584ce --- /dev/null +++ b/src/modules/backend/poi/PoiProvider.h @@ -0,0 +1,48 @@ +#pragma once + +#include "core/TimeProvider.h" +#include "core/ReadWriteLock.h" +#include +#include +#include + +namespace voxel { +class World; +typedef std::shared_ptr WorldPtr; +} + +namespace backend { + +/** + * @brief Maintains a list of points of interest that are only valid for a particular time. + * + * @note One can add new POIs by calling @c PoiProvider::addPointOfInterest and get a random, + * not yet expired POI by calling @c PoiProvider::getPointOfInterest(). If there are not POIs + * left, you will get a random one from the @c voxel::World + */ +class PoiProvider { +private: + struct Poi { + glm::vec3 pos; + unsigned long time; + }; + + typedef std::vector PoiQueue; + PoiQueue _pois; + + voxel::WorldPtr _world; + core::TimeProviderPtr _timeProvider; + core::ReadWriteLock _lock; +public: + PoiProvider(voxel::WorldPtr world, core::TimeProviderPtr timeProvider); + + void update(long dt); + + void addPointOfInterest(const glm::vec3& pos); + size_t getPoisCount() const; + glm::vec3 getPointOfInterest() const; +}; + +typedef std::shared_ptr PoiProviderPtr; + +} diff --git a/src/modules/backend/spawn/SpawnMgr.cpp b/src/modules/backend/spawn/SpawnMgr.cpp new file mode 100644 index 000000000..1934467de --- /dev/null +++ b/src/modules/backend/spawn/SpawnMgr.cpp @@ -0,0 +1,94 @@ +#include "SpawnMgr.h" +#include "core/Common.h" +#include "core/Singleton.h" +#include "core/App.h" +#include "io/Filesystem.h" + +namespace backend { + +SpawnMgr::SpawnMgr(voxel::WorldPtr world, EntityStoragePtr entityStorage, network::MessageSenderPtr messageSender, core::TimeProviderPtr timeProvider, AILoaderPtr loader, attrib::ContainerProviderPtr containerProvider, PoiProviderPtr poiProvider) : + _loader(loader), _world(world), _entityStorage(entityStorage), _messageSender(messageSender), _timeProvider(timeProvider), _containerProvider(containerProvider), _poiProvider(poiProvider), _time(0L) { +} + +bool SpawnMgr::init() { + const std::string& lua = core::App::getInstance()->filesystem()->load("behaviourtrees.lua"); + if (!_loader->init(lua)) { + Log::error("could not load the behaviourtrees: %s", _loader->getError().c_str()); + return false; + } + std::vector trees; + _loader->getTrees(trees); + + Log::info("loaded %i behaviour trees", (int)trees.size()); + for (const std::string& tree : trees) { + std::stringstream s; + const ai::TreeNodePtr& node = _loader->load(tree); + core_assert(node); + s << *node; + Log::debug("%s", s.str().c_str()); + } + return true; +} + +void SpawnMgr::spawnCharacters(ai::Zone& zone) { + spawnEntity(zone, network::messages::NpcType_BEGIN_CHARACTERS, network::messages::NpcType_MAX_CHARACTERS, 0); +} + +void SpawnMgr::spawnAnimals(ai::Zone& zone) { + spawnEntity(zone, network::messages::NpcType_BEGIN_ANIMAL, network::messages::NpcType_MAX_ANIMAL, 2); +} + +void SpawnMgr::spawnEntity(ai::Zone& zone, network::messages::NpcType start, network::messages::NpcType end, int maxAmount) { + const int offset = start + 1; + int count[end - offset]; + memset(count, 0, sizeof(count)); + zone.visit([&] (const ai::AIPtr& ai) { + const AICharacter& chr = ai::character_cast(ai->getCharacter()); + const Npc& npc = chr.getNpc(); + const network::messages::NpcType type = npc.npcType(); + if (type <= start || type >= end) + return; + const int index = type - offset; + ++count[index]; + }); + + const int size = lengthof(count); + for (int i = 0; i < size; ++i) { + if (count[i] >= maxAmount) + continue; + + const int needToSpawn = maxAmount - count[i]; + network::messages::NpcType type = static_cast(offset + i); + spawn(zone, type, needToSpawn); + } +} + +int SpawnMgr::spawn(ai::Zone& zone, network::messages::NpcType type, int amount, const glm::ivec3* pos) { + const char *typeName = network::messages::EnumNameNpcType(type); + ai::TreeNodePtr behaviour = _loader->load(typeName); + if (!behaviour) { + Log::error("could not load the behaviour tree %s", typeName); + return 0; + } + for (int x = 0; x < amount; ++x) { + NpcPtr npc(new Npc(type, _entityStorage, behaviour, _world, _messageSender, _timeProvider, _containerProvider, _poiProvider)); + npc->init(pos); + // now let it tick + zone.scheduleAdd(npc->ai()); + _entityStorage->addNpc(npc); + } + + return amount; +} + +void SpawnMgr::onFrame(ai::Zone& zone, long dt) { + static const long spawnTime = 15000L; + _time += dt; + if (_time >= spawnTime) { + _time -= spawnTime; + spawnAnimals(zone); + spawnCharacters(zone); + } +} + +} diff --git a/src/modules/backend/spawn/SpawnMgr.h b/src/modules/backend/spawn/SpawnMgr.h new file mode 100644 index 000000000..73232a422 --- /dev/null +++ b/src/modules/backend/spawn/SpawnMgr.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include "voxel/World.h" +#include "backend/entity/EntityStorage.h" +#include "backend/entity/ai/AILoader.h" +#include "backend/poi/PoiProvider.h" +#include "network/messages/ServerMessages.h" +#include "core/Var.h" + +namespace backend { + +class SpawnMgr { +private: + AILoaderPtr _loader; + voxel::WorldPtr _world; + EntityStoragePtr _entityStorage; + network::MessageSenderPtr _messageSender; + core::TimeProviderPtr _timeProvider; + attrib::ContainerProviderPtr _containerProvider; + PoiProviderPtr _poiProvider; + long _time; + + void spawnEntity(ai::Zone& zone, network::messages::NpcType start, network::messages::NpcType end, int maxAmount); + void spawnAnimals(ai::Zone& zone); + void spawnCharacters(ai::Zone& zone); + +public: + SpawnMgr(voxel::WorldPtr world, EntityStoragePtr entityStorage, network::MessageSenderPtr messageSender, core::TimeProviderPtr timeProvider, AILoaderPtr loader, attrib::ContainerProviderPtr containerProvider, PoiProviderPtr poiProvider); + bool init(); + + int spawn(ai::Zone& zone, network::messages::NpcType type, int amount, const glm::ivec3* pos = nullptr); + void onFrame(ai::Zone& zone, long dt); +}; + +typedef std::shared_ptr SpawnMgrPtr; + +} diff --git a/src/modules/backend/storage/PQHandle.cpp b/src/modules/backend/storage/PQHandle.cpp new file mode 100644 index 000000000..49a1b135a --- /dev/null +++ b/src/modules/backend/storage/PQHandle.cpp @@ -0,0 +1,61 @@ +#include "PQHandle.h" +#include "dbpost/StoreInterface.h" +#include "UserStore.h" +#include "core/Log.h" +#include "core/Var.h" + +namespace backend { + +PQHandle::PQHandle() : + _pqConnection(), _pqStore(&_pqConnection) { +} + +PQHandle::~PQHandle() { + _pqConnection.disconnect(); +} + +void PQHandle::storeUser(const std::string& mail, const std::string& passwd, const std::string& uid) { + UserStore dbUser(mail, passwd, uid); + _pqStore.storeModel(dbUser); +} + +int PQHandle::loadUser(const std::string& mail, const std::string& passwd, const std::string& uid) { + const UserStore dbUser(mail, passwd, uid); + _userData = std::move(_pqStore.loadModel(dbUser)); + if (_userData.size() > 0) { + const int uid = std::stoi(_userData["userid"]); + return uid; + } + return 0; +} +void PQHandle::close() { + _pqConnection.disconnect(); +} + +void PQHandle::initTables() { + std::string tmUid = "0"; + std::string tmUser = std::string("a"); + std::string tmPw = std::string("b"); + UserStore dbUser(tmUser, tmPw, tmUid); + _pqStore.createNeeds(dbUser); +} + +void PQHandle::init() { + Log::trace("init database connection"); + const core::VarPtr& dbName = core::Var::get("db_name", "engine_db"); + const core::VarPtr& dbHost = core::Var::get("db_host", "localhost"); + const core::VarPtr& dbPw = core::Var::get("db_pw", "ben711cCefIUit887"); + const core::VarPtr& dbUser = core::Var::get("db_user", "dbmaster"); + + _pqConnection.changeDb(dbName->strVal()); + _pqConnection.changeHost(dbHost->strVal()); + _pqConnection.setLoginData(dbUser->strVal(), dbPw->strVal()); + + if (_pqConnection.connect() == 0) { + Log::debug("database connection established"); + } else { + Log::error("database connection failed"); + } +} + +} diff --git a/src/modules/backend/storage/PQHandle.h b/src/modules/backend/storage/PQHandle.h new file mode 100644 index 000000000..798e3ecde --- /dev/null +++ b/src/modules/backend/storage/PQHandle.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include +#include "dbpost/PQStore.h" +#include "dbpost/PQConnect.h" + +namespace backend { + +class PQHandle { +private: + dbpost::PQConnect _pqConnection; + dbpost::PQStore _pqStore; + std::unordered_map _userData; +public: + PQHandle(); + void init(); + void close(); + void initTables(); + void storeUser(const std::string& uMail, const std::string& uPasswd, const std::string& uid); + int loadUser(const std::string& uMail, const std::string& uPasswd, const std::string& uid); + virtual ~PQHandle(); +}; + +} diff --git a/src/modules/backend/storage/StoreCmd.cpp b/src/modules/backend/storage/StoreCmd.cpp new file mode 100644 index 000000000..1fb0aa7ae --- /dev/null +++ b/src/modules/backend/storage/StoreCmd.cpp @@ -0,0 +1,28 @@ +#include "StoreCmd.h" + +namespace backend { + +void StoreCmd::addComd() { + core::Command::registerCommand("store", [&](const core::CmdArgs & args) { + if (args.size() == 1) { + if (args[0] == "help") { + Log::info("store useradd \tadd a new users"); + } else if (args[0] == "init") { + PQHandle pq; + pq.init(); + pq.initTables(); + } + } else if (args.size() == 3) { + if (args[0] == "useradd") { + const std::string tmUid = "0"; + const std::string& tmUser = args[1]; + const std::string& tmPw = args[2]; + PQHandle pq; + pq.init(); + pq.storeUser(tmUser, tmPw, tmUid); + } + } + }); +} + +} diff --git a/src/modules/backend/storage/StoreCmd.h b/src/modules/backend/storage/StoreCmd.h new file mode 100644 index 000000000..df7535b8c --- /dev/null +++ b/src/modules/backend/storage/StoreCmd.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include +#include +#include "core/Log.h" +#include "core/Var.h" +#include "core/Command.h" +#include "PQHandle.h" + +namespace backend { + +class StoreCmd { +public: + void addComd(); +}; + +} diff --git a/src/modules/backend/storage/UserStore.cpp b/src/modules/backend/storage/UserStore.cpp new file mode 100644 index 000000000..6aa14e96b --- /dev/null +++ b/src/modules/backend/storage/UserStore.cpp @@ -0,0 +1,47 @@ +#include "UserStore.h" +#include "core/Log.h" +#include "backend/entity/User.h" + +namespace backend { + +UserStore::UserStore(const std::string& email, const std::string& password, const std::string& userid) : + _email(email), _password(password), _userid(userid) { +} + +std::string UserStore::getCreate() const { + const std::string crSql = "CREATE TABLE " + getTableName() + " ( userid bigserial primary key," + " user_email varchar(180) UNIQUE," + " user_pw_hash varchar(60) " + ");"; + return crSql; +} + +void UserStore::update(const std::string& fieldName, const std::string& value) const { + Log::trace("update called"); + if (fieldName == "userid") { + Log::trace("userid read %s", value.c_str()); + } +} + +std::string UserStore::getTableName() const { + static const std::string tabName = "user_table"; + return tabName; +} + +std::unordered_map UserStore::getFields() const { + std::unordered_map storeData; + storeData["userid"] = _userid; + storeData["user_email"] = _email; + storeData["user_pw_hash"] = _password; + + return storeData; +} + +bool UserStore::isSerial(const std::string& fieldname) const { + if (fieldname == "userid") { + return true; + } + return false; +} + +} diff --git a/src/modules/backend/storage/UserStore.h b/src/modules/backend/storage/UserStore.h new file mode 100644 index 000000000..818e681ea --- /dev/null +++ b/src/modules/backend/storage/UserStore.h @@ -0,0 +1,30 @@ +#include +#include +#include +#include "dbpost/StoreInterface.h" + +#pragma once + +namespace backend { + +class UserStore: public dbpost::StoreInterface { +private: + std::string _email; + std::string _password; + std::string _userid; + std::unordered_map _storage; +public: + UserStore(const std::string& email, const std::string& password, const std::string& userid); + + std::string getCreate() const override; + + std::unordered_map getFields() const override; + + bool isSerial(const std::string& fieldname) const override; + + virtual void update(const std::string& fieldName, const std::string& value) const override; + + std::string getTableName() const override; +}; + +} diff --git a/src/modules/backend/tests/PoiProviderTest.cpp b/src/modules/backend/tests/PoiProviderTest.cpp new file mode 100644 index 000000000..f3a763e39 --- /dev/null +++ b/src/modules/backend/tests/PoiProviderTest.cpp @@ -0,0 +1,50 @@ +#include "core/tests/AbstractTest.h" +#include "backend/poi/PoiProvider.h" +#include "voxel/World.h" + +namespace backend { + +class PoiProviderTest: public core::AbstractTest { +public: + PoiProviderPtr _poiProvider; + core::TimeProviderPtr _timeProvider; + void SetUp() override { + core::AbstractTest::SetUp(); + io::FilesystemPtr filesystem(new io::Filesystem()); + voxel::WorldPtr world(new voxel::World); + _timeProvider = core::TimeProviderPtr(new core::TimeProvider); + _poiProvider = PoiProviderPtr(new PoiProvider(world, _timeProvider)); + } +}; + +TEST_F(PoiProviderTest, testUpdate) { + _poiProvider->addPointOfInterest(glm::vec3(1.0)); + ASSERT_EQ(glm::vec3(1.0), _poiProvider->getPointOfInterest()); +} + +TEST_F(PoiProviderTest, testExpire) { + _poiProvider->addPointOfInterest(glm::vec3(1.0)); + _poiProvider->addPointOfInterest(glm::vec3(2.0)); + _poiProvider->addPointOfInterest(glm::vec3(3.0)); + ASSERT_EQ(3u, _poiProvider->getPoisCount()); + _timeProvider->update(60 * 1000UL); + _poiProvider->update(0UL); + ASSERT_EQ(0u, _poiProvider->getPoisCount()); +} + +TEST_F(PoiProviderTest, testExpireWithProperPos) { + const int max = 3; + for (int i = 0; i < max; ++i) { + _timeProvider->update(i * 60 * 1000UL); + _poiProvider->addPointOfInterest(glm::vec3(static_cast(i))); + } + ASSERT_EQ(3u, _poiProvider->getPoisCount()); + _poiProvider->update(0UL); + ASSERT_EQ(1u, _poiProvider->getPoisCount()); + ASSERT_EQ(glm::vec3(static_cast(max - 1)), _poiProvider->getPointOfInterest()); + _timeProvider->update(max * 60 * 1000UL); + _poiProvider->update(0UL); + ASSERT_EQ(0u, _poiProvider->getPoisCount()); +} + +} diff --git a/src/modules/backend/tests/SpawnMgrTest.cpp b/src/modules/backend/tests/SpawnMgrTest.cpp new file mode 100644 index 000000000..969dcfa4c --- /dev/null +++ b/src/modules/backend/tests/SpawnMgrTest.cpp @@ -0,0 +1,8 @@ +#include + +namespace backend { + +TEST(SpawnMgrTest, testSpawn) { +} + +} diff --git a/src/modules/backend/tests/StorageTest.cpp b/src/modules/backend/tests/StorageTest.cpp new file mode 100644 index 000000000..345664d6f --- /dev/null +++ b/src/modules/backend/tests/StorageTest.cpp @@ -0,0 +1,14 @@ +#include +#include "backend/storage/PQHandle.h" + +namespace backend { + +TEST(StorageTest, testCreate) { +#if 0 + PQHandle pq; + pq.init(); + pq.initTables(); +#endif +} + +} diff --git a/src/modules/commonlua/CMakeLists.txt b/src/modules/commonlua/CMakeLists.txt new file mode 100644 index 000000000..a6dce1e86 --- /dev/null +++ b/src/modules/commonlua/CMakeLists.txt @@ -0,0 +1,14 @@ +fips_begin_module(commonlua) + fips_files( + LUA.h LUA.cpp + ) + fips_deps(core lua52) +fips_end_module() + +begin_googleunittest(commonlua) + fips_dir(tests) + fips_files( + LUATest.cpp + ) + fips_deps(commonlua) +end_googleunittest() diff --git a/src/modules/commonlua/LUA.cpp b/src/modules/commonlua/LUA.cpp new file mode 100644 index 000000000..1d92f4363 --- /dev/null +++ b/src/modules/commonlua/LUA.cpp @@ -0,0 +1,343 @@ +#include "LUA.h" +#include +#include +#include +#include + +namespace lua { + +class StackChecker { +private: + lua_State *_state; + const int _startStackDepth; +public: + StackChecker(lua_State *state) : + _state(state), _startStackDepth(lua_gettop(_state)) { + } + ~StackChecker() { + assert(_startStackDepth == lua_gettop(_state)); + } +}; + +namespace { +int panicCB(lua_State *L) { + std::cout << "Lua panic. Error message: " << (lua_isnil(L, -1) ? "" : lua_tostring(L, -1)) << std::endl << std::flush; + return 0; +} + +void debugHook(lua_State *L, lua_Debug *ar) { + if (!lua_getinfo(L, "Sn", ar)) + return; + + std::cout << "LUADBG: "; + if (ar->namewhat != nullptr) + std::cout << ar->namewhat << " "; + if (ar->name != nullptr) + std::cout << ar->name << " "; + std::cout << ar->short_src << " "; + std::cout << ar->currentline; + std::cout << std::endl << std::flush; +} +} + +#ifdef DEBUG +#define checkStack() StackChecker(this->_state) +#else +#define checkStack() +#endif + +LUAType::LUAType(lua_State* state, const std::string& name) : + _state(state) { + const std::string metaTable = META_PREFIX + name; + luaL_newmetatable(_state, metaTable.c_str()); + lua_pushvalue(_state, -1); + lua_setfield(_state, -2, "__index"); +} + +void LUAType::addFunction(const std::string& name, lua_CFunction func) { + lua_pushcfunction(_state, func); + lua_setfield(_state, -2, name.c_str()); +} + +LUA::LUA(bool debug) { + _state = luaL_newstate(); + + luaL_openlibs(_state); + + // Register panic callback function + lua_atpanic(_state, panicCB); + + int mask = 0; + if (debug) { + mask |= LUA_MASKCALL; + mask |= LUA_MASKRET; + mask |= LUA_MASKLINE; + } + + // Register debug callback function + lua_sethook(_state, debugHook, mask, 0); +} + +LUA::~LUA() { + lua_close(_state); +} + +void LUA::reg(const std::string& prefix, luaL_Reg* funcs) { + const std::string metaTableName = META_PREFIX + prefix; + luaL_newmetatable(_state, metaTableName.c_str()); + luaL_setfuncs(_state, funcs, 0); + lua_pushvalue(_state, -1); + lua_setfield(_state, -1, "__index"); + lua_setglobal(_state, prefix.c_str()); +} + +LUAType LUA::registerType(const std::string& name) { + return LUAType(_state, name); +} + +bool LUA::load(const std::string& luaString) { + if (luaL_loadbufferx(_state, luaString.c_str(), luaString.length(), "", nullptr) || lua_pcall(_state, 0, 0, 0)) { + setError(lua_tostring(_state, -1)); + pop(1); + return false; + } + + return true; +} + +bool LUA::getValueBoolFromTable(const char * key, bool defaultValue) { + checkStack(); + lua_getfield(_state, -1, key); + if (lua_isnil(_state, -1)) { + lua_pop(_state, 1); + return defaultValue; + } + + const bool rtn = lua_toboolean(_state, -1); + lua_pop(_state, 1); + return rtn; +} + +std::string LUA::getValueStringFromTable(const char * key, const std::string& defaultValue) { + checkStack(); + lua_getfield(_state, -1, key); + if (lua_isnil(_state, -1)) { + lua_pop(_state, 1); + return defaultValue; + } + + const std::string rtn = lua_tostring(_state, -1); + lua_pop(_state, 1); + return rtn; +} + +float LUA::getValueFloatFromTable(const char * key, float defaultValue) { + checkStack(); + lua_getfield(_state, -1, key); + if (lua_isnil(_state, -1)) { + lua_pop(_state, 1); + return defaultValue; + } + + const float rtn = static_cast(lua_tonumber(_state, -1)); + lua_pop(_state, 1); + return rtn; +} + +int LUA::getValueIntegerFromTable(const char * key, int defaultValue) { + checkStack(); + lua_getfield(_state, -1, key); + if (lua_isnil(_state, -1)) { + lua_pop(_state, 1); + return defaultValue; + } + + const int rtn = static_cast(lua_tointeger(_state, -1)); + lua_pop(_state, 1); + return rtn; +} + +/** + * @param[in] function function to be called + */ +bool LUA::execute(const std::string &function, int returnValues) { + lua_getglobal(_state, function.c_str()); + const int ret = lua_pcall(_state, 0, returnValues, 0); + if (ret != 0) { + setError(lua_tostring(_state, -1)); + return false; + } + + return true; +} + +std::string LUA::stackDump(lua_State *L) { +#ifdef DEBUG + StackChecker check(L); +#endif + std::stringstream ss; + const int top = lua_gettop(L); + for (int i = 1; i <= top; i++) { /* repeat for each level */ + const int t = lua_type(L, i); + ss << i << ": "; + switch (t) { + case LUA_TSTRING: + ss << lua_typename(L, t) << ": '" << lua_tostring(L, i) << "'"; + break; + + case LUA_TBOOLEAN: + ss << lua_typename(L, t) << ": '" << (lua_toboolean(L, i) ? "true" : "false") << "'"; + break; + + case LUA_TNUMBER: + ss << lua_typename(L, t) << ": '" << lua_tonumber(L, i) << "'"; + break; + + case LUA_TUSERDATA: + ss << lua_typename(L, t) << ": '" << lua_touserdata(L, i) << "'"; + break; + + case LUA_TLIGHTUSERDATA: + ss << lua_typename(L, t) << ": '" << lua_touserdata(L, i) << "'"; + break; + + case LUA_TTABLE: + ss << lua_typename(L, t) << ": '...'"; + break; + + case LUA_TFUNCTION: + ss << lua_typename(L, t) << ": '...'"; + break; + + case LUA_TTHREAD: + ss << lua_typename(L, t) << ": '...'"; + break; + + default: + ss << lua_typename(L, t); + break; + } + ss << std::endl; + } + + return ss.str(); +} + +std::string LUA::stackDump() { + return stackDump(_state); +} + +std::string LUA::getStringFromStack() { + const char* id = lua_tostring(_state, -1); + pop(); + if (id == nullptr) + return ""; + return id; +} + +std::string LUA::getString(const std::string& expr, const std::string& defaultValue) { + checkStack(); + const char* r = defaultValue.c_str(); + /* Assign the Lua expression to a Lua global variable. */ + const std::string buf("evalExpr=" + expr); + if (!luaL_dostring(_state, buf.c_str())) { + /* Get the value of the global variable */ + lua_getglobal(_state, "evalExpr"); + if (lua_isstring(_state, -1)) + r = lua_tostring(_state, -1); + else if (lua_isboolean(_state, -1)) + r = lua_toboolean(_state, -1) ? "true" : "false"; + /* remove lua_getglobal value */ + lua_pop(_state, 1); + } + return r; +} + +void LUA::getKeyValueMap(std::map& map, const char *key) { + checkStack(); + lua_getglobal(_state, key); + lua_pushnil(_state); + + while (lua_next(_state, -2) != 0) { + const char *_key = lua_tostring(_state, -2); + assert(_key); + std::string _value; + if (lua_isstring(_state, -1)) { + _value = lua_tostring(_state, -1); + } else if (lua_isnumber(_state, -1)) { + std::stringstream ss; + ss << lua_tonumber(_state, -1); + _value = ss.str(); + } else if (lua_isboolean(_state, -1)) { + _value = lua_toboolean(_state, -1) ? "true" : "false"; + } + map[_key] = _value; + lua_pop(_state, 1); + } + + lua_pop(_state, 1); +} + +int LUA::getIntValue(const std::string& path, int defaultValue) { + const std::string& str = getString(path); + if (str.empty()) + return defaultValue; + return atoi(str.c_str()); +} + +float LUA::getFloatValue(const std::string& path, float defaultValue) { + const std::string& str = getString(path); + if (str.empty()) + return defaultValue; + return static_cast(atof(str.c_str())); +} + +void LUA::getGlobalKeyValue(const std::string& name) { + lua_getglobal(_state, name.c_str()); + lua_pushnil(_state); +} + +int LUA::getTable(const std::string& name) { + lua_getfield(_state, -1, name.c_str()); + return static_cast(lua_rawlen(_state, -1)); +} + +std::string LUA::getTableString(int i) { + checkStack(); + lua_rawgeti(_state, -1, i); + const std::string str = lua_tostring(_state, -1); + pop(); + return str; +} + +int LUA::getTableInteger(int i) { + lua_rawgeti(_state, -1, i); + const int val = static_cast(lua_tointeger(_state, -1)); + pop(); + return val; +} + +float LUA::getTableFloat(int i) { + lua_rawgeti(_state, -1, i); + const float val = static_cast(lua_tonumber(_state, -1)); + pop(); + return val; +} + +std::string LUA::getKey() { + return lua_tostring(_state, -2); +} + +void LUA::pop(int amount) { + lua_pop(_state, amount); +} + +bool LUA::getNextKeyValue() { + return lua_next(_state, -2) != 0; +} + +void LUA::getGlobal(const std::string& name) { + lua_getglobal(_state, name.c_str()); +} + +} diff --git a/src/modules/commonlua/LUA.h b/src/modules/commonlua/LUA.h new file mode 100644 index 000000000..675375d6b --- /dev/null +++ b/src/modules/commonlua/LUA.h @@ -0,0 +1,142 @@ +#pragma once +extern "C" { +#include +#include +#include +} +#include +#include +#include +#include + +namespace lua { + +namespace { +const std::string META_PREFIX = "META_"; +} + +class LUAType { +private: + lua_State* _state; +public: + LUAType(lua_State* state, const std::string& name); + virtual ~LUAType() { + } + + void addFunction(const std::string& name, lua_CFunction func); +}; + +class LUA { +private: + lua_State *_state; + std::string _error; + +public: + LUA(bool debug = false); + ~LUA(); + + inline lua_State* getState() const; + + template + static void newGlobalData(lua_State *L, const std::string& prefix, T *userData) { + lua_pushlightuserdata(L, userData); + lua_setglobal(L, prefix.c_str()); + } + + template + inline void newGlobalData(const std::string& prefix, T *userData) const { + newGlobalData(_state, prefix, userData); + } + + template + static T* getGlobalData(lua_State *L, const std::string& prefix) { + lua_getglobal(L, prefix.c_str()); + T* data = (T*) lua_touserdata(L, -1); + lua_pop(L, 1); + return data; + } + + template + inline T* getGlobalData(const std::string& prefix) const { + return getGlobalData(_state, prefix); + } + + template + static T** newUserdata(lua_State *L, const std::string& prefix) { + T ** udata = (T **) lua_newuserdata(L, sizeof(T *)); + const std::string name = META_PREFIX + prefix; + luaL_getmetatable(L, name.c_str()); + lua_setmetatable(L, -2); + return udata; + } + + template + static T* getUserData(lua_State *L, int n, const std::string& prefix) { + const std::string name = META_PREFIX + prefix; + return *(T **) luaL_checkudata(L, n, name.c_str()); + } + + static void returnError(lua_State *L, const std::string& error) { + std::cerr << "LUA error: " << error << std::endl; + luaL_error(L, "%s", error.c_str()); + } + + void getGlobal(const std::string& name); + + std::string getKey(); + + void getGlobalKeyValue(const std::string& name); + + bool getNextKeyValue(); + + void pop(int amount = 1); + + int getTable(const std::string& name); + + std::string getTableString(int i); + + int getTableInteger(int i); + + float getTableFloat(int i); + + void reg(const std::string& prefix, luaL_Reg* funcs); + LUAType registerType(const std::string& name); + + void setError(const std::string& error); + const std::string& getError() const; + bool load(const std::string &file); + /** + * @param[in] function function to be called + */ + bool execute(const std::string &function, int returnValues = 0); + + std::string getValueStringFromTable(const char * key, const std::string& defaultValue = ""); + float getValueFloatFromTable(const char * key, float defaultValue = 0.0f); + int getValueIntegerFromTable(const char * key, int defaultValue = 0); + bool getValueBoolFromTable(const char * key, bool defaultValue = false); + void getKeyValueMap(std::map& map, const char *key); + + int getIntValue(const std::string& xpath, int defaultValue = 0); + float getFloatValue(const std::string& path, float defaultValue = 0.0f); + std::string getStringFromStack(); + std::string getString(const std::string& expr, const std::string& defaultValue = ""); + + static std::string stackDump(lua_State *L); + std::string stackDump(); +}; + +inline lua_State* LUA::getState() const { + return _state; +} + +inline void LUA::setError(const std::string& error) { + _error = error; +} + +inline const std::string& LUA::getError() const { + return _error; +} + +typedef std::shared_ptr LUAPtr; + +} diff --git a/src/modules/commonlua/tests/LUATest.cpp b/src/modules/commonlua/tests/LUATest.cpp new file mode 100644 index 000000000..629681452 --- /dev/null +++ b/src/modules/commonlua/tests/LUATest.cpp @@ -0,0 +1,9 @@ +#include +#include "commonlua/LUA.h" + +namespace lua { + +TEST(LUA, testVoid) { +} + +} diff --git a/src/modules/cooldown/CMakeLists.txt b/src/modules/cooldown/CMakeLists.txt new file mode 100644 index 000000000..c5a74d762 --- /dev/null +++ b/src/modules/cooldown/CMakeLists.txt @@ -0,0 +1,16 @@ +fips_begin_module(cooldown) + fips_files( + CooldownMgr.h CooldownMgr.cpp + CooldownType.h + CooldownTriggerState.h + ) + fips_deps(core) +fips_end_module() + +begin_googleunittest(cooldown) + fips_dir(tests) + fips_files( + CooldownMgrTest.cpp + ) + fips_deps(cooldown) +end_googleunittest() diff --git a/src/modules/cooldown/Cooldown.h b/src/modules/cooldown/Cooldown.h new file mode 100644 index 000000000..c9b05fb2d --- /dev/null +++ b/src/modules/cooldown/Cooldown.h @@ -0,0 +1,81 @@ +#pragma once + +#include "core/TimeProvider.h" +#include "CooldownType.h" +#include "CooldownTriggerState.h" + +#include + +namespace cooldown { + +class Cooldown { +private: + CooldownType _type; + unsigned long _durationMillis; + unsigned long _startMillis; + unsigned long _expireMillis; + core::TimeProviderPtr _timeProvider; + +public: + Cooldown(CooldownType type, unsigned long durationMillis, const core::TimeProviderPtr& timeProvider) : + _type(type), _durationMillis(durationMillis), _startMillis(0ul), _expireMillis(0ul), _timeProvider(timeProvider) { + } + + inline void start() { + _startMillis = _timeProvider->tickTime(); + _expireMillis = _startMillis + _durationMillis; + } + + inline void reset() { + _startMillis = 0ul; + _expireMillis = 0ul; + } + + inline void expire() { + reset(); + } + + inline void cancel() { + reset(); + } + + unsigned long durationMillis() const { + return _durationMillis; + } + + inline bool started() const { + return _expireMillis > 0ul; + } + + inline bool running() const { + return _expireMillis > 0ul && _timeProvider->tickTime() < _expireMillis; + } + + inline unsigned long duration() const { + return _expireMillis - _startMillis; + } + + inline unsigned long startMillis() const { + return _startMillis; + } + + inline CooldownType type() const { + return _type; + } + + inline bool operator<(const Cooldown& rhs) const { + return _expireMillis < rhs._expireMillis; + } +}; + +typedef std::shared_ptr CooldownPtr; + +} + +namespace std { +template<> struct hash { + inline size_t operator()(const cooldown::Cooldown &c) const { + return std::hash()(static_cast(c.type())); + } +}; +} diff --git a/src/modules/cooldown/CooldownMgr.cpp b/src/modules/cooldown/CooldownMgr.cpp new file mode 100644 index 000000000..c3ce23f49 --- /dev/null +++ b/src/modules/cooldown/CooldownMgr.cpp @@ -0,0 +1,97 @@ +#include "CooldownMgr.h" +#include "core/Common.h" + +namespace cooldown { + +namespace { +unsigned long durations[] = { + 0ul, + 15000ul, + 10000ul, + 100ul +}; +CASSERT(lengthof(durations) == CooldownType::MAX); +} + +CooldownMgr::CooldownMgr(const core::TimeProviderPtr& timeProvider) : + _timeProvider(timeProvider), _lock("CooldownMgr") { +} + +CooldownTriggerState CooldownMgr::triggerCooldown(CooldownType type) { + core::ScopedWriteLock lock(_lock); + CooldownPtr cooldown = _cooldowns[type]; + if (!cooldown) { + cooldown = CooldownPtr(new Cooldown(type, defaultDuration(type), _timeProvider)); + _cooldowns[type] = cooldown; + } else if (cooldown->running()) { + Log::error("Failed to trigger the cooldown of type %i: already running", type); + return CooldownTriggerState::ALREADY_RUNNING; + } + cooldown->start(); + _queue.push(cooldown); + Log::debug("Triggered the cooldown of type %i (expires in %lims, started at %li)", + type, cooldown->duration(), cooldown->startMillis()); + return CooldownTriggerState::SUCCESS; +} + +CooldownPtr CooldownMgr::cooldown(CooldownType type) const { + core::ScopedReadLock lock(_lock); + auto i = _cooldowns.find(type); + if (i == _cooldowns.end()) + return CooldownPtr(); + return i->second; +} + +unsigned long CooldownMgr::defaultDuration(CooldownType type) const { + return durations[type]; +} + +bool CooldownMgr::resetCooldown(CooldownType type) { + const CooldownPtr& c = cooldown(type); + if (!c) { + return false; + } + c->reset(); + return true; +} + +bool CooldownMgr::cancelCooldown(CooldownType type) { + const CooldownPtr& c = cooldown(type); + if (!c) { + return false; + } + c->cancel(); + return true; +} + +bool CooldownMgr::isCooldown(CooldownType type) { + const CooldownPtr& c = cooldown(type); + if (!c || !c->running()) { + Log::trace("Cooldown of type %i is not running", type); + return false; + } + Log::debug("Cooldown of type %i is running and has a runtime of %lims", type, c->duration()); + return true; +} + +void CooldownMgr::update() { + for (;;) { + _lock.lockRead(); + if (_queue.empty()) { + _lock.unlockRead(); + break; + } + CooldownPtr cooldown = _queue.top(); + _lock.unlockRead(); + if (cooldown->running()) { + break; + } + + _lock.lockWrite(); + _queue.pop(); + _lock.unlockWrite(); + Log::debug("Cooldown of type %i has just expired at %li", cooldown->type(), _timeProvider->tickTime()); + cooldown->expire(); + } +} +} diff --git a/src/modules/cooldown/CooldownMgr.h b/src/modules/cooldown/CooldownMgr.h new file mode 100644 index 000000000..067fad129 --- /dev/null +++ b/src/modules/cooldown/CooldownMgr.h @@ -0,0 +1,69 @@ +#pragma once + +#include "core/ReadWriteLock.h" +#include "Cooldown.h" +#include "core/NonCopyable.h" +#include "core/TimeProvider.h" +#include "core/ReadWriteLock.h" + +#include +#include +#include +#include +#include + +namespace cooldown { + +/** + * @brief Cooldown manager that handles cooldowns for one entity + */ +class CooldownMgr: public core::NonCopyable { +private: + core::TimeProviderPtr _timeProvider; + core::ReadWriteLock _lock; + + struct CooldownComparatorLess: public std::binary_function { + inline bool operator()(const CooldownPtr x, const CooldownPtr y) const { + return std::less()(*x.get(), *y.get()); + } + }; + + typedef std::priority_queue, CooldownComparatorLess> CooldownQueue; + CooldownQueue _queue; + typedef std::unordered_map Cooldowns; + Cooldowns _cooldowns; +public: + CooldownMgr(const core::TimeProviderPtr& timeProvider); + + /** + * @brief Tries to trigger the specified cooldown for the given entity + */ + CooldownTriggerState triggerCooldown(CooldownType type); + + /** + * @brief Reset a cooldown and restart it + */ + bool resetCooldown(CooldownType type); + + unsigned long defaultDuration(CooldownType type) const; + CooldownPtr cooldown(CooldownType type) const; + + /** + * @brief Cancel an already running cooldown + */ + bool cancelCooldown(CooldownType type); + + /** + * @brief Checks whether a user has the given cooldown running + */ + bool isCooldown(CooldownType type); + + /** + * @brief Update cooldown states + */ + void update(); +}; + +typedef std::shared_ptr CooldownMgrPtr; + +} diff --git a/src/modules/cooldown/CooldownTriggerState.h b/src/modules/cooldown/CooldownTriggerState.h new file mode 100644 index 000000000..30e3028fc --- /dev/null +++ b/src/modules/cooldown/CooldownTriggerState.h @@ -0,0 +1,9 @@ +#pragma once + +namespace cooldown { + +enum CooldownTriggerState { + SUCCESS, ALREADY_RUNNING +}; + +} diff --git a/src/modules/cooldown/CooldownType.h b/src/modules/cooldown/CooldownType.h new file mode 100644 index 000000000..36a484aa9 --- /dev/null +++ b/src/modules/cooldown/CooldownType.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +namespace cooldown { + +enum CooldownType { + NONE, + // the cooldown for increasing the population + INCREASE, + // defines the delay between hunts + HUNT, + // the cooldown for removing a disconnected user from the server + LOGOUT, + + MAX +}; + +} + +namespace std { +template<> struct hash { + inline size_t operator()(const cooldown::CooldownType &c) const { + return std::hash()(static_cast(c)); + } +}; +} diff --git a/src/modules/cooldown/tests/CooldownMgrTest.cpp b/src/modules/cooldown/tests/CooldownMgrTest.cpp new file mode 100644 index 000000000..885764692 --- /dev/null +++ b/src/modules/cooldown/tests/CooldownMgrTest.cpp @@ -0,0 +1,74 @@ +#include +#include "cooldown/CooldownMgr.h" + +namespace cooldown { + +namespace { +const core::TimeProviderPtr& timeProvider = std::make_shared(); +} + +TEST(CooldownMgr, testTriggerCooldown) { + CooldownMgr mgr(timeProvider); + ASSERT_EQ(CooldownTriggerState::SUCCESS, mgr.triggerCooldown(CooldownType::LOGOUT)) << "Logout cooldown couldn't get triggered"; +} + +TEST(CooldownMgr, testCancelCooldown) { + CooldownMgr mgr(timeProvider); + ASSERT_EQ(CooldownTriggerState::SUCCESS, mgr.triggerCooldown(CooldownType::LOGOUT)) << "Logout cooldown couldn't get triggered"; + ASSERT_TRUE(mgr.cancelCooldown(CooldownType::LOGOUT)) << "Failed to cancel the logout cooldown"; +} + +TEST(CooldownMgr, testExpireCooldown) { + CooldownMgr mgr(timeProvider); + timeProvider->update(0ul); + ASSERT_EQ(CooldownTriggerState::SUCCESS, mgr.triggerCooldown(CooldownType::LOGOUT)) << "Logout cooldown couldn't get triggered"; + ASSERT_EQ(mgr.defaultDuration(CooldownType::LOGOUT), mgr.cooldown(CooldownType::LOGOUT)->durationMillis()); + ASSERT_EQ(mgr.defaultDuration(CooldownType::LOGOUT), mgr.cooldown(CooldownType::LOGOUT)->duration()); + ASSERT_TRUE(mgr.cooldown(CooldownType::LOGOUT)->started()) << "Cooldown is not started"; + ASSERT_TRUE(mgr.cooldown(CooldownType::LOGOUT)->running()) << "Cooldown is not running"; + ASSERT_TRUE(mgr.isCooldown(CooldownType::LOGOUT)); + mgr.update(); + ASSERT_TRUE(mgr.cooldown(CooldownType::LOGOUT)->started()) << "Cooldown is not started"; + ASSERT_TRUE(mgr.cooldown(CooldownType::LOGOUT)->running()) << "Cooldown is not running"; + ASSERT_TRUE(mgr.isCooldown(CooldownType::LOGOUT)); + timeProvider->update(mgr.defaultDuration(CooldownType::LOGOUT)); + ASSERT_FALSE(mgr.isCooldown(CooldownType::LOGOUT)); + mgr.update(); + ASSERT_FALSE(mgr.cooldown(CooldownType::LOGOUT)->running()) << "Cooldown is still running"; + ASSERT_FALSE(mgr.isCooldown(CooldownType::LOGOUT)); + ASSERT_TRUE(mgr.resetCooldown(CooldownType::LOGOUT)) << "Failed to reset the logout cooldown"; +} + +TEST(CooldownMgr, testMultipleCooldown) { + CooldownMgr mgr(timeProvider); + + timeProvider->update(0ul); + ASSERT_EQ(CooldownTriggerState::SUCCESS, mgr.triggerCooldown(CooldownType::LOGOUT)) << "Logout cooldown couldn't get triggered"; + ASSERT_EQ(CooldownTriggerState::SUCCESS, mgr.triggerCooldown(CooldownType::INCREASE)) << "Increase cooldown couldn't get triggered"; + ASSERT_TRUE(mgr.isCooldown(CooldownType::LOGOUT)); + ASSERT_TRUE(mgr.isCooldown(CooldownType::INCREASE)); + mgr.update(); + + const unsigned long logoutDuration = mgr.defaultDuration(CooldownType::LOGOUT); + const unsigned long increaseDuration = mgr.defaultDuration(CooldownType::INCREASE); + + if (logoutDuration > increaseDuration) { + timeProvider->update(increaseDuration); + mgr.update(); + ASSERT_TRUE(mgr.isCooldown(CooldownType::LOGOUT)); + ASSERT_FALSE(mgr.isCooldown(CooldownType::INCREASE)); + } else { + timeProvider->update(logoutDuration); + mgr.update(); + ASSERT_TRUE(mgr.isCooldown(CooldownType::INCREASE)); + ASSERT_FALSE(mgr.isCooldown(CooldownType::LOGOUT)); + } +} + +TEST(CooldownMgr, testTriggerCooldownTwice) { + CooldownMgr mgr(timeProvider); + ASSERT_EQ(CooldownTriggerState::SUCCESS, mgr.triggerCooldown(CooldownType::LOGOUT)) << "Logout cooldown couldn't get triggered"; + ASSERT_EQ(CooldownTriggerState::ALREADY_RUNNING, mgr.triggerCooldown(CooldownType::LOGOUT)) << "Logout cooldown was triggered twice"; +} + +} diff --git a/src/modules/core/AbstractModule.h b/src/modules/core/AbstractModule.h new file mode 100644 index 000000000..dda0bbf1a --- /dev/null +++ b/src/modules/core/AbstractModule.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include "core/TimeProvider.h" +#include "core/EventBus.h" +#include "io/Filesystem.h" + +namespace core { + +class AbstractModule: public sauce::AbstractModule { +protected: + void configure() const override { + bind().in().to(); + bind().in().to(); + bind().in().to(); + } +}; + +} diff --git a/src/modules/core/App.cpp b/src/modules/core/App.cpp new file mode 100644 index 000000000..2691a6344 --- /dev/null +++ b/src/modules/core/App.cpp @@ -0,0 +1,196 @@ +#include "App.h" +#include "Var.h" +#include "Command.h" +#include "Log.h" +#include "Tokenizer.h" +#include +#include + +namespace core { + +App* App::_staticInstance; + +App::App(const io::FilesystemPtr& filesystem, const core::EventBusPtr& eventBus, uint16_t traceport) : + _argc(0), _argv(nullptr), _trace(traceport), _curState(AppState::Construct), _nextState(AppState::InvalidAppState), _suspendRequested(false), _deltaFrame(0L), _initTime(0L), _filesystem(filesystem), _eventBus(eventBus) { + _now = currentMillis(); + _staticInstance = this; +} + +App::~App() { +} + +void App::init(const std::string& organisation, const std::string& appname) { + _organisation = organisation; + _appname = appname; +} + +void App::startMainLoop(int argc, char *argv[]) { + _argc = argc; + _argv = argv; + + while (AppState::InvalidAppState != _curState) { + core_trace_scoped("AppMainLoop"); + onFrame(); + } +} + +void App::addBlocker(AppState blockedState) { + _blockers.insert(blockedState); +} + +void App::remBlocker(AppState blockedState) { + _blockers.erase(blockedState); +} + +void App::onFrame() { + if ((_nextState != AppState::InvalidAppState) && (_nextState != _curState)) { + if (_blockers.find(_nextState) != _blockers.end()) { + if (AppState::Blocked != _curState) { + _curState = AppState::Blocked; + } + } else { + _curState = _nextState; + _nextState = AppState::InvalidAppState; + } + } + + if (AppState::Blocked == _curState) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } else { + const long now = currentMillis(); + _deltaFrame = now - _now; + _now = now; + + switch (_curState) { + case AppState::Construct: + _nextState = onConstruct(); + break; + case AppState::Init: + _nextState = onInit(); + break; + case AppState::Running: + onBeforeRunning(); + _nextState = onRunning(); + if (AppState::Running == _nextState) + onAfterRunning(); + break; + case AppState::Cleanup: + _nextState = onCleanup(); + break; + case AppState::Destroy: + _nextState = onDestroy(); + _curState = AppState::InvalidAppState; + break; + default: + break; + } + } +} + +AppState App::onConstruct() { + _filesystem->init(_organisation, _appname); + + core::Command::registerCommand("set", [] (const core::CmdArgs& args) { + if (args.size() != 2) + return; + core::Var::get(args[0])->setVal(args[1]); + }); + // show a specific variable + core::Command::registerCommand("show", [] (const core::CmdArgs& args) { + if (args.size() != 1) + return; + VarPtr st = core::Var::get(args[0]); + Log::info(" -> %s ",st->strVal().c_str()); + }); + + return AppState::Init; +} + +AppState App::onInit() { + _initTime = _now; + + const std::string& content = _filesystem->load(_appname + ".vars"); + core::Tokenizer t(content); + while (t.hasNext()) { + const std::string& name = t.next(); + if (!t.hasNext()) + break; + const std::string& value = t.next(); + core::Var::get(name)->setVal(value); + } + + Log::trace("handle %i command line arguments", _argc); + for (int i = 0; i < _argc; ++i) { + // every command is started with a '-' + if (_argv[i][0] != '-') + continue; + + const std::string command = &_argv[i][1]; + CmdArgs args; + for (++i; i < _argc;) { + if (_argv[i][0] == '-') { + --i; + break; + } + args.push_back(_argv[i++]); + } + Log::trace("Execute %s with %i arguments", command.c_str(), (int)args.size()); + core::Command::execute(command, args); + } + return AppState::Running; +} + +void App::onAfterRunning() { +} + +void App::onBeforeRunning() { +} + +AppState App::onRunning() { + return AppState::Cleanup; +} + +AppState App::onCleanup() { + if (_suspendRequested) { + addBlocker(AppState::Init); + return AppState::Init; + } + + if (!_organisation.empty() && !_appname.empty()) { + Log::debug("save the config variables"); + std::stringstream ss; + core::Var::visit([&](const core::VarPtr& var) { + if (var->getFlags() & core::CV_NOPERSIST) + return; + ss << var->name() << " \"" << var->strVal() << "\"" << std::endl; + }); + const std::string& str = ss.str(); + _filesystem->write(_appname + ".vars", str); + } else { + Log::warn("don't save the config variables"); + } + return AppState::Destroy; +} + +AppState App::onDestroy() { + return AppState::InvalidAppState; +} + +void App::readyForInit() { + remBlocker(AppState::Init); +} + +void App::requestQuit() { + if (AppState::Running == _curState) { + _nextState = AppState::Cleanup; + } else { + _nextState = AppState::Destroy; + } +} + +void App::requestSuspend() { + _nextState = AppState::Cleanup; + _suspendRequested = true; +} + +} diff --git a/src/modules/core/App.h b/src/modules/core/App.h new file mode 100644 index 000000000..d95b0a24d --- /dev/null +++ b/src/modules/core/App.h @@ -0,0 +1,93 @@ +#pragma once + +#include +#include +#include "Trace.h" +#include "EventBus.h" +#include "io/Filesystem.h" + +namespace core { + +enum AppState { + Construct, Init, Running, Cleanup, Destroy, Blocked, NumAppStates, InvalidAppState, +}; + +class App { +private: + //std::streambuf* _oldOut; + //std::streambuf* _oldErr; + +protected: + int _argc; + char **_argv; + + std::string _organisation; + std::string _appname; + + Trace _trace; + AppState _curState; + AppState _nextState; + std::unordered_set > _blockers; + bool _suspendRequested; + long _now; + long _deltaFrame; + long _initTime; + io::FilesystemPtr _filesystem; + core::EventBusPtr _eventBus; + static App* _staticInstance; + +public: + App(const io::FilesystemPtr& filesystem, const core::EventBusPtr& eventBus, uint16_t traceport); + virtual ~App(); + + void init(const std::string& organisation, const std::string& appname); + void startMainLoop(int argc, char *argv[]); + + // e.g. register your commands here + virtual AppState onConstruct(); + // evaluates the command line parameters that the application was started with. Make sure your commands are already registered + virtual AppState onInit(); + virtual void onBeforeRunning(); + // called every frame after the initalization was done + virtual AppState onRunning(); + virtual void onAfterRunning(); + virtual AppState onCleanup(); + virtual AppState onDestroy(); + + void addBlocker(AppState blockedState); + void remBlocker(AppState blockedState); + + // handle the app state changes here + virtual void onFrame(); + void readyForInit(); + void requestQuit(); + void requestSuspend(); + + /** + * @return the millis since the epoch + */ + long currentMillis() const; + + io::FilesystemPtr filesystem() const; + + core::EventBusPtr eventBus() const; + + static App* getInstance() { + core_assert(_staticInstance != nullptr); + return _staticInstance; + } +}; + +inline long App::currentMillis() const { + return static_cast(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); +} + +inline io::FilesystemPtr App::filesystem() const { + return _filesystem; +} + +inline core::EventBusPtr App::eventBus() const { + return _eventBus; +} + +} diff --git a/src/modules/core/ByteStream.cpp b/src/modules/core/ByteStream.cpp new file mode 100644 index 000000000..c730f32cf --- /dev/null +++ b/src/modules/core/ByteStream.cpp @@ -0,0 +1,114 @@ +#include "ByteStream.h" +#include + +namespace core { + +ByteStream::ByteStream(int size) : + _buffer(size), _pos(0) { +} + +ByteStream::~ByteStream() { + _buffer.clear(); +} + +int32_t ByteStream::peekInt() const { + const int l = 4; + if (size() < l) + return -1; + uint8_t buf[l]; + VectorBuffer::const_iterator it = begin(); + for (int i = 0; i < l; ++i) { + buf[i] = *it++; + } + const int32_t *word = (const int32_t*) (void*) buf; + const int32_t val = SDL_SwapLE32(*word); + return val; +} + +int16_t ByteStream::peekShort() const { + const int l = 2; + if (size() < l) + return -1; + uint8_t buf[l]; + VectorBuffer::const_iterator it = begin(); + for (int i = 0; i < l; ++i) { + buf[i] = *it++; + } + const int16_t *word = reinterpret_cast(buf); + const int16_t val = SDL_SwapLE16(*word); + return val; +} + +void ByteStream::addFormat(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + + while (*fmt) { + const char typeID = *fmt++; + switch (typeID) { + case 'b': + addByte((uint8_t) va_arg(ap, int)); + break; + case 's': + addShort((uint16_t) va_arg(ap, int)); + break; + case 'i': + addInt((uint32_t) va_arg(ap, int)); + break; + case 'l': + addLong((uint64_t) va_arg(ap, long)); + break; + default: + core_assert(false); + } + } + + va_end(ap); +} + +void ByteStream::readFormat(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + + while (*fmt) { + const char typeID = *fmt++; + switch (typeID) { + case 'b': + *va_arg(ap, int *) = readByte(); + break; + case 's': + *va_arg(ap, int *) = readShort(); + break; + case 'i': + *va_arg(ap, int *) = readInt(); + break; + case 'l': + *va_arg(ap, long *) = readLong(); + break; + default: + core_assert(false); + } + } + + va_end(ap); +} + +std::string ByteStream::readString() { + int size = 0; + std::string strbuff; + strbuff.reserve(64); + for (;;) { + const char chr = *std::next(begin(), size); + ++size; + core_assert(size <= this->size()); + if (chr == '\0') + break; + strbuff += chr; + } + _pos += size; + return strbuff; +} + +} diff --git a/src/modules/core/ByteStream.h b/src/modules/core/ByteStream.h new file mode 100644 index 000000000..b56877ff7 --- /dev/null +++ b/src/modules/core/ByteStream.h @@ -0,0 +1,239 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include "Common.h" + +namespace core { + +#define BYTE_MASK 0XFF +#define WORD_MASK 0XFFFF + +class ByteStream { +private: + typedef std::vector VectorBuffer; + VectorBuffer _buffer; + int _pos; + + inline int size() const { + return _buffer.size() - _pos; + } + + inline VectorBuffer::const_iterator begin() const { + return _buffer.begin() + _pos; + } + + inline VectorBuffer::iterator begin() { + return _buffer.begin() + _pos; + } + +public: + ByteStream(int size = 0); + virtual ~ByteStream(); + + void addBool(bool value, bool prepend = false); + void addByte(uint8_t byte, bool prepend = false); + void addShort(int16_t word, bool prepend = false); + void addInt(int32_t dword); + void addLong(int64_t dword); + void addFloat(float value); + void addString(const std::string& string); + void addFormat(const char *fmt, ...); + + bool readBool(); + uint8_t readByte(); + int16_t readShort(); + int32_t readInt(); + int64_t readLong(); + float readFloat(); + std::string readString(); + void readFormat(const char *fmt, ...); + + int32_t peekInt() const; + int16_t peekShort() const; + + // get the raw data pointer for the buffer + const uint8_t* getBuffer() const; + + void append(const uint8_t *buf, size_t size); + + bool empty() const; + + // clear the buffer if it's no longer needed + void clear(); + + // return the amount of bytes in the buffer + size_t getSize() const; + + void resize(size_t size); + + ByteStream &operator<<(const uint8_t &x) { + addByte(x, false); + return *this; + } + + ByteStream &operator<<(const int16_t &x) { + addShort(x); + return *this; + } + + ByteStream &operator<<(const bool &x) { + addBool(x); + return *this; + } + + ByteStream &operator<<(const int32_t &x) { + addInt(x); + return *this; + } + + ByteStream &operator<<(const float &x) { + addFloat(x); + return *this; + } + + ByteStream &operator<<(const std::string &x) { + addString(x); + return *this; + } +}; + +inline bool ByteStream::empty() const { + return size() <= 0; +} + +inline void ByteStream::resize(size_t size) { + _buffer.resize(size); +} + +inline void ByteStream::append(const uint8_t *buf, size_t size) { + // TODO: optimize + for (std::size_t i = 0; i < size; ++i) { + addByte(buf[i]); + } +} + +inline const uint8_t* ByteStream::getBuffer() const { + return &_buffer[0] + _pos; +} + +inline void ByteStream::clear() { + _buffer.clear(); +} + +inline size_t ByteStream::getSize() const { + return _buffer.size() - _pos; +} + +inline void ByteStream::addByte(uint8_t byte, bool prepend) { + if (prepend) { + _buffer.insert(_buffer.begin(), byte); + } else { + _buffer.push_back(byte); + } +} + +inline void ByteStream::addBool(bool value, bool prepend) { + addByte(value, prepend); +} + +inline void ByteStream::addString(const std::string& string) { + const size_t length = string.length(); + for (std::size_t i = 0; i < length; i++) { + addByte(uint8_t(string[i])); + } + addByte(uint8_t('\0')); +} + +inline void ByteStream::addShort(int16_t word, bool prepend) { + const int16_t swappedWord = SDL_SwapLE16(word); + if (prepend) { + _buffer.insert(_buffer.begin(), uint8_t(swappedWord >> CHAR_BIT)); + _buffer.insert(_buffer.begin(), uint8_t(swappedWord)); + } else { + _buffer.push_back(uint8_t(swappedWord)); + _buffer.push_back(uint8_t(swappedWord >> CHAR_BIT)); + } +} + +inline void ByteStream::addInt(int32_t dword) { + int32_t swappedDWord = SDL_SwapLE32(dword); + _buffer.push_back(uint8_t(swappedDWord)); + _buffer.push_back(uint8_t(swappedDWord >>= CHAR_BIT)); + _buffer.push_back(uint8_t(swappedDWord >>= CHAR_BIT)); + _buffer.push_back(uint8_t(swappedDWord >> CHAR_BIT)); +} + +inline void ByteStream::addLong(int64_t dword) { + int64_t swappedDWord = SDL_SwapLE64(dword); + _buffer.push_back(uint8_t(swappedDWord)); + _buffer.push_back(uint8_t(swappedDWord >>= CHAR_BIT)); + _buffer.push_back(uint8_t(swappedDWord >>= CHAR_BIT)); + _buffer.push_back(uint8_t(swappedDWord >>= CHAR_BIT)); + _buffer.push_back(uint8_t(swappedDWord >>= CHAR_BIT)); + _buffer.push_back(uint8_t(swappedDWord >>= CHAR_BIT)); + _buffer.push_back(uint8_t(swappedDWord >>= CHAR_BIT)); + _buffer.push_back(uint8_t(swappedDWord >> CHAR_BIT)); +} + +inline void ByteStream::addFloat(float value) { + union toint { + float f; + uint32_t i; + } tmp; + tmp.f = value; + addInt(tmp.i); +} + +inline uint8_t ByteStream::readByte() { + core_assert(size() > 0); + const uint8_t byte = _buffer[_pos]; + ++_pos; + return byte; +} + +inline bool ByteStream::readBool() { + return readByte() != 0; +} + +inline int16_t ByteStream::readShort() { + core_assert(size() >= 2); + const int16_t *word = reinterpret_cast(getBuffer()); + const int16_t val = SDL_SwapLE16(*word); + _pos += 2; + return val; +} + +inline float ByteStream::readFloat() { + union toint { + float f; + uint32_t i; + } tmp; + tmp.i = readInt(); + + return tmp.f; +} + +inline int32_t ByteStream::readInt() { + core_assert(size() >= 4); + const int32_t *word = reinterpret_cast(getBuffer()); + const int32_t val = SDL_SwapLE32(*word); + _pos += 4; + return val; +} + +inline int64_t ByteStream::readLong() { + core_assert(size() >= 8); + const int64_t *word = reinterpret_cast(getBuffer()); + const int64_t val = SDL_SwapLE64(*word); + _pos += 8; + return val; +} + +} diff --git a/src/modules/core/CMakeLists.txt b/src/modules/core/CMakeLists.txt new file mode 100644 index 000000000..e9b0e5840 --- /dev/null +++ b/src/modules/core/CMakeLists.txt @@ -0,0 +1,42 @@ +fips_begin_module(core) + fips_files( + Rect.h + App.cpp App.h + ByteStream.cpp ByteStream.h + Common.h + Command.h Command.cpp + EventBus.h + IFactoryRegistry.h + NonCopyable.h + String.h + Input.h + QuadTree.h + Singleton.h + Set.h + Log.cpp Log.h + Var.cpp Var.h + Trace.h + ThreadPool.h ThreadPool.cpp + Tokenizer.h + TimeProvider.h TimeProvider.cpp + ) + find_package(SDL2 REQUIRED) + include_directories(${SDL2_INCLUDE_DIRS}) + fips_deps(io ${SDL2_LIBRARIES}) +fips_end_module() + +begin_googleunittest(core) + fips_dir(tests) + fips_files( + RectTest.cpp + ByteStreamTest.cpp + ThreadPoolTest.cpp + EventBusTest.cpp + QuadTreeTest.cpp + VarTest.cpp + CommandTest.cpp + SetTest.cpp + TokenizerTest.cpp + ) + fips_deps(core) +end_googleunittest() diff --git a/src/modules/core/Command.cpp b/src/modules/core/Command.cpp new file mode 100644 index 000000000..6d2dfcd1b --- /dev/null +++ b/src/modules/core/Command.cpp @@ -0,0 +1,8 @@ +#include "Command.h" + +namespace core { + +Command::CommandMap Command::_cmds; +ReadWriteLock Command::_lock("Command"); + +} diff --git a/src/modules/core/Command.h b/src/modules/core/Command.h new file mode 100644 index 000000000..2e0e1317a --- /dev/null +++ b/src/modules/core/Command.h @@ -0,0 +1,94 @@ +#pragma once + +#include +#include +#include +#include +#include "String.h" +#include "ReadWriteLock.h" + +namespace core { + +typedef std::vector CmdArgs; + +/** + * @brief A command is a string bound c++ function/method/lambda. You can bind + * this to keys or execute on the console. + */ +class Command { +private: + typedef std::unordered_map CommandMap; + typedef std::function FunctionType; + + static CommandMap _cmds; + static ReadWriteLock _lock; + + std::string _name; + FunctionType _func; + + Command(std::string&& name, FunctionType&& func) : + _name(std::move(name)), _func(std::move(func)) { + } + +public: + static void registerCommand(std::string&& name, FunctionType&& func) { + ScopedWriteLock lock(_lock); + const Command c(std::move(name), std::move(func)); + _cmds.insert(std::make_pair(c.name(), c)); + } + + template + static void registerCommand2(std::string&& name, Function&& func) { + registerCommand(std::move(name), std::bind(std::forward(func))); + } + + static void unregisterCommand(const std::string& name) { + ScopedWriteLock lock(_lock); + _cmds.erase(name); + } + + static int execute(const std::string& command) { + std::vector commands; + core::string::splitString(command, commands, ";"); + int executed = 0; + for (const std::string& c : commands) { + std::vector args; + core::string::splitString(c, args); + if (args.empty()) + continue; + const std::string cmd = core::string::eraseAllSpaces(args[0]); + args.erase(args.begin()); + if (execute(cmd, args)) + ++executed; + } + return executed; + } + + static bool execute(const std::string& command, const CmdArgs& args) { + ScopedReadLock lock(_lock); + auto i = _cmds.find(command); + if (i == _cmds.end()) + return false; + const Command& cmd = i->second; + cmd._func(args); + return true; + } + + inline bool operator==(const Command& rhs) const { + return rhs._name == _name; + } + + inline const std::string& name() const { + return _name; + } +}; + +} + +namespace std { +template<> struct hash { + inline size_t operator()(const core::Command &c) const { + return std::hash()(c.name()); + } +}; +} diff --git a/src/modules/core/Common.h b/src/modules/core/Common.h new file mode 100644 index 000000000..784a0095d --- /dev/null +++ b/src/modules/core/Common.h @@ -0,0 +1,35 @@ +#pragma once + +#include "Log.h" +#include +#include +//#include + +namespace core { + +inline float toRadians(float degree) { + return degree * static_cast(M_PI) / 180.0f; +} + +inline float toDegrees(float radians) { + return radians * 180.0f / static_cast(M_PI); +} + +template +inline T clamp(T a, T low, T high) { + return std::max(low, std::min(a, high)); +} + +} + +#define lengthof(x) (sizeof(x) / sizeof(*(x))) +/** @brief compile time assert */ +#define CASSERT(x) extern int ASSERT_COMPILE[((x) != 0) * 2 - 1] + +#define CORE_STRINGIFY_INTERNAL(x) #x +#define CORE_STRINGIFY(x) CORE_STRINGIFY_INTERNAL(x) + +#ifndef core_assert +//#define core_assert(condition) SDL_assert(condition) +#define core_assert(condition) assert(condition) +#endif diff --git a/src/modules/core/EventBus.h b/src/modules/core/EventBus.h new file mode 100644 index 000000000..bfa068518 --- /dev/null +++ b/src/modules/core/EventBus.h @@ -0,0 +1,202 @@ +#pragma once + +#include +#include +#include +#include +#include +#include "core/ReadWriteLock.h" + +namespace core { + +class IEventBusEvent; + +/** + * @brief The handler will get notified for every published IEventBusEvent that it is registered for. + */ +template +class IEventBusHandler { +private: + friend class EventBus; + void dispatch(const IEventBusEvent& e) { + onEvent(reinterpret_cast(e)); + } +public: + IEventBusHandler() { + static_assert(std::is_base_of::value, "Wrong type given"); + } + + virtual ~IEventBusHandler() { + } + + /** + * @brief Callback for the event. Keep in mind that this can be called from multiple different threads + */ + virtual void onEvent(const T&) = 0; +}; + +/** + * @brief With a topic you can filter your event dispatching to those IEventBusHandler instances that were subscribed with the same topic. + * @see EventBus::subscribe for more details. + */ +class IEventBusTopic { +protected: + const std::type_index _index; + + IEventBusTopic() : + _index(typeid(*this)) { + } +public: + virtual ~IEventBusTopic() { + } + + inline bool operator==(const IEventBusTopic& other) const { + return _index == other._index; + } +}; + +/** + * @brief Base class for all the events that EventBus::publish is publishing + */ +class IEventBusEvent { +protected: + const IEventBusTopic *_topic; + + IEventBusEvent(const IEventBusTopic* const topic = nullptr) : + _topic(topic) { + } +private: + friend class EventBus; + inline const IEventBusTopic* getTopic() const { + return _topic; + } +public: + + virtual ~IEventBusEvent() { + } +}; + +/** + * @brief Generates a new default event without a topic and any state attached + */ +#define EVENTBUSEVENT(name) class name: public IEventBusEvent { public: name() : IEventBusEvent(nullptr) { } } + +class EventBus { +private: + class EventBusHandlerReference; + typedef std::list EventBusHandlerReferences; + typedef std::unordered_map EventBusHandlerReferenceMap; + core::ReadWriteLock _lock; + + class EventBusHandlerReference { + private: + void* const _handler; + const IEventBusTopic *_topic; + + public: + EventBusHandlerReference(void* handler, const IEventBusTopic* topic) : + _handler(handler), _topic(topic) { + } + + inline IEventBusHandler* getHandler() const { + return static_cast*>(_handler); + } + + inline const IEventBusTopic* getTopic() const { + return _topic; + } + }; + + EventBusHandlerReferenceMap _handlers; + +public: + EventBus() : + _lock("EventBus") { + } + + /** + * @brief Subscribe a handler with the ability to filter by the given IEventBusTopic + * @param[in,out] handler The IEventBusHandler to subscribe + * @param[in] topic The specific topic to subscribe the IEventBusHandler for. If this is @c nullptr + * the handler is notified no matter which IEventBusTopic the IEventBusEvent is published with. + */ + template + void subscribe(IEventBusHandler& handler, const IEventBusTopic* topic = nullptr) { + const std::type_index& index = typeid(T); + ScopedWriteLock lock(_lock); + EventBusHandlerReferences& handlers = _handlers[index]; + const EventBusHandlerReference registration(&handler, topic); + handlers.push_back(registration); + } + + /** + * @brief Unsubscribe the given handler for the specified topic + * @param[in,out] handler The IEventBusHandler to unsubscribe + * @param[in] topic The specific topic to unsubscribe the IEventBusHandler for. If this is + * @c nullptr the given handler is unsubscribed no matter which topic it was subscribed with. + * @return The amount of unsubscribed IEventBusHandler instances + */ + template + int unsubscribe(IEventBusHandler& handler, const IEventBusTopic* topic = nullptr) { + int unsubscribedHandlers = 0; + const std::type_index& index = typeid(T); + ScopedWriteLock lock(_lock); + EventBusHandlerReferences& handlers = _handlers[index]; + for (EventBusHandlerReferences::iterator i = handlers.begin(); i != handlers.end();) { + EventBusHandlerReference& r = *i; + if (r.getHandler() != reinterpret_cast*>(&handler)) { + ++i; + continue; + } + if (topic != nullptr) { + if (r.getTopic() == nullptr) { + ++i; + continue; + } + if (!(*r.getTopic() == *topic)) { + ++i; + continue; + } + } + i = handlers.erase(i); + ++unsubscribedHandlers; + } + return unsubscribedHandlers; + } + + /** + * @brief Publishes the given IEventBusEvent and notifies the IEventBusHandler + * @param[in] e The event that should be published + * @note Only those IEventBusHandler are notified that have registered with the same topic + * that the event is publishing with (or if the handler was not registered with a topic at + * all). + * @return The amount of notified IEventBusHandler instances + */ + int publish(const IEventBusEvent& e) { + const std::type_index& index = typeid(e); + ScopedReadLock lock(_lock); + EventBusHandlerReferenceMap::iterator i = _handlers.find(index); + if (i == _handlers.end()) + return 0; + + int notifiedHandlers = 0; + EventBusHandlerReferences& handlers = i->second; + for (auto& r : handlers) { + if (r.getTopic() != nullptr) { + const IEventBusTopic* topic = e.getTopic(); + if (topic == nullptr) + continue; + if (!(*r.getTopic() == *topic)) + continue; + } + IEventBusHandler* handler = r.getHandler(); + handler->dispatch(e); + ++notifiedHandlers; + } + return notifiedHandlers; + } +}; + +typedef std::shared_ptr EventBusPtr; + +} diff --git a/src/modules/core/IFactoryRegistry.h b/src/modules/core/IFactoryRegistry.h new file mode 100644 index 000000000..f24b6a885 --- /dev/null +++ b/src/modules/core/IFactoryRegistry.h @@ -0,0 +1,52 @@ +#pragma once + +#include +#include + +#include "NonCopyable.h" + +namespace core { + +template +class IFactory { +public: + virtual ~IFactory() { + } + virtual std::shared_ptr create(const CTX* ctx) const = 0; +}; + +template +class IFactoryRegistry: public NonCopyable { +public: + typedef std::unordered_map*> FactoryMap; + typedef typename FactoryMap::const_iterator FactoryMapConstIter; + typedef typename FactoryMap::iterator FactoryMapIter; +protected: + FactoryMap _factories; +public: + bool registerFactory(const KEY& type, const IFactory& factory) { + FactoryMapConstIter i = _factories.find(&type); + if (i != _factories.end()) { + return false; + } + + _factories[&type] = &factory; + return true; + } + + std::shared_ptr create(const KEY& type, const CTX* ctx = 0) const { + FactoryMapConstIter i = _factories.find(&type); + if (i == _factories.end()) { + return std::shared_ptr(); + } + + const IFactory* factory = i->second; + return factory->create(ctx); + } + + inline const FactoryMap& getFactories() const { + return _factories; + } +}; + +} diff --git a/src/modules/core/Input.h b/src/modules/core/Input.h new file mode 100644 index 000000000..01b7ff9f3 --- /dev/null +++ b/src/modules/core/Input.h @@ -0,0 +1,54 @@ +#pragma once + +#include + +#if defined(__LINUX__) || defined(__MACOSX__) +#include +#include +#include +#include +#endif + +namespace core { + +class Input { +private: + char _input[256]; +public: + Input() { +#if defined(__LINUX__) || defined(__MACOSX__) + ::signal(SIGTTIN, SIG_IGN); + ::signal(SIGTTOU, SIG_IGN); + ::signal(SIGCONT, SIG_IGN); +#ifdef __LINUX__ + ::fcntl(STDIN_FILENO, F_SETFL, ::fcntl(STDIN_FILENO, F_GETFL, 0) | O_NONBLOCK); +#endif + ::fcntl(STDIN_FILENO, F_SETFL, ::fcntl(STDIN_FILENO, F_GETFL, 0) | FNDELAY); +#endif + } + + const char* read() { +#if defined(__LINUX__) || defined(__MACOSX__) + fd_set fdset; + FD_ZERO(&fdset); + FD_SET(STDIN_FILENO, &fdset); + + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + if (::select(STDIN_FILENO + 1, &fdset, nullptr, nullptr, &timeout) == -1 || !FD_ISSET(STDIN_FILENO, &fdset)) + return nullptr; + + const int len = ::read(STDIN_FILENO, _input, sizeof(_input)); + if (len <= 1) + return nullptr; + + _input[len - 1] = '\0'; + return _input; +#else + return nullptr; +#endif + } +}; + +} diff --git a/src/modules/core/Log.cpp b/src/modules/core/Log.cpp new file mode 100644 index 000000000..06cd6fc00 --- /dev/null +++ b/src/modules/core/Log.cpp @@ -0,0 +1,67 @@ +#include "Log.h" +#include "Var.h" +#include +#include + +enum { + TRACE = 4, DEBUG = 3, INFO = 2, WARN = 1, ERROR = 0 +}; + +Log::Log() { + _logLevel = core::Var::get("core_loglevel", "2"); +} + +void Log::vsnprint(const char* msg, va_list args) { + char buf[1024]; + SDL_vsnprintf(buf, sizeof(buf), msg, args); + buf[sizeof(buf) - 1] = 0; + if (buf[strlen(buf) - 1] == '\r') + SDL_Log("%s\n", buf); + else + SDL_Log("%s\n", buf); +} + +void Log::trace(const char* msg, ...) { + if (get()._logLevel->intVal() < DEBUG) + return; + va_list args; + va_start(args, msg); + get().vsnprint(msg, args); + va_end(args); +} + +void Log::debug(const char* msg, ...) { + if (get()._logLevel->intVal() < DEBUG) + return; + va_list args; + va_start(args, msg); + get().vsnprint(msg, args); + va_end(args); +} + +void Log::info(const char* msg, ...) { + if (get()._logLevel->intVal() < INFO) + return; + va_list args; + va_start(args, msg); + get().vsnprint(msg, args); + va_end(args); +} + +void Log::warn(const char* msg, ...) { + if (get()._logLevel->intVal() < INFO) + return; + va_list args; + va_start(args, msg); + get().vsnprint(msg, args); + va_end(args); +} + +void Log::error(const char* msg, ...) { + if (get()._logLevel->intVal() < INFO) + return; + va_list args; + va_start(args, msg); + get().vsnprint(msg, args); + va_end(args); +} diff --git a/src/modules/core/Log.h b/src/modules/core/Log.h new file mode 100644 index 000000000..0feee277c --- /dev/null +++ b/src/modules/core/Log.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + +namespace core { +class Var; +typedef std::shared_ptr VarPtr; +} + +class Log { +private: + core::VarPtr _logLevel; + + Log(); + + static inline Log& get() { + static Log log; + return log; + } + + void vsnprint(const char* msg, va_list args); + +public: + static void trace(const char* msg, ...) __attribute__((format(printf, 1, 2))); + static void debug(const char* msg, ...) __attribute__((format(printf, 1, 2))); + static void info(const char* msg, ...) __attribute__((format(printf, 1, 2))); + static void warn(const char* msg, ...) __attribute__((format(printf, 1, 2))); + static void error(const char* msg, ...) __attribute__((format(printf, 1, 2))); +}; diff --git a/src/modules/core/MemoryAllocator.h b/src/modules/core/MemoryAllocator.h new file mode 100644 index 000000000..1ddc1e14f --- /dev/null +++ b/src/modules/core/MemoryAllocator.h @@ -0,0 +1,68 @@ +#pragma once + +#include + +namespace core { + +class _DefaultAllocator { +private: + _DefaultAllocator() { + } +public: + static inline void* allocate(size_t count) { + void* ptr = new unsigned char[count]; + return ptr; + } + + static inline void deallocate(void* ptr) { + delete[] ((unsigned char*) ptr); + } +}; + +template +class _MemObject { +public: + explicit _MemObject() { + } + + virtual ~_MemObject() { + } + + inline void* operator new(size_t size) { + return AllocatorClass::allocate(size); + } + + inline void* operator new(size_t, void* ptr) { + return ptr; + } + + inline void* operator new[](size_t size) { + return AllocatorClass::allocate(size); + } + + inline void operator delete(void* ptr) { + AllocatorClass::deallocate(ptr); + } + + inline void operator delete(void* ptr, void*) { + AllocatorClass::deallocate(ptr); + } + + inline void operator delete[](void* ptr) { + AllocatorClass::deallocate(ptr); + } +}; + +/** + * @brief define the macro @c ALLOCATOR_CLASS with your own allocator implementation. just create a class + * with static functions for @c allocate and @c deallocate. + */ +#ifndef ALLOCATOR_CLASS +#define ALLOCATOR_CLASS _DefaultAllocator +#endif +/** + * @brief Every object that is derived from @c MemObject is allocated with the @c ALLOCATOR_CLASS allocator. + */ +typedef _MemObject MemObject; + +} diff --git a/src/modules/core/NonCopyable.h b/src/modules/core/NonCopyable.h new file mode 100644 index 000000000..0e4269c70 --- /dev/null +++ b/src/modules/core/NonCopyable.h @@ -0,0 +1,14 @@ +#pragma once + +namespace core { + +class NonCopyable { +public: + NonCopyable() { + } +private: + NonCopyable(const NonCopyable&) = delete; + NonCopyable& operator=(const NonCopyable&) = delete; +}; + +} diff --git a/src/modules/core/QuadTree.h b/src/modules/core/QuadTree.h new file mode 100644 index 000000000..a550511ca --- /dev/null +++ b/src/modules/core/QuadTree.h @@ -0,0 +1,265 @@ +#pragma once + +#include +#include +#include +#include "Rect.h" + +namespace core { + +template +class QuadTree { +public: + typedef typename std::vector Contents; +private: + class QuadTreeNode; + typedef typename std::vector Nodes; + class QuadTreeNode { + friend class QuadTree; + private: + const int _maxDepth; + int _depth; + const Rect _area; + Contents _contents; + Nodes _nodes; + + QuadTreeNode(const Rect& bounds, int maxDepth, int depth) : + _maxDepth(maxDepth), _depth(depth), _area(bounds) { + _nodes.reserve(4); + } + + void createNodes() { + if (_depth >= _maxDepth) { + return; + } + + const std::array, 4>& subareas = _area.split(); + _nodes.push_back(QuadTreeNode(subareas[0], _maxDepth, _depth + 1)); + _nodes.push_back(QuadTreeNode(subareas[1], _maxDepth, _depth + 1)); + _nodes.push_back(QuadTreeNode(subareas[2], _maxDepth, _depth + 1)); + _nodes.push_back(QuadTreeNode(subareas[3], _maxDepth, _depth + 1)); + } + + inline int count() const { + int count = 0; + for (auto& node : _nodes) { + count += node.count(); + } + count += _contents.size(); + return count; + } + + inline const Rect& getRect() const { + return _area; + } + + inline const Contents& getContents() const { + return _contents; + } + + Contents getAllContents() const { + Contents results; + + for (auto& node : _nodes) { + const Contents& childNodes = node.getAllContents(); + results.insert(results.begin(), childNodes.begin(), childNodes.end()); + } + + results.insert(results.begin(), _contents.begin(), _contents.end()); + return results; + } + + bool remove(const NODE& item) { + const Rect& area = item.getRect(); + if (!_area.contains(area)) { + return false; + } + for (auto& node : _nodes) { + if (!node._area.contains(area)) + continue; + return node.remove(item); + } + + auto i = std::find(_contents.begin(), _contents.end(), item); + if (i == _contents.end()) + return false; + _contents.erase(i); + return true; + } + + bool insert(const NODE& item) { + const Rect& area = item.getRect(); + if (!_area.contains(area)) { + return false; + } + + if (_nodes.empty()) { + createNodes(); + } + + for (auto& node : _nodes) { + if (!node._area.contains(area)) + continue; + node.insert(item); + return true; + } + + _contents.push_back(item); + return true; + } + + inline bool isEmpty() const { + if (_nodes.empty() && _contents.empty()) + return true; + + return false; + } + + Contents query(const Rect& queryArea) const { + Contents results; + + for (auto& item : _contents) { + const Rect& area = item.getRect(); + if (queryArea.intersectsWith(area)) { + results.push_back(item); + } + } + + for (auto& node : _nodes) { + if (node.isEmpty()) { + continue; + } + + if (node._area.contains(queryArea)) { + const Contents& contents = node.query(queryArea); + if (!contents.empty()) { + results.reserve(results.size() + contents.size()); + results.insert(results.end(), contents.begin(), contents.end()); + } + // the queried area is completely part of the node + break; + } + + if (queryArea.contains(node._area)) { + const Contents& contents = node.getAllContents(); + if (!contents.empty()) { + results.reserve(results.size() + contents.size()); + results.insert(results.end(), contents.begin(), contents.end()); + } + // the whole node content is part of the query + continue; + } + + if (node._area.intersectsWith(queryArea)) { + const Contents& contents = node.query(queryArea); + if (!contents.empty()) { + results.reserve(results.size() + contents.size()); + results.insert(results.end(), contents.begin(), contents.end()); + } + } + } + return results; + } + + inline std::string indent() const { + std::string indent; + for (int i = 0; i < _depth; ++i) { + indent.push_back(' '); + indent.push_back(' '); + } + return indent; + } + }; + + QuadTreeNode _root; + // dirty flag can be used for query caches + bool _dirty; +public: + QuadTree(const Rect& rectangle, int maxDepth = 10) : + _root(rectangle, maxDepth, 0), _dirty(false) { + } + + inline int count() const { + return _root.count(); + } + + inline bool insert(const NODE& item) { + if (_root.insert(item)) { + _dirty = true; + return true; + } + return false; + } + + inline bool remove(const NODE& item) { + if (_root.remove(item)) { + _dirty = true; + return true; + } + return false; + } + + inline Contents query(const Rect& area) const { + return _root.query(area); + } + + void clear() { + auto size = _root._contents.size(); + _dirty = true; + _root._contents.clear(); + _root._contents.reserve(size); + _root._nodes.clear(); + _root._nodes.reserve(4); + } + + inline void markAsClean() { + _dirty = false; + } + + inline bool isDirty() { + return _dirty; + } + + inline Contents getContents() const { + return _root.getAllContents(); + } +}; + +#define CACHE 0 +template +class QuadTreeCache { +private: + QuadTree& _tree; +#if CACHE + std::unordered_map, typename QuadTree::Contents> _cache; +#endif +public: + QuadTreeCache(QuadTree& tree) : + _tree(tree) { + } + + inline void clear() { +#if CACHE + _cache.clear(); +#endif + } + +#if CACHE + inline const typename QuadTree::Contents& query(const Rect& area) { + if (_tree.isDirty()) { + _tree.markAsClean(); + clear(); + } + auto iter = _cache.find(area); + if (iter != _cache.end()) + return iter->second; + auto insertIter = _cache.insert(std::make_pair(area, std::move(_tree.query(area)))); + return insertIter->first; +#else + inline typename QuadTree::Contents query(const Rect& area) { + return _tree.query(area); +#endif + } +}; + +} diff --git a/src/modules/core/Random.h b/src/modules/core/Random.h new file mode 100644 index 000000000..ce5b94ac1 --- /dev/null +++ b/src/modules/core/Random.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include + +namespace core { + +inline std::default_random_engine& randomEngine() { + thread_local static std::default_random_engine engine; + return engine; +} + +inline void randomSeed (unsigned int seed) { + randomEngine().seed(seed); +} + +inline float randomf (float min = 0.0f, float max = 1.0f) { + std::uniform_real_distribution distribution(min, max); + return distribution(randomEngine()); +} + +inline int random (int min, int max) { + std::uniform_int_distribution distribution(min, max); + return distribution(randomEngine()); +} + +inline float randomBinomial (float max = 1.0f) { + return randomf(0.0f, max) - randomf(0.0f, max); +} + +template +inline I randomElement(I begin, I end) { + const int n = static_cast(std::distance(begin, end)); + std::uniform_int_distribution<> dis(0, n - 1); + std::advance(begin, dis(randomEngine())); + return begin; +} + +} diff --git a/src/modules/core/ReadWriteLock.h b/src/modules/core/ReadWriteLock.h new file mode 100644 index 000000000..494da1324 --- /dev/null +++ b/src/modules/core/ReadWriteLock.h @@ -0,0 +1,61 @@ +#pragma once + +#include +#include +#include +#include + +namespace core { + +class ReadWriteLock { +private: + mutable std::atomic_int _readers; + mutable std::atomic _lock; + const std::string _name; +public: + ReadWriteLock(const std::string& name) : _readers(0), _lock(false), _name(name) {} + + inline void lockRead() const { + while (_lock) {} + ++_readers; + } + + inline void unlockRead() const { + --_readers; + } + + inline void lockWrite() { + while (std::atomic_exchange_explicit(&_lock, true, std::memory_order_acquire)) {} + while (_readers > 0) {} + } + + inline void unlockWrite() { + std::atomic_store_explicit(&_lock, false, std::memory_order_release); + } +}; + +class ScopedReadLock { +private: + const ReadWriteLock& _lock; +public: + ScopedReadLock(const ReadWriteLock& lock) : _lock(lock) { + _lock.lockRead(); + } + ~ScopedReadLock() { + _lock.unlockRead(); + } +}; + +class ScopedWriteLock { +private: + ReadWriteLock& _lock; +public: + ScopedWriteLock(ReadWriteLock& lock) : _lock(lock) { + _lock.lockWrite(); + } + ~ScopedWriteLock() { + _lock.unlockWrite(); + } +}; + +} diff --git a/src/modules/core/Rect.h b/src/modules/core/Rect.h new file mode 100644 index 000000000..a0ebee937 --- /dev/null +++ b/src/modules/core/Rect.h @@ -0,0 +1,114 @@ +#pragma once +#include +#include +#include +#include "core/Common.h" + +namespace core { + +template +class Rect { +private: + glm::tvec2 _mins; + glm::tvec2 _maxs; +public: + Rect(TYPE minX, TYPE minZ, TYPE maxX, TYPE maxZ) : + _mins(minX, minZ), _maxs(maxX, maxZ) { + core_assert(_mins.x < _maxs.x); + core_assert(_mins.y < _maxs.y); + } + + Rect(const glm::tvec2& mins, const glm::tvec2& maxs) : + _mins(mins), _maxs(maxs) { + core_assert(_mins.x < _maxs.x); + core_assert(_mins.y < _maxs.y); + } + + static inline Rect getMaxRect() { + static const TYPE lowest = std::numeric_limits::lowest(); + static const TYPE max = std::numeric_limits::max(); + static const Rect maxRect(lowest, lowest, max, max); + return maxRect; + } + + inline TYPE getMaxZ() const { + return _maxs.y; + } + + inline TYPE getMinX() const { + return _mins.x; + } + + inline TYPE getMaxX() const { + return _maxs.x; + } + + inline TYPE getMinZ() const { + return _mins.y; + } + + inline bool operator==(const Rect& other) const { + return _mins == other._mins && _maxs == other._maxs; + } + + inline bool intersectsWith(const Rect& other) const { + if (getMaxX() <= other.getMinX() || getMinX() >= other.getMaxX()) + return false; + if (getMaxZ() <= other.getMinZ() || getMinZ() >= other.getMaxZ()) + return false; + return true; + } + + inline void offset(TYPE dx, TYPE dz) { + if (getMaxRect() == *this) + return; + _mins.x += dx; + _mins.y += dz; + _maxs.x += dx; + _maxs.y += dz; + } + + std::array, 4> split() const { + if (getMaxRect() == *this) { + // special case because the length would exceed the max possible value of TYPE + if (std::numeric_limits::is_signed) { + static const std::array, 4> maxSplit = { + Rect(_mins.x, _mins.y, 0, 0), + Rect(0, _mins.y, _maxs.x, 0), + Rect(_mins.x, 0, 0, _maxs.y), + Rect(0, 0, _maxs.x, _maxs.y), + }; + return maxSplit; + } + } + + const TYPE lengthX = glm::abs(_maxs.x - _mins.x); + const TYPE halfX = lengthX / 2.0; + const TYPE lengthY = glm::abs(_maxs.y - _mins.y); + const TYPE halfY = lengthY / 2.0; + const std::array, 4> split = { + Rect(_mins.x, _mins.y, _mins.x + halfX, _mins.y + halfY), + Rect(_mins.x + halfX, _mins.y, _maxs.x, _mins.y + halfY), + Rect(_mins.x, _mins.y + halfY, _mins.x + halfX, _maxs.y), + Rect(_mins.x + halfX, _mins.y + halfY, _maxs.x, _maxs.y), + }; + return split; + } + + inline bool contains(const Rect& rect) const { + if (rect.getMaxX() > getMaxX()) + return false; + if (rect.getMaxZ() > getMaxZ()) + return false; + if (rect.getMinX() < getMinX()) + return false; + if (rect.getMinZ() < getMinZ()) + return false; + return true; + } +}; + +typedef Rect RectuInt; +typedef Rect RectFloat; + +} diff --git a/src/modules/core/Set.h b/src/modules/core/Set.h new file mode 100644 index 000000000..d02d7bda5 --- /dev/null +++ b/src/modules/core/Set.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +namespace core { + +template +inline std::unordered_set setIntersection(const std::unordered_set& set1, const std::unordered_set& set2) { + if (set1.size() > set2.size()) + return setIntersection(set2, set1); + + std::unordered_set intersection; + for (auto const& element : set1) + if (set2.count(element) > 0) + intersection.insert(element); + return intersection; +} + +template +inline std::unordered_set setUnion(const std::unordered_set& in1, const std::unordered_set& in2) { + std::unordered_set out; + out.reserve(in1.size() + in2.size()); + out.insert(in1.begin(), in1.end()); + out.insert(in2.begin(), in2.end()); + return out; +} + +template +inline std::unordered_set setDifference(const std::unordered_set& in1, const std::unordered_set& in2) { + std::unordered_set out; + for (const TYPE& element : in1) + if (in2.find(element) == in2.end()) + out.insert(element); + for (const TYPE& element : in2) + if (in1.find(element) == in1.end()) + out.insert(element); + return out; +} + +} diff --git a/src/modules/core/Singleton.h b/src/modules/core/Singleton.h new file mode 100644 index 000000000..15a99d48c --- /dev/null +++ b/src/modules/core/Singleton.h @@ -0,0 +1,17 @@ +#pragma once + +namespace core { + +/** + * @brief A singleton is only a singleton for the current thread. + */ +template +class Singleton { +public: + static T& getInstance() { + static thread_local T theInstance; + return theInstance; + } +}; + +} diff --git a/src/modules/core/String.h b/src/modules/core/String.h new file mode 100644 index 000000000..3ee19d011 --- /dev/null +++ b/src/modules/core/String.h @@ -0,0 +1,220 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace core { +namespace string { + +inline bool isUTF8Multibyte(char c) { + return (c & 0xc0) == 0x80; +} + +inline size_t getUTF8LengthForCharacter(const unsigned char c) { + if (c < 0x80) + return 1; + if (c < 0xc0) + return 0; + if (c < 0xe0) + return 2; + if (c < 0xf0) + return 3; + if (c < 0xf8) + return 4; + /* 5 and 6 byte sequences are no longer valid. */ + return 0; +} + +inline size_t getUTF8LengthForInt(int c) { + if (c <= 0x7F) + return 1; + if (c <= 0x07FF) + return 2; + if (c <= 0xFFFF) + return 3; + if (c <= 0x10FFFF) /* highest defined Unicode code */ + return 4; + return 0; +} + +inline int getUTF8Next (const char** str) +{ + const char* s = *str; + if (s[0] == '\0') + return -1; + + const unsigned char* buf = reinterpret_cast(s); + + int character; + int min; + if (buf[0] < 0x80) { + min = 0; + character = buf[0]; + } else if (buf[0] < 0xc0) { + return -1; + } else if (buf[0] < 0xe0) { + min = 1 << 7; + character = buf[0] & 0x1f; + } else if (buf[0] < 0xf0) { + min = 1 << (5 + 6); + character = buf[0] & 0x0f; + } else if (buf[0] < 0xf8) { + min = 1 << (4 + 6 + 6); + character = buf[0] & 0x07; + } else { + return -1; + } + + const int utf8Length = getUTF8LengthForCharacter(buf[0]); + for (int i = 1; i < utf8Length; ++i) { + if (!isUTF8Multibyte(buf[i])) + return -1; + character = (character << 6) | (buf[i] & 0x3F); + } + + if (character < min) + return -1; + + if (0xD800 <= character && character <= 0xDFFF) + return -1; + + if (0x110000 <= character) + return -1; + + *str += utf8Length; + return character; +} + + +inline size_t getUTF8Length(const std::string& str) { + size_t result = 0; + const char *string = str.c_str(); + + while (string[0] != '\0') { + const int n = getUTF8LengthForCharacter((const unsigned char) *string); + string += n; + result++; + } + return result; +} + +inline std::string format(const char *msg, ...) { + va_list ap; + const std::size_t bufSize = 1024; + char text[bufSize]; + + va_start(ap, msg); + vsnprintf(text, bufSize, msg, ap); + va_end(ap); + + return std::string(text); +} + +inline int toInt(const std::string& str) { + return ::atoi(str.c_str()); +} + +inline int toLong(const std::string& str) { + return ::atol(str.c_str()); +} + +inline bool toBool(const std::string& str) { + return str == "1" || str == "true"; +} + +inline float toFloat(const std::string& str) { + return atof(str.c_str()); +} + +inline void splitString(const std::string& string, std::vector& tokens, const std::string& delimiters = " \t\r\n\f\v") { + // Skip delimiters at beginning. + std::string::size_type lastPos = string.find_first_not_of(delimiters, 0); + // Find first "non-delimiter". + std::string::size_type pos = string.find_first_of(delimiters, lastPos); + + while (std::string::npos != pos || std::string::npos != lastPos) { + // Found a token, add it to the vector. + tokens.push_back(string.substr(lastPos, pos - lastPos)); + // Skip delimiters. Note the "not_of" + lastPos = string.find_first_not_of(delimiters, pos); + // Find next "non-delimiter" + pos = string.find_first_of(delimiters, lastPos); + } +} + +inline std::string toLower(const std::string& string) { + std::string convert = string; + std::transform(convert.begin(), convert.end(), convert.begin(), (int (*)(int)) std::tolower); + return convert; +} + +inline bool startsWith(const std::string& string, const std::string& token) { + return !string.compare(0, token.size(), token); +} + +inline bool endsWith(const std::string& string, const std::string& end) { + const std::size_t strLength = string.length(); + const std::size_t endLength = end.length(); + if (strLength >= endLength) { + const std::size_t index = strLength - endLength; + return string.compare(index, endLength, end) == 0; + } + return false; +} + +inline std::string replaceAll(const std::string& str, const std::string& searchStr, const std::string& replaceStr) { + if (str.empty()) + return str; + std::string sNew = str; + std::string::size_type loc; + const std::string::size_type replaceLength = replaceStr.length(); + const std::string::size_type searchLength = searchStr.length(); + std::string::size_type lastPosition = 0; + while (std::string::npos != (loc = sNew.find(searchStr, lastPosition))) { + sNew.replace(loc, searchLength, replaceStr); + lastPosition = loc + replaceLength; + } + return sNew; +} + +inline std::string cutAfterFirstMatch(const std::string& str, const std::string& pattern, size_t start = 0) { + std::string::size_type pos = str.find_first_of(pattern, 0); + return str.substr(start, pos); +} + +inline std::string eraseAllSpaces(const std::string& str) { + std::string tmp = str; + tmp.erase(std::remove(tmp.begin(), tmp.end(), ' '), tmp.end()); + return tmp; +} + +inline bool contains(const std::string& str, const std::string& search) { + return str.rfind(search) != std::string::npos; +} + +inline std::string ltrim(const std::string &str) { + size_t startpos = str.find_first_not_of(" \t"); + if (std::string::npos != startpos) { + return str.substr(startpos); + } + return str; +} + +inline std::string rtrim(const std::string &str) { + size_t endpos = str.find_last_not_of(" \t"); + if (std::string::npos != endpos) { + return str.substr(0, endpos + 1); + } + return str; +} + +inline std::string trim(const std::string &str) { + return ltrim(rtrim(str)); +} + +} +} diff --git a/src/modules/core/TextConsole.cpp b/src/modules/core/TextConsole.cpp new file mode 100644 index 000000000..1dcee1d38 --- /dev/null +++ b/src/modules/core/TextConsole.cpp @@ -0,0 +1,274 @@ +#include "TextConsole.h" +#include "engine/common/ConfigManager.h" +#include "engine/common/System.h" +#include "engine/common/Application.h" +#include +#include +#include + +namespace { +#ifdef HAVE_NCURSES_H +const int COLOR_DEFAULT = 0; +const int COLOR_ALT = COLOR_RED; +#else +const int COLOR_DEFAULT = 0; +const int COLOR_ALT = 0; +#endif +} + +TextConsole::TextConsole () : + IConsole(), _lastUpdate(0) +{ +#ifdef HAVE_NCURSES_H + _scrollPos = 0; + _stdwin = nullptr; + _createWidth = _createHeight = 0; +#endif +} + +TextConsole::~TextConsole () +{ +#ifdef HAVE_NCURSES_H + clrtoeol(); + refresh(); + endwin(); +#endif + for (EntriesIter i = _entries.begin(); i != _entries.end(); ++i) { + delete *i; + } +} + +void TextConsole::update (uint32_t deltaTime) +{ + _lastUpdate += deltaTime; + +#ifdef HAVE_NCURSES_H + int key = wgetch(_stdwin); + while (key != ERR) { + if (key == KEY_ENTER || key == '\n') { + executeCommandLine(); + } else if (key == KEY_CTAB || key == '\t') { + autoComplete(); + } else if (key == KEY_BACKSPACE || key == 8 || key == 127) { + _cursorPos--; + if (_cursorPos > 0) + _commandLine.erase(_cursorPos, 1); + else + _cursorPos = 0; + } else if (key == KEY_LEFT) { + _cursorPos--; + if (_cursorPos < 0) + _cursorPos = 0; + } else if (key == KEY_PPAGE) { + _scrollPos++; + } else if (key == KEY_NPAGE) { + _scrollPos--; + } else if (key == KEY_HOME) { + _cursorPos = 0; + } else if (key == KEY_RIGHT) { + _cursorPos++; + if (_cursorPos >= _commandLine.size()) + _cursorPos = _commandLine.size() - 1; + if (_cursorPos >= COLS - 1) + _cursorPos = COLS - 1; + } else if (key == KEY_END) { + _cursorPos = _commandLine.size() - 1; + } else if (key == KEY_UP) { + cursorUp(); + } else if (key == KEY_DOWN) { + cursorDown(); + } else if (key >= 32 && key < 127) { + if (_cursorPos >= _commandLine.size()) + _commandLine += (char) key; + else + _commandLine[_cursorPos] = (char) key; + _cursorPos++; + } + key = wgetch(_stdwin); + } +#endif +} + +void TextConsole::cursorDelete (bool moveCursor) +{ + IConsole::cursorDelete(moveCursor); + std::cout << "\b"; + std::cout << " "; +} + +void TextConsole::logInfo (const std::string& string) +{ + _entries.push_back(new ConsoleEntry(COLOR_DEFAULT, false, string)); +} + +void TextConsole::logError (const std::string& string) +{ + _entries.push_back(new ConsoleEntry(COLOR_ALT, true, string)); +} + +void TextConsole::logDebug (const std::string& string) +{ + if (!Config.isDebug()) { + return; + } + + logInfo(string); +} + +bool TextConsole::onKeyPress (int32_t key, int16_t modifier) +{ +#ifdef HAVE_NCURSES_H + // curses is handling our key presses in console mode + return false; +#else + if (key == SDLK_RETURN) { + executeCommandLine(); + } else if (key == SDLK_TAB) { + autoComplete(); + } else if (key >= 32 && key <= 126) { + const char chr = (char) key; + _commandLine += chr; + } + return true; +#endif +} + +void TextConsole::render () +{ + int timeout = 200; + + if (_lastUpdate < timeout) + return; + + _lastUpdate = 0; + +#ifdef HAVE_NCURSES_H + bkgdset(' '); + wclear(_stdwin); + + const int w = COLS - 1; + const int h = LINES - 1; + + if (w < 3 && h < 3) { + return; + } + + box(_stdwin, ACS_VLINE , ACS_HLINE); + + // Draw the header + setColor(COLOR_GREEN); + mvaddstr(0, 2, Singleton::getInstance().getName().c_str()); + + const int lines = LINES - 2; + const int lastLine = _entries.size(); + const int startLine = std::max(0, (int) _entries.size() - _scrollPos - lines); + int y = 1; + for (EntriesIter i = _entries.begin() + startLine; i != _entries.end() && i != _entries.begin() + lines; ++i) { + const ConsoleEntry &e = *(*i); + int x = 1; + // color of the first character of the line + setColor(e.color); + if (e.bold) + wattron(_stdwin, A_BOLD); + + for (const char *pos = e.text.c_str(); pos[0] != '\0'; ++pos) { + if (pos[0] == '\n' || pos[0] == '\r') { + x++; + } else if (x < w) { + mvaddnstr(y, x, pos, 1); + x++; + } else { + y++; + x = 1; + mvaddnstr(y, x, "> ", 2); + x += 2; + mvaddnstr(y, x, pos, 1); + } + } + + if (e.bold) + wattroff(_stdwin, A_BOLD); + y++; + } + + // draw a scroll indicator + if (_scrollPos != 0) { + setColor(COLOR_GREEN); + mvaddnstr(1 + ((lastLine - _scrollPos) * lines / lastLine), w, "O", 1); + } + + // reset drawing colors + resetColor(); + const int32_t xPos = COLS - 5; + + for (int x = 2; x < COLS - 1; x++) { + mvaddstr(LINES - 1, x, " "); + } + + // TODO: fix rendering for too long strings + mvaddnstr(LINES - 1, 3, _commandLine.c_str(), xPos); + + wrefresh(_stdwin); + + renderHook(); + + // move the cursor to input position + wmove(_stdwin, LINES - 1, 3 + _cursorPos); + waddch(_stdwin, '_'); + + // Print it on to the real screen + refresh(); +#endif +} + +void TextConsole::renderHook() +{ +} + +void TextConsole::init (IFrontend *frontend) +{ +#ifdef HAVE_NCURSES_H + // Start curses mode + _stdwin = initscr(); + // Line buffering disabled + cbreak(); + // We get F1, F2 etc.. + keypad(stdscr, TRUE); + // Don't echo() while we do getch + noecho(); + // non-blocking input + nodelay(_stdwin, TRUE); + // enable the cursor + curs_set(0); + + if (has_colors()) { + start_color(); + // this is ncurses-specific + use_default_colors(); + // COLOR_PAIR(0) is terminal default + init_pair(1, COLOR_RED, -1); + init_pair(2, COLOR_GREEN, -1); + init_pair(3, COLOR_YELLOW, -1); + init_pair(4, COLOR_BLUE, -1); + init_pair(5, COLOR_CYAN, -1); + init_pair(6, COLOR_MAGENTA, -1); + init_pair(7, -1, -1); + } +#endif +} + +inline void TextConsole::setColor (int color) const +{ +#ifdef HAVE_NCURSES_H + if (!has_colors()) { + return; + } + + color_set(color, nullptr); +#endif +} + +inline void TextConsole::resetColor () const +{ + setColor(COLOR_DEFAULT); +} diff --git a/src/modules/core/TextConsole.h b/src/modules/core/TextConsole.h new file mode 100644 index 000000000..a987d992c --- /dev/null +++ b/src/modules/core/TextConsole.h @@ -0,0 +1,53 @@ +#pragma once + +#include "engine/common/IConsole.h" +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#include + +#ifdef HAVE_NCURSES_H +#include +#include +#endif + +class TextConsole: public IConsole { +protected: + struct ConsoleEntry { + ConsoleEntry (int _color, bool _bold, const std::string& _text) : + color(_color), bold(_bold), text(_text) + { + } + const int color; + const bool bold; + const std::string text; + }; + +#ifdef HAVE_NCURSES_H + WINDOW *_stdwin; + int _createWidth, _createHeight; // the dimensions that the window was created with + int _scrollPos; +#endif + + int _lastUpdate; + typedef std::vector Entries; + typedef Entries::const_iterator EntriesIter; + Entries _entries; + + virtual void resetColor () const; + virtual void setColor (int color) const; + virtual void renderHook (); +public: + TextConsole (); + virtual ~TextConsole (); + + virtual void logInfo (const std::string& string) override; + virtual void logError (const std::string& string) override; + virtual void logDebug (const std::string& string) override; + virtual bool onKeyPress (int32_t key, int16_t modifier) override; + virtual void update (uint32_t deltaTime) override; + virtual void render () override; + virtual void init (IFrontend *frontend) override; + virtual void cursorDelete (bool moveCursor = true) override; +}; diff --git a/src/modules/core/ThreadPool.cpp b/src/modules/core/ThreadPool.cpp new file mode 100644 index 000000000..778768093 --- /dev/null +++ b/src/modules/core/ThreadPool.cpp @@ -0,0 +1,26 @@ +#include "ThreadPool.h" + +namespace core { + +void ThreadPool::tick() { + FunctionType task; + for (;;) { + { + std::unique_lock lock(_mutex); + while (!_join && _tasks.empty()) { + _cond.wait(lock); + } + if (_join) { + core_assert(_tasks.empty()); + return; + } + + task = _tasks.front(); + _tasks.pop_front(); + } + + task(); + } +} + +} diff --git a/src/modules/core/ThreadPool.h b/src/modules/core/ThreadPool.h new file mode 100644 index 000000000..35309bc1a --- /dev/null +++ b/src/modules/core/ThreadPool.h @@ -0,0 +1,61 @@ +#pragma once + +#include "Common.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace core { + +class ThreadPool { +private: + typedef std::function FunctionType; + bool _join; + std::vector _workers; + std::deque _tasks; + std::condition_variable _cond; + std::mutex _mutex; + + void tick(); +public: + ThreadPool(unsigned int numThreads = 2) : + _join(false) { + for (unsigned int i = 0; i < numThreads; ++i) { + _workers.push_back(std::move(std::thread(std::bind(&ThreadPool::tick, this)))); + } + } + + template + auto push(Function&& func, Args&&... args) -> std::future::type> { + core_assert(!_join); + using retType = typename std::result_of::type; + + auto task = std::make_shared >(std::bind(std::forward(func), std::forward(args)...)); + std::future res = task->get_future(); + + auto funcWrapper = [task]() { + (*task)(); + }; + { + std::unique_lock lock(_mutex); + _tasks.push_back(funcWrapper); + } + _cond.notify_one(); + return res; + } + + ~ThreadPool() { + _join = true; + _cond.notify_all(); + for (std::thread &worker : _workers) { + worker.join(); + } + } +}; + +} diff --git a/src/modules/core/TimeProvider.cpp b/src/modules/core/TimeProvider.cpp new file mode 100644 index 000000000..23e9eee6f --- /dev/null +++ b/src/modules/core/TimeProvider.cpp @@ -0,0 +1,9 @@ +#include "TimeProvider.h" + +namespace core { + +TimeProvider::TimeProvider() : + _tickTime(0ul) { +} + +} diff --git a/src/modules/core/TimeProvider.h b/src/modules/core/TimeProvider.h new file mode 100644 index 000000000..cdb346709 --- /dev/null +++ b/src/modules/core/TimeProvider.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include + +namespace core { + +/** + * The time provider will get an updated tick time with every tick. It does not perform any timer system call on getting the + * tick time - only if you really need the current time. + */ +class TimeProvider { +private: + unsigned long _tickTime; +public: + TimeProvider(); + + /** + * @brief The tick time gives you the time in milliseconds when the tick was started. + * @note Updated once per tick + */ + unsigned long tickTime() const { + return _tickTime; + } + + unsigned long currentTime() const { + const unsigned long now = std::chrono::system_clock::now().time_since_epoch() / std::chrono::milliseconds(1); + return now; + } + + void update(unsigned long now) { + _tickTime = now; + } +}; + +typedef std::shared_ptr TimeProviderPtr; + +} diff --git a/src/modules/core/Tokenizer.h b/src/modules/core/Tokenizer.h new file mode 100644 index 000000000..500c304b4 --- /dev/null +++ b/src/modules/core/Tokenizer.h @@ -0,0 +1,119 @@ +#pragma once + +#include "Common.h" +#include "String.h" + +namespace core { + +class Tokenizer { +protected: + std::vector _tokens; + std::size_t _posIndex; + std::size_t _size; + + inline char skip(const char **s) const { + char c; + while ((c = **s) <= ' ') { + if (c == '\0') + return '\0'; + *s += core::string::getUTF8LengthForCharacter(c); + } + + // skip multiline and singleline comments + if (c == '/') { + const char next = (*s)[1]; + if (next == '*') { + int l = 0; + *s += 2; + const char* data = *s; + while (!(data[l] != '\0' && data[l] == '*') && (data[l + 1] != '\0' && data[l + 1] == '/')) { + ++l; + } + *s += l + 2; + } else if (next == '/') { + while (**s != '\0' && **s != '\n') { + (*s)++; + } + } + } + + return c; + } +public: + Tokenizer(const std::string& string) : + _posIndex(0u) { + const char *s = string.c_str(); + + for (;;) { + char c = skip(&s); + if (c == '\0') + break; + std::string token; + if (c == '"') { + ++s; + for (;;) { + c = *s++; + if (c == '"' || c == '\0') { + _tokens.push_back(token); + break; + } else if (c == '\\') { + const char next = *s; + if (next == 'n') { + c = '\n'; + } else if (next == 't') { + c = '\t'; + } else if (next == '"') { + c = '"'; + } + ++s; + } + token.push_back(c); + } + continue; + } + + token.push_back(c); + for (;;) { + s++; + c = *s; + if (c <= ' ' || c == '(' || c == ')' || c == '{' || c == '}') + break; + token.push_back(c); + } + _tokens.push_back(token); + } + + _size = _tokens.size(); + } + + inline bool hasNext() const { + return _posIndex < _tokens.size(); + } + + inline const std::string& next() { + core_assert(hasNext()); + return _tokens[_posIndex++]; + } + + inline bool hasPrev() const { + return _posIndex > 0; + } + + inline std::size_t size() const { + return _tokens.size(); + } + + /** + * @return the current position in the tokens + */ + inline std::size_t pos() const { + return _posIndex; + } + + inline const std::string& prev() { + core_assert(hasPrev()); + return _tokens[--_posIndex]; + } +}; + +} diff --git a/src/modules/core/Trace.h b/src/modules/core/Trace.h new file mode 100644 index 000000000..8537f20ce --- /dev/null +++ b/src/modules/core/Trace.h @@ -0,0 +1,74 @@ +#pragma once + +#ifdef __EMSCRIPTEN__ +#define USE_EMTRACE 1 +#include +#else +#endif + +#include "Var.h" + +namespace core { + +// a singleton - available via core::App +class Trace { +public: + Trace(uint16_t port = 0x4597) { +#if USE_EMTRACE + emscripten_trace_configure("http://localhost:5000/", "Engine"); +#endif + } + ~Trace() { + } + + static inline bool enabled() { +#if USE_EMTRACE + return true; +#else + return false; +#endif + } +}; + +#if USE_EMTRACE +#define core_trace_begin_frame() if (core::Trace::enabled()) emscripten_trace_record_frame_start() +#define core_trace_end_frame() if (core::Trace::enabled()) emscripten_trace_record_frame_end() +#define core_trace_begin(name) if (core::Trace::enabled()) emscripten_trace_enter_context(#name) +#define core_trace_end(name) if (core::Trace::enabled()) emscripten_trace_exit_context() +#else +#define core_trace_begin_frame() +#define core_trace_end_frame() +#define core_trace_begin(name) +#define core_trace_end() +#endif + +class TraceScoped { +private: + const bool enabled; +public: + TraceScoped(const char* name) : + enabled(Trace::enabled()) { + if (enabled) { +#if USE_EMTRACE + emscripten_trace_enter_context(name); +#endif + } + } + + ~TraceScoped() { + if (enabled) { +#if USE_EMTRACE + emscripten_trace_exit_context(); +#endif + } + } +}; + +#define core_trace_scoped(name) core::TraceScoped(name) +#if USE_EMTRACE +#define core_trace_msg(name) +#else +#define core_trace_msg(message) +#endif + +} diff --git a/src/modules/core/Var.cpp b/src/modules/core/Var.cpp new file mode 100644 index 000000000..9494a3d5e --- /dev/null +++ b/src/modules/core/Var.cpp @@ -0,0 +1,52 @@ +#include "Var.h" +#include "Log.h" + +namespace core { + +Var::VarMap Var::_vars; +ReadWriteLock Var::_lock("Var"); + +VarPtr Var::get(const std::string& name, const std::string& value, unsigned int flags) { + VarMap::const_iterator i; + bool missing; + { + ScopedReadLock lock(_lock); + i = _vars.find(name); + missing = i == _vars.end(); + } + if (missing) { + if (value.empty() && (flags & CV_NOTCREATEEMPTY)) + return VarPtr(); + VarPtr p(new Var(name, value, flags)); + ScopedWriteLock lock(_lock); + _vars[name] = p; + return p; + } + return i->second; +} + +Var::Var(const std::string& name, const std::string& value, unsigned int flags) : + _name(name), _flags(flags), _value(value), _dirty(false) { + _intValue = string::toInt(_value); + _longValue = string::toLong(_value); + _floatValue = string::toFloat(_value); +} + +Var::~Var() { +} + +void Var::setVal(const std::string& value) { + if (_flags & CV_READONLY) { + Log::error("%s is write protected", _name.c_str()); + return; + } + _dirty = _value != value; + if (_dirty) { + _value = value; + _intValue = string::toInt(_value); + _longValue = string::toLong(_value); + _floatValue = string::toFloat(_value); + } +} + +} diff --git a/src/modules/core/Var.h b/src/modules/core/Var.h new file mode 100644 index 000000000..bbcdcb23a --- /dev/null +++ b/src/modules/core/Var.h @@ -0,0 +1,161 @@ +#pragma once + +#include +#include +#include +#include "String.h" +#include "ReadWriteLock.h" + +namespace core { + +const unsigned int CV_READONLY = 1 << 0; +// don't create empty value config vars +const unsigned int CV_NOTCREATEEMPTY = 1 << 1; +// will not get saved to the file +const unsigned int CV_NOPERSIST = 1 << 2; + +class Var; +typedef std::shared_ptr VarPtr; + +/** + * @brief A var can be changed and queried at runtime + * + * Create a new variable with all parameters + * @code + * core::VarPtr var = core::Var::get("prefix_name", "defaultvalue", 0); + * @endcode + * + * If you just want to get an existing variable use: + * @code + * core::Var::get("prefix_name"); + * @endcode + * But beware, if the variable is not yet created, you will create a new variable with an empty string. + * A later following call that specifies a saner default value would not count anymore (because the + * variable already exists. + */ +class Var { +private: + typedef std::unordered_map VarMap; + static VarMap _vars; + static ReadWriteLock _lock; + + const std::string _name; + const unsigned int _flags; + + float _floatValue; + int _intValue; + long _longValue; + std::string _value; + bool _dirty; + + // private - use the static get method + Var(const std::string& name, const std::string& value = "", unsigned int flags = 0u); +public: + /** + * @brief Creates a new or gets an already existing var + * + * @param[in] name The name that this var is registered under (must be unique) + * @param[in] value The initial value of the var + * @param[in] flags A bitmask of var flags - e.g. @c CV_READONLY + * + * @note This is using a read/write lock to allow access from different threads. + */ + static VarPtr get(const std::string& name, const std::string& value = "", unsigned int flags = 0u); + virtual ~Var(); + + template + static void visit(Functor func) { + ScopedReadLock lock(_lock); + for (auto i = _vars.begin(); i != _vars.end(); ++i) { + func(i->second); + } + } + + /** + * @return the bitmask of flags for this var + * @note See the existing @c CV_ ints + */ + int getFlags() const; + /** + * @return the value of the variable as @c int. + * + * @note There is no conversion happening here - this is done in @c Var::setVal + */ + int intVal() const; + /** + * @return the value of the variable as @c unsigned int. + * + * @note There is no conversion happening here - this is done in @c Var::setVal + */ + unsigned int uintVal() const; + /** + * @return the value of the variable as @c long. + * + * @note There is no conversion happening here - this is done in @c Var::setVal + */ + long longVal() const; + unsigned long ulongVal() const; + /** + * @return the value of the variable as @c float. + * + * @note There is no conversion happening here - this is done in @c Var::setVal + */ + float floatVal() const; + /** + * @return the value of the variable as @c bool. @c true if the string value is either @c 1 or @c true, @c false otherwise + */ + bool boolVal() const; + void setVal(const std::string& value); + /** + * @return The string value of this var + */ + const std::string& strVal() const; + const std::string& name() const; + /** + * @return @c true if some @c Var::setVal call changed the initial/default value that was specified on construction + */ + bool isDirty() const; +}; + +inline float Var::floatVal() const { + return _floatValue; +} + +inline int Var::intVal() const { + return _intValue; +} + +inline long Var::longVal() const { + return _longValue; +} + +inline unsigned long Var::ulongVal() const { + return static_cast(_longValue); +} + +inline bool Var::boolVal() const { + return _value == "true" || _value == "1"; +} + +inline const std::string& Var::strVal() const { + return _value; +} + +inline const std::string& Var::name() const { + return _name; +} + +inline bool Var::isDirty() const { + return _dirty; +} + +inline int Var::getFlags() const { + return _flags; +} + +inline unsigned int Var::uintVal() const { + return static_cast(_intValue); +} + + +} diff --git a/src/modules/core/tests/AbstractTest.h b/src/modules/core/tests/AbstractTest.h new file mode 100644 index 000000000..f863cf6af --- /dev/null +++ b/src/modules/core/tests/AbstractTest.h @@ -0,0 +1,33 @@ +#include + +#include "core/App.h" +#include "core/EventBus.h" +#include "io/Filesystem.h" + +namespace core { + +class AbstractTest: public testing::Test { +private: + class TestApp: public core::App { + public: + TestApp(const io::FilesystemPtr& filesystem, const core::EventBusPtr& eventBus) : + core::App(filesystem, eventBus, 10000) { + init("engine", "test"); + } + }; + + TestApp *_testApp; + +public: + void SetUp() override { + core::EventBusPtr eventBus = core::EventBusPtr(new core::EventBus()); + io::FilesystemPtr filesystem = io::FilesystemPtr(new io::Filesystem()); + _testApp = new TestApp(filesystem,eventBus); + } + + void TearDown() override { + delete _testApp; + } +}; + +} diff --git a/src/modules/core/tests/ByteStreamTest.cpp b/src/modules/core/tests/ByteStreamTest.cpp new file mode 100644 index 000000000..d5817c426 --- /dev/null +++ b/src/modules/core/tests/ByteStreamTest.cpp @@ -0,0 +1,355 @@ +#include +#include "core/ByteStream.h" +#include +#include +#include +#include +#include +#include + +namespace { +const uint8_t BYTE_ADD = UCHAR_MAX; +const int16_t SHORT_ADD = SHRT_MAX; +const int32_t INT_ADD = INT_MAX; +} + +namespace core { + +TEST(ByteStreamTest, testCopy) { + std::vector v; + for (int j = 0; j < 1000; ++j) { + ByteStream byteStream; + for (int i = 0; i < 1000; ++i) { + byteStream.addInt(i); + } + byteStream.addByte(1, true); + v.push_back(byteStream); + } + + for (std::vector::const_iterator i = v.begin(); i != v.end(); ++i) { + ByteStream s = *i; + ASSERT_EQ(4001u, s.getSize()); + } + + ASSERT_EQ(1000u, v.size()); +} + +TEST(ByteStreamTest, testBigChunk) { + const int size = 1000 * 1000 * 50; + core::ByteStream bs(size); + for (int i = 0; i < size; ++i) { + bs.addByte(1); + } + + for (int i = 0; i < size; ++i) { + bs.readByte(); + } +} + +TEST(ByteStreamTest, testBigChunkAdd) { + const int size = 1000 * 1000 * 50; + core::ByteStream bs(size); + for (int i = 0; i < size; ++i) { + bs.addByte(1); + } +} + +TEST(ByteStreamTest, testFormat) { + core::ByteStream bs; + bs.addFormat("ibli", 245678, 1, 2L, 12345678); + ASSERT_EQ(17u, bs.getSize()); + int len; + int version; + long seed; + int size; + bs.readFormat("ibli", &len, &version, &seed, &size); + ASSERT_EQ(245678, len); + ASSERT_EQ(1, version); + ASSERT_EQ(2L, seed); + ASSERT_EQ(12345678, size); +} + +TEST(ByteStreamTest, testWriteByte) { + ByteStream byteStream; + const size_t previous = byteStream.getSize(); + byteStream.addByte(BYTE_ADD); + ASSERT_EQ(previous + 1, byteStream.getSize()); +} + +TEST(ByteStreamTest, testWriteShort) { + ByteStream byteStream; + const size_t previous = byteStream.getSize(); + byteStream.addShort(SHORT_ADD); + ASSERT_EQ(previous + 2, byteStream.getSize()); +} + +TEST(ByteStreamTest, testWriteEmptyString) { + ByteStream byteStream; + byteStream.addString(""); + ASSERT_EQ(1u, byteStream.getSize()); + const std::string empty = byteStream.readString(); + ASSERT_EQ("", empty); + ASSERT_EQ(0u, byteStream.getSize()); +} + +TEST(ByteStreamTest, testWriteInt) { + ByteStream byteStream; + const size_t previous = byteStream.getSize(); + byteStream.addInt(INT_ADD); + ASSERT_EQ(previous + 4, byteStream.getSize()); +} + +TEST(ByteStreamTest, testWriteLong) { + ByteStream byteStream; + const size_t previous = byteStream.getSize(); + byteStream.addLong(234L); + ASSERT_EQ(previous + 8, byteStream.getSize()); +} + +TEST(ByteStreamTest, testPeekShort) { + int16_t peek; + ByteStream byteStream; + peek = byteStream.peekShort(); + byteStream.addByte(1); + ASSERT_EQ(-1, peek); + byteStream.addByte(1); + peek = byteStream.peekShort(); + ASSERT_EQ(257, peek); + ASSERT_EQ(257, byteStream.readShort()); + peek = byteStream.peekShort(); + ASSERT_EQ(-1, peek); +} + +TEST(ByteStreamTest, testReadByte) { + ByteStream byteStream; + byteStream.addByte(BYTE_ADD); + const size_t previous = byteStream.getSize(); + const uint8_t byte = byteStream.readByte(); + ASSERT_EQ(BYTE_ADD, byte); + ASSERT_EQ(previous - 1, byteStream.getSize()); +} + +TEST(ByteStreamTest, testReadShort) { + ByteStream byteStream; + byteStream.addShort(SHORT_ADD); + const size_t previous = byteStream.getSize(); + const int16_t word = byteStream.readShort(); + ASSERT_EQ(SHORT_ADD, word); + ASSERT_EQ(previous - 2, byteStream.getSize()); +} + +TEST(ByteStreamTest, testReadInt) { + ByteStream byteStream; + byteStream.addInt(INT_ADD); + const size_t previous = byteStream.getSize(); + int32_t dword = byteStream.readInt(); + ASSERT_EQ(INT_ADD, dword); + ASSERT_EQ(previous - 4, byteStream.getSize()); +} + +TEST(ByteStreamTest, testReadLong) { + ByteStream byteStream; + byteStream.addLong(234L); + const size_t previous = byteStream.getSize(); + int64_t dword = byteStream.readLong(); + ASSERT_EQ(234L, dword); + ASSERT_EQ(previous - 8, byteStream.getSize()); +} + +TEST(ByteStreamTest, testReadFloat) { + ByteStream byteStream; + const float expected = 0.1f; + byteStream.addFloat(expected); + const size_t previous = byteStream.getSize(); + const float dword = byteStream.readFloat(); + ASSERT_DOUBLE_EQ(expected, dword); + ASSERT_EQ(previous - 4, byteStream.getSize()); +} + +TEST(ByteStreamTest, testReadString) { + ByteStream byteStream; + const std::string str = "hello IT!"; + byteStream.addString(str); + const size_t previous = byteStream.getSize(); + const std::string readstr = byteStream.readString(); + ASSERT_EQ(str, readstr); + ASSERT_EQ(previous - str.length() - 1, byteStream.getSize()); +} + +TEST(ByteStreamTest, testReadStrings) { + ByteStream byteStream; + byteStream.addString("hello IT!"); + byteStream.addString("some other string"); + byteStream.addString("yet another string"); + byteStream.addString("0"); + byteStream.readString(); + byteStream.readString(); + byteStream.readString(); + ASSERT_EQ("0", byteStream.readString()); +} + +TEST(ByteStreamTest, testReadWriteVariadic) { + ByteStream byteStream; + const uint8_t byte = BYTE_ADD; + const int16_t word = SHORT_ADD; + const int32_t dword = INT_ADD; + int pByte; + int pShort; + int pInt; + byteStream.addFormat("bsi", byte, word, dword); + byteStream.readFormat("bsi", &pByte, &pShort, &pInt); + ASSERT_TRUE(byte == pByte); + ASSERT_TRUE(word == pShort); + ASSERT_TRUE(dword == pInt); +} + +TEST(ByteStreamTest, testReadWriteAll) { + ByteStream byteStream; + srandom(SDL_GetTicks()); + uint8_t byte = random() % BYTE_ADD; + int16_t word = random() % SHORT_ADD; + int32_t dword = random() % INT_ADD; + float floatv = floorf((random() % INT_ADD) / float(INT_ADD) * 100.0) + / 100.0; + size_t size = sizeof(byte) + sizeof(word) + sizeof(dword) + sizeof(floatv); + byteStream.addByte(byte); + byteStream.addShort(word); + byteStream.addInt(dword); + byteStream.addFloat(floatv); + ASSERT_EQ(byteStream.getSize(), size); + ASSERT_EQ(byteStream.readByte(), byte); + ASSERT_EQ(byteStream.getSize(), size -= 1); + ASSERT_EQ(byteStream.readShort(), word); + ASSERT_EQ(byteStream.getSize(), size -= 2); + ASSERT_EQ(byteStream.readInt(), dword); + ASSERT_EQ(byteStream.getSize(), size -= 4); + ASSERT_DOUBLE_EQ(byteStream.readFloat(), floatv); + ASSERT_EQ(byteStream.getSize(), size_t(0)); +} + +typedef enum DataType { + e_byte = 0, e_short, e_int, e_float, e_string, count +} DataType; + +typedef struct TypeValue { + DataType type; + void* pValue; +} TypeValue; + +typedef std::vector TypeValueList; +typedef TypeValueList::iterator TypeValueListIter; + +TEST(ByteStreamTest, testRandomReadWrite) { + ByteStream byteStream; + srandom(SDL_GetTicks()); + + TypeValueList _typeValueList; + TypeValueListIter _typeValueListIter; + + unsigned int iterations = random() % 20 + 1; + unsigned int index = 0; + size_t size = 0; + + //add random types to byte stream + do { + DataType dataType = DataType(random() % count); + TypeValue typeValue; + typeValue.type = dataType; + switch (dataType) { + case e_byte: { + uint8_t* byte = new uint8_t(random() % BYTE_ADD); + byteStream.addByte(*byte); + typeValue.pValue = byte; + size += 1; + break; + } + case e_short: { + int16_t* word = new int16_t(random() % SHORT_ADD); + byteStream.addShort(*word); + typeValue.pValue = word; + size += 2; + break; + } + case e_int: { + int32_t* dword = new int32_t(random() % INT_ADD); + byteStream.addInt(*dword); + typeValue.pValue = dword; + size += 4; + break; + } + case e_float: { + float* dword = new float( + floorf((random() % INT_ADD) / float(INT_ADD) * 100.0) + / 100.0); + byteStream.addFloat(*dword); + typeValue.pValue = dword; + size += 4; + break; + } + case e_string: { + std::string* str = new std::string("hello IT!"); + byteStream.addString(*str); + typeValue.pValue = str; + size += str->length() + 1; //plus the '\0' char + break; + } + default: + ASSERT_TRUE(false); + break; + } + _typeValueList.push_back(typeValue); + } while (index++ < iterations); + ASSERT_EQ(byteStream.getSize(), size); + + //read and verify added types in byte stream + index = 0; + do { + DataType dataType = _typeValueList.front().type; + void* value = _typeValueList.front().pValue; + switch (dataType) { + case e_byte: { + uint8_t byte = byteStream.readByte(); + size -= 1; + ASSERT_EQ(byte, *(uint8_t* ) value); + delete (uint8_t*) value; + break; + } + case e_short: { + int16_t word = byteStream.readShort(); + size -= 2; + ASSERT_EQ(word, *(int16_t* ) value); + delete (int16_t*) value; + break; + } + case e_int: { + int32_t dword = byteStream.readInt(); + size -= 4; + ASSERT_EQ(dword, *(int32_t* ) value); + delete (int32_t*) value; + break; + } + case e_float: { + float dword = byteStream.readFloat(); + size -= 4; + ASSERT_DOUBLE_EQ(dword, *(float* ) value); + delete (float*) value; + break; + } + case e_string: { + std::string str = byteStream.readString(); + size -= str.length() + 1; //plus the '\0' char + ASSERT_EQ(str, *(std::string* ) value); + delete (std::string*) value; + break; + } + default: + ASSERT_TRUE(false); + break; + } + _typeValueList.erase(_typeValueList.begin()); + ASSERT_EQ(byteStream.getSize(), size); + } while (index++ < iterations); + ASSERT_EQ(byteStream.getSize(), size_t(0)); +} + +} diff --git a/src/modules/core/tests/CommandTest.cpp b/src/modules/core/tests/CommandTest.cpp new file mode 100644 index 000000000..2df43e499 --- /dev/null +++ b/src/modules/core/tests/CommandTest.cpp @@ -0,0 +1,14 @@ +#include +#include "core/Command.h" + +namespace core { + +TEST(CommandTest, testExecute) { + ASSERT_FALSE(Command::execute("test")); + Command::registerCommand2("test", [] () {}); + ASSERT_TRUE(Command::execute("test")); + Command::unregisterCommand("test"); + ASSERT_FALSE(Command::execute("test")); +} + +} diff --git a/src/modules/core/tests/EventBusTest.cpp b/src/modules/core/tests/EventBusTest.cpp new file mode 100644 index 000000000..ce70528af --- /dev/null +++ b/src/modules/core/tests/EventBusTest.cpp @@ -0,0 +1,133 @@ +#include +#include "core/EventBus.h" + +namespace core { + +EVENTBUSEVENT(TestEvent); + +template +class CountHandlerTest: public IEventBusHandler { +private: + int _count; +public: + CountHandlerTest() : _count(0) {} + + void onEvent(const T&) override { + ++_count; + } + + inline int getCount() const { + return _count; + } +}; + +class HandlerTest: public CountHandlerTest { +}; + +TEST(EventBusTest, testSubscribeAndPublish_1) { + EventBus eventBus; + HandlerTest handler; + TestEvent event; + + eventBus.subscribe(handler); + ASSERT_EQ(1, eventBus.publish(event)) << "Expected one handler to be notified"; + ASSERT_EQ(1, handler.getCount()) << "Expected the handler to be notified once"; + + ASSERT_EQ(1, eventBus.unsubscribe(handler)); + ASSERT_EQ(0, eventBus.publish(event)) << "Expected no handler to be notified"; + ASSERT_EQ(1, handler.getCount()) << "Expected the handler not to be notified twice because we unsubscribed it before we published the event"; +} + +TEST(EventBusTest, testMassSubscribeAndPublish_10000000) { + EventBus eventBus; + HandlerTest handler; + TestEvent event; + + const int n = 10000000; + for (int i = 0; i < n; ++i) { + eventBus.subscribe(handler); + } + ASSERT_EQ(n, eventBus.publish(event)) << "Unexpected amount of handlers notified"; + ASSERT_EQ(n, handler.getCount()) << "Unexpected handler notification amount"; + + ASSERT_EQ(n, eventBus.unsubscribe(handler)); + ASSERT_EQ(0, eventBus.publish(event)) << "Expected no handler to be notified"; + ASSERT_EQ(n, handler.getCount()) << "Expected the handler not to be notified again because we unsubscribed it before we published the event"; +} + +TEST(EventBusTest, testSubscribeAndUnsubscribe_1000) { + EventBus eventBus; + HandlerTest handler; + + const int n = 1000; + for (int i = 0; i < n; ++i) { + eventBus.subscribe(handler); + } + ASSERT_EQ(n, eventBus.unsubscribe(handler)); +} + +TEST(EventBusTest, testMassPublish_10000000) { + EventBus eventBus; + HandlerTest handler; + TestEvent event; + + eventBus.subscribe(handler); + const int n = 10000000; + for (int i = 0; i < n; ++i) { + ASSERT_EQ(1, eventBus.publish(event)) << "Unexpected amount of handlers notified"; + ASSERT_EQ(i + 1, handler.getCount()) << "Unexpected handler notification amount"; + } + + ASSERT_EQ(1, eventBus.unsubscribe(handler)); + ASSERT_EQ(0, eventBus.publish(event)) << "Expected no handler to be notified"; + ASSERT_EQ(n, handler.getCount()) << "Expected the handler not to be notified again because we unsubscribed it before we published the event"; +} + +#define TOPIC(topic) \ +class topic: public IEventBusTopic {}; \ +topic __##topic + +#define EVENT(event, topic) \ +class event: public IEventBusEvent { public: event(topic _##topic) : IEventBusEvent(&_##topic) {} event() : IEventBusEvent(nullptr) {} } + +#define EVENTTOPIC(event, topic) \ +TOPIC(topic); \ +EVENT(event, topic); + +#define EVENTTOPICHANDLER(event, topic, handler) \ +EVENTTOPIC(event, topic); \ +class handler: public CountHandlerTest {} + +TEST(EventBusTest, testTopic_1) { + EVENTTOPICHANDLER(Topic1Event, Topic1, Topic1EventHandler); + EventBus eventBus; + Topic1EventHandler handler; + Topic1Event event(__Topic1); + + eventBus.subscribe(handler, &__Topic1); + ASSERT_EQ(1, eventBus.publish(event)) << "Unexpected amount of handlers notified - topic filtering isn't working"; + ASSERT_EQ(1, handler.getCount()) << "Unexpected handler notification amount"; + + Topic1Event noTopicEvent; + ASSERT_EQ(0, eventBus.publish(noTopicEvent)) << "Unexpected amount of handlers notified - topic filtering isn't working"; + ASSERT_EQ(1, handler.getCount()) << "Unexpected handler notification amount"; +} + +TEST(EventBusTest, testMultipleTopics_1) { + EVENTTOPICHANDLER(Topic1Event, Topic1, Topic1EventHandler); + EventBus eventBus; + Topic1EventHandler handler; + Topic1Event event(__Topic1); + + eventBus.subscribe(handler, &__Topic1); + eventBus.subscribe(handler); + ASSERT_EQ(2, eventBus.publish(event)) << "Unexpected amount of handlers notified - topic filtering isn't working"; + ASSERT_EQ(2, handler.getCount()) << "Unexpected handler notification amount"; + + eventBus.unsubscribe(handler, &__Topic1); + Topic1Event noTopicEvent; + ASSERT_EQ(1, eventBus.publish(noTopicEvent)) << "Unexpected amount of handlers notified - topic filtering isn't working"; + ASSERT_EQ(3, handler.getCount()) << "Unexpected handler notification amount"; +} + +} diff --git a/src/modules/core/tests/QuadTreeTest.cpp b/src/modules/core/tests/QuadTreeTest.cpp new file mode 100644 index 000000000..41fbe6a61 --- /dev/null +++ b/src/modules/core/tests/QuadTreeTest.cpp @@ -0,0 +1,71 @@ +#include +#include "core/QuadTree.h" + +namespace core { + +class Item { +private: + RectFloat _rect; + int _id; +public: + Item(const RectFloat& rect, int id) : + _rect(rect), _id(id) { + } + + RectFloat getRect() const { + return _rect; + } + + bool operator==(const Item& rhs) const { + return rhs._id == _id; + } +}; + +TEST(QuadTreeTest, testAdd) { + core::QuadTree quadTree(RectFloat(0, 0, 100, 100)); + ASSERT_EQ(0, quadTree.count())<< "Expected to have no entries in the quad tree"; + const Item item1(RectFloat(51, 51, 53, 53), 1); + ASSERT_TRUE(quadTree.insert(item1)); + ASSERT_EQ(1, quadTree.count())<< "Expected to have 1 entry in the quad tree"; + const Item item2(RectFloat(15, 15, 18, 18), 2); + ASSERT_TRUE(quadTree.insert(item2)); + ASSERT_EQ(2, quadTree.count())<< "Expected to have 2 entries in the quad tree"; +} + +TEST(QuadTreeTest, testRemove) { + core::QuadTree quadTree(RectFloat(0, 0, 100, 100)); + ASSERT_EQ(0, quadTree.count())<< "Expected to have no entries in the quad tree"; + const Item item(RectFloat(51, 51, 53, 53), 1); + ASSERT_TRUE(quadTree.insert(item)); + ASSERT_EQ(1, quadTree.count())<< "Expected to have 1 entry in the quad tree"; + ASSERT_TRUE(quadTree.remove(item)); + ASSERT_EQ(0, quadTree.count())<<"Expected to have 0 entries in the quad tree"; +} + +TEST(QuadTreeTest, testMax) { + core::QuadTree quadTree(RectFloat::getMaxRect()); + ASSERT_EQ(0, quadTree.count())<< "Expected to have no entries in the quad tree"; + const Item item1(RectFloat(51, 51, 53, 53), 1); + ASSERT_TRUE(quadTree.insert(item1)) << "Could not enter the item"; + ASSERT_EQ(1, quadTree.count())<< "Expected to have 1 entry in the quad tree"; +} + +TEST(QuadTreeTest, testQuery) { + core::QuadTree quadTree(RectFloat(0, 0, 100, 100)); + { + const QuadTree::Contents& contents = quadTree.query(RectFloat(50, 50, 60, 60)); + ASSERT_EQ(0u, contents.size())<<"expected to find nothing in an empty tree"; + } + const Item item1(RectFloat(51, 51, 53, 53), 1); + ASSERT_TRUE(quadTree.insert(item1)); + { + const QuadTree::Contents& contents = quadTree.query(RectFloat::getMaxRect()); + ASSERT_EQ(1u, contents.size())<<"expected to find one entry for the max rect"; + } + { + const QuadTree::Contents& contents = quadTree.query(item1.getRect()); + ASSERT_EQ(1u, contents.size())<<"expected to find one entry for the item rect"; + } +} + +} diff --git a/src/modules/core/tests/RectTest.cpp b/src/modules/core/tests/RectTest.cpp new file mode 100644 index 000000000..60698271c --- /dev/null +++ b/src/modules/core/tests/RectTest.cpp @@ -0,0 +1,31 @@ +#include +#include "core/Rect.h" + +namespace core { + +TEST(RectTest, testContains) { + RectuInt aabb(0, 0, 100, 100); + + ASSERT_TRUE(aabb.contains(aabb)); + ASSERT_TRUE(aabb.contains(RectuInt(0, 0, 1, 1))); + ASSERT_TRUE(aabb.contains(RectuInt(99, 99, 100, 100))); + + ASSERT_FALSE(aabb.contains(RectuInt(101, 101, 102, 102))); + ASSERT_FALSE(aabb.contains(RectuInt(0, 0, 101, 101))); + ASSERT_FALSE(aabb.contains(RectuInt(100, 100, 101, 101))); + ASSERT_FALSE(aabb.contains(RectuInt(1, 100, 100, 101))); +} + +TEST(RectTest, testIntersectswith) { + RectuInt aabb(0, 0, 100, 100); + ASSERT_TRUE(aabb.intersectsWith(aabb)); + ASSERT_TRUE(aabb.intersectsWith(RectuInt(0, 0, 1, 1))); + ASSERT_TRUE(aabb.intersectsWith(RectuInt(99, 99, 100, 100))); + ASSERT_TRUE(aabb.intersectsWith(RectuInt(0, 0, 101, 101))); + ASSERT_TRUE(aabb.intersectsWith(RectuInt(1, 99, 100, 100))); + + ASSERT_FALSE(aabb.intersectsWith(RectuInt(101, 101, 102, 102))); + ASSERT_FALSE(aabb.intersectsWith(RectuInt(100, 100, 101, 101))); +} + +} diff --git a/src/modules/core/tests/SetTest.cpp b/src/modules/core/tests/SetTest.cpp new file mode 100644 index 000000000..613241089 --- /dev/null +++ b/src/modules/core/tests/SetTest.cpp @@ -0,0 +1,39 @@ +#include +#include "core/Set.h" + +namespace core { + +TEST(SetTest, testDiff) { + std::unordered_set set1; + const int n = 1000; + for (int i = 0; i < n; ++i) { + set1.insert(i); + } + std::unordered_set set2; + for (int i = 0; i < n; ++i) { + set2.insert(i); + } + set2.insert(n + 1); + auto diff = core::setDifference(set1, set2); + ASSERT_FALSE(diff.empty()); + ASSERT_EQ(1u, diff.size()); +} + +TEST(SetTest, testDiff2) { + std::unordered_set set1; + const int n = 1000; + for (int i = 0; i < n; ++i) { + set1.insert(i); + set1.insert(-n - i); + } + std::unordered_set set2; + for (int i = 0; i < n; ++i) { + set2.insert(i); + set2.insert(n + i); + } + auto diff = core::setDifference(set1, set2); + ASSERT_FALSE(diff.empty()); + ASSERT_EQ(2000u, diff.size()); +} + +} diff --git a/src/modules/core/tests/ThreadPoolTest.cpp b/src/modules/core/tests/ThreadPoolTest.cpp new file mode 100644 index 000000000..44c2bf6b3 --- /dev/null +++ b/src/modules/core/tests/ThreadPoolTest.cpp @@ -0,0 +1,33 @@ +#include +#include "core/ThreadPool.h" + +namespace core { + +class ThreadPoolTest: public ::testing::Test { +public: + std::atomic_int _count; + bool _executed; + ThreadPoolTest() : + _count(0), _executed(false) { + } +}; + +TEST_F(ThreadPoolTest, testPush) { + core::ThreadPool pool(1); + auto future = pool.push([this] () {_executed = true;}); + future.get(); + ASSERT_TRUE(_executed) << "Thread wasn't executed"; +} + +TEST_F(ThreadPoolTest, testMultiplePush) { + const int x = 1000; + { + core::ThreadPool pool(2); + for (int i = 0; i < x; ++i) { + pool.push([this] () {_count++;}); + } + } + ASSERT_EQ(x, _count) << "Not all threads were executed"; +} + +} diff --git a/src/modules/core/tests/TokenizerTest.cpp b/src/modules/core/tests/TokenizerTest.cpp new file mode 100644 index 000000000..e50c3fa43 --- /dev/null +++ b/src/modules/core/tests/TokenizerTest.cpp @@ -0,0 +1,24 @@ +#include +#include "core/Tokenizer.h" + +namespace core { + +TEST(TokenizerTest, testTokenizerSimple) { + ASSERT_EQ(9u, core::Tokenizer("some nice string that is easy to be tokenized").size()); + ASSERT_EQ(3u, core::Tokenizer("foo()").size()); + ASSERT_EQ("foo", core::Tokenizer("foo()").next()); + ASSERT_EQ(5u, core::Tokenizer("a +foo\nb+bar\nc +foobar").size()); + ASSERT_EQ(1u, core::Tokenizer("\"somecommand +\"").size()); + ASSERT_EQ(2u, core::Tokenizer("\"somecommand +\" \"somecommand +\"").size()); + ASSERT_EQ(1u, core::Tokenizer("\"somecommand \\\"inner\\\"\"").size()); + ASSERT_EQ(3u, core::Tokenizer("1 \"somecommand \\\"inner\\\"\" 3").size()); + ASSERT_EQ(4u, core::Tokenizer("()()").size()); + ASSERT_EQ(0u, core::Tokenizer("\n").size()); + ASSERT_EQ("foo", core::Tokenizer("foo\n").next()); + ASSERT_EQ("foo", core::Tokenizer("\nfoo\n").next()); + ASSERT_EQ(4u, core::Tokenizer("{}{}").size()); + ASSERT_EQ(4u, core::Tokenizer("(){}").size()); + ASSERT_EQ(8u, core::Tokenizer("w +foo\nalt+a \"somecommand +\"\nCTRL+s +bar\nSHIFT+d +xyz\n").size()); +} + +} diff --git a/src/modules/core/tests/VarTest.cpp b/src/modules/core/tests/VarTest.cpp new file mode 100644 index 000000000..ab89e2a2f --- /dev/null +++ b/src/modules/core/tests/VarTest.cpp @@ -0,0 +1,14 @@ +#include +#include "core/Var.h" + +namespace core { + +TEST(VarTest, testChange) { + const VarPtr& v = Var::get("test", "nonsense"); + ASSERT_EQ("nonsense", v->strVal()); + v->setVal("1"); + ASSERT_EQ("1", v->strVal()); + ASSERT_EQ(1, v->intVal()); +} + +} diff --git a/src/modules/dbpost/CMakeLists.txt b/src/modules/dbpost/CMakeLists.txt new file mode 100644 index 000000000..d0e8b591d --- /dev/null +++ b/src/modules/dbpost/CMakeLists.txt @@ -0,0 +1,20 @@ +fips_begin_module(dbpost) + fips_files( + PQConnect.cpp PQConnect.h + PQStore.cpp PQStore.h + StoreInterface.cpp StoreInterface.h + ) + set(PostgreSQL_ADDITIONAL_VERSIONS "9.3" "9.4.1") + set(PostgreSQL_ADDITIONAL_SEARCH_PATHS "/usr/include/postgresql/9.3/server" "/usr/include/postgresql/9.4/server") + find_package(PostgreSQL REQUIRED) + include_directories(${PostgreSQL_INCLUDE_DIRS}) + fips_deps(core ${PostgreSQL_LIBRARIES}) +fips_end_module() + +begin_googleunittest(dbpost) + fips_dir(tests) + fips_files( + PQStoreTest.cpp + ) + fips_deps(dbpost) +end_googleunittest() diff --git a/src/modules/dbpost/PQConnect.cpp b/src/modules/dbpost/PQConnect.cpp new file mode 100644 index 000000000..e5fd29744 --- /dev/null +++ b/src/modules/dbpost/PQConnect.cpp @@ -0,0 +1,64 @@ +#include "PQConnect.h" +#include "core/Log.h" + +namespace dbpost { + +PQConnect::PQConnect() : + _pgConnection(nullptr) { +} + +PQConnect::~PQConnect() { + disconnect(); +} + +void PQConnect::setLoginData(const std::string& username, const std::string& password) { + _password = password; + _user = username; +} + +void PQConnect::changeDb(const std::string& dbname) { + _dbname = dbname; +} + +void PQConnect::changeHost(const std::string& host) { + _host = host; +} + +void PQConnect::changePort(const std::string& port) { + _port = port; +} + +int PQConnect::connect() { + //const std::string conninfo = "hostaddr=" + _host + " port=" + _port + " dbname=" + _dbname + " user=" + _user + " password=" + _password; + std::string conninfo = ""; + + if (!_host.empty()) + conninfo += " host=" + _host; + if (!_dbname.empty()) + conninfo += " dbname=" + _dbname; + if (!_user.empty()) + conninfo += " user=" + _user; + if (!_password.empty()) + conninfo += " password=" + _password; + if (!_port.empty()) + conninfo += " port=" + _port; + + Log::info("Connection: %s", conninfo.c_str()); + + _pgConnection = PQconnectdb(conninfo.c_str()); + + if (PQstatus(_pgConnection) != CONNECTION_OK) { + Log::error("Connection to database failed: %s", PQerrorMessage(_pgConnection)); + disconnect(); + return -1; + } + + return 0; +} + +void PQConnect::disconnect() { + PQfinish(_pgConnection); + _pgConnection = nullptr; +} + +} diff --git a/src/modules/dbpost/PQConnect.h b/src/modules/dbpost/PQConnect.h new file mode 100644 index 000000000..853248c57 --- /dev/null +++ b/src/modules/dbpost/PQConnect.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +namespace dbpost { + +class PQConnect { +private: + PGconn* _pgConnection; + std::string _host; + std::string _port; + std::string _dbname; + std::string _user; + std::string _password; +public: + PQConnect(); + ~PQConnect(); + void setLoginData(const std::string& username, const std::string& password); + void changeHost(const std::string& host); + void changePort(const std::string& port); + void changeDb(const std::string& dbname); + void disconnect(); + int connect(); + PGconn* connection() const; +}; + +inline PGconn* PQConnect::connection() const { + return _pgConnection; +} + +} diff --git a/src/modules/dbpost/PQStore.cpp b/src/modules/dbpost/PQStore.cpp new file mode 100644 index 000000000..b56f2864c --- /dev/null +++ b/src/modules/dbpost/PQStore.cpp @@ -0,0 +1,160 @@ +#include "PQStore.h" +#include "StoreInterface.h" +#include "core/Log.h" +#include + +namespace dbpost { + +PQStore::PQStore(PQConnect* conn) : + _connection(conn), _usable(true), _res(nullptr), _lastState(PGRES_EMPTY_QUERY), _affectedRows(0) { +} + +void PQStore::storeModel(StoreInterface& model) { + const std::string& insertSql = sqlBuilder(model, false); + + //trBegin(); + query(insertSql); + //trEnd(); +} + +void PQStore::createNeeds(const StoreInterface& model) { + const std::string& crSql = model.getCreate(); + query(crSql); +} + +std::unordered_map PQStore::loadModel(const StoreInterface& model) { + const std::string& loadSql = sqlLoadBuilder(model, false); + Log::trace("sql used %s", loadSql.c_str()); + std::unordered_map dbResult; + if (query(loadSql) && _affectedRows == 1) { + const int nFields = PQnfields(_res); + for (int i = 0; i < nFields; ++i) { + const char* name = PQfname(_res, i); + const char* value = PQgetvalue(_res, 0, i); + dbResult[std::string(name)] = std::string(value); + //model.update(tname, fvalue); + } + } + PQclear(_res); + + return dbResult; +} + +std::string PQStore::sqlBuilder(const StoreInterface& model, bool update) const { + std::stringstream insertSql; + insertSql << "INSERT INTO " << model.getTableName() << " "; + std::stringstream fieldKeys; + std::stringstream valueKeys; + + const std::unordered_map& fields = model.getFields(); + + std::string add = ""; + for (auto p = fields.begin(); p != fields.end(); ++p) { + const std::string& strKey = p->first; + const std::string& strValue = p->second; + if (!model.isSerial(strKey)) { + fieldKeys << add << strKey; + valueKeys << add << "'" << strValue << "'"; + add = ", "; + } + } + + insertSql << "(" << fieldKeys.str() << ") VALUES (" << valueKeys.str() << ");"; + const std::string& str = insertSql.str(); + Log::trace("used query %s", str.c_str()); + return str; +} + +std::string PQStore::sqlLoadBuilder(const StoreInterface& model, bool update) const { + std::string loadSql = "SELECT * FROM " + model.getTableName() + " "; + std::string fieldKeys = ""; + + const std::unordered_map& fields = model.getFields(); + + std::string add = ""; + for (auto p = fields.begin(); p != fields.end(); ++p) { + const std::string& strKey = p->first; + const std::string& strValue = p->second; + if (!model.isSerial(strKey)) { + fieldKeys += add + strKey + " = '" + strValue + "'"; + add = " AND "; + } + } + + loadSql += "WHERE " + fieldKeys + ";"; + return loadSql; +} + +void PQStore::trBegin() { + if (!_usable) + return; + + _res = PQexec(_connection->connection(), "BEGIN"); + if (checkLastResult()) { + // anyway ..res no longer needed but already closed in case of fail + PQclear(_res); + } +} + +void PQStore::trEnd() { + if (!_usable) + return; + + _res = PQexec(_connection->connection(), "END"); + if (checkLastResult()) { + // anyway ..res no longer needed but already closed in case of fail + PQclear(_res); + } +} + +bool PQStore::checkLastResult() { + _affectedRows = 0; + Log::info("get result"); + if (_res != nullptr) + _lastState = PQresultStatus(_res); + else + return false; + + if ((_lastState == PGRES_EMPTY_QUERY) || (_lastState == PGRES_BAD_RESPONSE) || (_lastState == PGRES_FATAL_ERROR)) { + PQclear(_res); + char* msg = PQerrorMessage(_connection->connection()); + _lastErrorMsg = std::string(msg); + + Log::error("Failed to execute sql: %s ", _lastErrorMsg.c_str()); + return false; + } + + if (_lastState == PGRES_COMMAND_OK) { + // no data in return but all fine + PQclear(_res); + _affectedRows = 0; + return true; + } + + if (_lastState == PGRES_TUPLES_OK) { + _affectedRows = PQntuples(_res); + Log::info("Data read %i", _affectedRows); + return true; + } + + Log::error("not catched state: %s", PQresStatus(_lastState)); + // what else ? + return false; +} + +bool PQStore::query(const std::string& query) { + if (_usable) { + Log::trace("SEND: %s", query.c_str()); + _res = PQexec(_connection->connection(), query.c_str()); + return checkLastResult(); + } + Log::error("DB Error: connection not usable"); + return false; +} + +PQStore::~PQStore() { + // TODO: assigning a nullptr is not possible for a reference + //_connection = nullptr; +} + +} diff --git a/src/modules/dbpost/PQStore.h b/src/modules/dbpost/PQStore.h new file mode 100644 index 000000000..c8b5ca435 --- /dev/null +++ b/src/modules/dbpost/PQStore.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include +#include "core/NonCopyable.h" +#include "PQConnect.h" +#include "StoreInterface.h" + +typedef std::unordered_map TStrStrMap; +typedef std::pair TStrStrPair; + +namespace dbpost { + +class PQStore : public core::NonCopyable { +private: + std::string sqlBuilder(const StoreInterface& model, bool update) const; + std::string sqlLoadBuilder(const StoreInterface& model, bool update) const; + PQConnect* _connection; + bool _usable; + PGresult* _res; + std::string _lastErrorMsg; + ExecStatusType _lastState; + int _affectedRows; +public: + PQStore(PQConnect* conn); + bool query(const std::string& query); + void trBegin(); + void trEnd(); + bool checkLastResult(); + void storeModel(StoreInterface& model); + void createNeeds(const StoreInterface& model); + std::unordered_map loadModel(const StoreInterface& model); + ~PQStore(); + + PGresult* result() const; +}; + +inline PGresult* PQStore::result() const { + return _res; +} +} diff --git a/src/modules/dbpost/StoreInterface.cpp b/src/modules/dbpost/StoreInterface.cpp new file mode 100644 index 000000000..4378fb356 --- /dev/null +++ b/src/modules/dbpost/StoreInterface.cpp @@ -0,0 +1 @@ +#include "StoreInterface.h" diff --git a/src/modules/dbpost/StoreInterface.h b/src/modules/dbpost/StoreInterface.h new file mode 100644 index 000000000..84d0f01cc --- /dev/null +++ b/src/modules/dbpost/StoreInterface.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include +#include +#include + +namespace dbpost { + +class StoreInterface { +public: + virtual ~StoreInterface() { + } + virtual std::string getCreate() const = 0; + virtual std::string getTableName() const = 0; + virtual std::unordered_map getFields() const = 0; + virtual void update(const std::string& fieldName,const std::string& value) const = 0; + virtual bool isSerial(const std::string& fieldname) const = 0; +}; + +} diff --git a/src/modules/dbpost/tests/PQStoreTest.cpp b/src/modules/dbpost/tests/PQStoreTest.cpp new file mode 100644 index 000000000..95874146c --- /dev/null +++ b/src/modules/dbpost/tests/PQStoreTest.cpp @@ -0,0 +1,8 @@ +#include + +namespace dbpost { + +TEST(PQStoreTest, testFoo) { +} + +} diff --git a/src/modules/frontend/CMakeLists.txt b/src/modules/frontend/CMakeLists.txt new file mode 100644 index 000000000..e3e6aa561 --- /dev/null +++ b/src/modules/frontend/CMakeLists.txt @@ -0,0 +1,16 @@ +fips_begin_module(frontend) + fips_files( + ClientEntity.h ClientEntity.cpp + ClientEntityId.h + MeshShader.h MeshShader.cpp + WorldShader.h WorldShader.cpp + WaterShader.h WaterShader.cpp + ) + fips_dir(ui) + fips_files( + LoginWindow.h + ) + find_package(SDL2 REQUIRED) + include_directories(${SDL2_INCLUDE_DIRS}) + fips_deps(ui network voxel cooldown ${SDL2_LIBRARIES}) +fips_end_module() diff --git a/src/modules/frontend/ClientEntity.cpp b/src/modules/frontend/ClientEntity.cpp new file mode 100644 index 000000000..84d5ddc83 --- /dev/null +++ b/src/modules/frontend/ClientEntity.cpp @@ -0,0 +1,19 @@ +#include "ClientEntity.h" + +namespace frontend { + +ClientEntity::ClientEntity(ClientEntityId id, int type, long now, const glm::vec3& pos, float orientation, const video::MeshPtr& mesh) : + _id(id), _type(type), _orientation(orientation), _mesh(mesh) { + _posLerp.setPosition(now, pos); +} + +void ClientEntity::lerpPosition(long now, const glm::vec3& position, float orientation) { + _posLerp.lerpPosition(now, position); + _orientation = orientation; +} + +void ClientEntity::update(long now) { + _posLerp.update(now); +} + +} diff --git a/src/modules/frontend/ClientEntity.h b/src/modules/frontend/ClientEntity.h new file mode 100644 index 000000000..235dd0080 --- /dev/null +++ b/src/modules/frontend/ClientEntity.h @@ -0,0 +1,60 @@ +#pragma once + +#include "ClientEntityId.h" +#include "util/PosLerp.h" +#include +#include +#include "video/Mesh.h" +#include + +namespace frontend { + +class ClientEntity { +private: + util::PosLerp _posLerp; + ClientEntityId _id; + int _type; + float _orientation; + video::MeshPtr _mesh; +public: + ClientEntity(ClientEntityId id, int type, long now, const glm::vec3& pos, float orientation, const video::MeshPtr& mesh); + + void lerpPosition(long now, const glm::vec3& position, float orientation); + void update(long now); + + inline int type() const { + return _type; + } + + inline ClientEntityId id() const { + return _id; + } + + inline float orientation() const { + return _orientation; + } + + inline const glm::vec3& position() const { + return _posLerp.position(); + } + + inline const video::MeshPtr& mesh() const { + return _mesh; + } + + inline bool operator==(const ClientEntity& other) const { + return _id == other._id; + } +}; + +typedef std::shared_ptr ClientEntityPtr; + +} + +namespace std { +template<> struct hash { + size_t operator()(const frontend::ClientEntity &c) const { + return hash()(c.id()); + } +}; +} diff --git a/src/modules/frontend/ClientEntityId.h b/src/modules/frontend/ClientEntityId.h new file mode 100644 index 000000000..2d328bb87 --- /dev/null +++ b/src/modules/frontend/ClientEntityId.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace frontend { + +typedef int64_t ClientEntityId; + +} diff --git a/src/modules/frontend/MeshShader.cpp b/src/modules/frontend/MeshShader.cpp new file mode 100644 index 000000000..71da328b0 --- /dev/null +++ b/src/modules/frontend/MeshShader.cpp @@ -0,0 +1,42 @@ +#include "MeshShader.h" + +namespace frontend { + +bool MeshShader::init() { + if (!loadProgram("shaders/mesh")) { + return false; + } + + if (!hasAttribute("a_pos")) { + Log::error("no attribute a_pos found"); + return false; + } + if (!hasAttribute("a_texcoords")) { + Log::error("no attribute a_texcoords found"); + return false; + } + if (!hasAttribute("a_norm")) { + Log::error("no attribute a_norm found"); + return false; + } + if (!hasUniform("u_projection")) { + Log::error("no uniform u_projection found"); + return false; + } + if (!hasUniform("u_model")) { + Log::error("no uniform u_model found"); + return false; + } + if (!hasUniform("u_view")) { + Log::error("no uniform u_view found"); + return false; + } + if (!hasUniform("u_texture")) { + Log::error("no uniform u_texture found"); + return false; + } + + return true; +} + +} diff --git a/src/modules/frontend/MeshShader.h b/src/modules/frontend/MeshShader.h new file mode 100644 index 000000000..1f894abb6 --- /dev/null +++ b/src/modules/frontend/MeshShader.h @@ -0,0 +1,14 @@ +#pragma once + +#include "video/Shader.h" + +namespace frontend { + +class MeshShader : public video::Shader { +public: + bool init(); +}; + +typedef std::shared_ptr MeshShaderPtr; + +} diff --git a/src/modules/frontend/WaterShader.cpp b/src/modules/frontend/WaterShader.cpp new file mode 100644 index 000000000..e422f9e1f --- /dev/null +++ b/src/modules/frontend/WaterShader.cpp @@ -0,0 +1,42 @@ +#include "WaterShader.h" + +namespace frontend { + +bool WaterShader::init() { + if (!loadProgram("shaders/water")) { + return false; + } + + if (!hasAttribute("a_pos")) { + Log::error("no attribute a_pos found"); + return false; + } + if (!hasUniform("u_projection")) { + Log::error("no uniform u_projection found"); + return false; + } + if (!hasUniform("u_model")) { + Log::error("no uniform u_model found"); + return false; + } + if (!hasUniform("u_view")) { + Log::error("no uniform u_view found"); + return false; + } + if (!hasUniform("u_wavetime")) { + Log::error("no uniform u_wavetime found"); + return false; + } + if (!hasUniform("u_wavewidth")) { + Log::error("no uniform u_wavewidth found"); + return false; + } + if (!hasUniform("u_waveheight")) { + Log::error("no uniform u_waveheight found"); + return false; + } + + return true; +} + +} diff --git a/src/modules/frontend/WaterShader.h b/src/modules/frontend/WaterShader.h new file mode 100644 index 000000000..bc98aa011 --- /dev/null +++ b/src/modules/frontend/WaterShader.h @@ -0,0 +1,14 @@ +#pragma once + +#include "video/Shader.h" + +namespace frontend { + +class WaterShader : public video::Shader { +public: + bool init(); +}; + +typedef std::shared_ptr WaterShaderPtr; + +} diff --git a/src/modules/frontend/WorldShader.cpp b/src/modules/frontend/WorldShader.cpp new file mode 100644 index 000000000..2046ca0a8 --- /dev/null +++ b/src/modules/frontend/WorldShader.cpp @@ -0,0 +1,34 @@ +#include "WorldShader.h" + +namespace frontend { + +bool WorldShader::init() { + if (!loadProgram("shaders/world")) { + return false; + } + + if (!hasAttribute("a_pos")) { + Log::error("no attribute a_pos found"); + return false; + } + if (!hasAttribute("a_materialdensity")) { + Log::error("no attribute a_materialdensity found"); + return false; + } + if (!hasUniform("u_projection")) { + Log::error("no uniform u_projection found"); + return false; + } + if (!hasUniform("u_model")) { + Log::error("no uniform u_model found"); + return false; + } + if (!hasUniform("u_view")) { + Log::error("no uniform u_view found"); + return false; + } + + return true; +} + +} diff --git a/src/modules/frontend/WorldShader.h b/src/modules/frontend/WorldShader.h new file mode 100644 index 000000000..e1a1bcceb --- /dev/null +++ b/src/modules/frontend/WorldShader.h @@ -0,0 +1,14 @@ +#pragma once + +#include "video/Shader.h" + +namespace frontend { + +class WorldShader : public video::Shader { +public: + bool init(); +}; + +typedef std::shared_ptr WorldShaderPtr; + +} diff --git a/src/modules/frontend/ui/AuthFailedWindow.h b/src/modules/frontend/ui/AuthFailedWindow.h new file mode 100644 index 000000000..b5e635d6b --- /dev/null +++ b/src/modules/frontend/ui/AuthFailedWindow.h @@ -0,0 +1,24 @@ +#pragma once + +#include "ui/Window.h" +#include "core/Common.h" + +namespace frontend { + +class AuthFailedWindow: public ui::Window { +public: + AuthFailedWindow(Window* parent) : + ui::Window(parent) { + core_assert(loadResourceFile("ui/window/authfailed.tb.txt")); + } + + bool OnEvent(const tb::TBWidgetEvent &ev) override { + if (ev.type == tb::EVENT_TYPE_CLICK && ev.target->GetID() == tb::TBIDC("ok")) { + Close(); + return true; + } + return ui::Window::OnEvent(ev); + } +}; + +} diff --git a/src/modules/frontend/ui/DisconnectWindow.h b/src/modules/frontend/ui/DisconnectWindow.h new file mode 100644 index 000000000..b136df973 --- /dev/null +++ b/src/modules/frontend/ui/DisconnectWindow.h @@ -0,0 +1,24 @@ +#pragma once + +#include "ui/Window.h" +#include "core/Common.h" + +namespace frontend { + +class DisconnectWindow: public ui::Window { +public: + DisconnectWindow(Window* parent) : + ui::Window(parent) { + core_assert(loadResourceFile("ui/window/disconnect.tb.txt")); + } + + bool OnEvent(const tb::TBWidgetEvent &ev) override { + if (ev.type == tb::EVENT_TYPE_CLICK && ev.target->GetID() == tb::TBIDC("ok")) { + Close(); + return true; + } + return ui::Window::OnEvent(ev); + } +}; + +} diff --git a/src/modules/frontend/ui/HudWindow.h b/src/modules/frontend/ui/HudWindow.h new file mode 100644 index 000000000..14cd56f2a --- /dev/null +++ b/src/modules/frontend/ui/HudWindow.h @@ -0,0 +1,29 @@ +#pragma once + +#include "ui/Window.h" +#include "core/Common.h" +#include "Client.h" + +namespace frontend { + +class HudWindow: public ui::Window { +private: + Client* _client; +public: + HudWindow(Client* client, int width, int /*height*/) : + ui::Window(client), _client(client) { + core_assert(loadResourceFile("ui/window/hud.tb.txt")); + SetSettings(tb::WINDOW_SETTINGS_NONE); + SetSize(width, 20); + } + + bool OnEvent(const tb::TBWidgetEvent &ev) override { + if (ev.type == tb::EVENT_TYPE_CLICK && ev.target->GetID() == tb::TBIDC("disconnect")) { + _client->disconnect(); + return true; + } + return ui::Window::OnEvent(ev); + } +}; + +} diff --git a/src/modules/frontend/ui/LoginWindow.h b/src/modules/frontend/ui/LoginWindow.h new file mode 100644 index 000000000..3de12f2f3 --- /dev/null +++ b/src/modules/frontend/ui/LoginWindow.h @@ -0,0 +1,50 @@ +#pragma once + +#include "ui/Window.h" +#include "core/Common.h" +#include "Client.h" + +namespace frontend { + +class LoginWindow: public ui::Window { +private: + Client* _client; +public: + LoginWindow(Client* client) : + ui::Window(client), _client(client) { + core_assert(loadResourceFile("ui/window/login.tb.txt")); + SetSettings(tb::WINDOW_SETTINGS_TITLEBAR); + + const std::string& email = core::Var::get("cl_email")->strVal(); + const std::string& password = core::Var::get("cl_password")->strVal(); + if (!email.empty()) + GetWidgetByID(tb::TBID("email"))->SetText(email.c_str()); + if (!password.empty()) + GetWidgetByID(tb::TBID("password"))->SetText(password.c_str()); + } + + bool OnEvent(const tb::TBWidgetEvent &ev) override { + if ((ev.type == tb::EVENT_TYPE_CLICK && ev.target->GetID() == tb::TBIDC("login")) || ev.special_key == tb::TB_KEY_ENTER) { + TBWidget *email = ev.target->GetParentWindow()->GetWidgetByID(tb::TBID("email")); + TBWidget *password = ev.target->GetParentWindow()->GetWidgetByID(tb::TBID("password")); + + core::Var::get("cl_email")->setVal(email->GetText().CStr()); + core::Var::get("cl_password")->setVal(password->GetText().CStr()); + + const core::VarPtr& port = core::Var::get("cl_port", "11337"); + const core::VarPtr& host = core::Var::get("cl_host", "127.0.0.1"); + if (!_client->connect(port->intVal(), host->strVal())) { + tb::TBStr text; + text.SetFormatted("Failed to connect"); + tb::TBMessageWindow *win = new tb::TBMessageWindow(this, tb::TBIDC("")); + win->Show("Failed to connect", text); + } else { + Close(); + } + return true; + } + return ui::Window::OnEvent(ev); + } +}; + +} diff --git a/src/modules/io/CMakeLists.txt b/src/modules/io/CMakeLists.txt new file mode 100644 index 000000000..ffa99a1ef --- /dev/null +++ b/src/modules/io/CMakeLists.txt @@ -0,0 +1,11 @@ +fips_begin_module(io) + fips_files( + EventHandler.cpp EventHandler.h IEventObserver.h + Filesystem.cpp Filesystem.h + File.cpp File.h + IOResource.h + ) + find_package(SDL2 REQUIRED) + include_directories(${SDL2_INCLUDE_DIRS}) + fips_deps(${SDL2_LIBRARIES}) +fips_end_module() diff --git a/src/modules/io/EventHandler.cpp b/src/modules/io/EventHandler.cpp new file mode 100644 index 000000000..c9ccc8dea --- /dev/null +++ b/src/modules/io/EventHandler.cpp @@ -0,0 +1,331 @@ +#include "EventHandler.h" +#include "IEventObserver.h" +#include "core/Common.h" +#include + +namespace io { + +EventHandler::EventHandler() : + _multiGesture(false) { + //SDL_JoystickEventState(SDL_DISABLE); + SDL_EventState(SDL_JOYAXISMOTION, SDL_ENABLE); +} + +EventHandler::~EventHandler() { +} + +void EventHandler::registerObserver(IEventObserver* observer) { + core_assert(observer); + _observers.push_back(observer); +} + +void EventHandler::removeObserver(IEventObserver* observer) { + // Traverse through the list and try to find the specified observer + for (EventObservers::iterator i = _observers.begin(); i != _observers.end(); ++i) { + if (*i == observer) { + _observers.erase(i); + break; + } + } +} + +inline std::string EventHandler::getControllerButtonName(uint8_t button) const { + const char *name = SDL_GameControllerGetStringForButton(static_cast(button)); + if (name == nullptr) + return "unknown"; + return name; +} + +bool EventHandler::handleEvent(SDL_Event &event) { + switch (event.type) { + case SDL_TEXTINPUT: + textInput(std::string(event.text.text)); + break; + case SDL_KEYUP: + keyRelease((int32_t) event.key.keysym.sym); + break; + case SDL_KEYDOWN: + // we are handling this on our own + if (!event.key.repeat) + keyPress((int32_t) event.key.keysym.sym, (int16_t) event.key.keysym.mod); + break; + case SDL_MOUSEMOTION: { + if (event.motion.which == SDL_TOUCH_MOUSEID) + break; + SDL_Window *window = SDL_GetWindowFromID(event.motion.windowID); + if (!(SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS)) + break; + mouseMotion(event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel); + break; + } + case SDL_MOUSEBUTTONDOWN: + if (event.button.which == SDL_TOUCH_MOUSEID) + break; + mouseButtonPress(event.button.x, event.button.y, event.button.button); + break; + case SDL_MOUSEBUTTONUP: + if (event.button.which == SDL_TOUCH_MOUSEID) + break; + mouseButtonRelease(event.button.x, event.button.y, event.button.button); + break; + case SDL_MOUSEWHEEL: + if (event.wheel.which == SDL_TOUCH_MOUSEID) + break; + mouseWheel(event.wheel.x, event.wheel.y); + break; + case SDL_CONTROLLERAXISMOTION: { + const uint8_t axis = event.caxis.axis; + if (axis != SDL_CONTROLLER_AXIS_LEFTX && axis != SDL_CONTROLLER_AXIS_LEFTY && axis != SDL_CONTROLLER_AXIS_RIGHTX && axis != SDL_CONTROLLER_AXIS_RIGHTY) + break; + const bool horizontal = (axis == SDL_CONTROLLER_AXIS_LEFTX || axis == SDL_CONTROLLER_AXIS_RIGHTX); + joystickMotion(horizontal, event.caxis.value); + break; + } + case SDL_CONTROLLERBUTTONDOWN: + controllerButtonPress(getControllerButtonName(event.cbutton.button)); + break; + case SDL_CONTROLLERBUTTONUP: + controllerButtonRelease(getControllerButtonName(event.cbutton.button)); + break; + case SDL_CONTROLLERDEVICEADDED: + joystickDeviceAdded(event.cdevice.which); + break; + case SDL_CONTROLLERDEVICEREMOVED: + joystickDeviceRemoved(event.cdevice.which); + break; + case SDL_JOYDEVICEADDED: + joystickDeviceAdded(event.jdevice.which); + break; + case SDL_JOYDEVICEREMOVED: + joystickDeviceRemoved(event.jdevice.which); + break; + case SDL_DOLLARRECORD: + gestureRecord(event.dgesture.gestureId); + break; + case SDL_DOLLARGESTURE: + gesture(event.dgesture.gestureId, event.dgesture.error, event.dgesture.numFingers); + break; + case SDL_MULTIGESTURE: + multiGesture(event.mgesture.dTheta, event.mgesture.dDist, event.mgesture.numFingers); + break; + case SDL_JOYHATMOTION: + break; + case SDL_JOYBUTTONDOWN: + joystickButtonPress(event.jbutton.button); + break; + case SDL_JOYBUTTONUP: + joystickButtonRelease(event.jbutton.button); + break; + case SDL_JOYAXISMOTION: + joystickMotion(event.jaxis.axis == 0, event.jaxis.value); + break; + case SDL_FINGERDOWN: + fingerPress(event.tfinger.fingerId, event.tfinger.x, event.tfinger.y); + break; + case SDL_FINGERUP: + fingerRelease(event.tfinger.fingerId, event.tfinger.x, event.tfinger.y); + break; + case SDL_FINGERMOTION: + fingerMotion(event.tfinger.fingerId, event.tfinger.x, event.tfinger.y, event.tfinger.dx, event.tfinger.dy); + break; + case SDL_WINDOWEVENT: + switch (event.window.event) { + case SDL_WINDOWEVENT_RESIZED: + case SDL_WINDOWEVENT_SIZE_CHANGED: + for (EventObservers::iterator i = _observers.begin(); i != _observers.end(); ++i) { + (*i)->onWindowResize(); + } + break; + case SDL_WINDOWEVENT_CLOSE: + return false; + } + break; + } + return true; +} + +bool EventHandler::handleAppEvent(SDL_Event &event) { + switch (event.type) { + case SDL_APP_TERMINATING: + prepareShutdown(); + break; + case SDL_APP_LOWMEMORY: + lowMemory(); + break; + case SDL_APP_WILLENTERBACKGROUND: + prepareBackground(); + return true; + case SDL_APP_DIDENTERBACKGROUND: + background(); + return true; + case SDL_APP_WILLENTERFOREGROUND: + prepareForeground(); + return true; + case SDL_APP_DIDENTERFOREGROUND: + foreground(); + return true; + } + return false; +} + +void EventHandler::joystickDeviceAdded(int32_t device) { + for (IEventObserver* observer : _observers) { + observer->onJoystickDeviceAdded(device); + } +} + +void EventHandler::joystickDeviceRemoved(int32_t device) { + for (IEventObserver* observer : _observers) { + observer->onJoystickDeviceRemoved(device); + } +} + +void EventHandler::lowMemory() { + for (IEventObserver* observer : _observers) { + observer->onLowMemory(); + } +} + +void EventHandler::prepareShutdown() { + for (IEventObserver* observer : _observers) { + observer->onPrepareShutdown(); + } +} + +void EventHandler::prepareBackground() { + for (IEventObserver* observer : _observers) { + observer->onPrepareBackground(); + } +} + +void EventHandler::prepareForeground() { + for (IEventObserver* observer : _observers) { + observer->onPrepareForeground(); + } +} + +void EventHandler::background() { + for (EventObservers::iterator i = _observers.begin(); i != _observers.end(); ++i) { + (*i)->onBackground(); + } +} + +void EventHandler::foreground() { + for (IEventObserver* observer : _observers) { + observer->onForeground(); + } +} + +void EventHandler::joystickMotion(bool horizontal, int value) { + for (IEventObserver* observer : _observers) { + observer->onJoystickMotion(horizontal, value); + } +} + +void EventHandler::mouseWheel(int32_t x, int32_t y) { + for (IEventObserver* observer : _observers) { + observer->onMouseWheel(x, y); + } +} + +void EventHandler::mouseMotion(int32_t x, int32_t y, int32_t relX, int32_t relY) { + for (IEventObserver* observer : _observers) { + observer->onMouseMotion(x, y, relX, relY); + } +} + +void EventHandler::controllerButtonPress(const std::string& button) { + for (IEventObserver* observer : _observers) { + observer->onControllerButtonPress(button); + } +} + +void EventHandler::controllerButtonRelease(const std::string& button) { + for (IEventObserver* observer : _observers) { + observer->onControllerButtonRelease(button); + } +} + +void EventHandler::joystickButtonPress(uint8_t button) { + for (IEventObserver* observer : _observers) { + observer->onJoystickButtonPress(button); + } +} + +void EventHandler::joystickButtonRelease(uint8_t button) { + for (IEventObserver* observer : _observers) { + observer->onJoystickButtonRelease(button); + } +} + +void EventHandler::mouseButtonPress(int32_t x, int32_t y, uint8_t button) { + for (IEventObserver* observer : _observers) { + observer->onMouseButtonPress(x, y, button); + } +} + +void EventHandler::mouseButtonRelease(int32_t x, int32_t y, uint8_t button) { + for (IEventObserver* observer : _observers) { + observer->onMouseButtonRelease(x, y, button); + } +} + +void EventHandler::textInput(const std::string& text) { + for (IEventObserver* observer : _observers) { + observer->onTextInput(text); + } +} + +void EventHandler::keyRelease(int32_t key) { + for (IEventObserver* observer : _observers) { + observer->onKeyRelease(key); + } +} + +void EventHandler::keyPress(int32_t key, int16_t modifier) { + for (IEventObserver* observer : _observers) { + observer->onKeyPress(key, modifier); + } +} + +void EventHandler::fingerPress(int64_t finger, float x, float y) { + for (IEventObserver* observer : _observers) { + observer->onFingerPress(finger, x, y); + } +} + +void EventHandler::fingerRelease(int64_t finger, float x, float y) { + _multiGesture = false; + for (IEventObserver* observer : _observers) { + observer->onFingerRelease(finger, x, y); + } +} + +void EventHandler::fingerMotion(int64_t finger, float x, float y, float dx, float dy) { + if (_multiGesture) + return; + for (IEventObserver* observer : _observers) { + observer->onFingerMotion(finger, x, y, dx, dy); + } +} + +void EventHandler::gestureRecord(int64_t gestureId) { + for (IEventObserver* observer : _observers) { + observer->onGestureRecord(gestureId); + } +} + +void EventHandler::gesture(int64_t gestureId, float error, int32_t numFingers) { + for (IEventObserver* observer : _observers) { + observer->onGesture(gestureId, error, numFingers); + } +} + +void EventHandler::multiGesture(float theta, float dist, int32_t numFingers) { + _multiGesture = true; + for (IEventObserver* observer : _observers) { + observer->onMultiGesture(theta, dist, numFingers); + } +} + +} diff --git a/src/modules/io/EventHandler.h b/src/modules/io/EventHandler.h new file mode 100644 index 000000000..14fe97b31 --- /dev/null +++ b/src/modules/io/EventHandler.h @@ -0,0 +1,61 @@ +#pragma once + +#include +#include +#include + +union SDL_Event; + +namespace io { + +class IEventObserver; + +class EventHandler { +private: + bool _multiGesture; + + typedef std::vector EventObservers; + EventObservers _observers; + + std::string getControllerButtonName(uint8_t button) const; + +public: + EventHandler(); + virtual ~EventHandler(); + + // returns true if the processed event did not lead to the application quit + bool handleEvent(SDL_Event &event); + // returns true if the event was processed, false if it should get added to the event queue. + bool handleAppEvent(SDL_Event &event); + + void registerObserver(IEventObserver* observer); + void removeObserver(IEventObserver* observer); + void joystickDeviceAdded(int32_t device); + void joystickDeviceRemoved(int32_t device); + void lowMemory(); + void prepareShutdown(); + void prepareBackground(); + void prepareForeground(); + void background(); + void foreground(); + void controllerButtonPress(const std::string& button); + void controllerButtonRelease(const std::string& button); + void joystickButtonPress(uint8_t button); + void joystickButtonRelease(uint8_t button); + void joystickMotion(bool horizontal, int value); + void mouseWheel(int32_t x, int32_t y); + void mouseMotion(int32_t x, int32_t y, int32_t relX, int32_t relY); + void mouseButtonPress(int32_t x, int32_t y, uint8_t button); + void mouseButtonRelease(int32_t x, int32_t y, uint8_t button); + void textInput(const std::string& text); + void keyRelease(int32_t key); + void keyPress(int32_t key, int16_t modifier = 0); + void fingerPress(int64_t finger, float x, float y); + void fingerRelease(int64_t finger, float x, float y); + void fingerMotion(int64_t finger, float x, float y, float dx, float dy); + void gestureRecord(int64_t gestureId); + void gesture(int64_t gestureId, float error, int32_t numFingers); + void multiGesture(float theta, float dist, int32_t numFingers); +}; + +} diff --git a/src/modules/io/File.cpp b/src/modules/io/File.cpp new file mode 100644 index 000000000..97fc2dbaf --- /dev/null +++ b/src/modules/io/File.cpp @@ -0,0 +1,156 @@ +#include "File.h" +#include + +namespace io { + +File::File(const std::string& rawPath) : + IOResource(), _file(SDL_RWFromFile(rawPath.c_str(), "rb")), _rawPath(rawPath) { +} + +File::~File() { + close(); +} + +const std::string& File::getName() const { + return _rawPath; +} + +std::string File::load() { + char *includeBuffer; + const int includeLen = read((void **) &includeBuffer); + std::unique_ptr p(includeBuffer); + if (!includeBuffer || includeLen <= 0) { + return ""; + } + return std::string(includeBuffer, includeLen); +} + +long File::write(const unsigned char *buf, size_t len) const { + SDL_RWops *rwops = SDL_RWFromFile(_rawPath.c_str(), "wb"); + if (!rwops) { + return -1L; + } + + int remaining = len; + while (remaining) { + const size_t written = SDL_RWwrite(rwops, buf, 1, remaining); + if (written == 0) { + return -1L; + } + + remaining -= written; + buf += written; + } + + SDL_RWclose(rwops); + + return len; +} + +std::string File::getPath() const { + const std::string& name = getName(); + const size_t pos = name.rfind("/"); + if (pos == std::string::npos) + return ""; + return name.substr(0, pos); +} + +std::string File::getFileName() const { + std::string name = getName(); + const size_t pathPos = name.rfind("/"); + if (pathPos != std::string::npos) { + name = name.substr(pathPos + 1); + } + const size_t extPos = name.rfind("."); + if (extPos != std::string::npos) { + name = name.substr(0, extPos); + } + return name; +} + +std::string File::getExtension() const { + const char *ext = ::strrchr(getName().c_str(), '.'); + if (ext == nullptr) + return ""; + ++ext; + return std::string(ext); +} + +long File::length() const { + if (!exists()) { + return -1; + } + + const long pos = tell(); + seek(0, RW_SEEK_END); + const long end = tell(); + seek(pos, RW_SEEK_SET); + return end; +} + +bool File::exists() const { + return _file != nullptr; +} + +int File::read(void **buffer) { + *buffer = nullptr; + const long len = length(); + if (len <= 0) + return len; + *buffer = new char[len]; + return read(*buffer, len); +} + +int File::read(void *buffer, int n) { + const size_t blockSize = 0x10000; + unsigned char *buf; + size_t remaining, len; + + len = remaining = n; + buf = (unsigned char *) buffer; + + seek(0, RW_SEEK_SET); + + while (remaining) { + size_t block = remaining; + if (block > blockSize) + block = blockSize; + const int readAmount = read(buf, 1, block); + + /* end of file reached */ + if (readAmount == 0) + return (len - remaining + readAmount); + + else if (readAmount == -1) + return -1; + + /* do some progress bar thing here... */ + remaining -= readAmount; + buf += readAmount; + } + return len; +} + +int File::read(void *buf, size_t size, size_t maxnum) { + const int n = SDL_RWread(_file, buf, size, maxnum); + if (n == 0) + _state = IOSTATE_LOADED; + else if (n == -1) + _state = IOSTATE_FAILED; + return n; +} + +void File::close() { + if (_file != nullptr) + SDL_RWclose(_file); +} + +long File::tell() const { + return SDL_RWtell(_file); +} + +long File::seek(long offset, int seekType) const { + return SDL_RWseek(_file, offset, seekType); +} + +} diff --git a/src/modules/io/File.h b/src/modules/io/File.h new file mode 100644 index 000000000..38d61c8c3 --- /dev/null +++ b/src/modules/io/File.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include +#include "IOResource.h" + +struct SDL_RWops; + +namespace io { + +class File : public IOResource { +protected: + SDL_RWops* _file; + const std::string _rawPath; + + void close(); + int read(void *buf, size_t size, size_t maxnum); + long tell() const; + long seek(long offset, int seekType) const; + +public: + File(const std::string& rawPath); + + virtual ~File(); + + bool exists() const; + long length() const; + std::string getExtension() const; + std::string getPath() const; + std::string getFileName() const; + + long write(const unsigned char *buf, size_t len) const; + int read(void **buffer); + int read(void *buffer, int n); + const std::string& getName() const; + std::string load(); +}; + +typedef std::shared_ptr FilePtr; + +} diff --git a/src/modules/io/Filesystem.cpp b/src/modules/io/Filesystem.cpp new file mode 100644 index 000000000..4364be862 --- /dev/null +++ b/src/modules/io/Filesystem.cpp @@ -0,0 +1,63 @@ +#include "Filesystem.h" +#include "core/Var.h" +#include "core/Log.h" +#include + +namespace io { + +Filesystem::Filesystem() : + _threadPool(1) { +} + +void Filesystem::init(const std::string& organisation, const std::string& appname) { + _organisation = organisation; + _appname = appname; + + char *path = SDL_GetBasePath(); + if (path == nullptr) { + _basePath = ""; + } else { + _basePath = path; + SDL_free(path); + } + + char *prefPath = SDL_GetPrefPath(_organisation.c_str(), _organisation.c_str()); + if (prefPath == nullptr) { + _homePath = ""; + } else { + _homePath = prefPath; + SDL_free(prefPath); + } + + Log::info("basepath: %s", _basePath.c_str()); + Log::info("homepath: %s", _homePath.c_str()); + core::Var::get("app_homepath", _homePath, core::CV_READONLY | core::CV_NOPERSIST); + core::Var::get("app_basepath", _basePath, core::CV_READONLY | core::CV_NOPERSIST); +} + +io::FilePtr Filesystem::open(const std::string& filename) { + const std::string homePath = _homePath + filename; + if (io::File(homePath).exists()) { + Log::debug("loading file %s from %s", filename.c_str(), _homePath.c_str()); + return io::FilePtr(new io::File(homePath)); + } + Log::debug("loading file %s from %s (doesn't exist at %s)", filename.c_str(), _basePath.c_str(), homePath.c_str()); + return io::FilePtr(new io::File(_basePath + filename)); +} + +std::string Filesystem::load(const std::string& filename) { + const io::FilePtr& f = open(filename); + return f->load(); +} + +bool Filesystem::write(const std::string& filename, const uint8_t* content, size_t length) { + io::File f(_homePath + filename); + return f.write(content, length) == static_cast(length); +} + +bool Filesystem::write(const std::string& filename, const std::string& string) { + const uint8_t* buf = reinterpret_cast(string.c_str()); + return write(filename, buf, string.size()); +} + +} diff --git a/src/modules/io/Filesystem.h b/src/modules/io/Filesystem.h new file mode 100644 index 000000000..8e31f572e --- /dev/null +++ b/src/modules/io/Filesystem.h @@ -0,0 +1,64 @@ +#pragma once + +#include +#include "core/ThreadPool.h" +#include "File.h" + +namespace io { + +class Filesystem { +private: + core::ThreadPool _threadPool; + std::string _organisation; + std::string _appname; + + std::string _basePath; + std::string _homePath; +public: + Filesystem(); + + void init(const std::string& organisation, const std::string& appname); + + /** + * @brief Get the path where the application resides. + * + * Get the "base path". This is the directory where the application was run + * from, which is probably the installation directory, and may or may not + * be the process's current working directory. + */ + const std::string& basePath() const; + /** + * @brief The path where the application can store data + */ + const std::string& homePath() const; + + io::FilePtr open(const std::string& filename); + + std::string load(const std::string& filename); + /** + * @brief Loads a file asynchronously and executes the given @c CompleteHandle once some result is avaiable. + */ + template + void loadAsync(const std::string& filename, CompleteHandle completeHandle) { + _threadPool.push([=]() { + io::FilePtr f(new io::File(filename)); + completeHandle(f); + }); + } + + bool write(const std::string& filename, const uint8_t* content, size_t length); + + bool write(const std::string& filename, const std::string& string); +}; + +inline const std::string& Filesystem::basePath() const { + return _basePath; +} + +inline const std::string& Filesystem::homePath() const { + return _homePath; +} + +typedef std::shared_ptr FilesystemPtr; + +} diff --git a/src/modules/io/IEventObserver.h b/src/modules/io/IEventObserver.h new file mode 100644 index 000000000..bfb505952 --- /dev/null +++ b/src/modules/io/IEventObserver.h @@ -0,0 +1,115 @@ +#pragma once + +#include +#include + +namespace io { + +class IEventObserver { +public: + virtual ~IEventObserver() { + } + + /* Prepare your app to go into the background. Stop loops, etc. This gets called when the user hits the home button, or gets a call. */ + virtual void onPrepareBackground() { + } + + /* You will get this when your app is paused and iOS wants more memory. Release as much memory as possible. */ + virtual void onLowMemory() { + } + + /* Terminate the app. Shut everything down before returning from this function. */ + virtual void onPrepareShutdown() { + } + + /* This call happens when your app is coming back to the foreground. Restore all your state here. */ + virtual void onPrepareForeground() { + } + + /* This will get called if the user accepted whatever sent your app to the background. + * If the user got a phone call and canceled it, you'll instead get an SDL_APP_DIDENTERFOREGROUND event and restart your loops. + * When you get this, you have 5 seconds to save all your state or the app will be terminated. + * Your app is NOT active at this point. */ + virtual void onBackground() { + } + + /* Restart your loops here. Your app is interactive and getting CPU again. */ + virtual void onForeground() { + } + + /** + * @param[in] horizontal + * @param[in] value The relative value that the joystick was moved, [-32768,32767] + */ + virtual void onJoystickMotion(bool horizontal, int value) { + } + + virtual void onMouseWheel(int32_t x, int32_t y) { + } + + virtual void onMouseMotion(int32_t x, int32_t y, int32_t relX, int32_t relY) { + } + + virtual void onMouseButtonPress(int32_t x, int32_t y, uint8_t button) { + } + + virtual void onMouseButtonRelease(int32_t x, int32_t y, uint8_t button) { + } + + virtual void onJoystickDeviceRemoved(int32_t device) { + } + + virtual void onJoystickDeviceAdded(int32_t device) { + } + + virtual void onControllerButtonPress(const std::string& button) { + } + + virtual void onControllerButtonRelease(const std::string& button) { + } + + virtual void onJoystickButtonPress(uint8_t button) { + } + + virtual void onJoystickButtonRelease(uint8_t button) { + } + + virtual bool onTextInput(const std::string& text) { + return false; + } + + // returns true if the key release was handled + virtual bool onKeyRelease(int32_t key) { + return false; + } + + // returns true if the key was handled + virtual bool onKeyPress(int32_t key, int16_t modifier) { + return false; + } + + virtual bool onFingerPress(int64_t finger, float x, float y) { + return false; + } + + virtual bool onFingerRelease(int64_t finger, float x, float y) { + return false; + } + + virtual void onFingerMotion(int64_t finger, float x, float y, float dx, float dy) { + } + + virtual void onWindowResize() { + } + + virtual void onMultiGesture(float theta, float dist, int32_t numFingers) { + } + + virtual void onGesture(int64_t gestureId, float error, int32_t numFingers) { + } + + virtual void onGestureRecord(int64_t gestureId) { + } +}; + +} diff --git a/src/modules/io/IOResource.h b/src/modules/io/IOResource.h new file mode 100644 index 000000000..c664a4c43 --- /dev/null +++ b/src/modules/io/IOResource.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include +#include + +namespace io { + +enum IOState { + IOSTATE_LOADING, IOSTATE_LOADED, IOSTATE_FAILED +}; + +class IOResource { +protected: + std::atomic _state; + + IOResource() : + _state(IOSTATE_LOADING) { + } + + virtual ~IOResource() { + } + +public: + inline bool isLoaded() const { + return _state == io::IOSTATE_LOADED; + } + + inline bool isFailed() const { + return _state == io::IOSTATE_FAILED; + } + + inline bool isLoading() const { + return _state == io::IOSTATE_LOADING; + } +}; + +} diff --git a/src/modules/network/CMakeLists.txt b/src/modules/network/CMakeLists.txt new file mode 100644 index 000000000..142379416 --- /dev/null +++ b/src/modules/network/CMakeLists.txt @@ -0,0 +1,16 @@ +fips_begin_module(network) + fips_files( + IProtocolHandler.h + IMsgProtocolHandler.h + Network.cpp Network.h + MessageSender.h MessageSender.cpp + NetworkEvents.h + ProtocolHandlerRegistry.h + ) + find_package(SDL2 REQUIRED) + include_directories(${SDL2_INCLUDE_DIRS}) + fips_deps(core enet ${SDL2_LIBRARIES}) + fips_generate(TYPE FlatC FROM definitions/Shared.fbs HEADER ../messages/Shared_generated.h) + fips_generate(TYPE FlatC FROM definitions/ClientMessages.fbs HEADER ../messages/ClientMessages.h) + fips_generate(TYPE FlatC FROM definitions/ServerMessages.fbs HEADER ../messages/ServerMessages.h) +fips_end_module() diff --git a/src/modules/network/IMsgProtocolHandler.h b/src/modules/network/IMsgProtocolHandler.h new file mode 100644 index 000000000..de5d529a4 --- /dev/null +++ b/src/modules/network/IMsgProtocolHandler.h @@ -0,0 +1,39 @@ +#pragma once + +#include "IProtocolHandler.h" +#include "core/Log.h" + +namespace network { + +template +class IMsgProtocolHandler: public IProtocolHandler { +private: + bool _needsAttachment; +public: + IMsgProtocolHandler(bool needsAttachment = false) : + _needsAttachment(needsAttachment) { + } + + virtual ~IMsgProtocolHandler() { + } + + virtual void execute(ATTACHMENTTYPE* attachment, const MSGTYPE* message) = 0; + + virtual void execute(ENetPeer* peer, const void* message) { + auto* attachment = getAttachment(peer); + if (_needsAttachment && attachment == nullptr) { + Log::error("No attachment yet for a message that needs one"); + return; + } + const auto* msg = getMsg(message); + execute(attachment, msg); + } +}; + +} + +#define MSGPROTOHANDLER(attachmentType, msgType, attachmentNeeded) \ +struct msgType##Handler: public network::IMsgProtocolHandler { \ + msgType##Handler() : network::IMsgProtocolHandler(true) {} \ + void execute(attachmentType* attachment, const msgType* message) override; \ +} diff --git a/src/modules/network/IProtocolHandler.h b/src/modules/network/IProtocolHandler.h new file mode 100644 index 000000000..44d6f29f9 --- /dev/null +++ b/src/modules/network/IProtocolHandler.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include + +namespace network { + +/** + * @brief Interface for the execution of assigned IProtocolMessage + * + * @note Register handler implementations at the @c ProtocolHandlerRegistry + */ +class IProtocolHandler { +protected: + template + inline ATTACHMENTTYPE* getAttachment(ENetPeer* peer) const { + return static_cast(peer->data); + } + + template + inline const MSGTYPE* getMsg(const void *data) const { + return static_cast(data); + } + +public: + virtual ~IProtocolHandler() { + } + + virtual void execute(ENetPeer* peer, const void* message) = 0; +}; + +typedef std::shared_ptr ProtocolHandlerPtr; + +} diff --git a/src/modules/network/MessageSender.cpp b/src/modules/network/MessageSender.cpp new file mode 100644 index 000000000..98b43b044 --- /dev/null +++ b/src/modules/network/MessageSender.cpp @@ -0,0 +1,53 @@ +#include "MessageSender.h" +#include "core/Log.h" +#include "core/Common.h" + +namespace network { + +inline ENetPacket* createServerPacket(FlatBufferBuilder& fbb, messages::server::Type type, Offset data, uint32_t flags) { + auto msg = messages::server::CreateServerMessage(fbb, type, data); + messages::server::FinishServerMessageBuffer(fbb, msg); + ENetPacket* packet = enet_packet_create(fbb.GetBufferPointer(), fbb.GetSize(), flags); + Log::trace("Create server package: %s - size %ui", messages::server::EnumNameType(type), fbb.GetSize()); + return packet; +} + +inline ENetPacket* createClientPacket(FlatBufferBuilder& fbb, messages::client::Type type, Offset data, uint32_t flags) { + auto msg = messages::client::CreateClientMessage(fbb, type, data); + messages::client::FinishClientMessageBuffer(fbb, msg); + ENetPacket* packet = enet_packet_create(fbb.GetBufferPointer(), fbb.GetSize(), flags); + Log::trace("Create client package: %s - size %ui", messages::client::EnumNameType(type), fbb.GetSize()); + return packet; +} + +MessageSender::MessageSender(NetworkPtr network) : + _network(network) { +} + +void MessageSender::sendServerMessage(ENetPeer* peer, FlatBufferBuilder& fbb, messages::server::Type type, Offset data, uint32_t flags) { + core_assert(peer != nullptr); + sendServerMessage(&peer, 1, fbb, type, data, flags); +} + +void MessageSender::sendServerMessage(ENetPeer** peers, int numPeers, FlatBufferBuilder& fbb, messages::server::Type type, Offset data, uint32_t flags) { + Log::debug("Send %s", messages::server::EnumNameType(type)); + core_assert(numPeers > 0); + auto packet = createServerPacket(fbb, type, data, flags); + for (int i = 0; i < numPeers; ++i) { + const bool success = _network->sendMessage(peers[i], packet); + if (success) + continue; + Log::error("Failed to send the message %s to peer %i (State: %i)", messages::server::EnumNameType(type), i, peers[i]->state); + } +} + +void MessageSender::broadcastServerMessage(FlatBufferBuilder& fbb, messages::server::Type type, Offset data, int channel, uint32_t flags) { + Log::debug("Broadcast %s", messages::server::EnumNameType(type)); + _network->broadcast(createServerPacket(fbb, type, data, flags), channel); +} + +void MessageSender::sendClientMessage(ENetPeer* peer, FlatBufferBuilder& fbb, messages::client::Type type, Offset data, uint32_t flags) { + _network->sendMessage(peer, createClientPacket(fbb, type, data, flags)); +} + +} diff --git a/src/modules/network/MessageSender.h b/src/modules/network/MessageSender.h new file mode 100644 index 000000000..b0b2fca83 --- /dev/null +++ b/src/modules/network/MessageSender.h @@ -0,0 +1,38 @@ +#pragma once + +#include "Network.h" +#include "messages/ServerMessages.h" +#include "messages/ClientMessages.h" +#include + +using namespace network::messages::server; +using namespace network::messages::client; + +#define sendServerMsgMultiple(peers, numPeers, msg, type) _messageSender->sendServerMessage(peers, numPeers, fbb, network::messages::server::Type_##type, network::messages::server::Create##msg.Union()); +#define sendServerMsg(msg, type) _messageSender->sendServerMessage(_peer, fbb, network::messages::server::Type_##type, network::messages::server::Create##msg.Union()); +#define broadcastServerMsg(msg, type) _messageSender->broadcastServerMessage(fbb, network::messages::server::Type_##type, network::messages::server::Create##msg.Union()); +#define sendClientMsg(msg, type) _messageSender->sendClientMessage(_peer, fbb, network::messages::client::Type_##type, network::messages::client::Create##msg.Union()); + +namespace network { + +using namespace flatbuffers; + +class MessageSender { +private: + NetworkPtr _network; + +public: + MessageSender(NetworkPtr network); + + void sendServerMessage(ENetPeer* peer, FlatBufferBuilder& fbb, messages::server::Type type, Offset data, uint32_t flags = ENET_PACKET_FLAG_RELIABLE); + void sendServerMessage(ENetPeer** peers, int numPeers, FlatBufferBuilder& fbb, messages::server::Type type, Offset data, uint32_t flags = ENET_PACKET_FLAG_RELIABLE); + void broadcastServerMessage(FlatBufferBuilder& fbb, messages::server::Type type, Offset data, int channel = 0, uint32_t flags = ENET_PACKET_FLAG_RELIABLE); + /** + * @brief Sends a message to the client + */ + void sendClientMessage(ENetPeer* peer, FlatBufferBuilder& fbb, messages::client::Type type, Offset data, uint32_t flags = ENET_PACKET_FLAG_RELIABLE); +}; + +typedef std::shared_ptr MessageSenderPtr; + +} diff --git a/src/modules/network/Network.cpp b/src/modules/network/Network.cpp new file mode 100644 index 000000000..ce610a2a7 --- /dev/null +++ b/src/modules/network/Network.cpp @@ -0,0 +1,181 @@ +#include "Network.h" +#include "IProtocolHandler.h" +#include "ProtocolHandlerRegistry.h" +#include "NetworkEvents.h" +#include "network/messages/ClientMessages.h" +#include "network/messages/ServerMessages.h" +#include "core/Trace.h" +#include "core/Log.h" + +#include + +namespace network { + +Network::Network(ProtocolHandlerRegistryPtr protocolHandlerRegistry, core::EventBusPtr eventBus) : + _protocolHandlerRegistry(protocolHandlerRegistry), _eventBus(eventBus), _server(nullptr), _client(nullptr) { +} + +Network::~Network() { + enet_host_destroy(_server); + enet_host_destroy(_client); + enet_deinitialize(); +} + +bool Network::start() { + if (enet_initialize() != 0) + return false; + enet_time_set(0); + return true; +} + +bool Network::bind(uint16_t port, const std::string& hostname, int maxPeers, int maxChannels) { + if (_server) + return false; + if (maxPeers <= 0) + return false; + if (maxChannels <= 0) + return false; + ENetAddress address; + if (hostname.empty()) + address.host = ENET_HOST_ANY; + else + enet_address_set_host(&address, hostname.c_str()); + address.port = port; + _server = enet_host_create(&address, maxPeers, maxChannels, 0, 0); + if (_server == nullptr) { + return false; + } + return true; +} + +ENetPeer* Network::connect(uint16_t port, const std::string& hostname, int maxChannels) { + if (_client) + disconnect(); + _client = enet_host_create(nullptr, 1, maxChannels, 57600 / 8, 14400 / 8); + if (_client == nullptr) { + return nullptr; + } + + ENetAddress address; + enet_address_set_host(&address, hostname.c_str()); + address.port = port; + + ENetPeer *peer = enet_host_connect(_client, &address, maxChannels, 0); + enet_host_flush(_client); + enet_peer_timeout(peer, ENET_PEER_TIMEOUT_LIMIT, ENET_PEER_TIMEOUT_MINIMUM, ENET_PEER_TIMEOUT_MAXIMUM); + return peer; +} + +void Network::disconnect() { + if (_client == nullptr) + return; + + for (size_t i = 0; i < _client->peerCount; ++i) { + ENetPeer *peer = &_client->peers[i]; + disconnectPeer(peer); + } + enet_host_destroy(_client); + _client = nullptr; +} + +void Network::disconnectPeer(ENetPeer *peer, uint32_t timeout) { + if (peer == nullptr) + return; + Log::info("trying to disconnect peer %i", peer->connectID); + ENetEvent event; + enet_peer_disconnect(peer, 0); + bool success = false; + /* Wait some time for the disconnect to succeed + * and drop any packets received packets. */ + while (enet_host_service(_client, &event, timeout) > 0) { + switch (event.type) { + case ENET_EVENT_TYPE_RECEIVE: + enet_packet_destroy(event.packet); + break; + case ENET_EVENT_TYPE_DISCONNECT: + success = true; + break; + case ENET_EVENT_TYPE_CONNECT: + case ENET_EVENT_TYPE_NONE: + break; + } + } + if (!success) { + /* We've arrived here, so the disconnect attempt didn't */ + /* succeed yet. Force the connection down. */ + enet_peer_reset(peer); + } +} + +bool Network::packetReceived(ENetEvent& event, bool server) { + flatbuffers::Verifier v(event.packet->data, event.packet->dataLength); + + if (!server) { + if (!messages::server::VerifyServerMessageBuffer(v)) { + Log::error("Illegal server packet received with length: %i", (int)event.packet->dataLength); + return false; + } + const messages::server::ServerMessage *req = messages::server::GetServerMessage(event.packet->data); + messages::server::Type type = req->data_type(); + ProtocolHandlerPtr handler = _protocolHandlerRegistry->getHandler(type); + if (!handler) { + Log::error("No handler for server msg type %s", messages::server::EnumNameType(type)); + return false; + } + Log::debug("Received %s", messages::server::EnumNameType(type)); + handler->execute(event.peer, req->data()); + return true; + } + + if (!messages::client::VerifyClientMessageBuffer(v)) { + Log::error("Illegal client packet received with length: %i", (int)event.packet->dataLength); + return false; + } + const messages::client::ClientMessage *req = messages::client::GetClientMessage(event.packet->data); + messages::client::Type type = req->data_type(); + ProtocolHandlerPtr handler = _protocolHandlerRegistry->getHandler(type); + if (!handler) { + Log::error("No handler for client msg type %s", messages::client::EnumNameType(type)); + return false; + } + Log::debug("Received %s", messages::client::EnumNameType(type)); + handler->execute(event.peer, req->data()); + return true; +} + +void Network::updateHost(ENetHost* host, bool server) { + if (host == nullptr) + return; + ENetEvent event; + while (enet_host_service(host, &event, 0) > 0) { + switch (event.type) { + case ENET_EVENT_TYPE_CONNECT: { + _eventBus->publish(NewConnectionEvent(event.peer)); + break; + } + case ENET_EVENT_TYPE_RECEIVE: { + if (!packetReceived(event, server)) { + Log::error("Failure while receiving a package - disconnecting now..."); + disconnectPeer(event.peer, 10); + } + enet_packet_destroy(event.packet); + break; + } + case ENET_EVENT_TYPE_DISCONNECT: { + _eventBus->publish(DisconnectEvent(event.peer)); + break; + } + case ENET_EVENT_TYPE_NONE: { + break; + } + } + } +} + +void Network::update() { + core_trace_scoped("Network"); + updateHost(_server, true); + updateHost(_client, false); +} + +} diff --git a/src/modules/network/Network.h b/src/modules/network/Network.h new file mode 100644 index 000000000..35ee3bb17 --- /dev/null +++ b/src/modules/network/Network.h @@ -0,0 +1,45 @@ +#pragma once + +#include "ProtocolHandlerRegistry.h" +#include "IMsgProtocolHandler.h" +#include "core/EventBus.h" +#include +#include +#include +#include +#include + +namespace network { + +class Network { +private: + ProtocolHandlerRegistryPtr _protocolHandlerRegistry; + core::EventBusPtr _eventBus; + ENetHost* _server; + ENetHost* _client; + + bool packetReceived(ENetEvent& event, bool server); + void disconnectPeer(ENetPeer *peer, uint32_t timeout = 3000); + void updateHost(ENetHost* host, bool server); +public: + Network(ProtocolHandlerRegistryPtr protocolHandlerRegistry, core::EventBusPtr eventBus); + virtual ~Network(); + + bool start(); + void update(); + + // Server related methods + bool bind(uint16_t port, const std::string& hostname = "", int maxPeers = 1024, int maxChannels = 1); + inline void broadcast(ENetPacket* packet, int channel = 0) { enet_host_broadcast(_server, channel, packet); } + + // Client related methods + ENetPeer* connect(uint16_t port, const std::string& hostname, int maxChannels = 1); + void disconnect(); + + // Shared methods + inline bool sendMessage(ENetPeer* peer, ENetPacket* packet, int channel = 0) { return enet_peer_send(peer, channel, packet) == 0; } +}; + +typedef std::shared_ptr NetworkPtr; + +} diff --git a/src/modules/network/NetworkEvents.h b/src/modules/network/NetworkEvents.h new file mode 100644 index 000000000..d12e06894 --- /dev/null +++ b/src/modules/network/NetworkEvents.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +namespace network { + +class NewConnectionEvent: public core::IEventBusEvent { +private: + ENetPeer* _peer; +public: + NewConnectionEvent(ENetPeer* peer) : + _peer(peer) { + } + inline ENetPeer* peer() const { + return _peer; + } +}; + +class DisconnectEvent: public core::IEventBusEvent { +private: + ENetPeer* _peer; +public: + DisconnectEvent(ENetPeer* peer) : + _peer(peer) { + } + inline ENetPeer* peer() const { + return _peer; + } +}; + +} diff --git a/src/modules/network/NetworkModule.h b/src/modules/network/NetworkModule.h new file mode 100644 index 000000000..aa2484ba4 --- /dev/null +++ b/src/modules/network/NetworkModule.h @@ -0,0 +1,20 @@ +#pragma once + +#include "Network.h" +#include "MessageSender.h" +#include "core/EventBus.h" +#include + +#define configureHandler(type, handler) bind().named(std::to_string(type)).to(); + +class NetworkModule: public sauce::AbstractModule { + void configure() const { + bind().in().to(); + bind().in().to(); + bind().in().to(); + + configureHandlers(); + } + + virtual void configureHandlers() const = 0; +}; diff --git a/src/modules/network/ProtocolHandlerRegistry.h b/src/modules/network/ProtocolHandlerRegistry.h new file mode 100644 index 000000000..312ae7aa5 --- /dev/null +++ b/src/modules/network/ProtocolHandlerRegistry.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include "IProtocolHandler.h" + +namespace network { + +class ProtocolHandlerRegistry { +private: + sauce::shared_ptr _injector; +public: + ProtocolHandlerRegistry(sauce::shared_ptr injector) : + _injector(injector) { + } + + inline ProtocolHandlerPtr getHandler(int type) { + return _injector->get(std::to_string(type)); + } +}; + +typedef std::shared_ptr ProtocolHandlerRegistryPtr; + +} diff --git a/src/modules/network/definitions/ClientMessages.fbs b/src/modules/network/definitions/ClientMessages.fbs new file mode 100644 index 000000000..05c286fd7 --- /dev/null +++ b/src/modules/network/definitions/ClientMessages.fbs @@ -0,0 +1,41 @@ +// Messages that the client send to the server + +include "Shared.fbs"; + +namespace network.messages.client; + +table UserConnect { + email:string (required); + password:string (required); +} + +/// a message that the client is sending once the connection is successful and it is +/// ready to receive more data +table UserConnected { +} + +table UserDisconnect { +} + +table Attack { + targetId:long; +} + +/// The move direction is a bit mask of the keys that the client currently holds pressed +enum MoveDirection:ubyte (bit_flags) { MOVEFORWARD = 1, MOVEBACKWARD = 2, MOVELEFT = 3, MOVERIGHT = 4 } + +table Move { + direction:MoveDirection; + /// vertical + pitch:float; + /// horizontal + yaw:float; +} + +union Type { UserConnect, UserConnected, UserDisconnect, Attack, Move } + +table ClientMessage { + data:Type; +} + +root_type ClientMessage; diff --git a/src/modules/network/definitions/ServerMessages.fbs b/src/modules/network/definitions/ServerMessages.fbs new file mode 100644 index 000000000..76aa80387 --- /dev/null +++ b/src/modules/network/definitions/ServerMessages.fbs @@ -0,0 +1,67 @@ +// Messages that the server send to the client + +include "Shared.fbs"; + +namespace network.messages.server; + +table Seed { + seed:long; +} + +table AuthFailed { +} + +table UserSpawn { + id:long; + name:string; + pos:Vec3; +} + +table UserUpdate { + pos:Vec3; +} + +table NpcSpawn { + id:long; + type:NpcType; + pos:Vec3; + // is this npc controlled by a human - if so, who is controlling it. + human:long = -1; +} + +// defines the human-controlled state - sending -1 for the human means, that that the npc was released +// and is no longer controlled by the previous human +table NpcTakeOver { + id:long; + // is this npc controlled by a human - if so, who is controlling it. + human:long = -1; +} + +table NpcRemove { + id:long; +} + +table NpcUpdate { + id:long; + pos:Vec3 (required); + rotation:float; +} + +// TODO: make enum +table NpcAnim { + id:long; + anim:ubyte; +} + +table NpcEffect { + id:long; + type:NpcEffectType = HUMAN_CONTROLLED; +} + +union Type { Seed, UserSpawn, UserUpdate, NpcSpawn, NpcRemove, NpcUpdate, NpcAnim, NpcEffect, AuthFailed, NpcTakeOver } + +table ServerMessage { + data:Type; +} + +root_type ServerMessage; diff --git a/src/modules/network/definitions/Shared.fbs b/src/modules/network/definitions/Shared.fbs new file mode 100644 index 000000000..856e047d4 --- /dev/null +++ b/src/modules/network/definitions/Shared.fbs @@ -0,0 +1,34 @@ +// Shared data structures for client and server messages + +namespace network.messages; + +struct Vec3 { + x:float; + y:float; + z:float; +} + +struct Vec2 { + x:float; + y:float; +} + +enum NpcType: int { + NONE, + + BEGIN_ANIMAL, + ANIMAL_WOLF, + ANIMAL_RABBIT, + MAX_ANIMAL, + + BEGIN_CHARACTERS, + BLACKSMITH, + MAX_CHARACTERS, + + MAX +} + +enum NpcEffectType: int { + HUMAN_CONTROLLED, + AUTONOMOUS +} diff --git a/src/modules/network/messages/ClientMessages.h b/src/modules/network/messages/ClientMessages.h new file mode 100644 index 000000000..ef9ee1d7f --- /dev/null +++ b/src/modules/network/messages/ClientMessages.h @@ -0,0 +1,270 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +#ifndef FLATBUFFERS_GENERATED_CLIENTMESSAGES_NETWORK_MESSAGES_CLIENT_H_ +#define FLATBUFFERS_GENERATED_CLIENTMESSAGES_NETWORK_MESSAGES_CLIENT_H_ + +#include "flatbuffers/flatbuffers.h" + +#include "Shared_generated.h" + +namespace network { +namespace messages { +struct Vec3; +struct Vec2; +} // namespace messages +} // namespace network + +namespace network { +namespace messages { +namespace client { + +struct UserConnect; +struct UserConnected; +struct UserDisconnect; +struct Attack; +struct Move; +struct ClientMessage; + +/// The move direction is a bit mask of the keys that the client currently holds pressed +enum MoveDirection { + MoveDirection_MOVEFORWARD = 2, + MoveDirection_MOVEBACKWARD = 4, + MoveDirection_MOVELEFT = 8, + MoveDirection_MOVERIGHT = 16 +}; + +inline const char **EnumNamesMoveDirection() { + static const char *names[] = { "MOVEFORWARD", "", "MOVEBACKWARD", "", "", "", "MOVELEFT", "", "", "", "", "", "", "", "MOVERIGHT", nullptr }; + return names; +} + +inline const char *EnumNameMoveDirection(MoveDirection e) { return EnumNamesMoveDirection()[e - MoveDirection_MOVEFORWARD]; } + +enum Type { + Type_NONE = 0, + Type_UserConnect = 1, + Type_UserConnected = 2, + Type_UserDisconnect = 3, + Type_Attack = 4, + Type_Move = 5 +}; + +inline const char **EnumNamesType() { + static const char *names[] = { "NONE", "UserConnect", "UserConnected", "UserDisconnect", "Attack", "Move", nullptr }; + return names; +} + +inline const char *EnumNameType(Type e) { return EnumNamesType()[e]; } + +inline bool VerifyType(flatbuffers::Verifier &verifier, const void *union_obj, Type type); + +struct UserConnect FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + const flatbuffers::String *email() const { return GetPointer(4); } + const flatbuffers::String *password() const { return GetPointer(6); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyFieldRequired(verifier, 4 /* email */) && + verifier.Verify(email()) && + VerifyFieldRequired(verifier, 6 /* password */) && + verifier.Verify(password()) && + verifier.EndTable(); + } +}; + +struct UserConnectBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_email(flatbuffers::Offset email) { fbb_.AddOffset(4, email); } + void add_password(flatbuffers::Offset password) { fbb_.AddOffset(6, password); } + UserConnectBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + UserConnectBuilder &operator=(const UserConnectBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 2)); + fbb_.Required(o, 4); // email + fbb_.Required(o, 6); // password + return o; + } +}; + +inline flatbuffers::Offset CreateUserConnect(flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset email = 0, + flatbuffers::Offset password = 0) { + UserConnectBuilder builder_(_fbb); + builder_.add_password(password); + builder_.add_email(email); + return builder_.Finish(); +} + +/// a message that the client is sending once the connection is successful and it is +/// ready to receive more data +struct UserConnected FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } +}; + +struct UserConnectedBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + UserConnectedBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + UserConnectedBuilder &operator=(const UserConnectedBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 0)); + return o; + } +}; + +inline flatbuffers::Offset CreateUserConnected(flatbuffers::FlatBufferBuilder &_fbb) { + UserConnectedBuilder builder_(_fbb); + return builder_.Finish(); +} + +struct UserDisconnect FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } +}; + +struct UserDisconnectBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + UserDisconnectBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + UserDisconnectBuilder &operator=(const UserDisconnectBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 0)); + return o; + } +}; + +inline flatbuffers::Offset CreateUserDisconnect(flatbuffers::FlatBufferBuilder &_fbb) { + UserDisconnectBuilder builder_(_fbb); + return builder_.Finish(); +} + +struct Attack FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + int64_t targetId() const { return GetField(4, 0); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, 4 /* targetId */) && + verifier.EndTable(); + } +}; + +struct AttackBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_targetId(int64_t targetId) { fbb_.AddElement(4, targetId, 0); } + AttackBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + AttackBuilder &operator=(const AttackBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 1)); + return o; + } +}; + +inline flatbuffers::Offset CreateAttack(flatbuffers::FlatBufferBuilder &_fbb, + int64_t targetId = 0) { + AttackBuilder builder_(_fbb); + builder_.add_targetId(targetId); + return builder_.Finish(); +} + +struct Move FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + MoveDirection direction() const { return static_cast(GetField(4, 0)); } + /// vertical + float pitch() const { return GetField(6, 0); } + /// horizontal + float yaw() const { return GetField(8, 0); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, 4 /* direction */) && + VerifyField(verifier, 6 /* pitch */) && + VerifyField(verifier, 8 /* yaw */) && + verifier.EndTable(); + } +}; + +struct MoveBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_direction(MoveDirection direction) { fbb_.AddElement(4, static_cast(direction), 0); } + void add_pitch(float pitch) { fbb_.AddElement(6, pitch, 0); } + void add_yaw(float yaw) { fbb_.AddElement(8, yaw, 0); } + MoveBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + MoveBuilder &operator=(const MoveBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 3)); + return o; + } +}; + +inline flatbuffers::Offset CreateMove(flatbuffers::FlatBufferBuilder &_fbb, + MoveDirection direction = static_cast(0), + float pitch = 0, + float yaw = 0) { + MoveBuilder builder_(_fbb); + builder_.add_yaw(yaw); + builder_.add_pitch(pitch); + builder_.add_direction(direction); + return builder_.Finish(); +} + +struct ClientMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + Type data_type() const { return static_cast(GetField(4, 0)); } + const void *data() const { return GetPointer(6); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, 4 /* data_type */) && + VerifyField(verifier, 6 /* data */) && + VerifyType(verifier, data(), data_type()) && + verifier.EndTable(); + } +}; + +struct ClientMessageBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_data_type(Type data_type) { fbb_.AddElement(4, static_cast(data_type), 0); } + void add_data(flatbuffers::Offset data) { fbb_.AddOffset(6, data); } + ClientMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + ClientMessageBuilder &operator=(const ClientMessageBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 2)); + return o; + } +}; + +inline flatbuffers::Offset CreateClientMessage(flatbuffers::FlatBufferBuilder &_fbb, + Type data_type = Type_NONE, + flatbuffers::Offset data = 0) { + ClientMessageBuilder builder_(_fbb); + builder_.add_data(data); + builder_.add_data_type(data_type); + return builder_.Finish(); +} + +inline bool VerifyType(flatbuffers::Verifier &verifier, const void *union_obj, Type type) { + switch (type) { + case Type_NONE: return true; + case Type_UserConnect: return verifier.VerifyTable(reinterpret_cast(union_obj)); + case Type_UserConnected: return verifier.VerifyTable(reinterpret_cast(union_obj)); + case Type_UserDisconnect: return verifier.VerifyTable(reinterpret_cast(union_obj)); + case Type_Attack: return verifier.VerifyTable(reinterpret_cast(union_obj)); + case Type_Move: return verifier.VerifyTable(reinterpret_cast(union_obj)); + default: return false; + } +} + +inline const ClientMessage *GetClientMessage(const void *buf) { return flatbuffers::GetRoot(buf); } + +inline bool VerifyClientMessageBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer(); } + +inline void FinishClientMessageBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset root) { fbb.Finish(root); } + +} // namespace client +} // namespace messages +} // namespace network + +#endif // FLATBUFFERS_GENERATED_CLIENTMESSAGES_NETWORK_MESSAGES_CLIENT_H_ diff --git a/src/modules/network/messages/ServerMessages.h b/src/modules/network/messages/ServerMessages.h new file mode 100644 index 000000000..8427c40da --- /dev/null +++ b/src/modules/network/messages/ServerMessages.h @@ -0,0 +1,444 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +#ifndef FLATBUFFERS_GENERATED_SERVERMESSAGES_NETWORK_MESSAGES_SERVER_H_ +#define FLATBUFFERS_GENERATED_SERVERMESSAGES_NETWORK_MESSAGES_SERVER_H_ + +#include "flatbuffers/flatbuffers.h" + +#include "Shared_generated.h" + +namespace network { +namespace messages { +struct Vec3; +struct Vec2; +} // namespace messages +} // namespace network + +namespace network { +namespace messages { +namespace server { + +struct Seed; +struct AuthFailed; +struct UserSpawn; +struct UserUpdate; +struct NpcSpawn; +struct NpcTakeOver; +struct NpcRemove; +struct NpcUpdate; +struct NpcAnim; +struct NpcEffect; +struct ServerMessage; + +enum Type { + Type_NONE = 0, + Type_Seed = 1, + Type_UserSpawn = 2, + Type_UserUpdate = 3, + Type_NpcSpawn = 4, + Type_NpcRemove = 5, + Type_NpcUpdate = 6, + Type_NpcAnim = 7, + Type_NpcEffect = 8, + Type_AuthFailed = 9, + Type_NpcTakeOver = 10 +}; + +inline const char **EnumNamesType() { + static const char *names[] = { "NONE", "Seed", "UserSpawn", "UserUpdate", "NpcSpawn", "NpcRemove", "NpcUpdate", "NpcAnim", "NpcEffect", "AuthFailed", "NpcTakeOver", nullptr }; + return names; +} + +inline const char *EnumNameType(Type e) { return EnumNamesType()[e]; } + +inline bool VerifyType(flatbuffers::Verifier &verifier, const void *union_obj, Type type); + +struct Seed FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + int64_t seed() const { return GetField(4, 0); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, 4 /* seed */) && + verifier.EndTable(); + } +}; + +struct SeedBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_seed(int64_t seed) { fbb_.AddElement(4, seed, 0); } + SeedBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + SeedBuilder &operator=(const SeedBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 1)); + return o; + } +}; + +inline flatbuffers::Offset CreateSeed(flatbuffers::FlatBufferBuilder &_fbb, + int64_t seed = 0) { + SeedBuilder builder_(_fbb); + builder_.add_seed(seed); + return builder_.Finish(); +} + +struct AuthFailed FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } +}; + +struct AuthFailedBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + AuthFailedBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + AuthFailedBuilder &operator=(const AuthFailedBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 0)); + return o; + } +}; + +inline flatbuffers::Offset CreateAuthFailed(flatbuffers::FlatBufferBuilder &_fbb) { + AuthFailedBuilder builder_(_fbb); + return builder_.Finish(); +} + +struct UserSpawn FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + int64_t id() const { return GetField(4, 0); } + const flatbuffers::String *name() const { return GetPointer(6); } + const network::messages::Vec3 *pos() const { return GetStruct(8); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, 4 /* id */) && + VerifyField(verifier, 6 /* name */) && + verifier.Verify(name()) && + VerifyField(verifier, 8 /* pos */) && + verifier.EndTable(); + } +}; + +struct UserSpawnBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_id(int64_t id) { fbb_.AddElement(4, id, 0); } + void add_name(flatbuffers::Offset name) { fbb_.AddOffset(6, name); } + void add_pos(const network::messages::Vec3 *pos) { fbb_.AddStruct(8, pos); } + UserSpawnBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + UserSpawnBuilder &operator=(const UserSpawnBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 3)); + return o; + } +}; + +inline flatbuffers::Offset CreateUserSpawn(flatbuffers::FlatBufferBuilder &_fbb, + int64_t id = 0, + flatbuffers::Offset name = 0, + const network::messages::Vec3 *pos = 0) { + UserSpawnBuilder builder_(_fbb); + builder_.add_id(id); + builder_.add_pos(pos); + builder_.add_name(name); + return builder_.Finish(); +} + +struct UserUpdate FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + const network::messages::Vec3 *pos() const { return GetStruct(4); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, 4 /* pos */) && + verifier.EndTable(); + } +}; + +struct UserUpdateBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_pos(const network::messages::Vec3 *pos) { fbb_.AddStruct(4, pos); } + UserUpdateBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + UserUpdateBuilder &operator=(const UserUpdateBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 1)); + return o; + } +}; + +inline flatbuffers::Offset CreateUserUpdate(flatbuffers::FlatBufferBuilder &_fbb, + const network::messages::Vec3 *pos = 0) { + UserUpdateBuilder builder_(_fbb); + builder_.add_pos(pos); + return builder_.Finish(); +} + +struct NpcSpawn FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + int64_t id() const { return GetField(4, 0); } + network::messages::NpcType type() const { return static_cast(GetField(6, 0)); } + const network::messages::Vec3 *pos() const { return GetStruct(8); } + int64_t human() const { return GetField(10, -1); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, 4 /* id */) && + VerifyField(verifier, 6 /* type */) && + VerifyField(verifier, 8 /* pos */) && + VerifyField(verifier, 10 /* human */) && + verifier.EndTable(); + } +}; + +struct NpcSpawnBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_id(int64_t id) { fbb_.AddElement(4, id, 0); } + void add_type(network::messages::NpcType type) { fbb_.AddElement(6, static_cast(type), 0); } + void add_pos(const network::messages::Vec3 *pos) { fbb_.AddStruct(8, pos); } + void add_human(int64_t human) { fbb_.AddElement(10, human, -1); } + NpcSpawnBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + NpcSpawnBuilder &operator=(const NpcSpawnBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 4)); + return o; + } +}; + +inline flatbuffers::Offset CreateNpcSpawn(flatbuffers::FlatBufferBuilder &_fbb, + int64_t id = 0, + network::messages::NpcType type = network::messages::NpcType_NONE, + const network::messages::Vec3 *pos = 0, + int64_t human = -1) { + NpcSpawnBuilder builder_(_fbb); + builder_.add_human(human); + builder_.add_id(id); + builder_.add_pos(pos); + builder_.add_type(type); + return builder_.Finish(); +} + +struct NpcTakeOver FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + int64_t id() const { return GetField(4, 0); } + int64_t human() const { return GetField(6, -1); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, 4 /* id */) && + VerifyField(verifier, 6 /* human */) && + verifier.EndTable(); + } +}; + +struct NpcTakeOverBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_id(int64_t id) { fbb_.AddElement(4, id, 0); } + void add_human(int64_t human) { fbb_.AddElement(6, human, -1); } + NpcTakeOverBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + NpcTakeOverBuilder &operator=(const NpcTakeOverBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 2)); + return o; + } +}; + +inline flatbuffers::Offset CreateNpcTakeOver(flatbuffers::FlatBufferBuilder &_fbb, + int64_t id = 0, + int64_t human = -1) { + NpcTakeOverBuilder builder_(_fbb); + builder_.add_human(human); + builder_.add_id(id); + return builder_.Finish(); +} + +struct NpcRemove FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + int64_t id() const { return GetField(4, 0); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, 4 /* id */) && + verifier.EndTable(); + } +}; + +struct NpcRemoveBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_id(int64_t id) { fbb_.AddElement(4, id, 0); } + NpcRemoveBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + NpcRemoveBuilder &operator=(const NpcRemoveBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 1)); + return o; + } +}; + +inline flatbuffers::Offset CreateNpcRemove(flatbuffers::FlatBufferBuilder &_fbb, + int64_t id = 0) { + NpcRemoveBuilder builder_(_fbb); + builder_.add_id(id); + return builder_.Finish(); +} + +struct NpcUpdate FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + int64_t id() const { return GetField(4, 0); } + const network::messages::Vec3 *pos() const { return GetStruct(6); } + float rotation() const { return GetField(8, 0); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, 4 /* id */) && + VerifyFieldRequired(verifier, 6 /* pos */) && + VerifyField(verifier, 8 /* rotation */) && + verifier.EndTable(); + } +}; + +struct NpcUpdateBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_id(int64_t id) { fbb_.AddElement(4, id, 0); } + void add_pos(const network::messages::Vec3 *pos) { fbb_.AddStruct(6, pos); } + void add_rotation(float rotation) { fbb_.AddElement(8, rotation, 0); } + NpcUpdateBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + NpcUpdateBuilder &operator=(const NpcUpdateBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 3)); + fbb_.Required(o, 6); // pos + return o; + } +}; + +inline flatbuffers::Offset CreateNpcUpdate(flatbuffers::FlatBufferBuilder &_fbb, + int64_t id = 0, + const network::messages::Vec3 *pos = 0, + float rotation = 0) { + NpcUpdateBuilder builder_(_fbb); + builder_.add_id(id); + builder_.add_rotation(rotation); + builder_.add_pos(pos); + return builder_.Finish(); +} + +struct NpcAnim FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + int64_t id() const { return GetField(4, 0); } + uint8_t anim() const { return GetField(6, 0); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, 4 /* id */) && + VerifyField(verifier, 6 /* anim */) && + verifier.EndTable(); + } +}; + +struct NpcAnimBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_id(int64_t id) { fbb_.AddElement(4, id, 0); } + void add_anim(uint8_t anim) { fbb_.AddElement(6, anim, 0); } + NpcAnimBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + NpcAnimBuilder &operator=(const NpcAnimBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 2)); + return o; + } +}; + +inline flatbuffers::Offset CreateNpcAnim(flatbuffers::FlatBufferBuilder &_fbb, + int64_t id = 0, + uint8_t anim = 0) { + NpcAnimBuilder builder_(_fbb); + builder_.add_id(id); + builder_.add_anim(anim); + return builder_.Finish(); +} + +struct NpcEffect FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + int64_t id() const { return GetField(4, 0); } + network::messages::NpcEffectType type() const { return static_cast(GetField(6, 0)); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, 4 /* id */) && + VerifyField(verifier, 6 /* type */) && + verifier.EndTable(); + } +}; + +struct NpcEffectBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_id(int64_t id) { fbb_.AddElement(4, id, 0); } + void add_type(network::messages::NpcEffectType type) { fbb_.AddElement(6, static_cast(type), 0); } + NpcEffectBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + NpcEffectBuilder &operator=(const NpcEffectBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 2)); + return o; + } +}; + +inline flatbuffers::Offset CreateNpcEffect(flatbuffers::FlatBufferBuilder &_fbb, + int64_t id = 0, + network::messages::NpcEffectType type = network::messages::NpcEffectType_HUMAN_CONTROLLED) { + NpcEffectBuilder builder_(_fbb); + builder_.add_id(id); + builder_.add_type(type); + return builder_.Finish(); +} + +struct ServerMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + Type data_type() const { return static_cast(GetField(4, 0)); } + const void *data() const { return GetPointer(6); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, 4 /* data_type */) && + VerifyField(verifier, 6 /* data */) && + VerifyType(verifier, data(), data_type()) && + verifier.EndTable(); + } +}; + +struct ServerMessageBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_data_type(Type data_type) { fbb_.AddElement(4, static_cast(data_type), 0); } + void add_data(flatbuffers::Offset data) { fbb_.AddOffset(6, data); } + ServerMessageBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + ServerMessageBuilder &operator=(const ServerMessageBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 2)); + return o; + } +}; + +inline flatbuffers::Offset CreateServerMessage(flatbuffers::FlatBufferBuilder &_fbb, + Type data_type = Type_NONE, + flatbuffers::Offset data = 0) { + ServerMessageBuilder builder_(_fbb); + builder_.add_data(data); + builder_.add_data_type(data_type); + return builder_.Finish(); +} + +inline bool VerifyType(flatbuffers::Verifier &verifier, const void *union_obj, Type type) { + switch (type) { + case Type_NONE: return true; + case Type_Seed: return verifier.VerifyTable(reinterpret_cast(union_obj)); + case Type_UserSpawn: return verifier.VerifyTable(reinterpret_cast(union_obj)); + case Type_UserUpdate: return verifier.VerifyTable(reinterpret_cast(union_obj)); + case Type_NpcSpawn: return verifier.VerifyTable(reinterpret_cast(union_obj)); + case Type_NpcRemove: return verifier.VerifyTable(reinterpret_cast(union_obj)); + case Type_NpcUpdate: return verifier.VerifyTable(reinterpret_cast(union_obj)); + case Type_NpcAnim: return verifier.VerifyTable(reinterpret_cast(union_obj)); + case Type_NpcEffect: return verifier.VerifyTable(reinterpret_cast(union_obj)); + case Type_AuthFailed: return verifier.VerifyTable(reinterpret_cast(union_obj)); + case Type_NpcTakeOver: return verifier.VerifyTable(reinterpret_cast(union_obj)); + default: return false; + } +} + +inline const ServerMessage *GetServerMessage(const void *buf) { return flatbuffers::GetRoot(buf); } + +inline bool VerifyServerMessageBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer(); } + +inline void FinishServerMessageBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset root) { fbb.Finish(root); } + +} // namespace server +} // namespace messages +} // namespace network + +#endif // FLATBUFFERS_GENERATED_SERVERMESSAGES_NETWORK_MESSAGES_SERVER_H_ diff --git a/src/modules/network/messages/Shared_generated.h b/src/modules/network/messages/Shared_generated.h new file mode 100644 index 000000000..86c01cf52 --- /dev/null +++ b/src/modules/network/messages/Shared_generated.h @@ -0,0 +1,79 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +#ifndef FLATBUFFERS_GENERATED_SHARED_NETWORK_MESSAGES_H_ +#define FLATBUFFERS_GENERATED_SHARED_NETWORK_MESSAGES_H_ + +#include "flatbuffers/flatbuffers.h" + + +namespace network { +namespace messages { + +struct Vec3; +struct Vec2; + +enum NpcType { + NpcType_NONE = 0, + NpcType_BEGIN_ANIMAL = 1, + NpcType_ANIMAL_WOLF = 2, + NpcType_ANIMAL_RABBIT = 3, + NpcType_MAX_ANIMAL = 4, + NpcType_BEGIN_CHARACTERS = 5, + NpcType_BLACKSMITH = 6, + NpcType_MAX_CHARACTERS = 7, + NpcType_MAX = 8 +}; + +inline const char **EnumNamesNpcType() { + static const char *names[] = { "NONE", "BEGIN_ANIMAL", "ANIMAL_WOLF", "ANIMAL_RABBIT", "MAX_ANIMAL", "BEGIN_CHARACTERS", "BLACKSMITH", "MAX_CHARACTERS", "MAX", nullptr }; + return names; +} + +inline const char *EnumNameNpcType(NpcType e) { return EnumNamesNpcType()[e]; } + +enum NpcEffectType { + NpcEffectType_HUMAN_CONTROLLED = 0, + NpcEffectType_AUTONOMOUS = 1 +}; + +inline const char **EnumNamesNpcEffectType() { + static const char *names[] = { "HUMAN_CONTROLLED", "AUTONOMOUS", nullptr }; + return names; +} + +inline const char *EnumNameNpcEffectType(NpcEffectType e) { return EnumNamesNpcEffectType()[e]; } + +MANUALLY_ALIGNED_STRUCT(4) Vec3 FLATBUFFERS_FINAL_CLASS { + private: + float x_; + float y_; + float z_; + + public: + Vec3(float x, float y, float z) + : x_(flatbuffers::EndianScalar(x)), y_(flatbuffers::EndianScalar(y)), z_(flatbuffers::EndianScalar(z)) { } + + float x() const { return flatbuffers::EndianScalar(x_); } + float y() const { return flatbuffers::EndianScalar(y_); } + float z() const { return flatbuffers::EndianScalar(z_); } +}; +STRUCT_END(Vec3, 12); + +MANUALLY_ALIGNED_STRUCT(4) Vec2 FLATBUFFERS_FINAL_CLASS { + private: + float x_; + float y_; + + public: + Vec2(float x, float y) + : x_(flatbuffers::EndianScalar(x)), y_(flatbuffers::EndianScalar(y)) { } + + float x() const { return flatbuffers::EndianScalar(x_); } + float y() const { return flatbuffers::EndianScalar(y_); } +}; +STRUCT_END(Vec2, 8); + +} // namespace messages +} // namespace network + +#endif // FLATBUFFERS_GENERATED_SHARED_NETWORK_MESSAGES_H_ diff --git a/src/modules/noise/AccidentalNoise.cpp b/src/modules/noise/AccidentalNoise.cpp new file mode 100644 index 000000000..028595266 --- /dev/null +++ b/src/modules/noise/AccidentalNoise.cpp @@ -0,0 +1,76 @@ +#include "AccidentalNoise.h" + +namespace noise { + +// TODO: erosion: https://code.google.com/p/accidental-noise-library/wiki/ModuleBasics +#if 0 +impad=anl.CImplicitBufferImplicitAdapter(turb, anl.SEAMLESS_NONE, anl.SMappingRanges(0,4,0,4,0,4), true, 0) +erode=anl.CImplicitBufferSimpleErode(impad, 0, 0.35) +blur=anl.CImplicitBufferBlur(erode, 3/256) +bump=anl.CImplicitBufferBumpMap(blur, -1.5, 3.5, 1.5, 0.5, false) +#endif +AccidentalNoise::AccidentalNoise() : +#if 0 + groundGradient(0.0, 0.0, 0.0, 1.0, 0.0, 0.0), + + plainFractal(anl::EFractalTypes::BILLOW, anl::GRADIENT, anl::QUINTIC, 1, 0.25, false), + plainAutoCorrect(&plainFractal, 0.0, 1.0), + plainScaleOffset(&plainAutoCorrect, 0.125, 0.3), + plainScaleDomain(&plainScaleOffset, 1.0, 0.0), + plainTranslateDomain(&groundGradient, 0.0, &plainScaleDomain, 0.0), + + highlandFractal(anl::EFractalTypes::FBM, anl::GRADIENT, anl::QUINTIC, 2, 0.5, false), + highlandAutoCorrect(&highlandFractal, 0.0, 1.0), + highlandScaleOffset(&highlandAutoCorrect, 0.15, 0.0), + highlandScaleDomain(&highlandScaleOffset, 1.0, 0.0), + highlandTranslateDomain(&groundGradient, 0.0, &highlandScaleDomain, 0.0), + + mountainFractal(anl::EFractalTypes::RIDGEDMULTI, anl::GRADIENT, anl::QUINTIC, 4, 0.8, false), + mountainAutoCorrect(&mountainFractal, 0.0, 1.0), + mountainScaleOffset(&mountainAutoCorrect, 1.5, -0.75), + mountainScaleDomain(&mountainScaleOffset, 1.0, 0.5), + mountainTranslateDomain(&groundGradient, 0.0, &mountainScaleDomain, 0.0), + + terrainControl(anl::EFractalTypes::BILLOW, anl::GRADIENT, anl::QUINTIC, 1, 0.05, false), + terrainAutoCorrect(&terrainControl, 0.0, 1.0), + terrainScaleOffset(&terrainAutoCorrect, 10.0, 0.0), + terrainScaleDomain(&terrainScaleOffset, 1.0, 0.0), + terrainCache(&terrainScaleDomain), + + highlandMountainSelect(&highlandTranslateDomain, &mountainTranslateDomain, &terrainCache, 9.0, 1.5), + highlandMountainColorSelect(&highland, &mountain, &terrainCache, 9.0, 0.0), + highlandMountainColorCache(&highlandMountainColorSelect), + plainHighlandSelect(&plainTranslateDomain, &highlandMountainSelect, &terrainCache, 4.0, 1.5), + plainHighlandColorSelect(&plain, &highlandMountainColorSelect, &terrainCache, 4.0, 0.0), + + plainHighlandCache(&plainHighlandSelect), + + groundBase() +#endif + plainFractal(anl::EFractalTypes::FBM, anl::GRADIENT, anl::QUINTIC, 10, 1.0, false) +{ +#if 0 + air.setConstant(0.0); + plain.setConstant(1.0); + highland.setConstant(2.0); + mountain.setConstant(3.0); + + groundBase.setLowSource(&plainHighlandColorSelect); + groundBase.setHighSource(&air); + groundBase.setControlSource(&plainHighlandCache); + groundBase.setThreshold(0.5); +#endif +} + +void AccidentalNoise::setSeed(long seed) { + anl::CMWC4096 rnd; + rnd.setSeed(seed); +#if 0 + plainFractal.setSeed(rnd.get()); + highlandFractal.setSeed(rnd.get()); + mountainFractal.setSeed(rnd.get()); + terrainControl.setSeed(rnd.get()); +#endif +} + +} diff --git a/src/modules/noise/AccidentalNoise.h b/src/modules/noise/AccidentalNoise.h new file mode 100644 index 000000000..cccfc730f --- /dev/null +++ b/src/modules/noise/AccidentalNoise.h @@ -0,0 +1,70 @@ +#pragma once + +#include "core/Random.h" +#include "core/Common.h" +#include +#include +#include +#include + +namespace noise { + +class AccidentalNoise { +private: +#if 0 + anl::CImplicitConstant air; + anl::CImplicitConstant plain; + anl::CImplicitConstant highland; + anl::CImplicitConstant mountain; + + anl::CImplicitGradient groundGradient; + + anl::CImplicitFractal plainFractal; + anl::CImplicitAutoCorrect plainAutoCorrect; + anl::CImplicitScaleOffset plainScaleOffset; + anl::CImplicitScaleDomain plainScaleDomain; + anl::CImplicitTranslateDomain plainTranslateDomain; + + anl::CImplicitFractal highlandFractal; + anl::CImplicitAutoCorrect highlandAutoCorrect; + anl::CImplicitScaleOffset highlandScaleOffset; + anl::CImplicitScaleDomain highlandScaleDomain; + anl::CImplicitTranslateDomain highlandTranslateDomain; + + anl::CImplicitFractal mountainFractal; + anl::CImplicitAutoCorrect mountainAutoCorrect; + anl::CImplicitScaleOffset mountainScaleOffset; + anl::CImplicitScaleDomain mountainScaleDomain; + anl::CImplicitTranslateDomain mountainTranslateDomain; + + anl::CImplicitFractal terrainControl; + anl::CImplicitAutoCorrect terrainAutoCorrect; + anl::CImplicitScaleOffset terrainScaleOffset; + anl::CImplicitScaleDomain terrainScaleDomain; + anl::CImplicitCache terrainCache; + + anl::CImplicitSelect highlandMountainSelect; + anl::CImplicitSelect highlandMountainColorSelect; + anl::CImplicitCache highlandMountainColorCache; + anl::CImplicitSelect plainHighlandSelect; + anl::CImplicitSelect plainHighlandColorSelect; + anl::CImplicitCache plainHighlandCache; + + anl::CImplicitSelect groundBase; +#endif + anl::CImplicitFractal plainFractal; + +public: + AccidentalNoise(); + + double get(double x, double y, double z, double worldDimension); + + void setSeed(long seed); +}; + +inline double AccidentalNoise::get(double x, double y, double z, double worldDimension) { + const double scale = 1.0 / worldDimension; + return plainFractal.get(x * scale, y * scale, z * scale); +} + +} diff --git a/src/modules/noise/CMakeLists.txt b/src/modules/noise/CMakeLists.txt new file mode 100644 index 000000000..ff162f1e7 --- /dev/null +++ b/src/modules/noise/CMakeLists.txt @@ -0,0 +1,20 @@ +fips_begin_module(noise) + fips_files( + PerlinNoise.h PerlinNoise.cpp stb_perlin.h + AccidentalNoise.h AccidentalNoise.cpp + NoisePPNoise.h NoisePPNoise.cpp + WorldShapeNoise.h WorldShapeNoise.cpp + ) + fips_deps(core noisepp accidentalnoise) +fips_end_module() + +begin_googleunittest(noise) + fips_dir(tests) + fips_files( + AccidentalNoiseTest.cpp + PerlinNoiseTest.cpp + NoisePPNoiseTest.cpp + NoiseTestHelper.h + ) + fips_deps(core noise accidentalnoise) +end_googleunittest() diff --git a/src/modules/noise/NoisePPNoise.cpp b/src/modules/noise/NoisePPNoise.cpp new file mode 100644 index 000000000..cc01346ac --- /dev/null +++ b/src/modules/noise/NoisePPNoise.cpp @@ -0,0 +1,91 @@ +#include "NoisePPNoise.h" +#include +#include +#include + +namespace noise { + +void NoisePPNoise::init() { + noisepp::ConstantModule lowConstant; + lowConstant.setValue(0); + + noisepp::ConstantModule highConstant; + highConstant.setValue(1); + + noisepp::BillowModule plainNoise; + plainNoise.setOctaveCount(1); + plainNoise.setQuality(noisepp::NOISE_QUALITY_STD); + plainNoise.setFrequency(0.25); + plainNoise.setLacunarity(2.0); + plainNoise.setPersistence(1); + + noisepp::PerlinModule highlandNoise; + highlandNoise.setOctaveCount(2); + highlandNoise.setQuality(noisepp::NOISE_QUALITY_STD); + highlandNoise.setFrequency(0.5); + highlandNoise.setLacunarity(2.0); + highlandNoise.setPersistence(1); + + noisepp::RidgedMultiModule mountainNoise; + mountainNoise.setOctaveCount(4); + mountainNoise.setQuality(noisepp::NOISE_QUALITY_STD); + mountainNoise.setFrequency(0.8); + mountainNoise.setLacunarity(2.0); + + noisepp::PerlinModule controlNoise; + controlNoise.setOctaveCount(1); + controlNoise.setQuality(noisepp::NOISE_QUALITY_STD); + controlNoise.setFrequency(0.05); + controlNoise.setLacunarity(2.0); + controlNoise.setPersistence(1); + + noisepp::SelectModule highlandMountainSelection; + highlandMountainSelection.setControlModule(controlNoise); + highlandMountainSelection.setSourceModule(0, highlandNoise); + highlandMountainSelection.setSourceModule(1, mountainNoise); + highlandMountainSelection.setLowerBound(0.2); + + noisepp::SelectModule plainHighlandSelection; + plainHighlandSelection.setControlModule(controlNoise); + plainHighlandSelection.setSourceModule(0, plainNoise); + plainHighlandSelection.setSourceModule(1, highlandMountainSelection); + plainHighlandSelection.setLowerBound(0.0); + + _buffer = new noisepp::Real[_w * _h]; + // create a builder + noisepp::utils::PlaneBuilder2D builder; + // set the source module + builder.setModule(plainHighlandSelection); + // set the buffer + builder.setDestination(_buffer); + // set the buffer size + builder.setSize(_w, _h); + // set the plane bounds - from (0.5|0) to (1.5|1) + builder.setBounds(0.5, 0, 1.5, 1); + // build + builder.build(); + + // create an image + noisepp::utils::Image img; + img.create(_w, _h); + // create the renderer and add some gradients to create a heat-vision like material + noisepp::utils::GradientRenderer renderer; + // renderer.addGradient (, noisepp::utils::ColourValue(, , )); + renderer.addGradient(-1.0, noisepp::utils::ColourValue(0.0f, 0.0f, 0.2f)); + renderer.addGradient(-0.8, noisepp::utils::ColourValue(0.0f, 0.0f, 0.6f)); + renderer.addGradient(0.0, noisepp::utils::ColourValue(1.0f, 0.0f, 0.0f)); + renderer.addGradient(0.6, noisepp::utils::ColourValue(1.0f, 1.0f, 0.0f)); + renderer.addGradient(1.0, noisepp::utils::ColourValue(1.0f, 1.0f, 1.0f)); + // render the image + renderer.renderImage(img, _buffer); + // save the image to an BMP + img.saveBMP("output.bmp"); + +} + +double NoisePPNoise::get(double x, double y, double z, double worldDimension) { + int value = x + y * _h; + return _buffer[value]; +} + +} diff --git a/src/modules/noise/NoisePPNoise.h b/src/modules/noise/NoisePPNoise.h new file mode 100644 index 000000000..bd4fcc616 --- /dev/null +++ b/src/modules/noise/NoisePPNoise.h @@ -0,0 +1,21 @@ +#pragma once +#include + +namespace noise { + +class NoisePPNoise { +private: + noisepp::Real *_buffer; + int _w = 64; + int _h = 64; + +public: + void init(); + + double get(double x, double y, double z, double worldDimension); + + void setSeed(long seed) { + } +}; + +} diff --git a/src/modules/noise/PerlinNoise.cpp b/src/modules/noise/PerlinNoise.cpp new file mode 100644 index 000000000..f336dfea2 --- /dev/null +++ b/src/modules/noise/PerlinNoise.cpp @@ -0,0 +1,16 @@ +#include "PerlinNoise.h" + +#define STB_PERLIN_IMPLEMENTATION +#include "stb_perlin.h" + +namespace noise { + +double PerlinNoise::get(double x, double y, double z, double worldDimension) { + const double scale = 1.0 / worldDimension; + const float height = stb_perlin_noise3(x * scale, y * scale, z * scale, 0, 0, 0); + if (::fabs(height) >= y * scale) + return 1.0; + return 0.0; +} + +} diff --git a/src/modules/noise/PerlinNoise.h b/src/modules/noise/PerlinNoise.h new file mode 100644 index 000000000..e50b7735c --- /dev/null +++ b/src/modules/noise/PerlinNoise.h @@ -0,0 +1,15 @@ +#pragma once + +#include "stb_perlin.h" + +namespace noise { + +class PerlinNoise { +public: + double get(double x, double y, double z, double worldDimension); + + void setSeed(long seed) { + } +}; + +} diff --git a/src/modules/noise/WorldShapeNoise.cpp b/src/modules/noise/WorldShapeNoise.cpp new file mode 100644 index 000000000..c46f614a9 --- /dev/null +++ b/src/modules/noise/WorldShapeNoise.cpp @@ -0,0 +1,59 @@ +#include "WorldShapeNoise.h" + +namespace noise { + +WorldShapeNoise::WorldShapeNoise() : + _sphere(1.0, 0.5, 0.0, 0.5), + _shape(), + + _elevationBase(anl::EFractalTypes::FBM, anl::GRADIENT, anl::QUINTIC, 6, 2, true), + _elevationAutoCorrect(&_elevationBase, 0.0, 1.0), + + _elevationTurbulence(anl::EFractalTypes::RIDGEDMULTI, anl::GRADIENT, anl::QUINTIC, 8, 1, true), + _elevationTurbulenceAutoCorrect(&_elevationTurbulence, 0.0, 1.0), + + _elevationTurbulenceTranslateDomain(&_elevationAutoCorrect, 0.0, &_elevationTurbulenceAutoCorrect, 0.0), + _elevation(anl::MULTIPLY, &_elevationTurbulenceTranslateDomain, &_shape), + + _groundBase() +{ + _shape.setOperation(anl::EASEQUINTIC); + _shape.setSource(&_sphere); + + _air.setConstant(0.0); + _soil.setConstant(1.0); + + _groundBase.setLowSource(&_soil); + _groundBase.setHighSource(&_air); + _groundBase.setControlSource(&_elevation); + _groundBase.setThreshold(0.5); +} + +void WorldShapeNoise::generateImage() { + anl::CRGBACompositeChannels composite; + + composite.setMode(anl::RGB); + composite.setRedSource(&_shape); + composite.setGreenSource(&_shape); + composite.setBlueSource(&_shape); + composite.setAlphaSource(1.0); + + anl::TArray2D> img(256, 256); + + anl::SMappingRanges ranges; + ranges.mapx0 = -1; + ranges.mapy0 = -1; + ranges.mapx1 = 1; + ranges.mapy1 = 1; + mapRGBA2D(anl::SEAMLESS_NONE, img ,composite ,ranges, 0); + + //Just for debugging purpose + saveRGBAArray((char*)"heightmap.tga", &img); + Log::info("+++++++++++++++generateImage"); +} + +void WorldShapeNoise::setSeed(long seed) { + anl::CMWC4096 rnd; + rnd.setSeed(seed); +} +} diff --git a/src/modules/noise/WorldShapeNoise.h b/src/modules/noise/WorldShapeNoise.h new file mode 100644 index 000000000..9c75b89c1 --- /dev/null +++ b/src/modules/noise/WorldShapeNoise.h @@ -0,0 +1,46 @@ +#pragma once + +#include "core/Random.h" +#include "core/Common.h" +#include +#include +#include +#include + +namespace noise { + +class WorldShapeNoise { +private: + anl::CImplicitSphere _sphere; + anl::CImplicitMath _shape; + + anl::CImplicitFractal _elevationBase; + anl::CImplicitAutoCorrect _elevationAutoCorrect; + + anl::CImplicitFractal _elevationTurbulence; + anl::CImplicitAutoCorrect _elevationTurbulenceAutoCorrect; + + anl::CImplicitTranslateDomain _elevationTurbulenceTranslateDomain; + anl::CImplicitMath _elevation; + + anl::CImplicitConstant _air; + anl::CImplicitConstant _soil; + + anl::CImplicitSelect _groundBase; + +public: + WorldShapeNoise(); + + double get(double x, double y, double z, double worldDimension = 128.0); + + void generateImage(); + + void setSeed(long seed); +}; + +inline double WorldShapeNoise::get(double x, double y, double z, double worldDimension) { + const double scale = 1.0 / worldDimension; + return _groundBase.get(x * scale, y * scale, z * scale); +} + +} diff --git a/src/modules/noise/stb_perlin.h b/src/modules/noise/stb_perlin.h new file mode 100644 index 000000000..a6a18cdb0 --- /dev/null +++ b/src/modules/noise/stb_perlin.h @@ -0,0 +1,175 @@ +// stb_perlin.h - v0.2 - perlin noise +// public domain single-file C implementation by Sean Barrett +// +// to create the implementation, +// #define STB_PERLIN_IMPLEMENTATION +// in *one* C/CPP file that includes this file. + + +// Documentation: +// +// float stb_perlin_noise3( float x, +// float y, +// float z, +// int x_wrap=0, +// int y_wrap=0, +// int z_wrap=0) +// +// This function computes a random value at the coordinate (x,y,z). +// Adjacent random values are continuous but the noise fluctuates +// its randomness with period 1, i.e. takes on wholly unrelated values +// at integer points. Specifically, this implements Ken Perlin's +// revised noise function from 2002. +// +// The "wrap" parameters can be used to create wraparound noise that +// wraps at powers of two. The numbers MUST be powers of two. Specify +// 0 to mean "don't care". (The noise always wraps every 256 due +// details of the implementation, even if you ask for larger or no +// wrapping.) + + +#ifdef __cplusplus +extern "C" float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap); +#else +extern float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap); +#endif + +#ifdef STB_PERLIN_IMPLEMENTATION + +#include // floor() + +// not same permutation table as Perlin's reference to avoid copyright issues; +// Perlin's table can be found at http://mrl.nyu.edu/~perlin/noise/ +// @OPTIMIZE: should this be unsigned char instead of int for cache? +static int stb__perlin_randtab[512] = +{ + 23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123, + 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, + 175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240, + 8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57, + 225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233, + 94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172, + 165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243, + 65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122, + 26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76, + 250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246, + 132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3, + 91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231, + 38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221, + 131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62, + 27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135, + 61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5, + + // and a second copy so we don't need an extra mask or static initializer + 23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123, + 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, + 175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240, + 8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57, + 225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233, + 94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172, + 165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243, + 65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122, + 26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76, + 250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246, + 132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3, + 91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231, + 38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221, + 131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62, + 27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135, + 61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5, +}; + +static float stb__perlin_lerp(float a, float b, float t) +{ + return a + (b-a) * t; +} + +// different grad function from Perlin's, but easy to modify to match reference +static float stb__perlin_grad(int hash, float x, float y, float z) +{ + static float basis[12][4] = + { + { 1, 1, 0 }, + { -1, 1, 0 }, + { 1,-1, 0 }, + { -1,-1, 0 }, + { 1, 0, 1 }, + { -1, 0, 1 }, + { 1, 0,-1 }, + { -1, 0,-1 }, + { 0, 1, 1 }, + { 0,-1, 1 }, + { 0, 1,-1 }, + { 0,-1,-1 }, + }; + + // perlin's gradient has 12 cases so some get used 1/16th of the time + // and some 2/16ths. We reduce bias by changing those fractions + // to 5/16ths and 6/16ths, and the same 4 cases get the extra weight. + static unsigned char indices[64] = + { + 0,1,2,3,4,5,6,7,8,9,10,11, + 0,9,1,11, + 0,1,2,3,4,5,6,7,8,9,10,11, + 0,1,2,3,4,5,6,7,8,9,10,11, + 0,1,2,3,4,5,6,7,8,9,10,11, + 0,1,2,3,4,5,6,7,8,9,10,11, + }; + + // if you use reference permutation table, change 63 below to 15 to match reference + float *grad = basis[indices[hash & 63]]; + return grad[0]*x + grad[1]*y + grad[2]*z; +} + +float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap) +{ + float u,v,w; + float n000,n001,n010,n011,n100,n101,n110,n111; + float n00,n01,n10,n11; + float n0,n1; + + unsigned int x_mask = (x_wrap-1) & 255; + unsigned int y_mask = (y_wrap-1) & 255; + unsigned int z_mask = (z_wrap-1) & 255; + int px = (int) floor(x); + int py = (int) floor(y); + int pz = (int) floor(z); + int x0 = px & x_mask, x1 = (px+1) & x_mask; + int y0 = py & y_mask, y1 = (py+1) & y_mask; + int z0 = pz & z_mask, z1 = (pz+1) & z_mask; + int r0,r1, r00,r01,r10,r11; + + #define stb__perlin_ease(a) (((a*6-15)*a + 10) * a * a * a) + + x -= px; u = stb__perlin_ease(x); + y -= py; v = stb__perlin_ease(y); + z -= pz; w = stb__perlin_ease(z); + + r0 = stb__perlin_randtab[x0]; + r1 = stb__perlin_randtab[x1]; + + r00 = stb__perlin_randtab[r0+y0]; + r01 = stb__perlin_randtab[r0+y1]; + r10 = stb__perlin_randtab[r1+y0]; + r11 = stb__perlin_randtab[r1+y1]; + + n000 = stb__perlin_grad(stb__perlin_randtab[r00+z0], x , y , z ); + n001 = stb__perlin_grad(stb__perlin_randtab[r00+z1], x , y , z-1 ); + n010 = stb__perlin_grad(stb__perlin_randtab[r01+z0], x , y-1, z ); + n011 = stb__perlin_grad(stb__perlin_randtab[r01+z1], x , y-1, z-1 ); + n100 = stb__perlin_grad(stb__perlin_randtab[r10+z0], x-1, y , z ); + n101 = stb__perlin_grad(stb__perlin_randtab[r10+z1], x-1, y , z-1 ); + n110 = stb__perlin_grad(stb__perlin_randtab[r11+z0], x-1, y-1, z ); + n111 = stb__perlin_grad(stb__perlin_randtab[r11+z1], x-1, y-1, z-1 ); + + n00 = stb__perlin_lerp(n000,n001,w); + n01 = stb__perlin_lerp(n010,n011,w); + n10 = stb__perlin_lerp(n100,n101,w); + n11 = stb__perlin_lerp(n110,n111,w); + + n0 = stb__perlin_lerp(n00,n01,v); + n1 = stb__perlin_lerp(n10,n11,v); + + return stb__perlin_lerp(n0,n1,u); +} +#endif // STB_PERLIN_IMPLEMENTATION diff --git a/src/modules/noise/tests/AccidentalNoiseTest.cpp b/src/modules/noise/tests/AccidentalNoiseTest.cpp new file mode 100644 index 000000000..2d7c50976 --- /dev/null +++ b/src/modules/noise/tests/AccidentalNoiseTest.cpp @@ -0,0 +1,21 @@ +#include +#include "noise/AccidentalNoise.h" +#include "NoiseTestHelper.h" + +namespace noise { + +TEST(AccidentalNoiseTest, testNoise) { + AccidentalNoise noise; + noise.setSeed(1L); + const int worldHeight = 256; + const int worldSize = 32; +#if 0 + anl::CArray3Dd a(worldSize, worldHeight, worldSize); + anl::CImplicitModuleBase* m = noise.get(); + anl::SMappingRanges ranges; + anl::map3D(anl::SEAMLESS_NONE, a, *m, ranges); +#endif + printNoise(noise, worldSize, worldHeight, worldSize); +} + +} diff --git a/src/modules/noise/tests/NoisePPNoiseTest.cpp b/src/modules/noise/tests/NoisePPNoiseTest.cpp new file mode 100644 index 000000000..77d55a72e --- /dev/null +++ b/src/modules/noise/tests/NoisePPNoiseTest.cpp @@ -0,0 +1,16 @@ +#include +#include "noise/NoisePPNoise.h" +#include "NoiseTestHelper.h" + +namespace noise { + +TEST(NoisePPNoiseTest, testNoise) { + NoisePPNoise noise; + noise.setSeed(1L); + const int worldHeight = 32; + const int worldSize = 32; + noise.init(); + printNoise(noise, worldSize, worldHeight, worldSize); +} + +} diff --git a/src/modules/noise/tests/NoiseTestHelper.h b/src/modules/noise/tests/NoiseTestHelper.h new file mode 100644 index 000000000..4666f19f0 --- /dev/null +++ b/src/modules/noise/tests/NoiseTestHelper.h @@ -0,0 +1,25 @@ +#pragma once + +#include "core/Log.h" +#include + +namespace noise { + +template +inline void printNoise(NOISE& noise, float width, float height, float depth) { + for (float y = 0; y < 32; ++y) { + Log::info("y: %f", y); + Log::info("------------"); + for (float z = depth-1; z >= 0; --z) { + Log::info("%.3f: ", z); + std::stringstream sb; + for (float x = 0; x < width; ++x) { + sb << noise.get(x, y, z, 256.0) << " "; + } + Log::info("%s", sb.str().c_str()); + } + Log::info("------------"); + } +} + +} diff --git a/src/modules/noise/tests/PerlinNoiseTest.cpp b/src/modules/noise/tests/PerlinNoiseTest.cpp new file mode 100644 index 000000000..2caea9fa7 --- /dev/null +++ b/src/modules/noise/tests/PerlinNoiseTest.cpp @@ -0,0 +1,15 @@ +#include +#include "noise/PerlinNoise.h" +#include "NoiseTestHelper.h" + +namespace noise { + +TEST(PerlinNoiseTest, testNoise) { + PerlinNoise noise; + noise.setSeed(1L); + const int worldHeight = 16; + const int worldSize = 16; + printNoise(noise, worldSize, worldHeight, worldSize); +} + +} diff --git a/src/modules/ui/CMakeLists.txt b/src/modules/ui/CMakeLists.txt new file mode 100644 index 000000000..9ec95264b --- /dev/null +++ b/src/modules/ui/CMakeLists.txt @@ -0,0 +1,24 @@ +fips_begin_module(ui) + fips_files( + UIApp.cpp UIApp.h + TurboBadger.h + Window.cpp Window.h + KeybindingParser.h + ui_renderer_gl.cpp ui_renderer_gl.h + ) + find_package(OpenGL) + find_package(SDL2 REQUIRED) + fips_include_directories(${SDL2_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIR}) + fips_deps(core io video turbobadger ${SDL2_LIBRARIES} ${OPENGL_LIBRARIES}) +fips_end_module() + +begin_googleunittest(ui) + fips_dir(tests) + fips_files( + KeybindingParserTest.cpp + ) + find_package(OpenGL) + find_package(SDL2 REQUIRED) + fips_include_directories(. ${SDL2_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIR}) + fips_deps(core io video turbobadger ui ${SDL2_LIBRARIES} ${OPENGL_LIBRARIES}) +end_googleunittest() diff --git a/src/modules/ui/KeybindingParser.h b/src/modules/ui/KeybindingParser.h new file mode 100644 index 000000000..8454227fe --- /dev/null +++ b/src/modules/ui/KeybindingParser.h @@ -0,0 +1,64 @@ +#pragma once + +#include "core/Tokenizer.h" +#include +#include + +namespace ui { + +typedef std::unordered_multimap > BindMap; + +class KeybindingParser: public core::Tokenizer { +private: + BindMap _bindings; + int _invalidBindings; +public: + KeybindingParser(const std::string& bindings) : + core::Tokenizer(bindings), _invalidBindings(0) { + for (;;) { + if (!hasNext()) + break; + std::string key = next(); + if (!hasNext()) + break; + const std::string& command = next(); + + int modifier = KMOD_NONE; + if (key.size() > 1) { + if (core::string::contains(key, "+")) { + std::vector line; + core::string::splitString(key, line, "+"); + for (const std::string& token : line) { + const std::string& lower = core::string::toLower(token); + if (lower == "shift") { + modifier |= KMOD_SHIFT; + } else if (lower == "alt") { + modifier |= KMOD_ALT; + } else if (lower == "ctrl") { + modifier |= KMOD_CTRL; + } else { + key = token; + } + } + } + } + + const SDL_Keycode keyCode = SDL_GetKeyFromName(key.c_str()); + if (keyCode == SDLK_UNKNOWN) { + ++_invalidBindings; + continue; + } + _bindings.insert(std::make_pair(keyCode, std::make_pair(command, modifier))); + } + } + + inline int invalidBindings() const { + return _invalidBindings; + } + + inline const BindMap& getBindings() const { + return _bindings; + } +}; + +} diff --git a/src/modules/ui/TurboBadger.h b/src/modules/ui/TurboBadger.h new file mode 100644 index 000000000..615c8bb7f --- /dev/null +++ b/src/modules/ui/TurboBadger.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/src/modules/ui/UIApp.cpp b/src/modules/ui/UIApp.cpp new file mode 100644 index 000000000..56a5289f1 --- /dev/null +++ b/src/modules/ui/UIApp.cpp @@ -0,0 +1,380 @@ +#include "UIApp.h" +#include "TurboBadger.h" + +#include "io/File.h" +#include "core/Command.h" +#include "core/Common.h" +#include "ui_renderer_gl.h" + +extern void register_tbbf_font_renderer(); + +namespace ui { + +namespace { +tb::MODIFIER_KEYS mapModifier(int16_t modifier) { + tb::MODIFIER_KEYS code = tb::TB_MODIFIER_NONE; + if (modifier & KMOD_ALT) + code |= tb::TB_ALT; + if (modifier & KMOD_CTRL) + code |= tb::TB_CTRL; + if (modifier & KMOD_SHIFT) + code |= tb::TB_SHIFT; + if (modifier & KMOD_GUI) + code |= tb::TB_SUPER; + return code; +} + +tb::SPECIAL_KEY mapSpecialKey(int32_t key) { + switch (key) { + case SDLK_F1: + return tb::TB_KEY_F1; + case SDLK_F2: + return tb::TB_KEY_F2; + case SDLK_F3: + return tb::TB_KEY_F3; + case SDLK_F4: + return tb::TB_KEY_F4; + case SDLK_F5: + return tb::TB_KEY_F5; + case SDLK_F6: + return tb::TB_KEY_F6; + case SDLK_F7: + return tb::TB_KEY_F7; + case SDLK_F8: + return tb::TB_KEY_F8; + case SDLK_F9: + return tb::TB_KEY_F9; + case SDLK_F10: + return tb::TB_KEY_F10; + case SDLK_F11: + return tb::TB_KEY_F11; + case SDLK_F12: + return tb::TB_KEY_F12; + case SDLK_LEFT: + return tb::TB_KEY_LEFT; + case SDLK_UP: + return tb::TB_KEY_UP; + case SDLK_RIGHT: + return tb::TB_KEY_RIGHT; + case SDLK_DOWN: + return tb::TB_KEY_DOWN; + case SDLK_PAGEUP: + return tb::TB_KEY_PAGE_UP; + case SDLK_PAGEDOWN: + return tb::TB_KEY_PAGE_DOWN; + case SDLK_HOME: + return tb::TB_KEY_HOME; + case SDLK_END: + return tb::TB_KEY_END; + case SDLK_INSERT: + return tb::TB_KEY_INSERT; + case SDLK_TAB: + return tb::TB_KEY_TAB; + case SDLK_DELETE: + return tb::TB_KEY_DELETE; + case SDLK_BACKSPACE: + return tb::TB_KEY_BACKSPACE; + case SDLK_RETURN: + case SDLK_KP_ENTER: + return tb::TB_KEY_ENTER; + case SDLK_ESCAPE: + return tb::TB_KEY_ESC; + } + return tb::TB_KEY_UNDEFINED; +} + +int mapKey(int32_t key) { + if (mapSpecialKey(key) == tb::TB_KEY_UNDEFINED) + return key; + return 0; +} + +} + +tb::UIRendererGL _renderer; + +UIApp::UIApp(const io::FilesystemPtr& filesystem, const core::EventBusPtr& eventBus) : + WindowedApp(filesystem, eventBus), _quit(false) { +} + +UIApp::~UIApp() { + tb::tb_core_shutdown(); +} + +bool UIApp::loadKeyBindings() { + const std::string& bindings = filesystem()->load("ui/keybindings.cfg"); + if (bindings.empty()) + return false; + const KeybindingParser p(bindings); + _bindings = p.getBindings(); + return true; +} + +bool UIApp::invokeKey(int key, tb::SPECIAL_KEY special, tb::MODIFIER_KEYS mod, bool down) { +#ifdef MACOSX + bool shortcutKey = (mod & tb::TB_SUPER) ? true : false; +#else + bool shortcutKey = (mod & tb::TB_CTRL) ? true : false; +#endif + if (tb::TBWidget::focused_widget && down && shortcutKey) { + bool reverseKey = (mod & tb::TB_SHIFT) ? true : false; + if (key >= 'a' && key <= 'z') + key += 'A' - 'a'; + tb::TBID id; + if (key == 'X') + id = tb::TBIDC("cut"); + else if (key == 'C' || special == tb::TB_KEY_INSERT) + id = tb::TBIDC("copy"); + else if (key == 'V' || (special == tb::TB_KEY_INSERT && reverseKey)) + id = tb::TBIDC("paste"); + else if (key == 'A') + id = tb::TBIDC("selectall"); + else if (key == 'Z' || key == 'Y') { + bool undo = key == 'Z'; + if (reverseKey) + undo = !undo; + id = undo ? tb::TBIDC("undo") : tb::TBIDC("redo"); + } else if (key == 'N') + id = tb::TBIDC("new"); + else if (key == 'O') + id =tb:: TBIDC("open"); + else if (key == 'S') + id = tb::TBIDC("save"); + else if (key == 'W') + id = tb::TBIDC("close"); + else if (special == tb::TB_KEY_PAGE_UP) + id = tb::TBIDC("prev_doc"); + else if (special == tb::TB_KEY_PAGE_DOWN) + id = tb::TBIDC("next_doc"); + else + return false; + + tb::TBWidgetEvent ev(tb::EVENT_TYPE_SHORTCUT); + ev.modifierkeys = mod; + ev.ref_id = id; + return tb::TBWidget::focused_widget->InvokeEvent(ev); + } + + if (key >= ' ' && key <= '~') + return false; + return _root.InvokeKey(key, special, mod, down); +} + +void UIApp::onMouseWheel(int32_t x, int32_t y) { + int posX, posY; + SDL_GetMouseState(&posX, &posY); + _root.InvokeWheel(posX, posY, x, -y, mapModifier(SDL_GetModState())); +} + +void UIApp::onMouseMotion(int32_t x, int32_t y, int32_t relX, int32_t relY) { + if (tb::TBWidget::captured_widget != nullptr) + return; + _root.InvokePointerMove(x, y, mapModifier(SDL_GetModState()), false); +} + +void UIApp::onMouseButtonPress(int32_t x, int32_t y, uint8_t button) { + if (button != SDL_BUTTON_LEFT) + return; + static double lastTime = 0; + static int lastX = 0; + static int lastY = 0; + static int counter = 1; + + const double time = tb::TBSystem::GetTimeMS(); + if (time < lastTime + 600 && lastX == x && lastY == y) + ++counter; + else + counter = 1; + lastX = x; + lastY = y; + lastTime = time; + + _root.InvokePointerDown(x, y, counter, mapModifier(SDL_GetModState()), false); +} + +void UIApp::onMouseButtonRelease(int32_t x, int32_t y, uint8_t button) { + if (button == SDL_BUTTON_RIGHT) { + _root.InvokePointerMove(x, y, mapModifier(SDL_GetModState()), false); + tb::TBWidget* hover = tb::TBWidget::hovered_widget; + if (hover != nullptr) { + hover->ConvertFromRoot(x, y); + tb::TBWidgetEvent ev(tb::EVENT_TYPE_CONTEXT_MENU, x, y, false, tb::TB_MODIFIER_NONE); + hover->InvokeEvent(ev); + } + } else { + _root.InvokePointerUp(x, y, mapModifier(SDL_GetModState()), false); + } +} + +bool UIApp::onKeyRelease(int32_t key) { + auto range = _bindings.equal_range(key); + for (auto i = range.first; i != range.second; ++i) { + const std::string& command = i->second.first; + if (command[0] == '+' && _keys.erase(key) > 0) { + core_assert(1 == core::Command::execute(command + " false")); + } + } + + return invokeKey(mapKey(key), mapSpecialKey(key), mapModifier(SDL_GetModState()), false); +} + +bool UIApp::onTextInput(const std::string& text) { + const char *c = text.c_str(); + for (;;) { + const int key = core::string::getUTF8Next(&c); + if (key == -1) + return true; + _root.InvokeKey(key, tb::TB_KEY_UNDEFINED, tb::TB_MODIFIER_NONE, true); + _root.InvokeKey(key, tb::TB_KEY_UNDEFINED, tb::TB_MODIFIER_NONE, false); + } + return true; +} + +bool UIApp::onKeyPress(int32_t key, int16_t modifier) { + auto range = _bindings.equal_range(key); + for (auto i = range.first; i != range.second; ++i) { + const std::string& command = i->second.first; + if ((modifier == 0 && i->second.second == 0) || (modifier != 0 && (i->second.second & modifier) == modifier)) { + if (command[0] == '+') { + if (core::Command::execute(command + " true") == 1) + _keys[key] = modifier; + } else { + core::Command::execute(command); + } + } + } + + return invokeKey(mapKey(key), mapSpecialKey(key), mapModifier(modifier), true); +} + +core::AppState UIApp::onConstruct() { + core::Command::registerCommand("cl_ui_debug", [&] (const core::CmdArgs& args) { +#ifndef NDEBUG + tb::ShowDebugInfoSettingsWindow(&_root); +#endif + }); + + core::Command::registerCommand("quit", [&] (const core::CmdArgs& args) {_quit = true;}); + + return WindowedApp::onConstruct(); +} + +core::AppState UIApp::onInit() { + if (!tb::tb_core_init(&_renderer, "ui/lang/en.tb.txt")) { + Log::error("failed to initialize the ui"); + return core::AppState::Cleanup; + } + + if (!tb::g_tb_skin->Load("ui/skin/skin.tb.txt", nullptr)) { + Log::error("could not load the skin"); + return core::AppState::Cleanup; + } + + if (!_renderer.init()) { + Log::error("could not init ui renderer"); + return core::AppState::Cleanup; + } + + tb::TBWidgetsAnimationManager::Init(); + if (!loadKeyBindings()) { + Log::error("failed to init the keybindings"); + } + + register_tbbf_font_renderer(); + tb::g_font_manager->AddFontInfo("ui/font/font.tb.txt", "Segoe"); + tb::TBFontDescription fd; + fd.SetID(tb::TBIDC("Segoe")); + fd.SetSize(tb::g_tb_skin->GetDimensionConverter()->DpToPx(14)); + tb::g_font_manager->SetDefaultFontDescription(fd); + tb::TBFontFace *font = tb::g_font_manager->CreateFontFace(tb::g_font_manager->GetDefaultFontDescription()); + if (font == nullptr) { + Log::error("could not create the font face"); + return core::AppState::Cleanup; + } + + font->RenderGlyphs(" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~•·åäöÅÄÖ"); + _root.SetRect(tb::TBRect(0, 0, _width, _height)); + _root.SetSkinBg(tb::TBIDC("background")); + + const core::AppState state = WindowedApp::onInit(); + return state; +} + +void UIApp::addChild(Window* window) { + _root.AddChild(window); +} + +core::AppState UIApp::onRunning() { + if (_quit) + return core::AppState::Cleanup; + core::AppState state = WindowedApp::onRunning(); + + for (KeyMapConstIter it = _keys.begin(); it != _keys.end(); ++it) { + const int key = it->first; + auto i = _bindings.find(key); + const std::string& command = i->second.first; + const int16_t modifier = it->second; + if (i->second.second == modifier && command[0] == '+') { + core_assert(1 == core::Command::execute(command + " true")); + _keys[key] = modifier; + } + } + + if (state == core::AppState::Running) { + beforeUI(); + + tb::TBAnimationManager::Update(); + _root.InvokeProcessStates(); + _root.InvokeProcess(); + + _renderer.BeginPaint(_width, _height); + _root.InvokePaint(tb::TBWidget::PaintProps()); + + ++_frameCounter; + + double time = tb::TBSystem::GetTimeMS(); + if (time > _frameCounterResetRime + 1000) { + fps = (int) ((_frameCounter / (time - _frameCounterResetRime)) * 1000); + _frameCounterResetRime = time; + _frameCounter = 0; + } + + tb::TBStr str; + str.SetFormatted("FPS: %d", fps); + _root.GetFont()->DrawString(5, 5, tb::TBColor(255, 255, 255), str); + + _renderer.EndPaint(); + // If animations are running, reinvalidate immediately + if (tb::TBAnimationManager::HasAnimationsRunning()) + _root.Invalidate(); + + afterUI(); + } + return state; +} + +core::AppState UIApp::onCleanup() { + tb::TBWidgetsAnimationManager::Shutdown(); + return WindowedApp::onCleanup(); +} + +void UIApp::afterUI() { + // render the console +} + +} + +void tb::TBSystem::RescheduleTimer(double fireTime) { +#if 0 + static double setFireTime = -1; + if (fireTime == TB_NOT_SOON) { + setFireTime = -1; + //glfwKillTimer(); + } else if (fireTime != setFireTime || fireTime == 0.0) { + setFireTime = fireTime; + double delay = fireTime - tb::TBSystem::GetTimeMS(); + unsigned int idelay = (unsigned int) std::max(delay, 0.0); + //glfwRescheduleTimer(idelay); + } +#endif +} diff --git a/src/modules/ui/UIApp.h b/src/modules/ui/UIApp.h new file mode 100644 index 000000000..e1e04c72e --- /dev/null +++ b/src/modules/ui/UIApp.h @@ -0,0 +1,86 @@ +#pragma once + +#include +#include +#include + +#include "video/WindowedApp.h" +#include "KeybindingParser.h" +#include "Window.h" + +namespace ui { + +class UIApp: public video::WindowedApp { +protected: + /** + * @brief This struct allows you to determine how long a key was pressed or how long it is pressed + */ + struct KeyState { + // how long was the key down + long downtime = 0; + // when was the key pressed + long msec = 0; + // is it still pressed + bool active = false; + }; + + /** + * @brief Call this in a key up key binding function + */ + inline void keyUp(KeyState& state) { + state.active = false; + state.downtime = _now - state.msec; + state.downtime = std::max(_now - state.msec, 10L); + } + + /** + * @brief Call this in a key down key binding function + */ + inline void keyDown(KeyState& state) { + if (state.active) + return; + state.msec = _now; + state.active = true; + state.downtime = 0; + } + + typedef std::unordered_map KeyMap; + typedef KeyMap::const_iterator KeyMapConstIter; + typedef KeyMap::iterator KeyMapIter; + KeyMap _keys; + BindMap _bindings; + bool _quit; + tb::TBWidget _root; + int fps = 0; + uint32_t _frameCounter = 0; + double _frameCounterResetRime = 0.0; + + bool loadKeyBindings(); + + virtual bool onKeyRelease(int32_t key) override; + virtual bool onKeyPress(int32_t key, int16_t modifier) override; + virtual bool onTextInput(const std::string& text) override; + virtual void onMouseWheel(int32_t x, int32_t y) override; + virtual void onMouseMotion(int32_t x, int32_t y, int32_t relX, int32_t relY) override; + virtual void onMouseButtonPress(int32_t x, int32_t y, uint8_t button) override; + virtual void onMouseButtonRelease(int32_t x, int32_t y, uint8_t button) override; + + bool invokeKey(int key, tb::SPECIAL_KEY special, tb::MODIFIER_KEYS mod, bool down); +public: + UIApp(const io::FilesystemPtr& filesystem, const core::EventBusPtr& eventBus); + virtual ~UIApp(); + + virtual void beforeUI() { + } + + void addChild(Window* window); + + virtual void afterUI(); + + virtual core::AppState onConstruct() override; + virtual core::AppState onInit() override; + virtual core::AppState onRunning() override; + virtual core::AppState onCleanup() override; +}; + +} diff --git a/src/modules/ui/Window.cpp b/src/modules/ui/Window.cpp new file mode 100644 index 000000000..81cfe2674 --- /dev/null +++ b/src/modules/ui/Window.cpp @@ -0,0 +1,70 @@ +#include "Window.h" +#include "UIApp.h" + +namespace ui { + +Window::Window(UIApp* app) { + app->addChild(this); +} + +Window::Window(Window* parent) { + parent->AddChild(this); +} + +bool Window::loadResourceFile(const char *filename) { + tb::TBNode node; + if (!node.ReadFile(filename)) + return false; + loadResource(node); + return true; +} + +void Window::loadResourceData(const char *data) { + tb::TBNode node; + node.ReadData(data); + loadResource(node); +} + +void Window::loadResource(tb::TBNode &node) { + tb::g_widgets_reader->LoadNodeTree(this, &node); + + // Get title from the WindowInfo section (or use "" if not specified) + SetText(node.GetValueString("WindowInfo>title", "")); + + const tb::TBRect parentRect(0, 0, GetParent()->GetRect().w, GetParent()->GetRect().h); + const tb::TBDimensionConverter *dc = tb::g_tb_skin->GetDimensionConverter(); + tb::TBRect windowRect = GetResizeToFitContentRect(); + + // Use specified size or adapt to the preferred content size. + tb::TBNode *tmp = node.GetNode("WindowInfo>size"); + if (tmp && tmp->GetValue().GetArrayLength() == 2) { + windowRect.w = dc->GetPxFromString(tmp->GetValue().GetArray()->GetValue(0)->GetString(), windowRect.w); + windowRect.h = dc->GetPxFromString(tmp->GetValue().GetArray()->GetValue(1)->GetString(), windowRect.h); + } + + // Use the specified position or center in parent. + tmp = node.GetNode("WindowInfo>position"); + if (tmp && tmp->GetValue().GetArrayLength() == 2) { + windowRect.x = dc->GetPxFromString(tmp->GetValue().GetArray()->GetValue(0)->GetString(), windowRect.x); + windowRect.y = dc->GetPxFromString(tmp->GetValue().GetArray()->GetValue(1)->GetString(), windowRect.y); + } else { + windowRect = windowRect.CenterIn(parentRect); + } + + // Make sure the window is inside the parent, and not larger. + windowRect = windowRect.MoveIn(parentRect).Clip(parentRect); + + SetRect(windowRect); + + // Ensure we have focus - now that we've filled the window with possible focusable + // widgets. EnsureFocus was automatically called when the window was activated (by + // adding the window to the root), but then we had nothing to focus. + // Alternatively, we could add the window after setting it up properly. + EnsureFocus(); +} + +bool Window::OnEvent(const tb::TBWidgetEvent &ev) { + return TBWindow::OnEvent(ev); +} + +} diff --git a/src/modules/ui/Window.h b/src/modules/ui/Window.h new file mode 100644 index 000000000..3c310bc48 --- /dev/null +++ b/src/modules/ui/Window.h @@ -0,0 +1,22 @@ +#pragma once + +#include "TurboBadger.h" + +namespace ui { + +class UIApp; + +class Window: public tb::TBWindow { +public: + Window(UIApp* app); + Window(Window* parent); + virtual ~Window() {} + + bool loadResourceFile(const char *filename); + void loadResourceData(const char *data); + void loadResource(tb::TBNode &node); + + virtual bool OnEvent(const tb::TBWidgetEvent &ev) override; +}; + +} diff --git a/src/modules/ui/tb_config.h b/src/modules/ui/tb_config.h new file mode 100644 index 000000000..dc3aa7ed2 --- /dev/null +++ b/src/modules/ui/tb_config.h @@ -0,0 +1,124 @@ +// ================================================================================ +// == This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås == +// == See tb_core.h for more information. == +// ================================================================================ +// +// This file contains defines for the default configuration of Turbo Badger. +// You may change these here, but to make upgrades easier it's better to create a +// copy of this file in a include path that is searched before Turbo Badger during +// build (F.ex the solution directory for Visual Studio). + +#ifndef TB_CONFIG_H +#define TB_CONFIG_H + +/** Enable for some handy runtime debugging, enabled by modifying + the various settings in g_tb_debug. A settings window can be + shown by calling ShowDebugInfoSettingsWindow. */ +#ifndef NDEBUG +#define TB_RUNTIME_DEBUG_INFO +#endif + +#ifndef NDEBUG +/** Enable compilation of unit tests. */ +#define TB_UNIT_TESTING +#endif + +/** Enable if the focus state should automatically be set on edit fields even + when using the pointer. It is normally set only while moving focus by keyboard. */ +//#define TB_ALWAYS_SHOW_EDIT_FOCUS + +/** Enable to use premultiplied alpha. Warning: This is not handled everywhere in + the default backends, so consider it an experimental and unfinished feature! */ +//#define TB_PREMULTIPLIED_ALPHA + +/** Enable to support TBBF fonts (Turbo Badger Bitmap Fonts) */ +#define TB_FONT_RENDERER_TBBF + +/** Enable to support truetype fonts using freetype. */ +//#define TB_FONT_RENDERER_FREETYPE + +/** Enable to support truetype fonts using stb_truetype.h (http://nothings.org/). + It's a *very unsafe* font library. Use only with fonts distributed with your + app, that you know work! Freetype generates much prettier glyphs (using + hinting) but is a lot larger. This implementation is kept here as alternative + as long as it compiles. */ +//#define TB_FONT_RENDERER_STB + +/** Enable to support image loading using stb_image.c (http://nothings.org/). + It's a *very unsafe* image library. Use only with images distributed with + your app, that you know work! */ +#define TB_IMAGE_LOADER_STB + +/** Enable to get TBRendererBatcher, an helper class for renderers that + implements batching of draw operations. Subclasses of TBRendererBatcher + can be done super easily, and still do batching. */ +#define TB_RENDERER_BATCHER + +/** Enable renderer using OpenGL. This renderer depends on TB_RENDERER_BATCHER. + It is using GL version 1.1, */ +//#define TB_RENDERER_GL + +/** Enable renderer using OpenGL ES. This renderer depends on TB_RENDERER_GL. + It is using GL ES version 1. */ +//#define TB_RENDERER_GLES_1 + +/** The width of the font glyph cache. Must be a power of two. */ +#define TB_GLYPH_CACHE_WIDTH 512 + +/** The height of the font glyph cache. Must be a power of two. */ +#define TB_GLYPH_CACHE_HEIGHT 512 + +// == Optional features =========================================================== + +/** Enable support for TBImage, TBImageManager, TBImageWidget. */ +#define TB_IMAGE + +// == Additional configuration of platform implementations ======================== + +/** Define for posix implementation of TBFile. */ +//#define TB_FILE_POSIX + +/** Defines for implementations of TBClipboard. */ +//#define TB_CLIPBOARD_DUMMY // Cross platform. Not integrating with the OS. +//#define TB_CLIPBOARD_GLFW // Cross platform using glfw API. +//#define TB_CLIPBOARD_WINDOWS + +/** Defines for implementations of TBSystem. */ +//#define TB_SYSTEM_LINUX +//#define TB_SYSTEM_WINDOWS +//#define TB_SYSTEM_ANDROID + +/** Defines for additional platform specific issues. */ +//#define TB_TARGET_WINDOWS +//#define TB_TARGET_MACOSX +//#define TB_TARGET_LINUX + +// == Setting some defaults for platform implementations ========================== + +#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__) +#define TB_FILE_POSIX +#define TB_TARGET_WINDOWS +#define TB_CLIPBOARD_WINDOWS +#define TB_SYSTEM_WINDOWS +#endif + +#if defined(__linux) || defined(__linux__) +#define TB_FILE_POSIX +#define TB_TARGET_LINUX +#define TB_SYSTEM_LINUX +#define TB_CLIPBOARD_DUMMY +#endif + +#ifdef MACOSX +#define TB_FILE_POSIX +#define TB_TARGET_MACOSX +#define TB_SYSTEM_LINUX +#define TB_CLIPBOARD_DUMMY +#endif + +#if defined(ANDROID) || defined(__ANDROID__) +#define TB_SYSTEM_ANDROID +#define TB_CLIPBOARD_DUMMY +#endif + +#endif // TB_CONFIG_H diff --git a/src/modules/ui/tests/KeybindingParserTest.cpp b/src/modules/ui/tests/KeybindingParserTest.cpp new file mode 100644 index 000000000..9ce8d027f --- /dev/null +++ b/src/modules/ui/tests/KeybindingParserTest.cpp @@ -0,0 +1,20 @@ +#include +#include "ui/KeybindingParser.h" + +namespace ui { + +const char *CFG = "w +foo\n" + "alt+a \"somecommand +\"\n" + "CTRL+s +bar\n" + "SHIFT+d +xyz\n"; + +TEST(KeybindingParserTest, testParsing) { + KeybindingParser p(CFG); + const BindMap& m = p.getBindings(); + ASSERT_FALSE(m.empty()); + ASSERT_EQ(0, p.invalidBindings()); + const std::size_t expected = 4; + ASSERT_EQ(expected, m.size()); +} + +} diff --git a/src/modules/ui/ui_renderer_gl.cpp b/src/modules/ui/ui_renderer_gl.cpp new file mode 100644 index 000000000..fe941d250 --- /dev/null +++ b/src/modules/ui/ui_renderer_gl.cpp @@ -0,0 +1,141 @@ +#include +#include +#include "ui_renderer_gl.h" +#include +#include +#include + +namespace tb { + +#ifdef TB_RUNTIME_DEBUG_INFO +uint32 dbg_bitmap_validations = 0; +#endif + +GLuint g_current_texture = (GLuint) -1; +TBRendererBatcher::Batch *g_current_batch = 0; + +void BindBitmap(TBBitmap *bitmap) { + GLuint texture = bitmap ? static_cast(bitmap)->m_texture : 0; + if (texture != g_current_texture) { + g_current_texture = texture; + glBindTexture(GL_TEXTURE_2D, g_current_texture); + } +} + +UIBitmapGL::UIBitmapGL(UIRendererGL *renderer) : + m_renderer(renderer), m_w(0), m_h(0), m_texture(0) { +} + +UIBitmapGL::~UIBitmapGL() { + m_renderer->FlushBitmap(this); + if (m_texture == g_current_texture) + BindBitmap(nullptr); + + glDeleteTextures(1, &m_texture); +} + +bool UIBitmapGL::Init(int width, int height, uint32 *data) { + assert(width == TBGetNearestPowerOfTwo(width)); + assert(height == TBGetNearestPowerOfTwo(height)); + + m_w = width; + m_h = height; + + glGenTextures(1, &m_texture); + BindBitmap(this); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + GL_checkError(); + + SetData(data); + + return true; +} + +void UIBitmapGL::SetData(uint32 *data) { + m_renderer->FlushBitmap(this); + BindBitmap(this); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_w, m_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + TB_IF_DEBUG_SETTING(RENDER_BATCHES, dbg_bitmap_validations++); +} + +UIRendererGL::UIRendererGL() : _buffer(0) { +} + +bool UIRendererGL::init() { + if (!_shader.loadProgram("shaders/ui")) + return false; + glGenBuffers(1, &_buffer); + GL_checkError(); + return true; +} + +void UIRendererGL::BeginPaint(int render_target_w, int render_target_h) { +#ifdef TB_RUNTIME_DEBUG_INFO + dbg_bitmap_validations = 0; +#endif + + TBRendererBatcher::BeginPaint(render_target_w, render_target_h); + + _shader.activate(); + + const glm::mat4& ortho = glm::ortho(0.0f, (float) render_target_w, (float) render_target_h, 0.0f, -1.0f, 1.0f); + _shader.setUniformMatrix("u_projection", ortho, false); + + g_current_texture = (GLuint) -1; + g_current_batch = nullptr; + + glViewport(0, 0, render_target_w, render_target_h); + glScissor(0, 0, render_target_w, render_target_h); + + glEnable(GL_BLEND); + glEnable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_checkError(); +} + +void UIRendererGL::EndPaint() { + TBRendererBatcher::EndPaint(); + _shader.deactivate(); + glBindBuffer(GL_ARRAY_BUFFER, 0); + +#ifdef TB_RUNTIME_DEBUG_INFO + if (TB_DEBUG_SETTING(RENDER_BATCHES)) + TBDebugPrint("Frame caused %d bitmap validations.\n", dbg_bitmap_validations); +#endif + GL_checkError(); +} + +TBBitmap *UIRendererGL::CreateBitmap(int width, int height, uint32 *data) { + UIBitmapGL *bitmap = new UIBitmapGL(this); + if (!bitmap || !bitmap->Init(width, height, data)) { + delete bitmap; + return nullptr; + } + return bitmap; +} + +void UIRendererGL::RenderBatch(Batch *batch) { + BindBitmap(batch->bitmap); + if (g_current_batch != batch) { + g_current_batch = batch; + } + glBindBuffer(GL_ARRAY_BUFFER, _buffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * batch->vertex_count, batch->vertex, GL_STATIC_DRAW); + glVertexAttribPointer(_shader.enableVertexAttribute("a_color"), 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), GL_OFFSET(offsetof(Batch, vertex[0].col))); + glVertexAttribPointer(_shader.enableVertexAttribute("a_texcoord"), 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), GL_OFFSET(offsetof(Batch, vertex[0].u))); + glVertexAttribPointer(_shader.enableVertexAttribute("a_pos"), 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), GL_OFFSET(offsetof(Batch, vertex[0].x))); + + glDrawArrays(GL_TRIANGLES, 0, batch->vertex_count); + GL_checkError(); +} + +void UIRendererGL::SetClipRect(const TBRect &rect) { + glScissor(m_clip_rect.x, m_screen_rect.h - (m_clip_rect.y + m_clip_rect.h), m_clip_rect.w, m_clip_rect.h); + GL_checkError(); +} + +} diff --git a/src/modules/ui/ui_renderer_gl.h b/src/modules/ui/ui_renderer_gl.h new file mode 100644 index 000000000..e763dd94b --- /dev/null +++ b/src/modules/ui/ui_renderer_gl.h @@ -0,0 +1,47 @@ +#pragma once + +#include "video/GLFunc.h" +#include "video/Shader.h" + +#include + +namespace tb { + +class UIRendererGL; + +class UIBitmapGL: public TBBitmap { +public: + UIBitmapGL(UIRendererGL *renderer); + ~UIBitmapGL();bool Init(int width, int height, uint32 *data); + virtual int Width() { + return m_w; + } + virtual int Height() { + return m_h; + } + virtual void SetData(uint32 *data); +public: + UIRendererGL *m_renderer; + int m_w, m_h; + GLuint m_texture; +}; + +class UIRendererGL: public TBRendererBatcher { +private: + video::Shader _shader; + GLuint _buffer; +public: + UIRendererGL(); + + bool init(); + + virtual void BeginPaint(int render_target_w, int render_target_h); + virtual void EndPaint(); + + virtual TBBitmap *CreateBitmap(int width, int height, uint32 *data); + + virtual void RenderBatch(Batch *batch); + virtual void SetClipRect(const TBRect &rect); +}; + +} diff --git a/src/modules/util/CMakeLists.txt b/src/modules/util/CMakeLists.txt new file mode 100644 index 000000000..6b0aca700 --- /dev/null +++ b/src/modules/util/CMakeLists.txt @@ -0,0 +1,8 @@ +fips_begin_module(util) + fips_files( + Velocity.h + IProgressMonitor.h + PosLerp.h + Dummy.cpp + ) +fips_end_module() diff --git a/src/modules/util/Dummy.cpp b/src/modules/util/Dummy.cpp new file mode 100644 index 000000000..2cae79189 --- /dev/null +++ b/src/modules/util/Dummy.cpp @@ -0,0 +1 @@ +#include "Velocity.h" diff --git a/src/modules/util/IProgressMonitor.h b/src/modules/util/IProgressMonitor.h new file mode 100644 index 000000000..974015ff4 --- /dev/null +++ b/src/modules/util/IProgressMonitor.h @@ -0,0 +1,33 @@ +#pragma once + +namespace util { + +class IProgressMonitor { +protected: + int _max; + int _steps; +public: + IProgressMonitor(int max = 100) : + _max(max), _steps(0) { + } + + virtual ~IProgressMonitor() { + } + + void init(int max) { + _max = max; + } + + virtual void step(int steps = 1) { + _steps += steps; + } + + virtual void done() { + } + + double progress() const { + return _steps * 100.0 / static_cast(_max); + } +}; + +} diff --git a/src/modules/util/PosLerp.h b/src/modules/util/PosLerp.h new file mode 100644 index 000000000..0b507dd00 --- /dev/null +++ b/src/modules/util/PosLerp.h @@ -0,0 +1,54 @@ +#pragma once + +#include "core/Log.h" +#include + +namespace util { + +class PosLerp { +private: + long MOVETIME = 200L; + glm::vec3 _currentPosition; + glm::vec3 _lastPosition; + glm::vec3 _nextPosition; + long _nextPosTime; +public: + PosLerp() : + _currentPosition(0.0f), _lastPosition(0.0f), _nextPosition(0.0f), _nextPosTime(0L) { + } + + inline const glm::vec3& position() const { + return _currentPosition; + } + + inline void setPosition(long now, const glm::vec3& position) { + _lastPosition = position; + _currentPosition = position; + _nextPosition = position; + _nextPosTime = now; + } + + inline void lerpPosition(long now, const glm::vec3& position) { + _lastPosition = _currentPosition; + _nextPosition = position; + _nextPosTime = now + MOVETIME; + Log::trace("update: c(%f:%f:%f) n(%f:%f:%f) l(%f:%f:%f)", _currentPosition.x, _currentPosition.y, _currentPosition.z, + _nextPosition.x, _nextPosition.y, _nextPosition.z, _lastPosition.x, _lastPosition.y, _lastPosition.z); + } + + void update(long now) { + if (now < _nextPosTime) { + const long remaining = _nextPosTime - now; + const long passed = MOVETIME - remaining; + const float lerp = passed / (float) MOVETIME; + _currentPosition = _lastPosition + ((_nextPosition - _lastPosition) * lerp); + Log::trace("lerp: %f, passed: %li c(%f:%f:%f) n(%f:%f:%f) l(%f:%f:%f)", lerp, passed, _currentPosition.x, _currentPosition.y, + _currentPosition.z, _nextPosition.x, _nextPosition.y, _nextPosition.z, _lastPosition.x, _lastPosition.y, + _lastPosition.z); + } else { + _currentPosition = _nextPosition; + } + } +}; + +} diff --git a/src/modules/util/Velocity.h b/src/modules/util/Velocity.h new file mode 100644 index 000000000..1f832706e --- /dev/null +++ b/src/modules/util/Velocity.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +namespace util { + +inline glm::vec3 getDirection(float yaw) { + const float angleRadians = yaw - M_PI_2; + const glm::vec3 direction(glm::sin(angleRadians), 0.0, glm::cos(angleRadians)); + return direction; +} + +inline glm::vec3 getDirection(float pitch, float yaw) { + const float cosV = glm::cos(pitch); + const float cosH = glm::cos(yaw); + const float sinH = glm::sin(yaw); + const float sinV = glm::sin(pitch); + const glm::vec3 direction(cosV * sinH, sinV, cosV * cosH); + return direction; +} + + +} diff --git a/src/modules/video/CMakeLists.txt b/src/modules/video/CMakeLists.txt new file mode 100644 index 000000000..0b49725f1 --- /dev/null +++ b/src/modules/video/CMakeLists.txt @@ -0,0 +1,22 @@ +fips_begin_module(video) + fips_files( + WindowedApp.cpp WindowedApp.h + GLFunc.cpp GLFunc.h + VertexBuffer.cpp VertexBuffer.h + FrameBuffer.cpp FrameBuffer.h + GBuffer.cpp GBuffer.h + Shader.cpp Shader.h + Camera.cpp Camera.h + GLMeshData.h + GLDebug.h + Image.cpp Image.h + Cubemap.cpp Cubemap.h + Texture.cpp Texture.h + Mesh.cpp Mesh.h + MeshPool.cpp MeshPool.h + ) + find_package(OpenGL) + find_package(SDL2 REQUIRED) + include_directories(${SDL2_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIR}) + fips_deps(core io assimp ${SDL2_LIBRARIES} ${OPENGL_LIBRARIES}) +fips_end_module() diff --git a/src/modules/video/Camera.cpp b/src/modules/video/Camera.cpp new file mode 100644 index 000000000..38f1c56a9 --- /dev/null +++ b/src/modules/video/Camera.cpp @@ -0,0 +1,61 @@ +#include "Camera.h" +#include "core/Common.h" +#include "core/Singleton.h" +#include "io/EventHandler.h" + +namespace video { + +Camera::Camera() : + _pos(0.0f, 0.0f, 0.0f), _width(0.0f), _height(0.0f), _pitch(-M_PI_2), _yaw(M_PI), _direction(0.0f, 0.0f, 0.0f), _mouseSpeed( + core::Var::get("cl_cammousespeed", "0.01")), _maxpitch(core::Var::get("cl_cammaxpitch", std::to_string(core::toRadians(89.0f)))) { + updateDirection(); +} + +Camera::~Camera() { +} + +void Camera::updatePosition(long dt, bool left, bool right, bool forward, bool backward) { + const float angle = _yaw - M_PI_2; + const glm::vec3 rightvec(glm::sin(angle), 0.0, glm::cos(angle)); + + const float deltaTime = static_cast(dt); + const float speed = _mouseSpeed->floatVal(); + if (forward) { + _pos += _direction * deltaTime * speed; + } + if (backward) { + _pos -= _direction * deltaTime * speed; + } + if (left) { + _pos -= rightvec * deltaTime * speed; + } + if (right) { + _pos += rightvec * deltaTime * speed; + } +} + +void Camera::init(int width, int height) { + _width = width; + _height = height; +} + +void Camera::updateDirection() { + const float maxPitch = _maxpitch->floatVal(); + _pitch = core::clamp(_pitch, -maxPitch, maxPitch); + + const float cosV = glm::cos(_pitch); + const float cosH = glm::cos(_yaw); + const float sinH = glm::sin(_yaw); + const float sinV = glm::sin(_pitch); + _direction = glm::vec3(cosV * sinH, sinV, cosV * cosH); +} + +void Camera::onMotion(int32_t x, int32_t y, int32_t deltaX, int32_t deltaY) { + const float mouseSpeed = _mouseSpeed->floatVal(); + _yaw -= static_cast(deltaX) * mouseSpeed; + _pitch -= static_cast(deltaY) * mouseSpeed; + + updateDirection(); +} + +} diff --git a/src/modules/video/Camera.h b/src/modules/video/Camera.h new file mode 100644 index 000000000..a1079d9d3 --- /dev/null +++ b/src/modules/video/Camera.h @@ -0,0 +1,78 @@ +#pragma once + +#include +#include +#include "io/IEventObserver.h" +#include "core/Var.h" +#include +#include + +namespace video { + +class Camera { +private: + glm::vec3 _pos; + glm::mat4 _viewMatrix; + int _width; + int _height; + float _pitch; + float _yaw; + glm::vec3 _direction; + core::VarPtr _mouseSpeed; + core::VarPtr _maxpitch; + +public: + Camera(); + ~Camera(); + void init(int width, int height); + + void onMotion(int32_t x, int32_t y, int32_t relX, int32_t relY); + void onMovement(int32_t forward, int32_t sideward); + + void updatePosition(long dt, bool left, bool right, bool forward, bool backward); + + // Direction : Spherical coordinates to Cartesian coordinates conversion + void updateDirection(); + + inline void updateViewMatrix() { + _viewMatrix = glm::lookAt(_pos, _pos + glm::normalize(_direction), glm::vec3(0.0, 1.0, 0.0)); + } + + inline void update() { + updateDirection(); + updateViewMatrix(); + } + + inline const glm::vec3 getPosition() const { + return _pos; + } + + /** + * @brief Return the horizontal angle of the camera view direction + */ + inline float yaw() const { + return _yaw; + } + + /** + * @brief Return the vertical angle of the camera view direction + */ + inline float pitch() const { + return _pitch; + } + + inline void setAngles(float pitch, float yaw) { + _pitch = pitch; + _yaw = yaw; + } + + inline void setPosition(const glm::vec3& pos) { + _pos = pos; + } + + inline const glm::mat4& getViewMatrix() const { + return _viewMatrix; + } +}; + +} diff --git a/src/modules/video/Cubemap.cpp b/src/modules/video/Cubemap.cpp new file mode 100644 index 000000000..528455d36 --- /dev/null +++ b/src/modules/video/Cubemap.cpp @@ -0,0 +1,58 @@ +#include "Cubemap.h" +#include "core/Log.h" +#include "core/String.h" +#include "video/Image.h" + +namespace video { + +Cubemap::Cubemap(const std::string& filename) : + _filename(filename), _textureHandle(0u) { +} + +Cubemap::~Cubemap() { + if (_textureHandle != 0) { + glDeleteTextures(1, &_textureHandle); + } +} + +bool Cubemap::load() { + glGenTextures(1, &_textureHandle); + glBindTexture(GL_TEXTURE_CUBE_MAP, _textureHandle); + + static const GLenum types[] = { + GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z + }; + + for (unsigned int i = 1; i <= 6; i++) { + const std::string& filename = core::string::format("%s-cm-%i", _filename.c_str(), i); + Image img(filename); + img.loadSync(); + const GLenum mode = img.hasAlpha() ? GL_RGBA : GL_RGB; + glTexImage2D(types[i - 1], 0, mode, img.width(), img.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.data()); + } + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + return true; +} + +void Cubemap::bind(GLenum texUnit) { + glActiveTexture(texUnit); + glBindTexture(GL_TEXTURE_CUBE_MAP, _textureHandle); +} + +void Cubemap::unbind(GLenum texUnit) { + glActiveTexture(texUnit); + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); +} + +} diff --git a/src/modules/video/Cubemap.h b/src/modules/video/Cubemap.h new file mode 100644 index 000000000..40f07df2c --- /dev/null +++ b/src/modules/video/Cubemap.h @@ -0,0 +1,31 @@ +#pragma once + +#include "GLFunc.h" + +namespace video { + +class Cubemap { +private: + std::string _filename; + GLuint _textureHandle; +public: + /** + * @brief Loads 6 textures that belongs to a cubemap. The naming schema must be "-cm-X" (where X is replaced by 1-6) + * + * The order of the 1-6 is as followed: + * - GL_TEXTURE_CUBE_MAP_POSITIVE_X + * - GL_TEXTURE_CUBE_MAP_NEGATIVE_X + * - GL_TEXTURE_CUBE_MAP_POSITIVE_Y + * - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y + * - GL_TEXTURE_CUBE_MAP_POSITIVE_Z + * - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z + */ + Cubemap(const std::string& filename); + ~Cubemap(); + + bool load(); + void bind(GLenum texUnit = GL_TEXTURE0); + void unbind(GLenum texUnit = GL_TEXTURE0); +}; + +} diff --git a/src/modules/video/FrameBuffer.cpp b/src/modules/video/FrameBuffer.cpp new file mode 100644 index 000000000..4028b3c87 --- /dev/null +++ b/src/modules/video/FrameBuffer.cpp @@ -0,0 +1,54 @@ +#include "FrameBuffer.h" + +namespace video { + +FrameBuffer::FrameBuffer() : + _framebuffer(0), _attached(0) { +} + +FrameBuffer::~FrameBuffer() { + if (_framebuffer != 0) + glDeleteFramebuffers(1, &_framebuffer); +} + +void FrameBuffer::bind() { + if (_framebuffer != 0) { + glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer); + return; + } + + glGenFramebuffers(1, &_framebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer); +} + +void FrameBuffer::unbind() { + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +bool FrameBuffer::isSuccessful() { + GLenum error = glCheckFramebufferStatus(GL_FRAMEBUFFER); + return error == GL_FRAMEBUFFER_COMPLETE; +} + +void FrameBuffer::attachRenderBuffer(GLenum internalformat, GLenum attachment, GLsizei width, GLsizei height) { + GLuint depthrenderbuffer; + glGenRenderbuffers(1, &depthrenderbuffer); + glBindRenderbuffer(GL_RENDERBUFFER, depthrenderbuffer); + glRenderbufferStorage(GL_RENDERBUFFER, internalformat, width, height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, depthrenderbuffer); +} + +void FrameBuffer::attachTexture(GLuint texture, GLenum attachmentType) { + if (texture != 0) + ++_attached; + else + --_attached; + glBindTexture(GL_TEXTURE_2D, texture); + glFramebufferTexture(GL_FRAMEBUFFER, attachmentType, texture, 0); +} + +void FrameBuffer::drawBuffers(GLsizei n, const GLenum *buffers) { + glDrawBuffers(n, buffers); +} + +} diff --git a/src/modules/video/FrameBuffer.h b/src/modules/video/FrameBuffer.h new file mode 100644 index 000000000..089a0eba2 --- /dev/null +++ b/src/modules/video/FrameBuffer.h @@ -0,0 +1,31 @@ +#pragma once + +#include "GLFunc.h" + +namespace video { + +class FrameBuffer { +private: + GLuint _framebuffer; + int _attached; +public: + FrameBuffer(); + ~FrameBuffer(); + + bool isSuccessful(); + + /** + * @note Call glViewport after the framebuffer was bound + */ + void bind(); + void unbind(); + /** + * @param[in] texture The texture handle + * @param[in] attachmentType Possible values are @c GL_COLOR_ATTACHMENT0..GL_COLOR_ATTACHMENTn, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT + */ + void attachTexture(GLuint texture, GLenum attachmentType); + void attachRenderBuffer(GLenum internalformat, GLenum attachment, GLsizei width, GLsizei height); + void drawBuffers(GLsizei n, const GLenum *buffers); +}; + +} diff --git a/src/modules/video/GBuffer.cpp b/src/modules/video/GBuffer.cpp new file mode 100644 index 000000000..2fd67770f --- /dev/null +++ b/src/modules/video/GBuffer.cpp @@ -0,0 +1,74 @@ +#include "GBuffer.h" + +#include +#include "core/Common.h" + +namespace video { + +GBuffer::GBuffer() : + _fbo(0), _depthTexture(0) { + for (std::size_t i = 0; i < lengthof(_textures); ++i) { + _textures[i] = 0; + } +} + +GBuffer::~GBuffer() { + if (_fbo != 0) { + glDeleteFramebuffers(1, &_fbo); + } + + if (_textures[0] != 0) { + glDeleteTextures(lengthof(_textures), _textures); + } + + if (_depthTexture != 0) { + glDeleteTextures(1, &_depthTexture); + } +} + +bool GBuffer::init(int width, int height) { + glGenFramebuffers(1, &_fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo); + + glGenTextures(lengthof(_textures), _textures); + glGenTextures(1, &_depthTexture); + + for (std::size_t i = 0; i < lengthof(_textures); ++i) { + glBindTexture(GL_TEXTURE_2D, _textures[i]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT, nullptr); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, _textures[i], 0); + } + + glBindTexture(GL_TEXTURE_2D, _depthTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depthTexture, 0); + + const GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 }; + glDrawBuffers(lengthof(drawBuffers), drawBuffers); + + const GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + + if (status != GL_FRAMEBUFFER_COMPLETE) { + Log::error("FB error, status: %i", (int)status); + return false; + } + + // restore default FBO + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + + return true; +} + +void GBuffer::bindForWriting() { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo); +} + +void GBuffer::bindForReading() { + glBindFramebuffer(GL_READ_FRAMEBUFFER, _fbo); +} + +void GBuffer::setReadBuffer(GBufferTextureType textureType) { + glReadBuffer(GL_COLOR_ATTACHMENT0 + textureType); +} + +} diff --git a/src/modules/video/GBuffer.h b/src/modules/video/GBuffer.h new file mode 100644 index 000000000..983ae8bf7 --- /dev/null +++ b/src/modules/video/GBuffer.h @@ -0,0 +1,28 @@ +#pragma once + +#include "GLFunc.h" + +namespace video { + +class GBuffer { +public: + enum GBufferTextureType { + GBUFFER_TEXTURE_TYPE_POSITION, GBUFFER_TEXTURE_TYPE_DIFFUSE, GBUFFER_TEXTURE_TYPE_NORMAL, GBUFFER_TEXTURE_TYPE_TEXCOORD, GBUFFER_NUM_TEXTURES + }; + + GBuffer(); + ~GBuffer(); + + bool init(int width, int height); + + void setReadBuffer(GBufferTextureType textureType); + void bindForWriting(); + void bindForReading(); + +private: + GLuint _fbo; + GLuint _textures[GBUFFER_NUM_TEXTURES]; + GLuint _depthTexture; +}; + +} diff --git a/src/modules/video/GLDebug.h b/src/modules/video/GLDebug.h new file mode 100644 index 000000000..0a345a316 --- /dev/null +++ b/src/modules/video/GLDebug.h @@ -0,0 +1,99 @@ +#include "core/Log.h" +#include "GLFunc.h" + +class GLDebug { +private: + static bool _enabled; +#if defined(GL_ARB_debug_output) + static void debugOutputCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const GLvoid* userParam) { + const char* typeStr; + switch (type) { + case GL_DEBUG_TYPE_ERROR_ARB: + typeStr = "ERROR"; + break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: + typeStr = "DEPRECATED_BEHAVIOR"; + break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: + typeStr = "UNDEFINED_BEHAVIOR"; + break; + case GL_DEBUG_TYPE_PORTABILITY_ARB: + typeStr = "PORTABILITY"; + break; + case GL_DEBUG_TYPE_PERFORMANCE_ARB: + typeStr = "PERFORMANCE"; + break; + case GL_DEBUG_TYPE_OTHER_ARB: + typeStr = "OTHER"; + break; + default: + typeStr = ""; + break; + } + const char* sevStr; + switch (severity) { + case GL_DEBUG_SEVERITY_LOW_ARB: + sevStr = "LOW"; + break; + case GL_DEBUG_SEVERITY_MEDIUM_ARB: + sevStr = "MEDIUM"; + break; + case GL_DEBUG_SEVERITY_HIGH_ARB: + sevStr = "HIGH"; + break; + default: + sevStr = ""; + break; + } + Log::warn("##### OpenGL Debug Message:\ntype: %s, id: %d, severity: %s\nmsg: %s\n", typeStr, id, sevStr, message); + } +#endif + +public: + enum Severity { + High, Medium, Low, + }; + + static void enable(Severity s) { +#if defined(GL_ARB_debug_output) + GLenum glSeverity = GL_DONT_CARE; + switch (s) { + case High: + glSeverity = GL_DEBUG_SEVERITY_HIGH_ARB; + break; + case Medium: + glSeverity = GL_DEBUG_SEVERITY_MEDIUM_ARB; + break; + case Low: + glSeverity = GL_DEBUG_SEVERITY_LOW_ARB; + break; + } + glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, glSeverity, 0, nullptr, GL_TRUE); + if (!_enabled) { + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); + glDebugMessageCallbackARB(debugOutputCallback, nullptr); + GL_checkError(); + _enabled = true; + } + Log::info("enable opengl debug messages"); +#else + Log::warn("Not implemented"); +#endif + } + + static void disable() { +#if defined(GL_ARB_debug_output) + glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); + GL_checkError(); + _enabled = false; + Log::info("disable opengl debug messages"); +#endif + } + + static bool isEnabled() { + return _enabled; + } +}; + +bool GLDebug::_enabled = false; + diff --git a/src/modules/video/GLFunc.cpp b/src/modules/video/GLFunc.cpp new file mode 100644 index 000000000..bbcd6e849 --- /dev/null +++ b/src/modules/video/GLFunc.cpp @@ -0,0 +1,655 @@ +#include "GLFunc.h" +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void ExtGLLoadFunctions(void) { + /* GL_VERSION_1_2 */ + + glpfDrawRangeElements = (PFNGLDRAWRANGEELEMENTS_PROC*) SDL_GL_GetProcAddress("glDrawRangeElements"); + glpfTexImage3D = (PFNGLTEXIMAGE3D_PROC*) SDL_GL_GetProcAddress("glTexImage3D"); + glpfTexSubImage3D = (PFNGLTEXSUBIMAGE3D_PROC*) SDL_GL_GetProcAddress("glTexSubImage3D"); + glpfCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3D_PROC*) SDL_GL_GetProcAddress("glCopyTexSubImage3D"); + + /* GL_VERSION_1_3 */ + + glpfActiveTexture = (PFNGLACTIVETEXTURE_PROC*) SDL_GL_GetProcAddress("glActiveTexture"); + glpfSampleCoverage = (PFNGLSAMPLECOVERAGE_PROC*) SDL_GL_GetProcAddress("glSampleCoverage"); + glpfCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3D_PROC*) SDL_GL_GetProcAddress("glCompressedTexImage3D"); + glpfCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2D_PROC*) SDL_GL_GetProcAddress("glCompressedTexImage2D"); + glpfCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1D_PROC*) SDL_GL_GetProcAddress("glCompressedTexImage1D"); + glpfCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3D_PROC*) SDL_GL_GetProcAddress("glCompressedTexSubImage3D"); + glpfCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2D_PROC*) SDL_GL_GetProcAddress("glCompressedTexSubImage2D"); + glpfCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1D_PROC*) SDL_GL_GetProcAddress("glCompressedTexSubImage1D"); + glpfGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGE_PROC*) SDL_GL_GetProcAddress("glGetCompressedTexImage"); + + /* GL_VERSION_1_4 */ + + glpfBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATE_PROC*) SDL_GL_GetProcAddress("glBlendFuncSeparate"); + glpfMultiDrawArrays = (PFNGLMULTIDRAWARRAYS_PROC*) SDL_GL_GetProcAddress("glMultiDrawArrays"); + glpfMultiDrawElements = (PFNGLMULTIDRAWELEMENTS_PROC*) SDL_GL_GetProcAddress("glMultiDrawElements"); + glpfPointParameterf = (PFNGLPOINTPARAMETERF_PROC*) SDL_GL_GetProcAddress("glPointParameterf"); + glpfPointParameterfv = (PFNGLPOINTPARAMETERFV_PROC*) SDL_GL_GetProcAddress("glPointParameterfv"); + glpfPointParameteri = (PFNGLPOINTPARAMETERI_PROC*) SDL_GL_GetProcAddress("glPointParameteri"); + glpfPointParameteriv = (PFNGLPOINTPARAMETERIV_PROC*) SDL_GL_GetProcAddress("glPointParameteriv"); + glpfBlendColor = (PFNGLBLENDCOLOR_PROC*) SDL_GL_GetProcAddress("glBlendColor"); + glpfBlendEquation = (PFNGLBLENDEQUATION_PROC*) SDL_GL_GetProcAddress("glBlendEquation"); + + /* GL_VERSION_1_5 */ + + glpfGenQueries = (PFNGLGENQUERIES_PROC*) SDL_GL_GetProcAddress("glGenQueries"); + glpfDeleteQueries = (PFNGLDELETEQUERIES_PROC*) SDL_GL_GetProcAddress("glDeleteQueries"); + glpfIsQuery = (PFNGLISQUERY_PROC*) SDL_GL_GetProcAddress("glIsQuery"); + glpfBeginQuery = (PFNGLBEGINQUERY_PROC*) SDL_GL_GetProcAddress("glBeginQuery"); + glpfEndQuery = (PFNGLENDQUERY_PROC*) SDL_GL_GetProcAddress("glEndQuery"); + glpfGetQueryiv = (PFNGLGETQUERYIV_PROC*) SDL_GL_GetProcAddress("glGetQueryiv"); + glpfGetQueryObjectiv = (PFNGLGETQUERYOBJECTIV_PROC*) SDL_GL_GetProcAddress("glGetQueryObjectiv"); + glpfGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIV_PROC*) SDL_GL_GetProcAddress("glGetQueryObjectuiv"); + glpfBindBuffer = (PFNGLBINDBUFFER_PROC*) SDL_GL_GetProcAddress("glBindBuffer"); + glpfDeleteBuffers = (PFNGLDELETEBUFFERS_PROC*) SDL_GL_GetProcAddress("glDeleteBuffers"); + glpfGenBuffers = (PFNGLGENBUFFERS_PROC*) SDL_GL_GetProcAddress("glGenBuffers"); + glpfIsBuffer = (PFNGLISBUFFER_PROC*) SDL_GL_GetProcAddress("glIsBuffer"); + glpfBufferData = (PFNGLBUFFERDATA_PROC*) SDL_GL_GetProcAddress("glBufferData"); + glpfBufferSubData = (PFNGLBUFFERSUBDATA_PROC*) SDL_GL_GetProcAddress("glBufferSubData"); + glpfGetBufferSubData = (PFNGLGETBUFFERSUBDATA_PROC*) SDL_GL_GetProcAddress("glGetBufferSubData"); + glpfMapBuffer = (PFNGLMAPBUFFER_PROC*) SDL_GL_GetProcAddress("glMapBuffer"); + glpfUnmapBuffer = (PFNGLUNMAPBUFFER_PROC*) SDL_GL_GetProcAddress("glUnmapBuffer"); + glpfGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIV_PROC*) SDL_GL_GetProcAddress("glGetBufferParameteriv"); + glpfGetBufferPointerv = (PFNGLGETBUFFERPOINTERV_PROC*) SDL_GL_GetProcAddress("glGetBufferPointerv"); + + /* GL_VERSION_2_0 */ + + glpfBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATE_PROC*) SDL_GL_GetProcAddress("glBlendEquationSeparate"); + glpfDrawBuffers = (PFNGLDRAWBUFFERS_PROC*) SDL_GL_GetProcAddress("glDrawBuffers"); + glpfStencilOpSeparate = (PFNGLSTENCILOPSEPARATE_PROC*) SDL_GL_GetProcAddress("glStencilOpSeparate"); + glpfStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATE_PROC*) SDL_GL_GetProcAddress("glStencilFuncSeparate"); + glpfStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATE_PROC*) SDL_GL_GetProcAddress("glStencilMaskSeparate"); + glpfAttachShader = (PFNGLATTACHSHADER_PROC*) SDL_GL_GetProcAddress("glAttachShader"); + glpfBindAttribLocation = (PFNGLBINDATTRIBLOCATION_PROC*) SDL_GL_GetProcAddress("glBindAttribLocation"); + glpfCompileShader = (PFNGLCOMPILESHADER_PROC*) SDL_GL_GetProcAddress("glCompileShader"); + glpfCreateProgram = (PFNGLCREATEPROGRAM_PROC*) SDL_GL_GetProcAddress("glCreateProgram"); + glpfCreateShader = (PFNGLCREATESHADER_PROC*) SDL_GL_GetProcAddress("glCreateShader"); + glpfDeleteProgram = (PFNGLDELETEPROGRAM_PROC*) SDL_GL_GetProcAddress("glDeleteProgram"); + glpfDeleteShader = (PFNGLDELETESHADER_PROC*) SDL_GL_GetProcAddress("glDeleteShader"); + glpfDetachShader = (PFNGLDETACHSHADER_PROC*) SDL_GL_GetProcAddress("glDetachShader"); + glpfDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAY_PROC*) SDL_GL_GetProcAddress("glDisableVertexAttribArray"); + glpfEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAY_PROC*) SDL_GL_GetProcAddress("glEnableVertexAttribArray"); + glpfGetActiveAttrib = (PFNGLGETACTIVEATTRIB_PROC*) SDL_GL_GetProcAddress("glGetActiveAttrib"); + glpfGetActiveUniform = (PFNGLGETACTIVEUNIFORM_PROC*) SDL_GL_GetProcAddress("glGetActiveUniform"); + glpfGetAttachedShaders = (PFNGLGETATTACHEDSHADERS_PROC*) SDL_GL_GetProcAddress("glGetAttachedShaders"); + glpfGetAttribLocation = (PFNGLGETATTRIBLOCATION_PROC*) SDL_GL_GetProcAddress("glGetAttribLocation"); + glpfGetProgramiv = (PFNGLGETPROGRAMIV_PROC*) SDL_GL_GetProcAddress("glGetProgramiv"); + glpfGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOG_PROC*) SDL_GL_GetProcAddress("glGetProgramInfoLog"); + glpfGetShaderiv = (PFNGLGETSHADERIV_PROC*) SDL_GL_GetProcAddress("glGetShaderiv"); + glpfGetShaderInfoLog = (PFNGLGETSHADERINFOLOG_PROC*) SDL_GL_GetProcAddress("glGetShaderInfoLog"); + glpfGetShaderSource = (PFNGLGETSHADERSOURCE_PROC*) SDL_GL_GetProcAddress("glGetShaderSource"); + glpfGetUniformLocation = (PFNGLGETUNIFORMLOCATION_PROC*) SDL_GL_GetProcAddress("glGetUniformLocation"); + glpfGetUniformfv = (PFNGLGETUNIFORMFV_PROC*) SDL_GL_GetProcAddress("glGetUniformfv"); + glpfGetUniformiv = (PFNGLGETUNIFORMIV_PROC*) SDL_GL_GetProcAddress("glGetUniformiv"); + glpfGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDV_PROC*) SDL_GL_GetProcAddress("glGetVertexAttribdv"); + glpfGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFV_PROC*) SDL_GL_GetProcAddress("glGetVertexAttribfv"); + glpfGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIV_PROC*) SDL_GL_GetProcAddress("glGetVertexAttribiv"); + glpfGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERV_PROC*) SDL_GL_GetProcAddress("glGetVertexAttribPointerv"); + glpfIsProgram = (PFNGLISPROGRAM_PROC*) SDL_GL_GetProcAddress("glIsProgram"); + glpfIsShader = (PFNGLISSHADER_PROC*) SDL_GL_GetProcAddress("glIsShader"); + glpfLinkProgram = (PFNGLLINKPROGRAM_PROC*) SDL_GL_GetProcAddress("glLinkProgram"); + glpfShaderSource = (PFNGLSHADERSOURCE_PROC*) SDL_GL_GetProcAddress("glShaderSource"); + glpfUseProgram = (PFNGLUSEPROGRAM_PROC*) SDL_GL_GetProcAddress("glUseProgram"); + glpfUniform1f = (PFNGLUNIFORM1F_PROC*) SDL_GL_GetProcAddress("glUniform1f"); + glpfUniform2f = (PFNGLUNIFORM2F_PROC*) SDL_GL_GetProcAddress("glUniform2f"); + glpfUniform3f = (PFNGLUNIFORM3F_PROC*) SDL_GL_GetProcAddress("glUniform3f"); + glpfUniform4f = (PFNGLUNIFORM4F_PROC*) SDL_GL_GetProcAddress("glUniform4f"); + glpfUniform1i = (PFNGLUNIFORM1I_PROC*) SDL_GL_GetProcAddress("glUniform1i"); + glpfUniform2i = (PFNGLUNIFORM2I_PROC*) SDL_GL_GetProcAddress("glUniform2i"); + glpfUniform3i = (PFNGLUNIFORM3I_PROC*) SDL_GL_GetProcAddress("glUniform3i"); + glpfUniform4i = (PFNGLUNIFORM4I_PROC*) SDL_GL_GetProcAddress("glUniform4i"); + glpfUniform1fv = (PFNGLUNIFORM1FV_PROC*) SDL_GL_GetProcAddress("glUniform1fv"); + glpfUniform2fv = (PFNGLUNIFORM2FV_PROC*) SDL_GL_GetProcAddress("glUniform2fv"); + glpfUniform3fv = (PFNGLUNIFORM3FV_PROC*) SDL_GL_GetProcAddress("glUniform3fv"); + glpfUniform4fv = (PFNGLUNIFORM4FV_PROC*) SDL_GL_GetProcAddress("glUniform4fv"); + glpfUniform1iv = (PFNGLUNIFORM1IV_PROC*) SDL_GL_GetProcAddress("glUniform1iv"); + glpfUniform2iv = (PFNGLUNIFORM2IV_PROC*) SDL_GL_GetProcAddress("glUniform2iv"); + glpfUniform3iv = (PFNGLUNIFORM3IV_PROC*) SDL_GL_GetProcAddress("glUniform3iv"); + glpfUniform4iv = (PFNGLUNIFORM4IV_PROC*) SDL_GL_GetProcAddress("glUniform4iv"); + glpfUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FV_PROC*) SDL_GL_GetProcAddress("glUniformMatrix2fv"); + glpfUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FV_PROC*) SDL_GL_GetProcAddress("glUniformMatrix3fv"); + glpfUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FV_PROC*) SDL_GL_GetProcAddress("glUniformMatrix4fv"); + glpfValidateProgram = (PFNGLVALIDATEPROGRAM_PROC*) SDL_GL_GetProcAddress("glValidateProgram"); + glpfVertexAttrib1d = (PFNGLVERTEXATTRIB1D_PROC*) SDL_GL_GetProcAddress("glVertexAttrib1d"); + glpfVertexAttrib1dv = (PFNGLVERTEXATTRIB1DV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib1dv"); + glpfVertexAttrib1f = (PFNGLVERTEXATTRIB1F_PROC*) SDL_GL_GetProcAddress("glVertexAttrib1f"); + glpfVertexAttrib1fv = (PFNGLVERTEXATTRIB1FV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib1fv"); + glpfVertexAttrib1s = (PFNGLVERTEXATTRIB1S_PROC*) SDL_GL_GetProcAddress("glVertexAttrib1s"); + glpfVertexAttrib1sv = (PFNGLVERTEXATTRIB1SV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib1sv"); + glpfVertexAttrib2d = (PFNGLVERTEXATTRIB2D_PROC*) SDL_GL_GetProcAddress("glVertexAttrib2d"); + glpfVertexAttrib2dv = (PFNGLVERTEXATTRIB2DV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib2dv"); + glpfVertexAttrib2f = (PFNGLVERTEXATTRIB2F_PROC*) SDL_GL_GetProcAddress("glVertexAttrib2f"); + glpfVertexAttrib2fv = (PFNGLVERTEXATTRIB2FV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib2fv"); + glpfVertexAttrib2s = (PFNGLVERTEXATTRIB2S_PROC*) SDL_GL_GetProcAddress("glVertexAttrib2s"); + glpfVertexAttrib2sv = (PFNGLVERTEXATTRIB2SV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib2sv"); + glpfVertexAttrib3d = (PFNGLVERTEXATTRIB3D_PROC*) SDL_GL_GetProcAddress("glVertexAttrib3d"); + glpfVertexAttrib3dv = (PFNGLVERTEXATTRIB3DV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib3dv"); + glpfVertexAttrib3f = (PFNGLVERTEXATTRIB3F_PROC*) SDL_GL_GetProcAddress("glVertexAttrib3f"); + glpfVertexAttrib3fv = (PFNGLVERTEXATTRIB3FV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib3fv"); + glpfVertexAttrib3s = (PFNGLVERTEXATTRIB3S_PROC*) SDL_GL_GetProcAddress("glVertexAttrib3s"); + glpfVertexAttrib3sv = (PFNGLVERTEXATTRIB3SV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib3sv"); + glpfVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib4Nbv"); + glpfVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib4Niv"); + glpfVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib4Nsv"); + glpfVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUB_PROC*) SDL_GL_GetProcAddress("glVertexAttrib4Nub"); + glpfVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib4Nubv"); + glpfVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib4Nuiv"); + glpfVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib4Nusv"); + glpfVertexAttrib4bv = (PFNGLVERTEXATTRIB4BV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib4bv"); + glpfVertexAttrib4d = (PFNGLVERTEXATTRIB4D_PROC*) SDL_GL_GetProcAddress("glVertexAttrib4d"); + glpfVertexAttrib4dv = (PFNGLVERTEXATTRIB4DV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib4dv"); + glpfVertexAttrib4f = (PFNGLVERTEXATTRIB4F_PROC*) SDL_GL_GetProcAddress("glVertexAttrib4f"); + glpfVertexAttrib4fv = (PFNGLVERTEXATTRIB4FV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib4fv"); + glpfVertexAttrib4iv = (PFNGLVERTEXATTRIB4IV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib4iv"); + glpfVertexAttrib4s = (PFNGLVERTEXATTRIB4S_PROC*) SDL_GL_GetProcAddress("glVertexAttrib4s"); + glpfVertexAttrib4sv = (PFNGLVERTEXATTRIB4SV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib4sv"); + glpfVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib4ubv"); + glpfVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib4uiv"); + glpfVertexAttrib4usv = (PFNGLVERTEXATTRIB4USV_PROC*) SDL_GL_GetProcAddress("glVertexAttrib4usv"); + glpfVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTER_PROC*) SDL_GL_GetProcAddress("glVertexAttribPointer"); + + /* GL_VERSION_2_1 */ + + glpfUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FV_PROC*) SDL_GL_GetProcAddress("glUniformMatrix2x3fv"); + glpfUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FV_PROC*) SDL_GL_GetProcAddress("glUniformMatrix3x2fv"); + glpfUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FV_PROC*) SDL_GL_GetProcAddress("glUniformMatrix2x4fv"); + glpfUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FV_PROC*) SDL_GL_GetProcAddress("glUniformMatrix4x2fv"); + glpfUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FV_PROC*) SDL_GL_GetProcAddress("glUniformMatrix3x4fv"); + glpfUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FV_PROC*) SDL_GL_GetProcAddress("glUniformMatrix4x3fv"); + + /* GL_VERSION_3_0 */ + + glpfColorMaski = (PFNGLCOLORMASKI_PROC*) SDL_GL_GetProcAddress("glColorMaski"); + glpfGetBooleani_v = (PFNGLGETBOOLEANI_V_PROC*) SDL_GL_GetProcAddress("glGetBooleani_v"); + glpfGetIntegeri_v = (PFNGLGETINTEGERI_V_PROC*) SDL_GL_GetProcAddress("glGetIntegeri_v"); + glpfEnablei = (PFNGLENABLEI_PROC*) SDL_GL_GetProcAddress("glEnablei"); + glpfDisablei = (PFNGLDISABLEI_PROC*) SDL_GL_GetProcAddress("glDisablei"); + glpfIsEnabledi = (PFNGLISENABLEDI_PROC*) SDL_GL_GetProcAddress("glIsEnabledi"); + glpfBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACK_PROC*) SDL_GL_GetProcAddress("glBeginTransformFeedback"); + glpfEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACK_PROC*) SDL_GL_GetProcAddress("glEndTransformFeedback"); + glpfBindBufferRange = (PFNGLBINDBUFFERRANGE_PROC*) SDL_GL_GetProcAddress("glBindBufferRange"); + glpfBindBufferBase = (PFNGLBINDBUFFERBASE_PROC*) SDL_GL_GetProcAddress("glBindBufferBase"); + glpfTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGS_PROC*) SDL_GL_GetProcAddress("glTransformFeedbackVaryings"); + glpfGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYING_PROC*) SDL_GL_GetProcAddress("glGetTransformFeedbackVarying"); + glpfClampColor = (PFNGLCLAMPCOLOR_PROC*) SDL_GL_GetProcAddress("glClampColor"); + glpfBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDER_PROC*) SDL_GL_GetProcAddress("glBeginConditionalRender"); + glpfEndConditionalRender = (PFNGLENDCONDITIONALRENDER_PROC*) SDL_GL_GetProcAddress("glEndConditionalRender"); + glpfVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTER_PROC*) SDL_GL_GetProcAddress("glVertexAttribIPointer"); + glpfGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIV_PROC*) SDL_GL_GetProcAddress("glGetVertexAttribIiv"); + glpfGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIV_PROC*) SDL_GL_GetProcAddress("glGetVertexAttribIuiv"); + glpfVertexAttribI1i = (PFNGLVERTEXATTRIBI1I_PROC*) SDL_GL_GetProcAddress("glVertexAttribI1i"); + glpfVertexAttribI2i = (PFNGLVERTEXATTRIBI2I_PROC*) SDL_GL_GetProcAddress("glVertexAttribI2i"); + glpfVertexAttribI3i = (PFNGLVERTEXATTRIBI3I_PROC*) SDL_GL_GetProcAddress("glVertexAttribI3i"); + glpfVertexAttribI4i = (PFNGLVERTEXATTRIBI4I_PROC*) SDL_GL_GetProcAddress("glVertexAttribI4i"); + glpfVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UI_PROC*) SDL_GL_GetProcAddress("glVertexAttribI1ui"); + glpfVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UI_PROC*) SDL_GL_GetProcAddress("glVertexAttribI2ui"); + glpfVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UI_PROC*) SDL_GL_GetProcAddress("glVertexAttribI3ui"); + glpfVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UI_PROC*) SDL_GL_GetProcAddress("glVertexAttribI4ui"); + glpfVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IV_PROC*) SDL_GL_GetProcAddress("glVertexAttribI1iv"); + glpfVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IV_PROC*) SDL_GL_GetProcAddress("glVertexAttribI2iv"); + glpfVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IV_PROC*) SDL_GL_GetProcAddress("glVertexAttribI3iv"); + glpfVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IV_PROC*) SDL_GL_GetProcAddress("glVertexAttribI4iv"); + glpfVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIV_PROC*) SDL_GL_GetProcAddress("glVertexAttribI1uiv"); + glpfVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIV_PROC*) SDL_GL_GetProcAddress("glVertexAttribI2uiv"); + glpfVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIV_PROC*) SDL_GL_GetProcAddress("glVertexAttribI3uiv"); + glpfVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIV_PROC*) SDL_GL_GetProcAddress("glVertexAttribI4uiv"); + glpfVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BV_PROC*) SDL_GL_GetProcAddress("glVertexAttribI4bv"); + glpfVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SV_PROC*) SDL_GL_GetProcAddress("glVertexAttribI4sv"); + glpfVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBV_PROC*) SDL_GL_GetProcAddress("glVertexAttribI4ubv"); + glpfVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USV_PROC*) SDL_GL_GetProcAddress("glVertexAttribI4usv"); + glpfGetUniformuiv = (PFNGLGETUNIFORMUIV_PROC*) SDL_GL_GetProcAddress("glGetUniformuiv"); + glpfBindFragDataLocation = (PFNGLBINDFRAGDATALOCATION_PROC*) SDL_GL_GetProcAddress("glBindFragDataLocation"); + glpfGetFragDataLocation = (PFNGLGETFRAGDATALOCATION_PROC*) SDL_GL_GetProcAddress("glGetFragDataLocation"); + glpfUniform1ui = (PFNGLUNIFORM1UI_PROC*) SDL_GL_GetProcAddress("glUniform1ui"); + glpfUniform2ui = (PFNGLUNIFORM2UI_PROC*) SDL_GL_GetProcAddress("glUniform2ui"); + glpfUniform3ui = (PFNGLUNIFORM3UI_PROC*) SDL_GL_GetProcAddress("glUniform3ui"); + glpfUniform4ui = (PFNGLUNIFORM4UI_PROC*) SDL_GL_GetProcAddress("glUniform4ui"); + glpfUniform1uiv = (PFNGLUNIFORM1UIV_PROC*) SDL_GL_GetProcAddress("glUniform1uiv"); + glpfUniform2uiv = (PFNGLUNIFORM2UIV_PROC*) SDL_GL_GetProcAddress("glUniform2uiv"); + glpfUniform3uiv = (PFNGLUNIFORM3UIV_PROC*) SDL_GL_GetProcAddress("glUniform3uiv"); + glpfUniform4uiv = (PFNGLUNIFORM4UIV_PROC*) SDL_GL_GetProcAddress("glUniform4uiv"); + glpfTexParameterIiv = (PFNGLTEXPARAMETERIIV_PROC*) SDL_GL_GetProcAddress("glTexParameterIiv"); + glpfTexParameterIuiv = (PFNGLTEXPARAMETERIUIV_PROC*) SDL_GL_GetProcAddress("glTexParameterIuiv"); + glpfGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIV_PROC*) SDL_GL_GetProcAddress("glGetTexParameterIiv"); + glpfGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIV_PROC*) SDL_GL_GetProcAddress("glGetTexParameterIuiv"); + glpfClearBufferiv = (PFNGLCLEARBUFFERIV_PROC*) SDL_GL_GetProcAddress("glClearBufferiv"); + glpfClearBufferuiv = (PFNGLCLEARBUFFERUIV_PROC*) SDL_GL_GetProcAddress("glClearBufferuiv"); + glpfClearBufferfv = (PFNGLCLEARBUFFERFV_PROC*) SDL_GL_GetProcAddress("glClearBufferfv"); + glpfClearBufferfi = (PFNGLCLEARBUFFERFI_PROC*) SDL_GL_GetProcAddress("glClearBufferfi"); + glpfGetStringi = (PFNGLGETSTRINGI_PROC*) SDL_GL_GetProcAddress("glGetStringi"); + glpfIsRenderbuffer = (PFNGLISRENDERBUFFER_PROC*) SDL_GL_GetProcAddress("glIsRenderbuffer"); + glpfBindRenderbuffer = (PFNGLBINDRENDERBUFFER_PROC*) SDL_GL_GetProcAddress("glBindRenderbuffer"); + glpfDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERS_PROC*) SDL_GL_GetProcAddress("glDeleteRenderbuffers"); + glpfGenRenderbuffers = (PFNGLGENRENDERBUFFERS_PROC*) SDL_GL_GetProcAddress("glGenRenderbuffers"); + glpfRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGE_PROC*) SDL_GL_GetProcAddress("glRenderbufferStorage"); + glpfGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIV_PROC*) SDL_GL_GetProcAddress("glGetRenderbufferParameteriv"); + glpfIsFramebuffer = (PFNGLISFRAMEBUFFER_PROC*) SDL_GL_GetProcAddress("glIsFramebuffer"); + glpfBindFramebuffer = (PFNGLBINDFRAMEBUFFER_PROC*) SDL_GL_GetProcAddress("glBindFramebuffer"); + glpfDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERS_PROC*) SDL_GL_GetProcAddress("glDeleteFramebuffers"); + glpfGenFramebuffers = (PFNGLGENFRAMEBUFFERS_PROC*) SDL_GL_GetProcAddress("glGenFramebuffers"); + glpfCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUS_PROC*) SDL_GL_GetProcAddress("glCheckFramebufferStatus"); + glpfFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1D_PROC*) SDL_GL_GetProcAddress("glFramebufferTexture1D"); + glpfFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2D_PROC*) SDL_GL_GetProcAddress("glFramebufferTexture2D"); + glpfFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3D_PROC*) SDL_GL_GetProcAddress("glFramebufferTexture3D"); + glpfFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFER_PROC*) SDL_GL_GetProcAddress("glFramebufferRenderbuffer"); + glpfGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIV_PROC*) SDL_GL_GetProcAddress("glGetFramebufferAttachmentParameteriv"); + glpfGenerateMipmap = (PFNGLGENERATEMIPMAP_PROC*) SDL_GL_GetProcAddress("glGenerateMipmap"); + glpfBlitFramebuffer = (PFNGLBLITFRAMEBUFFER_PROC*) SDL_GL_GetProcAddress("glBlitFramebuffer"); + glpfRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLE_PROC*) SDL_GL_GetProcAddress("glRenderbufferStorageMultisample"); + glpfFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYER_PROC*) SDL_GL_GetProcAddress("glFramebufferTextureLayer"); + glpfMapBufferRange = (PFNGLMAPBUFFERRANGE_PROC*) SDL_GL_GetProcAddress("glMapBufferRange"); + glpfFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGE_PROC*) SDL_GL_GetProcAddress("glFlushMappedBufferRange"); + glpfBindVertexArray = (PFNGLBINDVERTEXARRAY_PROC*) SDL_GL_GetProcAddress("glBindVertexArray"); + glpfDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYS_PROC*) SDL_GL_GetProcAddress("glDeleteVertexArrays"); + glpfGenVertexArrays = (PFNGLGENVERTEXARRAYS_PROC*) SDL_GL_GetProcAddress("glGenVertexArrays"); + glpfIsVertexArray = (PFNGLISVERTEXARRAY_PROC*) SDL_GL_GetProcAddress("glIsVertexArray"); + + /* GL_VERSION_3_1 */ + + glpfDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCED_PROC*) SDL_GL_GetProcAddress("glDrawArraysInstanced"); + glpfDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCED_PROC*) SDL_GL_GetProcAddress("glDrawElementsInstanced"); + glpfTexBuffer = (PFNGLTEXBUFFER_PROC*) SDL_GL_GetProcAddress("glTexBuffer"); + glpfPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEX_PROC*) SDL_GL_GetProcAddress("glPrimitiveRestartIndex"); + glpfCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATA_PROC*) SDL_GL_GetProcAddress("glCopyBufferSubData"); + glpfGetUniformIndices = (PFNGLGETUNIFORMINDICES_PROC*) SDL_GL_GetProcAddress("glGetUniformIndices"); + glpfGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIV_PROC*) SDL_GL_GetProcAddress("glGetActiveUniformsiv"); + glpfGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAME_PROC*) SDL_GL_GetProcAddress("glGetActiveUniformName"); + glpfGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEX_PROC*) SDL_GL_GetProcAddress("glGetUniformBlockIndex"); + glpfGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIV_PROC*) SDL_GL_GetProcAddress("glGetActiveUniformBlockiv"); + glpfGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAME_PROC*) SDL_GL_GetProcAddress("glGetActiveUniformBlockName"); + glpfUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDING_PROC*) SDL_GL_GetProcAddress("glUniformBlockBinding"); + + /* GL_VERSION_3_2 */ + + glpfDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEX_PROC*) SDL_GL_GetProcAddress("glDrawElementsBaseVertex"); + glpfDrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEX_PROC*) SDL_GL_GetProcAddress("glDrawRangeElementsBaseVertex"); + glpfDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEX_PROC*) SDL_GL_GetProcAddress("glDrawElementsInstancedBaseVertex"); + glpfMultiDrawElementsBaseVertex = (PFNGLMULTIDRAWELEMENTSBASEVERTEX_PROC*) SDL_GL_GetProcAddress("glMultiDrawElementsBaseVertex"); + glpfProvokingVertex = (PFNGLPROVOKINGVERTEX_PROC*) SDL_GL_GetProcAddress("glProvokingVertex"); + glpfFenceSync = (PFNGLFENCESYNC_PROC*) SDL_GL_GetProcAddress("glFenceSync"); + glpfIsSync = (PFNGLISSYNC_PROC*) SDL_GL_GetProcAddress("glIsSync"); + glpfDeleteSync = (PFNGLDELETESYNC_PROC*) SDL_GL_GetProcAddress("glDeleteSync"); + glpfClientWaitSync = (PFNGLCLIENTWAITSYNC_PROC*) SDL_GL_GetProcAddress("glClientWaitSync"); + glpfWaitSync = (PFNGLWAITSYNC_PROC*) SDL_GL_GetProcAddress("glWaitSync"); + glpfGetInteger64v = (PFNGLGETINTEGER64V_PROC*) SDL_GL_GetProcAddress("glGetInteger64v"); + glpfGetSynciv = (PFNGLGETSYNCIV_PROC*) SDL_GL_GetProcAddress("glGetSynciv"); + glpfGetInteger64i_v = (PFNGLGETINTEGER64I_V_PROC*) SDL_GL_GetProcAddress("glGetInteger64i_v"); + glpfGetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64V_PROC*) SDL_GL_GetProcAddress("glGetBufferParameteri64v"); + glpfFramebufferTexture = (PFNGLFRAMEBUFFERTEXTURE_PROC*) SDL_GL_GetProcAddress("glFramebufferTexture"); + glpfTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLE_PROC*) SDL_GL_GetProcAddress("glTexImage2DMultisample"); + glpfTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLE_PROC*) SDL_GL_GetProcAddress("glTexImage3DMultisample"); + glpfGetMultisamplefv = (PFNGLGETMULTISAMPLEFV_PROC*) SDL_GL_GetProcAddress("glGetMultisamplefv"); + glpfSampleMaski = (PFNGLSAMPLEMASKI_PROC*) SDL_GL_GetProcAddress("glSampleMaski"); + + /* GL_VERSION_3_3 */ + + glpfBindFragDataLocationIndexed = (PFNGLBINDFRAGDATALOCATIONINDEXED_PROC*) SDL_GL_GetProcAddress("glBindFragDataLocationIndexed"); + glpfGetFragDataIndex = (PFNGLGETFRAGDATAINDEX_PROC*) SDL_GL_GetProcAddress("glGetFragDataIndex"); + glpfGenSamplers = (PFNGLGENSAMPLERS_PROC*) SDL_GL_GetProcAddress("glGenSamplers"); + glpfDeleteSamplers = (PFNGLDELETESAMPLERS_PROC*) SDL_GL_GetProcAddress("glDeleteSamplers"); + glpfIsSampler = (PFNGLISSAMPLER_PROC*) SDL_GL_GetProcAddress("glIsSampler"); + glpfBindSampler = (PFNGLBINDSAMPLER_PROC*) SDL_GL_GetProcAddress("glBindSampler"); + glpfSamplerParameteri = (PFNGLSAMPLERPARAMETERI_PROC*) SDL_GL_GetProcAddress("glSamplerParameteri"); + glpfSamplerParameteriv = (PFNGLSAMPLERPARAMETERIV_PROC*) SDL_GL_GetProcAddress("glSamplerParameteriv"); + glpfSamplerParameterf = (PFNGLSAMPLERPARAMETERF_PROC*) SDL_GL_GetProcAddress("glSamplerParameterf"); + glpfSamplerParameterfv = (PFNGLSAMPLERPARAMETERFV_PROC*) SDL_GL_GetProcAddress("glSamplerParameterfv"); + glpfSamplerParameterIiv = (PFNGLSAMPLERPARAMETERIIV_PROC*) SDL_GL_GetProcAddress("glSamplerParameterIiv"); + glpfSamplerParameterIuiv = (PFNGLSAMPLERPARAMETERIUIV_PROC*) SDL_GL_GetProcAddress("glSamplerParameterIuiv"); + glpfGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIV_PROC*) SDL_GL_GetProcAddress("glGetSamplerParameteriv"); + glpfGetSamplerParameterIiv = (PFNGLGETSAMPLERPARAMETERIIV_PROC*) SDL_GL_GetProcAddress("glGetSamplerParameterIiv"); + glpfGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFV_PROC*) SDL_GL_GetProcAddress("glGetSamplerParameterfv"); + glpfGetSamplerParameterIuiv = (PFNGLGETSAMPLERPARAMETERIUIV_PROC*) SDL_GL_GetProcAddress("glGetSamplerParameterIuiv"); + glpfQueryCounter = (PFNGLQUERYCOUNTER_PROC*) SDL_GL_GetProcAddress("glQueryCounter"); + glpfGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64V_PROC*) SDL_GL_GetProcAddress("glGetQueryObjecti64v"); + glpfGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64V_PROC*) SDL_GL_GetProcAddress("glGetQueryObjectui64v"); + glpfVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOR_PROC*) SDL_GL_GetProcAddress("glVertexAttribDivisor"); + glpfVertexAttribP1ui = (PFNGLVERTEXATTRIBP1UI_PROC*) SDL_GL_GetProcAddress("glVertexAttribP1ui"); + glpfVertexAttribP1uiv = (PFNGLVERTEXATTRIBP1UIV_PROC*) SDL_GL_GetProcAddress("glVertexAttribP1uiv"); + glpfVertexAttribP2ui = (PFNGLVERTEXATTRIBP2UI_PROC*) SDL_GL_GetProcAddress("glVertexAttribP2ui"); + glpfVertexAttribP2uiv = (PFNGLVERTEXATTRIBP2UIV_PROC*) SDL_GL_GetProcAddress("glVertexAttribP2uiv"); + glpfVertexAttribP3ui = (PFNGLVERTEXATTRIBP3UI_PROC*) SDL_GL_GetProcAddress("glVertexAttribP3ui"); + glpfVertexAttribP3uiv = (PFNGLVERTEXATTRIBP3UIV_PROC*) SDL_GL_GetProcAddress("glVertexAttribP3uiv"); + glpfVertexAttribP4ui = (PFNGLVERTEXATTRIBP4UI_PROC*) SDL_GL_GetProcAddress("glVertexAttribP4ui"); + glpfVertexAttribP4uiv = (PFNGLVERTEXATTRIBP4UIV_PROC*) SDL_GL_GetProcAddress("glVertexAttribP4uiv"); + + /* GL_ARB_debug_output */ + + glpfDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARB_PROC*) SDL_GL_GetProcAddress("glDebugMessageControlARB"); + glpfDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARB_PROC*) SDL_GL_GetProcAddress("glDebugMessageInsertARB"); + glpfDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARB_PROC*) SDL_GL_GetProcAddress("glDebugMessageCallbackARB"); + glpfGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARB_PROC*) SDL_GL_GetProcAddress("glGetDebugMessageLogARB"); + +} + +/* GL_VERSION_1_2 */ + +PFNGLDRAWRANGEELEMENTS_PROC* glpfDrawRangeElements = NULL; +PFNGLTEXIMAGE3D_PROC* glpfTexImage3D = NULL; +PFNGLTEXSUBIMAGE3D_PROC* glpfTexSubImage3D = NULL; +PFNGLCOPYTEXSUBIMAGE3D_PROC* glpfCopyTexSubImage3D = NULL; + +/* GL_VERSION_1_3 */ + +PFNGLACTIVETEXTURE_PROC* glpfActiveTexture = NULL; +PFNGLSAMPLECOVERAGE_PROC* glpfSampleCoverage = NULL; +PFNGLCOMPRESSEDTEXIMAGE3D_PROC* glpfCompressedTexImage3D = NULL; +PFNGLCOMPRESSEDTEXIMAGE2D_PROC* glpfCompressedTexImage2D = NULL; +PFNGLCOMPRESSEDTEXIMAGE1D_PROC* glpfCompressedTexImage1D = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE3D_PROC* glpfCompressedTexSubImage3D = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE2D_PROC* glpfCompressedTexSubImage2D = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE1D_PROC* glpfCompressedTexSubImage1D = NULL; +PFNGLGETCOMPRESSEDTEXIMAGE_PROC* glpfGetCompressedTexImage = NULL; + +/* GL_VERSION_1_4 */ + +PFNGLBLENDFUNCSEPARATE_PROC* glpfBlendFuncSeparate = NULL; +PFNGLMULTIDRAWARRAYS_PROC* glpfMultiDrawArrays = NULL; +PFNGLMULTIDRAWELEMENTS_PROC* glpfMultiDrawElements = NULL; +PFNGLPOINTPARAMETERF_PROC* glpfPointParameterf = NULL; +PFNGLPOINTPARAMETERFV_PROC* glpfPointParameterfv = NULL; +PFNGLPOINTPARAMETERI_PROC* glpfPointParameteri = NULL; +PFNGLPOINTPARAMETERIV_PROC* glpfPointParameteriv = NULL; +PFNGLBLENDCOLOR_PROC* glpfBlendColor = NULL; +PFNGLBLENDEQUATION_PROC* glpfBlendEquation = NULL; + +/* GL_VERSION_1_5 */ + +PFNGLGENQUERIES_PROC* glpfGenQueries = NULL; +PFNGLDELETEQUERIES_PROC* glpfDeleteQueries = NULL; +PFNGLISQUERY_PROC* glpfIsQuery = NULL; +PFNGLBEGINQUERY_PROC* glpfBeginQuery = NULL; +PFNGLENDQUERY_PROC* glpfEndQuery = NULL; +PFNGLGETQUERYIV_PROC* glpfGetQueryiv = NULL; +PFNGLGETQUERYOBJECTIV_PROC* glpfGetQueryObjectiv = NULL; +PFNGLGETQUERYOBJECTUIV_PROC* glpfGetQueryObjectuiv = NULL; +PFNGLBINDBUFFER_PROC* glpfBindBuffer = NULL; +PFNGLDELETEBUFFERS_PROC* glpfDeleteBuffers = NULL; +PFNGLGENBUFFERS_PROC* glpfGenBuffers = NULL; +PFNGLISBUFFER_PROC* glpfIsBuffer = NULL; +PFNGLBUFFERDATA_PROC* glpfBufferData = NULL; +PFNGLBUFFERSUBDATA_PROC* glpfBufferSubData = NULL; +PFNGLGETBUFFERSUBDATA_PROC* glpfGetBufferSubData = NULL; +PFNGLMAPBUFFER_PROC* glpfMapBuffer = NULL; +PFNGLUNMAPBUFFER_PROC* glpfUnmapBuffer = NULL; +PFNGLGETBUFFERPARAMETERIV_PROC* glpfGetBufferParameteriv = NULL; +PFNGLGETBUFFERPOINTERV_PROC* glpfGetBufferPointerv = NULL; + +/* GL_VERSION_2_0 */ + +PFNGLBLENDEQUATIONSEPARATE_PROC* glpfBlendEquationSeparate = NULL; +PFNGLDRAWBUFFERS_PROC* glpfDrawBuffers = NULL; +PFNGLSTENCILOPSEPARATE_PROC* glpfStencilOpSeparate = NULL; +PFNGLSTENCILFUNCSEPARATE_PROC* glpfStencilFuncSeparate = NULL; +PFNGLSTENCILMASKSEPARATE_PROC* glpfStencilMaskSeparate = NULL; +PFNGLATTACHSHADER_PROC* glpfAttachShader = NULL; +PFNGLBINDATTRIBLOCATION_PROC* glpfBindAttribLocation = NULL; +PFNGLCOMPILESHADER_PROC* glpfCompileShader = NULL; +PFNGLCREATEPROGRAM_PROC* glpfCreateProgram = NULL; +PFNGLCREATESHADER_PROC* glpfCreateShader = NULL; +PFNGLDELETEPROGRAM_PROC* glpfDeleteProgram = NULL; +PFNGLDELETESHADER_PROC* glpfDeleteShader = NULL; +PFNGLDETACHSHADER_PROC* glpfDetachShader = NULL; +PFNGLDISABLEVERTEXATTRIBARRAY_PROC* glpfDisableVertexAttribArray = NULL; +PFNGLENABLEVERTEXATTRIBARRAY_PROC* glpfEnableVertexAttribArray = NULL; +PFNGLGETACTIVEATTRIB_PROC* glpfGetActiveAttrib = NULL; +PFNGLGETACTIVEUNIFORM_PROC* glpfGetActiveUniform = NULL; +PFNGLGETATTACHEDSHADERS_PROC* glpfGetAttachedShaders = NULL; +PFNGLGETATTRIBLOCATION_PROC* glpfGetAttribLocation = NULL; +PFNGLGETPROGRAMIV_PROC* glpfGetProgramiv = NULL; +PFNGLGETPROGRAMINFOLOG_PROC* glpfGetProgramInfoLog = NULL; +PFNGLGETSHADERIV_PROC* glpfGetShaderiv = NULL; +PFNGLGETSHADERINFOLOG_PROC* glpfGetShaderInfoLog = NULL; +PFNGLGETSHADERSOURCE_PROC* glpfGetShaderSource = NULL; +PFNGLGETUNIFORMLOCATION_PROC* glpfGetUniformLocation = NULL; +PFNGLGETUNIFORMFV_PROC* glpfGetUniformfv = NULL; +PFNGLGETUNIFORMIV_PROC* glpfGetUniformiv = NULL; +PFNGLGETVERTEXATTRIBDV_PROC* glpfGetVertexAttribdv = NULL; +PFNGLGETVERTEXATTRIBFV_PROC* glpfGetVertexAttribfv = NULL; +PFNGLGETVERTEXATTRIBIV_PROC* glpfGetVertexAttribiv = NULL; +PFNGLGETVERTEXATTRIBPOINTERV_PROC* glpfGetVertexAttribPointerv = NULL; +PFNGLISPROGRAM_PROC* glpfIsProgram = NULL; +PFNGLISSHADER_PROC* glpfIsShader = NULL; +PFNGLLINKPROGRAM_PROC* glpfLinkProgram = NULL; +PFNGLSHADERSOURCE_PROC* glpfShaderSource = NULL; +PFNGLUSEPROGRAM_PROC* glpfUseProgram = NULL; +PFNGLUNIFORM1F_PROC* glpfUniform1f = NULL; +PFNGLUNIFORM2F_PROC* glpfUniform2f = NULL; +PFNGLUNIFORM3F_PROC* glpfUniform3f = NULL; +PFNGLUNIFORM4F_PROC* glpfUniform4f = NULL; +PFNGLUNIFORM1I_PROC* glpfUniform1i = NULL; +PFNGLUNIFORM2I_PROC* glpfUniform2i = NULL; +PFNGLUNIFORM3I_PROC* glpfUniform3i = NULL; +PFNGLUNIFORM4I_PROC* glpfUniform4i = NULL; +PFNGLUNIFORM1FV_PROC* glpfUniform1fv = NULL; +PFNGLUNIFORM2FV_PROC* glpfUniform2fv = NULL; +PFNGLUNIFORM3FV_PROC* glpfUniform3fv = NULL; +PFNGLUNIFORM4FV_PROC* glpfUniform4fv = NULL; +PFNGLUNIFORM1IV_PROC* glpfUniform1iv = NULL; +PFNGLUNIFORM2IV_PROC* glpfUniform2iv = NULL; +PFNGLUNIFORM3IV_PROC* glpfUniform3iv = NULL; +PFNGLUNIFORM4IV_PROC* glpfUniform4iv = NULL; +PFNGLUNIFORMMATRIX2FV_PROC* glpfUniformMatrix2fv = NULL; +PFNGLUNIFORMMATRIX3FV_PROC* glpfUniformMatrix3fv = NULL; +PFNGLUNIFORMMATRIX4FV_PROC* glpfUniformMatrix4fv = NULL; +PFNGLVALIDATEPROGRAM_PROC* glpfValidateProgram = NULL; +PFNGLVERTEXATTRIB1D_PROC* glpfVertexAttrib1d = NULL; +PFNGLVERTEXATTRIB1DV_PROC* glpfVertexAttrib1dv = NULL; +PFNGLVERTEXATTRIB1F_PROC* glpfVertexAttrib1f = NULL; +PFNGLVERTEXATTRIB1FV_PROC* glpfVertexAttrib1fv = NULL; +PFNGLVERTEXATTRIB1S_PROC* glpfVertexAttrib1s = NULL; +PFNGLVERTEXATTRIB1SV_PROC* glpfVertexAttrib1sv = NULL; +PFNGLVERTEXATTRIB2D_PROC* glpfVertexAttrib2d = NULL; +PFNGLVERTEXATTRIB2DV_PROC* glpfVertexAttrib2dv = NULL; +PFNGLVERTEXATTRIB2F_PROC* glpfVertexAttrib2f = NULL; +PFNGLVERTEXATTRIB2FV_PROC* glpfVertexAttrib2fv = NULL; +PFNGLVERTEXATTRIB2S_PROC* glpfVertexAttrib2s = NULL; +PFNGLVERTEXATTRIB2SV_PROC* glpfVertexAttrib2sv = NULL; +PFNGLVERTEXATTRIB3D_PROC* glpfVertexAttrib3d = NULL; +PFNGLVERTEXATTRIB3DV_PROC* glpfVertexAttrib3dv = NULL; +PFNGLVERTEXATTRIB3F_PROC* glpfVertexAttrib3f = NULL; +PFNGLVERTEXATTRIB3FV_PROC* glpfVertexAttrib3fv = NULL; +PFNGLVERTEXATTRIB3S_PROC* glpfVertexAttrib3s = NULL; +PFNGLVERTEXATTRIB3SV_PROC* glpfVertexAttrib3sv = NULL; +PFNGLVERTEXATTRIB4NBV_PROC* glpfVertexAttrib4Nbv = NULL; +PFNGLVERTEXATTRIB4NIV_PROC* glpfVertexAttrib4Niv = NULL; +PFNGLVERTEXATTRIB4NSV_PROC* glpfVertexAttrib4Nsv = NULL; +PFNGLVERTEXATTRIB4NUB_PROC* glpfVertexAttrib4Nub = NULL; +PFNGLVERTEXATTRIB4NUBV_PROC* glpfVertexAttrib4Nubv = NULL; +PFNGLVERTEXATTRIB4NUIV_PROC* glpfVertexAttrib4Nuiv = NULL; +PFNGLVERTEXATTRIB4NUSV_PROC* glpfVertexAttrib4Nusv = NULL; +PFNGLVERTEXATTRIB4BV_PROC* glpfVertexAttrib4bv = NULL; +PFNGLVERTEXATTRIB4D_PROC* glpfVertexAttrib4d = NULL; +PFNGLVERTEXATTRIB4DV_PROC* glpfVertexAttrib4dv = NULL; +PFNGLVERTEXATTRIB4F_PROC* glpfVertexAttrib4f = NULL; +PFNGLVERTEXATTRIB4FV_PROC* glpfVertexAttrib4fv = NULL; +PFNGLVERTEXATTRIB4IV_PROC* glpfVertexAttrib4iv = NULL; +PFNGLVERTEXATTRIB4S_PROC* glpfVertexAttrib4s = NULL; +PFNGLVERTEXATTRIB4SV_PROC* glpfVertexAttrib4sv = NULL; +PFNGLVERTEXATTRIB4UBV_PROC* glpfVertexAttrib4ubv = NULL; +PFNGLVERTEXATTRIB4UIV_PROC* glpfVertexAttrib4uiv = NULL; +PFNGLVERTEXATTRIB4USV_PROC* glpfVertexAttrib4usv = NULL; +PFNGLVERTEXATTRIBPOINTER_PROC* glpfVertexAttribPointer = NULL; + +/* GL_VERSION_2_1 */ + +PFNGLUNIFORMMATRIX2X3FV_PROC* glpfUniformMatrix2x3fv = NULL; +PFNGLUNIFORMMATRIX3X2FV_PROC* glpfUniformMatrix3x2fv = NULL; +PFNGLUNIFORMMATRIX2X4FV_PROC* glpfUniformMatrix2x4fv = NULL; +PFNGLUNIFORMMATRIX4X2FV_PROC* glpfUniformMatrix4x2fv = NULL; +PFNGLUNIFORMMATRIX3X4FV_PROC* glpfUniformMatrix3x4fv = NULL; +PFNGLUNIFORMMATRIX4X3FV_PROC* glpfUniformMatrix4x3fv = NULL; + +/* GL_VERSION_3_0 */ + +PFNGLCOLORMASKI_PROC* glpfColorMaski = NULL; +PFNGLGETBOOLEANI_V_PROC* glpfGetBooleani_v = NULL; +PFNGLGETINTEGERI_V_PROC* glpfGetIntegeri_v = NULL; +PFNGLENABLEI_PROC* glpfEnablei = NULL; +PFNGLDISABLEI_PROC* glpfDisablei = NULL; +PFNGLISENABLEDI_PROC* glpfIsEnabledi = NULL; +PFNGLBEGINTRANSFORMFEEDBACK_PROC* glpfBeginTransformFeedback = NULL; +PFNGLENDTRANSFORMFEEDBACK_PROC* glpfEndTransformFeedback = NULL; +PFNGLBINDBUFFERRANGE_PROC* glpfBindBufferRange = NULL; +PFNGLBINDBUFFERBASE_PROC* glpfBindBufferBase = NULL; +PFNGLTRANSFORMFEEDBACKVARYINGS_PROC* glpfTransformFeedbackVaryings = NULL; +PFNGLGETTRANSFORMFEEDBACKVARYING_PROC* glpfGetTransformFeedbackVarying = NULL; +PFNGLCLAMPCOLOR_PROC* glpfClampColor = NULL; +PFNGLBEGINCONDITIONALRENDER_PROC* glpfBeginConditionalRender = NULL; +PFNGLENDCONDITIONALRENDER_PROC* glpfEndConditionalRender = NULL; +PFNGLVERTEXATTRIBIPOINTER_PROC* glpfVertexAttribIPointer = NULL; +PFNGLGETVERTEXATTRIBIIV_PROC* glpfGetVertexAttribIiv = NULL; +PFNGLGETVERTEXATTRIBIUIV_PROC* glpfGetVertexAttribIuiv = NULL; +PFNGLVERTEXATTRIBI1I_PROC* glpfVertexAttribI1i = NULL; +PFNGLVERTEXATTRIBI2I_PROC* glpfVertexAttribI2i = NULL; +PFNGLVERTEXATTRIBI3I_PROC* glpfVertexAttribI3i = NULL; +PFNGLVERTEXATTRIBI4I_PROC* glpfVertexAttribI4i = NULL; +PFNGLVERTEXATTRIBI1UI_PROC* glpfVertexAttribI1ui = NULL; +PFNGLVERTEXATTRIBI2UI_PROC* glpfVertexAttribI2ui = NULL; +PFNGLVERTEXATTRIBI3UI_PROC* glpfVertexAttribI3ui = NULL; +PFNGLVERTEXATTRIBI4UI_PROC* glpfVertexAttribI4ui = NULL; +PFNGLVERTEXATTRIBI1IV_PROC* glpfVertexAttribI1iv = NULL; +PFNGLVERTEXATTRIBI2IV_PROC* glpfVertexAttribI2iv = NULL; +PFNGLVERTEXATTRIBI3IV_PROC* glpfVertexAttribI3iv = NULL; +PFNGLVERTEXATTRIBI4IV_PROC* glpfVertexAttribI4iv = NULL; +PFNGLVERTEXATTRIBI1UIV_PROC* glpfVertexAttribI1uiv = NULL; +PFNGLVERTEXATTRIBI2UIV_PROC* glpfVertexAttribI2uiv = NULL; +PFNGLVERTEXATTRIBI3UIV_PROC* glpfVertexAttribI3uiv = NULL; +PFNGLVERTEXATTRIBI4UIV_PROC* glpfVertexAttribI4uiv = NULL; +PFNGLVERTEXATTRIBI4BV_PROC* glpfVertexAttribI4bv = NULL; +PFNGLVERTEXATTRIBI4SV_PROC* glpfVertexAttribI4sv = NULL; +PFNGLVERTEXATTRIBI4UBV_PROC* glpfVertexAttribI4ubv = NULL; +PFNGLVERTEXATTRIBI4USV_PROC* glpfVertexAttribI4usv = NULL; +PFNGLGETUNIFORMUIV_PROC* glpfGetUniformuiv = NULL; +PFNGLBINDFRAGDATALOCATION_PROC* glpfBindFragDataLocation = NULL; +PFNGLGETFRAGDATALOCATION_PROC* glpfGetFragDataLocation = NULL; +PFNGLUNIFORM1UI_PROC* glpfUniform1ui = NULL; +PFNGLUNIFORM2UI_PROC* glpfUniform2ui = NULL; +PFNGLUNIFORM3UI_PROC* glpfUniform3ui = NULL; +PFNGLUNIFORM4UI_PROC* glpfUniform4ui = NULL; +PFNGLUNIFORM1UIV_PROC* glpfUniform1uiv = NULL; +PFNGLUNIFORM2UIV_PROC* glpfUniform2uiv = NULL; +PFNGLUNIFORM3UIV_PROC* glpfUniform3uiv = NULL; +PFNGLUNIFORM4UIV_PROC* glpfUniform4uiv = NULL; +PFNGLTEXPARAMETERIIV_PROC* glpfTexParameterIiv = NULL; +PFNGLTEXPARAMETERIUIV_PROC* glpfTexParameterIuiv = NULL; +PFNGLGETTEXPARAMETERIIV_PROC* glpfGetTexParameterIiv = NULL; +PFNGLGETTEXPARAMETERIUIV_PROC* glpfGetTexParameterIuiv = NULL; +PFNGLCLEARBUFFERIV_PROC* glpfClearBufferiv = NULL; +PFNGLCLEARBUFFERUIV_PROC* glpfClearBufferuiv = NULL; +PFNGLCLEARBUFFERFV_PROC* glpfClearBufferfv = NULL; +PFNGLCLEARBUFFERFI_PROC* glpfClearBufferfi = NULL; +PFNGLGETSTRINGI_PROC* glpfGetStringi = NULL; +PFNGLISRENDERBUFFER_PROC* glpfIsRenderbuffer = NULL; +PFNGLBINDRENDERBUFFER_PROC* glpfBindRenderbuffer = NULL; +PFNGLDELETERENDERBUFFERS_PROC* glpfDeleteRenderbuffers = NULL; +PFNGLGENRENDERBUFFERS_PROC* glpfGenRenderbuffers = NULL; +PFNGLRENDERBUFFERSTORAGE_PROC* glpfRenderbufferStorage = NULL; +PFNGLGETRENDERBUFFERPARAMETERIV_PROC* glpfGetRenderbufferParameteriv = NULL; +PFNGLISFRAMEBUFFER_PROC* glpfIsFramebuffer = NULL; +PFNGLBINDFRAMEBUFFER_PROC* glpfBindFramebuffer = NULL; +PFNGLDELETEFRAMEBUFFERS_PROC* glpfDeleteFramebuffers = NULL; +PFNGLGENFRAMEBUFFERS_PROC* glpfGenFramebuffers = NULL; +PFNGLCHECKFRAMEBUFFERSTATUS_PROC* glpfCheckFramebufferStatus = NULL; +PFNGLFRAMEBUFFERTEXTURE1D_PROC* glpfFramebufferTexture1D = NULL; +PFNGLFRAMEBUFFERTEXTURE2D_PROC* glpfFramebufferTexture2D = NULL; +PFNGLFRAMEBUFFERTEXTURE3D_PROC* glpfFramebufferTexture3D = NULL; +PFNGLFRAMEBUFFERRENDERBUFFER_PROC* glpfFramebufferRenderbuffer = NULL; +PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIV_PROC* glpfGetFramebufferAttachmentParameteriv = NULL; +PFNGLGENERATEMIPMAP_PROC* glpfGenerateMipmap = NULL; +PFNGLBLITFRAMEBUFFER_PROC* glpfBlitFramebuffer = NULL; +PFNGLRENDERBUFFERSTORAGEMULTISAMPLE_PROC* glpfRenderbufferStorageMultisample = NULL; +PFNGLFRAMEBUFFERTEXTURELAYER_PROC* glpfFramebufferTextureLayer = NULL; +PFNGLMAPBUFFERRANGE_PROC* glpfMapBufferRange = NULL; +PFNGLFLUSHMAPPEDBUFFERRANGE_PROC* glpfFlushMappedBufferRange = NULL; +PFNGLBINDVERTEXARRAY_PROC* glpfBindVertexArray = NULL; +PFNGLDELETEVERTEXARRAYS_PROC* glpfDeleteVertexArrays = NULL; +PFNGLGENVERTEXARRAYS_PROC* glpfGenVertexArrays = NULL; +PFNGLISVERTEXARRAY_PROC* glpfIsVertexArray = NULL; + +/* GL_VERSION_3_1 */ + +PFNGLDRAWARRAYSINSTANCED_PROC* glpfDrawArraysInstanced = NULL; +PFNGLDRAWELEMENTSINSTANCED_PROC* glpfDrawElementsInstanced = NULL; +PFNGLTEXBUFFER_PROC* glpfTexBuffer = NULL; +PFNGLPRIMITIVERESTARTINDEX_PROC* glpfPrimitiveRestartIndex = NULL; +PFNGLCOPYBUFFERSUBDATA_PROC* glpfCopyBufferSubData = NULL; +PFNGLGETUNIFORMINDICES_PROC* glpfGetUniformIndices = NULL; +PFNGLGETACTIVEUNIFORMSIV_PROC* glpfGetActiveUniformsiv = NULL; +PFNGLGETACTIVEUNIFORMNAME_PROC* glpfGetActiveUniformName = NULL; +PFNGLGETUNIFORMBLOCKINDEX_PROC* glpfGetUniformBlockIndex = NULL; +PFNGLGETACTIVEUNIFORMBLOCKIV_PROC* glpfGetActiveUniformBlockiv = NULL; +PFNGLGETACTIVEUNIFORMBLOCKNAME_PROC* glpfGetActiveUniformBlockName = NULL; +PFNGLUNIFORMBLOCKBINDING_PROC* glpfUniformBlockBinding = NULL; + +/* GL_VERSION_3_2 */ + +PFNGLDRAWELEMENTSBASEVERTEX_PROC* glpfDrawElementsBaseVertex = NULL; +PFNGLDRAWRANGEELEMENTSBASEVERTEX_PROC* glpfDrawRangeElementsBaseVertex = NULL; +PFNGLDRAWELEMENTSINSTANCEDBASEVERTEX_PROC* glpfDrawElementsInstancedBaseVertex = NULL; +PFNGLMULTIDRAWELEMENTSBASEVERTEX_PROC* glpfMultiDrawElementsBaseVertex = NULL; +PFNGLPROVOKINGVERTEX_PROC* glpfProvokingVertex = NULL; +PFNGLFENCESYNC_PROC* glpfFenceSync = NULL; +PFNGLISSYNC_PROC* glpfIsSync = NULL; +PFNGLDELETESYNC_PROC* glpfDeleteSync = NULL; +PFNGLCLIENTWAITSYNC_PROC* glpfClientWaitSync = NULL; +PFNGLWAITSYNC_PROC* glpfWaitSync = NULL; +PFNGLGETINTEGER64V_PROC* glpfGetInteger64v = NULL; +PFNGLGETSYNCIV_PROC* glpfGetSynciv = NULL; +PFNGLGETINTEGER64I_V_PROC* glpfGetInteger64i_v = NULL; +PFNGLGETBUFFERPARAMETERI64V_PROC* glpfGetBufferParameteri64v = NULL; +PFNGLFRAMEBUFFERTEXTURE_PROC* glpfFramebufferTexture = NULL; +PFNGLTEXIMAGE2DMULTISAMPLE_PROC* glpfTexImage2DMultisample = NULL; +PFNGLTEXIMAGE3DMULTISAMPLE_PROC* glpfTexImage3DMultisample = NULL; +PFNGLGETMULTISAMPLEFV_PROC* glpfGetMultisamplefv = NULL; +PFNGLSAMPLEMASKI_PROC* glpfSampleMaski = NULL; + +/* GL_VERSION_3_3 */ + +PFNGLBINDFRAGDATALOCATIONINDEXED_PROC* glpfBindFragDataLocationIndexed = NULL; +PFNGLGETFRAGDATAINDEX_PROC* glpfGetFragDataIndex = NULL; +PFNGLGENSAMPLERS_PROC* glpfGenSamplers = NULL; +PFNGLDELETESAMPLERS_PROC* glpfDeleteSamplers = NULL; +PFNGLISSAMPLER_PROC* glpfIsSampler = NULL; +PFNGLBINDSAMPLER_PROC* glpfBindSampler = NULL; +PFNGLSAMPLERPARAMETERI_PROC* glpfSamplerParameteri = NULL; +PFNGLSAMPLERPARAMETERIV_PROC* glpfSamplerParameteriv = NULL; +PFNGLSAMPLERPARAMETERF_PROC* glpfSamplerParameterf = NULL; +PFNGLSAMPLERPARAMETERFV_PROC* glpfSamplerParameterfv = NULL; +PFNGLSAMPLERPARAMETERIIV_PROC* glpfSamplerParameterIiv = NULL; +PFNGLSAMPLERPARAMETERIUIV_PROC* glpfSamplerParameterIuiv = NULL; +PFNGLGETSAMPLERPARAMETERIV_PROC* glpfGetSamplerParameteriv = NULL; +PFNGLGETSAMPLERPARAMETERIIV_PROC* glpfGetSamplerParameterIiv = NULL; +PFNGLGETSAMPLERPARAMETERFV_PROC* glpfGetSamplerParameterfv = NULL; +PFNGLGETSAMPLERPARAMETERIUIV_PROC* glpfGetSamplerParameterIuiv = NULL; +PFNGLQUERYCOUNTER_PROC* glpfQueryCounter = NULL; +PFNGLGETQUERYOBJECTI64V_PROC* glpfGetQueryObjecti64v = NULL; +PFNGLGETQUERYOBJECTUI64V_PROC* glpfGetQueryObjectui64v = NULL; +PFNGLVERTEXATTRIBDIVISOR_PROC* glpfVertexAttribDivisor = NULL; +PFNGLVERTEXATTRIBP1UI_PROC* glpfVertexAttribP1ui = NULL; +PFNGLVERTEXATTRIBP1UIV_PROC* glpfVertexAttribP1uiv = NULL; +PFNGLVERTEXATTRIBP2UI_PROC* glpfVertexAttribP2ui = NULL; +PFNGLVERTEXATTRIBP2UIV_PROC* glpfVertexAttribP2uiv = NULL; +PFNGLVERTEXATTRIBP3UI_PROC* glpfVertexAttribP3ui = NULL; +PFNGLVERTEXATTRIBP3UIV_PROC* glpfVertexAttribP3uiv = NULL; +PFNGLVERTEXATTRIBP4UI_PROC* glpfVertexAttribP4ui = NULL; +PFNGLVERTEXATTRIBP4UIV_PROC* glpfVertexAttribP4uiv = NULL; + +/* GL_ARB_debug_output */ + +PFNGLDEBUGMESSAGECONTROLARB_PROC* glpfDebugMessageControlARB = NULL; +PFNGLDEBUGMESSAGEINSERTARB_PROC* glpfDebugMessageInsertARB = NULL; +PFNGLDEBUGMESSAGECALLBACKARB_PROC* glpfDebugMessageCallbackARB = NULL; +PFNGLGETDEBUGMESSAGELOGARB_PROC* glpfGetDebugMessageLogARB = NULL; + +#ifdef __cplusplus +} +#endif diff --git a/src/modules/video/GLFunc.h b/src/modules/video/GLFunc.h new file mode 100644 index 000000000..4608ca974 --- /dev/null +++ b/src/modules/video/GLFunc.h @@ -0,0 +1,2006 @@ +#pragma once + +#include "core/Log.h" + +// based on the generator script from oryol + +#ifdef __cplusplus +extern "C" { +#endif + +/* Function declaration macros - to move into glplatform.h */ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) +#define WIN32_LEAN_AND_MEAN 1 +#ifndef WINAPI +#define WINAPI __stdcall +#endif +#define APIENTRY WINAPI +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif +#ifndef GLAPI +#define GLAPI extern +#endif + +#define GL_OFFSET(i) ((void*)(i)) + +/* -------------------------------- DATA TYPES ------------------------------- */ + +#include +#ifndef GLEXT_64_TYPES_DEFINED +/* This code block is duplicated in glxext.h, so must be protected */ +#define GLEXT_64_TYPES_DEFINED +/* Define int32_t, int64_t, and uint64_t types for UST/MSC */ +/* (as used in the GL_EXT_timer_query extension). */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +#elif defined(__sun__) || defined(__digital__) +#include +#if defined(__STDC__) +#if defined(__arch64__) || defined(_LP64) +typedef long int int64_t; +typedef unsigned long int uint64_t; +#else +typedef long long int int64_t; +typedef unsigned long long int uint64_t; +#endif /* __arch64__ */ +#endif /* __STDC__ */ +#elif defined( __VMS ) || defined(__sgi) +#include +#elif defined(__SCO__) || defined(__USLC__) +#include +#elif defined(__UNIXOS2__) || defined(__SOL64__) +typedef long int int32_t; +typedef long long int int64_t; +typedef unsigned long long int uint64_t; +#elif defined(_WIN32) && defined(__GNUC__) +#include +#elif defined(_WIN32) +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +/* Fallback if nothing above works */ +#include +#endif +#endif +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef void GLvoid; +typedef signed char GLbyte; +typedef short GLshort; +typedef int GLint; +typedef unsigned char GLubyte; +typedef unsigned short GLushort; +typedef unsigned int GLuint; +typedef int GLsizei; +typedef float GLfloat; +typedef float GLclampf; +typedef double GLdouble; +typedef double GLclampd; +typedef char GLchar; +typedef unsigned short GLhalf; +typedef ptrdiff_t GLintptr; +typedef ptrdiff_t GLsizeiptr; +typedef int64_t GLint64; +typedef uint64_t GLuint64; +typedef struct __GLsync *GLsync; +typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); + +/* ----------------------------------- ENUMS --------------------------------- */ + +/* GL_VERSION_1_1 */ + +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_FALSE 0 +#define GL_TRUE 1 +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_NONE 0 +#define GL_FRONT_LEFT 0x0400 +#define GL_FRONT_RIGHT 0x0401 +#define GL_BACK_LEFT 0x0402 +#define GL_BACK_RIGHT 0x0403 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_LEFT 0x0406 +#define GL_RIGHT 0x0407 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_CW 0x0900 +#define GL_CCW 0x0901 +#define GL_POINT_SIZE 0x0B11 +#define GL_POINT_SIZE_RANGE 0x0B12 +#define GL_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_LINE_SMOOTH 0x0B20 +#define GL_LINE_WIDTH 0x0B21 +#define GL_LINE_WIDTH_RANGE 0x0B22 +#define GL_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_POLYGON_MODE 0x0B40 +#define GL_POLYGON_SMOOTH 0x0B41 +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_STENCIL_TEST 0x0B90 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_VIEWPORT 0x0BA2 +#define GL_DITHER 0x0BD0 +#define GL_BLEND_DST 0x0BE0 +#define GL_BLEND_SRC 0x0BE1 +#define GL_BLEND 0x0BE2 +#define GL_LOGIC_OP_MODE 0x0BF0 +#define GL_COLOR_LOGIC_OP 0x0BF2 +#define GL_DRAW_BUFFER 0x0C01 +#define GL_READ_BUFFER 0x0C02 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_DOUBLEBUFFER 0x0C32 +#define GL_STEREO 0x0C33 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_POLYGON_SMOOTH_HINT 0x0C53 +#define GL_UNPACK_SWAP_BYTES 0x0CF0 +#define GL_UNPACK_LSB_FIRST 0x0CF1 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_SWAP_BYTES 0x0D00 +#define GL_PACK_LSB_FIRST 0x0D01 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_OFFSET_POINT 0x2A01 +#define GL_POLYGON_OFFSET_LINE 0x2A02 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_TEXTURE_BINDING_1D 0x8068 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_TEXTURE_BORDER_COLOR 0x1004 +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_ALPHA_SIZE 0x805F +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_DOUBLE 0x140A +#define GL_CLEAR 0x1500 +#define GL_AND 0x1501 +#define GL_AND_REVERSE 0x1502 +#define GL_COPY 0x1503 +#define GL_AND_INVERTED 0x1504 +#define GL_NOOP 0x1505 +#define GL_XOR 0x1506 +#define GL_OR 0x1507 +#define GL_NOR 0x1508 +#define GL_EQUIV 0x1509 +#define GL_INVERT 0x150A +#define GL_OR_REVERSE 0x150B +#define GL_COPY_INVERTED 0x150C +#define GL_OR_INVERTED 0x150D +#define GL_NAND 0x150E +#define GL_SET 0x150F +#define GL_TEXTURE 0x1702 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_STENCIL_INDEX 0x1901 +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_RED 0x1903 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_POINT 0x1B00 +#define GL_LINE 0x1B01 +#define GL_FILL 0x1B02 +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_REPEAT 0x2901 +#define GL_R3_G3_B2 0x2A10 +#define GL_RGB4 0x804F +#define GL_RGB5 0x8050 +#define GL_RGB8 0x8051 +#define GL_RGB10 0x8052 +#define GL_RGB12 0x8053 +#define GL_RGB16 0x8054 +#define GL_RGBA2 0x8055 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_RGBA12 0x805A +#define GL_RGBA16 0x805B + +/* GL_VERSION_1_2 */ + +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E + +/* GL_VERSION_1_3 */ + +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_MULTISAMPLE 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_CLAMP_TO_BORDER 0x812D + +/* GL_VERSION_1_4 */ + +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32 0x81A7 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_LOD_BIAS 0x8501 +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_FUNC_ADD 0x8006 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 + +/* GL_VERSION_1_5 */ + +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_SAMPLES_PASSED 0x8914 +#define GL_SRC1_ALPHA 0x8589 + +/* GL_VERSION_2_0 */ + +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_SHADER_TYPE 0x8B4F +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_DELETE_STATUS 0x8B80 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_LOWER_LEFT 0x8CA1 +#define GL_UPPER_LEFT 0x8CA2 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 + +/* GL_VERSION_2_1 */ + +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB_ALPHA 0x8C42 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_COMPRESSED_SRGB 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 + +/* GL_VERSION_3_0 */ + +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_CLIP_DISTANCE0 0x3000 +#define GL_CLIP_DISTANCE1 0x3001 +#define GL_CLIP_DISTANCE2 0x3002 +#define GL_CLIP_DISTANCE3 0x3003 +#define GL_CLIP_DISTANCE4 0x3004 +#define GL_CLIP_DISTANCE5 0x3005 +#define GL_CLIP_DISTANCE6 0x3006 +#define GL_CLIP_DISTANCE7 0x3007 +#define GL_MAX_CLIP_DISTANCES 0x0D32 +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_CONTEXT_FLAGS 0x821E +#define GL_COMPRESSED_RED 0x8225 +#define GL_COMPRESSED_RG 0x8226 +#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001 +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_CLAMP_READ_COLOR 0x891C +#define GL_FIXED_ONLY 0x891D +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_TEXTURE_1D_ARRAY 0x8C18 +#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B +#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_PRIMITIVES_GENERATED 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_GREEN_INTEGER 0x8D95 +#define GL_BLUE_INTEGER 0x8D96 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_BGR_INTEGER 0x8D9A +#define GL_BGRA_INTEGER 0x8D9B +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_QUERY_WAIT 0x8E13 +#define GL_QUERY_NO_WAIT 0x8E14 +#define GL_QUERY_BY_REGION_WAIT 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_TEXTURE_STENCIL_SIZE 0x88F1 +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_STENCIL_INDEX1 0x8D46 +#define GL_STENCIL_INDEX4 0x8D47 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_STENCIL_INDEX16 0x8D49 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_FRAMEBUFFER_SRGB 0x8DB9 +#define GL_HALF_FLOAT 0x140B +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_COMPRESSED_RED_RGTC1 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define GL_COMPRESSED_RG_RGTC2 0x8DBD +#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_R16 0x822A +#define GL_RG8 0x822B +#define GL_RG16 0x822C +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_VERTEX_ARRAY_BINDING 0x85B5 + +/* GL_VERSION_3_1 */ + +#define GL_SAMPLER_2D_RECT 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_INT_SAMPLER_2D_RECT 0x8DCD +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_TEXTURE_BUFFER 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D +#define GL_TEXTURE_RECTANGLE 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_R16_SNORM 0x8F98 +#define GL_RG16_SNORM 0x8F99 +#define GL_RGB16_SNORM 0x8F9A +#define GL_RGBA16_SNORM 0x8F9B +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_PRIMITIVE_RESTART 0x8F9D +#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_INVALID_INDEX 0xFFFFFFFFu + +/* GL_VERSION_3_2 */ + +#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001 +#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 +#define GL_LINES_ADJACENCY 0x000A +#define GL_LINE_STRIP_ADJACENCY 0x000B +#define GL_TRIANGLES_ADJACENCY 0x000C +#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D +#define GL_PROGRAM_POINT_SIZE 0x8642 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8 +#define GL_GEOMETRY_SHADER 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT 0x8916 +#define GL_GEOMETRY_INPUT_TYPE 0x8917 +#define GL_GEOMETRY_OUTPUT_TYPE 0x8918 +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123 +#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_CONTEXT_PROFILE_MASK 0x9126 +#define GL_DEPTH_CLAMP 0x864F +#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C +#define GL_FIRST_VERTEX_CONVENTION 0x8E4D +#define GL_LAST_VERTEX_CONVENTION 0x8E4E +#define GL_PROVOKING_VERTEX 0x8E4F +#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_SAMPLE_POSITION 0x8E50 +#define GL_SAMPLE_MASK 0x8E51 +#define GL_SAMPLE_MASK_VALUE 0x8E52 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101 +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F +#define GL_MAX_INTEGER_SAMPLES 0x9110 + +/* GL_VERSION_3_3 */ + +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_SRC1_COLOR 0x88F9 +#define GL_ONE_MINUS_SRC1_COLOR 0x88FA +#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB +#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_SAMPLER_BINDING 0x8919 +#define GL_RGB10_A2UI 0x906F +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 +#define GL_TIME_ELAPSED 0x88BF +#define GL_TIMESTAMP 0x8E28 +#define GL_INT_2_10_10_10_REV 0x8D9F + +/* GL_ARB_debug_output */ + +#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243 +#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245 +#define GL_DEBUG_SOURCE_API_ARB 0x8246 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247 +#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249 +#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A +#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B +#define GL_DEBUG_TYPE_ERROR_ARB 0x824C +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E +#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F +#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250 +#define GL_DEBUG_TYPE_OTHER_ARB 0x8251 +#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145 +#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147 +#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148 + +/* --------------------------- FUNCTION PROTOTYPES --------------------------- */ + + +/* GL_VERSION_1_0 */ + +GLAPI void APIENTRY glCullFace (GLenum mode); +GLAPI void APIENTRY glFrontFace (GLenum mode); +GLAPI void APIENTRY glHint (GLenum target, GLenum mode); +GLAPI void APIENTRY glLineWidth (GLfloat width); +GLAPI void APIENTRY glPointSize (GLfloat size); +GLAPI void APIENTRY glPolygonMode (GLenum face, GLenum mode); +GLAPI void APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); +GLAPI void APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat * params); +GLAPI void APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint * params); +GLAPI void APIENTRY glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void * pixels); +GLAPI void APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels); +GLAPI void APIENTRY glDrawBuffer (GLenum buf); +GLAPI void APIENTRY glClear (GLbitfield mask); +GLAPI void APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GLAPI void APIENTRY glClearStencil (GLint s); +GLAPI void APIENTRY glClearDepth (GLdouble depth); +GLAPI void APIENTRY glStencilMask (GLuint mask); +GLAPI void APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GLAPI void APIENTRY glDepthMask (GLboolean flag); +GLAPI void APIENTRY glDisable (GLenum cap); +GLAPI void APIENTRY glEnable (GLenum cap); +GLAPI void APIENTRY glFinish (void); +GLAPI void APIENTRY glFlush (void); +GLAPI void APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); +GLAPI void APIENTRY glLogicOp (GLenum opcode); +GLAPI void APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); +GLAPI void APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); +GLAPI void APIENTRY glDepthFunc (GLenum func); +GLAPI void APIENTRY glPixelStoref (GLenum pname, GLfloat param); +GLAPI void APIENTRY glPixelStorei (GLenum pname, GLint param); +GLAPI void APIENTRY glReadBuffer (GLenum src); +GLAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels); +GLAPI void APIENTRY glGetBooleanv (GLenum pname, GLboolean * data); +GLAPI void APIENTRY glGetDoublev (GLenum pname, GLdouble * data); +GLAPI GLenum APIENTRY glGetError (void); +GLAPI void APIENTRY glGetFloatv (GLenum pname, GLfloat * data); +GLAPI void APIENTRY glGetIntegerv (GLenum pname, GLint * data); +GLAPI const GLubyte * APIENTRY glGetString (GLenum name); +GLAPI void APIENTRY glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type, void * pixels); +GLAPI void APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat * params); +GLAPI void APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint * params); +GLAPI void APIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat * params); +GLAPI void APIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint * params); +GLAPI GLboolean APIENTRY glIsEnabled (GLenum cap); +GLAPI void APIENTRY glDepthRange (GLdouble near, GLdouble far); +GLAPI void APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); + + +/* GL_VERSION_1_1 */ + +GLAPI void APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); +GLAPI void APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void * indices); +GLAPI void APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); +GLAPI void APIENTRY glCopyTexImage1D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +GLAPI void APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GLAPI void APIENTRY glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +GLAPI void APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels); +GLAPI void APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); +GLAPI void APIENTRY glBindTexture (GLenum target, GLuint texture); +GLAPI void APIENTRY glDeleteTextures (GLsizei n, const GLuint * textures); +GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint * textures); +GLAPI GLboolean APIENTRY glIsTexture (GLuint texture); + + +/* GL_VERSION_1_2 */ + +typedef void (APIENTRY PFNGLDRAWRANGEELEMENTS_PROC (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices)); +typedef void (APIENTRY PFNGLTEXIMAGE3D_PROC (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels)); +typedef void (APIENTRY PFNGLTEXSUBIMAGE3D_PROC (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels)); +typedef void (APIENTRY PFNGLCOPYTEXSUBIMAGE3D_PROC (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)); + +GLAPI PFNGLDRAWRANGEELEMENTS_PROC* glpfDrawRangeElements; +GLAPI PFNGLTEXIMAGE3D_PROC* glpfTexImage3D; +GLAPI PFNGLTEXSUBIMAGE3D_PROC* glpfTexSubImage3D; +GLAPI PFNGLCOPYTEXSUBIMAGE3D_PROC* glpfCopyTexSubImage3D; + +#define glDrawRangeElements glpfDrawRangeElements +#define glTexImage3D glpfTexImage3D +#define glTexSubImage3D glpfTexSubImage3D +#define glCopyTexSubImage3D glpfCopyTexSubImage3D + + +/* GL_VERSION_1_3 */ + +typedef void (APIENTRY PFNGLACTIVETEXTURE_PROC (GLenum texture)); +typedef void (APIENTRY PFNGLSAMPLECOVERAGE_PROC (GLfloat value, GLboolean invert)); +typedef void (APIENTRY PFNGLCOMPRESSEDTEXIMAGE3D_PROC (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data)); +typedef void (APIENTRY PFNGLCOMPRESSEDTEXIMAGE2D_PROC (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data)); +typedef void (APIENTRY PFNGLCOMPRESSEDTEXIMAGE1D_PROC (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void * data)); +typedef void (APIENTRY PFNGLCOMPRESSEDTEXSUBIMAGE3D_PROC (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data)); +typedef void (APIENTRY PFNGLCOMPRESSEDTEXSUBIMAGE2D_PROC (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data)); +typedef void (APIENTRY PFNGLCOMPRESSEDTEXSUBIMAGE1D_PROC (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * data)); +typedef void (APIENTRY PFNGLGETCOMPRESSEDTEXIMAGE_PROC (GLenum target, GLint level, void * img)); + +GLAPI PFNGLACTIVETEXTURE_PROC* glpfActiveTexture; +GLAPI PFNGLSAMPLECOVERAGE_PROC* glpfSampleCoverage; +GLAPI PFNGLCOMPRESSEDTEXIMAGE3D_PROC* glpfCompressedTexImage3D; +GLAPI PFNGLCOMPRESSEDTEXIMAGE2D_PROC* glpfCompressedTexImage2D; +GLAPI PFNGLCOMPRESSEDTEXIMAGE1D_PROC* glpfCompressedTexImage1D; +GLAPI PFNGLCOMPRESSEDTEXSUBIMAGE3D_PROC* glpfCompressedTexSubImage3D; +GLAPI PFNGLCOMPRESSEDTEXSUBIMAGE2D_PROC* glpfCompressedTexSubImage2D; +GLAPI PFNGLCOMPRESSEDTEXSUBIMAGE1D_PROC* glpfCompressedTexSubImage1D; +GLAPI PFNGLGETCOMPRESSEDTEXIMAGE_PROC* glpfGetCompressedTexImage; + +#define glActiveTexture glpfActiveTexture +#define glSampleCoverage glpfSampleCoverage +#define glCompressedTexImage3D glpfCompressedTexImage3D +#define glCompressedTexImage2D glpfCompressedTexImage2D +#define glCompressedTexImage1D glpfCompressedTexImage1D +#define glCompressedTexSubImage3D glpfCompressedTexSubImage3D +#define glCompressedTexSubImage2D glpfCompressedTexSubImage2D +#define glCompressedTexSubImage1D glpfCompressedTexSubImage1D +#define glGetCompressedTexImage glpfGetCompressedTexImage + + +/* GL_VERSION_1_4 */ + +typedef void (APIENTRY PFNGLBLENDFUNCSEPARATE_PROC (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha)); +typedef void (APIENTRY PFNGLMULTIDRAWARRAYS_PROC (GLenum mode, const GLint * first, const GLsizei * count, GLsizei drawcount)); +typedef void (APIENTRY PFNGLMULTIDRAWELEMENTS_PROC (GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount)); +typedef void (APIENTRY PFNGLPOINTPARAMETERF_PROC (GLenum pname, GLfloat param)); +typedef void (APIENTRY PFNGLPOINTPARAMETERFV_PROC (GLenum pname, const GLfloat * params)); +typedef void (APIENTRY PFNGLPOINTPARAMETERI_PROC (GLenum pname, GLint param)); +typedef void (APIENTRY PFNGLPOINTPARAMETERIV_PROC (GLenum pname, const GLint * params)); +typedef void (APIENTRY PFNGLBLENDCOLOR_PROC (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)); +typedef void (APIENTRY PFNGLBLENDEQUATION_PROC (GLenum mode)); + +GLAPI PFNGLBLENDFUNCSEPARATE_PROC* glpfBlendFuncSeparate; +GLAPI PFNGLMULTIDRAWARRAYS_PROC* glpfMultiDrawArrays; +GLAPI PFNGLMULTIDRAWELEMENTS_PROC* glpfMultiDrawElements; +GLAPI PFNGLPOINTPARAMETERF_PROC* glpfPointParameterf; +GLAPI PFNGLPOINTPARAMETERFV_PROC* glpfPointParameterfv; +GLAPI PFNGLPOINTPARAMETERI_PROC* glpfPointParameteri; +GLAPI PFNGLPOINTPARAMETERIV_PROC* glpfPointParameteriv; +GLAPI PFNGLBLENDCOLOR_PROC* glpfBlendColor; +GLAPI PFNGLBLENDEQUATION_PROC* glpfBlendEquation; + +#define glBlendFuncSeparate glpfBlendFuncSeparate +#define glMultiDrawArrays glpfMultiDrawArrays +#define glMultiDrawElements glpfMultiDrawElements +#define glPointParameterf glpfPointParameterf +#define glPointParameterfv glpfPointParameterfv +#define glPointParameteri glpfPointParameteri +#define glPointParameteriv glpfPointParameteriv +#define glBlendColor glpfBlendColor +#define glBlendEquation glpfBlendEquation + + +/* GL_VERSION_1_5 */ + +typedef void (APIENTRY PFNGLGENQUERIES_PROC (GLsizei n, GLuint * ids)); +typedef void (APIENTRY PFNGLDELETEQUERIES_PROC (GLsizei n, const GLuint * ids)); +typedef GLboolean (APIENTRY PFNGLISQUERY_PROC (GLuint id)); +typedef void (APIENTRY PFNGLBEGINQUERY_PROC (GLenum target, GLuint id)); +typedef void (APIENTRY PFNGLENDQUERY_PROC (GLenum target)); +typedef void (APIENTRY PFNGLGETQUERYIV_PROC (GLenum target, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETQUERYOBJECTIV_PROC (GLuint id, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETQUERYOBJECTUIV_PROC (GLuint id, GLenum pname, GLuint * params)); +typedef void (APIENTRY PFNGLBINDBUFFER_PROC (GLenum target, GLuint buffer)); +typedef void (APIENTRY PFNGLDELETEBUFFERS_PROC (GLsizei n, const GLuint * buffers)); +typedef void (APIENTRY PFNGLGENBUFFERS_PROC (GLsizei n, GLuint * buffers)); +typedef GLboolean (APIENTRY PFNGLISBUFFER_PROC (GLuint buffer)); +typedef void (APIENTRY PFNGLBUFFERDATA_PROC (GLenum target, GLsizeiptr size, const void * data, GLenum usage)); +typedef void (APIENTRY PFNGLBUFFERSUBDATA_PROC (GLenum target, GLintptr offset, GLsizeiptr size, const void * data)); +typedef void (APIENTRY PFNGLGETBUFFERSUBDATA_PROC (GLenum target, GLintptr offset, GLsizeiptr size, void * data)); +typedef void * (APIENTRY PFNGLMAPBUFFER_PROC (GLenum target, GLenum access)); +typedef GLboolean (APIENTRY PFNGLUNMAPBUFFER_PROC (GLenum target)); +typedef void (APIENTRY PFNGLGETBUFFERPARAMETERIV_PROC (GLenum target, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETBUFFERPOINTERV_PROC (GLenum target, GLenum pname, void ** params)); + +GLAPI PFNGLGENQUERIES_PROC* glpfGenQueries; +GLAPI PFNGLDELETEQUERIES_PROC* glpfDeleteQueries; +GLAPI PFNGLISQUERY_PROC* glpfIsQuery; +GLAPI PFNGLBEGINQUERY_PROC* glpfBeginQuery; +GLAPI PFNGLENDQUERY_PROC* glpfEndQuery; +GLAPI PFNGLGETQUERYIV_PROC* glpfGetQueryiv; +GLAPI PFNGLGETQUERYOBJECTIV_PROC* glpfGetQueryObjectiv; +GLAPI PFNGLGETQUERYOBJECTUIV_PROC* glpfGetQueryObjectuiv; +GLAPI PFNGLBINDBUFFER_PROC* glpfBindBuffer; +GLAPI PFNGLDELETEBUFFERS_PROC* glpfDeleteBuffers; +GLAPI PFNGLGENBUFFERS_PROC* glpfGenBuffers; +GLAPI PFNGLISBUFFER_PROC* glpfIsBuffer; +GLAPI PFNGLBUFFERDATA_PROC* glpfBufferData; +GLAPI PFNGLBUFFERSUBDATA_PROC* glpfBufferSubData; +GLAPI PFNGLGETBUFFERSUBDATA_PROC* glpfGetBufferSubData; +GLAPI PFNGLMAPBUFFER_PROC* glpfMapBuffer; +GLAPI PFNGLUNMAPBUFFER_PROC* glpfUnmapBuffer; +GLAPI PFNGLGETBUFFERPARAMETERIV_PROC* glpfGetBufferParameteriv; +GLAPI PFNGLGETBUFFERPOINTERV_PROC* glpfGetBufferPointerv; + +#define glGenQueries glpfGenQueries +#define glDeleteQueries glpfDeleteQueries +#define glIsQuery glpfIsQuery +#define glBeginQuery glpfBeginQuery +#define glEndQuery glpfEndQuery +#define glGetQueryiv glpfGetQueryiv +#define glGetQueryObjectiv glpfGetQueryObjectiv +#define glGetQueryObjectuiv glpfGetQueryObjectuiv +#define glBindBuffer glpfBindBuffer +#define glDeleteBuffers glpfDeleteBuffers +#define glGenBuffers glpfGenBuffers +#define glIsBuffer glpfIsBuffer +#define glBufferData glpfBufferData +#define glBufferSubData glpfBufferSubData +#define glGetBufferSubData glpfGetBufferSubData +#define glMapBuffer glpfMapBuffer +#define glUnmapBuffer glpfUnmapBuffer +#define glGetBufferParameteriv glpfGetBufferParameteriv +#define glGetBufferPointerv glpfGetBufferPointerv + + +/* GL_VERSION_2_0 */ + +typedef void (APIENTRY PFNGLBLENDEQUATIONSEPARATE_PROC (GLenum modeRGB, GLenum modeAlpha)); +typedef void (APIENTRY PFNGLDRAWBUFFERS_PROC (GLsizei n, const GLenum * bufs)); +typedef void (APIENTRY PFNGLSTENCILOPSEPARATE_PROC (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass)); +typedef void (APIENTRY PFNGLSTENCILFUNCSEPARATE_PROC (GLenum face, GLenum func, GLint ref, GLuint mask)); +typedef void (APIENTRY PFNGLSTENCILMASKSEPARATE_PROC (GLenum face, GLuint mask)); +typedef void (APIENTRY PFNGLATTACHSHADER_PROC (GLuint program, GLuint shader)); +typedef void (APIENTRY PFNGLBINDATTRIBLOCATION_PROC (GLuint program, GLuint index, const GLchar * name)); +typedef void (APIENTRY PFNGLCOMPILESHADER_PROC (GLuint shader)); +typedef GLuint (APIENTRY PFNGLCREATEPROGRAM_PROC (void)); +typedef GLuint (APIENTRY PFNGLCREATESHADER_PROC (GLenum type)); +typedef void (APIENTRY PFNGLDELETEPROGRAM_PROC (GLuint program)); +typedef void (APIENTRY PFNGLDELETESHADER_PROC (GLuint shader)); +typedef void (APIENTRY PFNGLDETACHSHADER_PROC (GLuint program, GLuint shader)); +typedef void (APIENTRY PFNGLDISABLEVERTEXATTRIBARRAY_PROC (GLuint index)); +typedef void (APIENTRY PFNGLENABLEVERTEXATTRIBARRAY_PROC (GLuint index)); +typedef void (APIENTRY PFNGLGETACTIVEATTRIB_PROC (GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name)); +typedef void (APIENTRY PFNGLGETACTIVEUNIFORM_PROC (GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name)); +typedef void (APIENTRY PFNGLGETATTACHEDSHADERS_PROC (GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders)); +typedef GLint (APIENTRY PFNGLGETATTRIBLOCATION_PROC (GLuint program, const GLchar * name)); +typedef void (APIENTRY PFNGLGETPROGRAMIV_PROC (GLuint program, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETPROGRAMINFOLOG_PROC (GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog)); +typedef void (APIENTRY PFNGLGETSHADERIV_PROC (GLuint shader, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETSHADERINFOLOG_PROC (GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog)); +typedef void (APIENTRY PFNGLGETSHADERSOURCE_PROC (GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source)); +typedef GLint (APIENTRY PFNGLGETUNIFORMLOCATION_PROC (GLuint program, const GLchar * name)); +typedef void (APIENTRY PFNGLGETUNIFORMFV_PROC (GLuint program, GLint location, GLfloat * params)); +typedef void (APIENTRY PFNGLGETUNIFORMIV_PROC (GLuint program, GLint location, GLint * params)); +typedef void (APIENTRY PFNGLGETVERTEXATTRIBDV_PROC (GLuint index, GLenum pname, GLdouble * params)); +typedef void (APIENTRY PFNGLGETVERTEXATTRIBFV_PROC (GLuint index, GLenum pname, GLfloat * params)); +typedef void (APIENTRY PFNGLGETVERTEXATTRIBIV_PROC (GLuint index, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETVERTEXATTRIBPOINTERV_PROC (GLuint index, GLenum pname, void ** pointer)); +typedef GLboolean (APIENTRY PFNGLISPROGRAM_PROC (GLuint program)); +typedef GLboolean (APIENTRY PFNGLISSHADER_PROC (GLuint shader)); +typedef void (APIENTRY PFNGLLINKPROGRAM_PROC (GLuint program)); +typedef void (APIENTRY PFNGLSHADERSOURCE_PROC (GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length)); +typedef void (APIENTRY PFNGLUSEPROGRAM_PROC (GLuint program)); +typedef void (APIENTRY PFNGLUNIFORM1F_PROC (GLint location, GLfloat v0)); +typedef void (APIENTRY PFNGLUNIFORM2F_PROC (GLint location, GLfloat v0, GLfloat v1)); +typedef void (APIENTRY PFNGLUNIFORM3F_PROC (GLint location, GLfloat v0, GLfloat v1, GLfloat v2)); +typedef void (APIENTRY PFNGLUNIFORM4F_PROC (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)); +typedef void (APIENTRY PFNGLUNIFORM1I_PROC (GLint location, GLint v0)); +typedef void (APIENTRY PFNGLUNIFORM2I_PROC (GLint location, GLint v0, GLint v1)); +typedef void (APIENTRY PFNGLUNIFORM3I_PROC (GLint location, GLint v0, GLint v1, GLint v2)); +typedef void (APIENTRY PFNGLUNIFORM4I_PROC (GLint location, GLint v0, GLint v1, GLint v2, GLint v3)); +typedef void (APIENTRY PFNGLUNIFORM1FV_PROC (GLint location, GLsizei count, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORM2FV_PROC (GLint location, GLsizei count, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORM3FV_PROC (GLint location, GLsizei count, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORM4FV_PROC (GLint location, GLsizei count, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORM1IV_PROC (GLint location, GLsizei count, const GLint * value)); +typedef void (APIENTRY PFNGLUNIFORM2IV_PROC (GLint location, GLsizei count, const GLint * value)); +typedef void (APIENTRY PFNGLUNIFORM3IV_PROC (GLint location, GLsizei count, const GLint * value)); +typedef void (APIENTRY PFNGLUNIFORM4IV_PROC (GLint location, GLsizei count, const GLint * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX2FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX3FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX4FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLVALIDATEPROGRAM_PROC (GLuint program)); +typedef void (APIENTRY PFNGLVERTEXATTRIB1D_PROC (GLuint index, GLdouble x)); +typedef void (APIENTRY PFNGLVERTEXATTRIB1DV_PROC (GLuint index, const GLdouble * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB1F_PROC (GLuint index, GLfloat x)); +typedef void (APIENTRY PFNGLVERTEXATTRIB1FV_PROC (GLuint index, const GLfloat * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB1S_PROC (GLuint index, GLshort x)); +typedef void (APIENTRY PFNGLVERTEXATTRIB1SV_PROC (GLuint index, const GLshort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB2D_PROC (GLuint index, GLdouble x, GLdouble y)); +typedef void (APIENTRY PFNGLVERTEXATTRIB2DV_PROC (GLuint index, const GLdouble * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB2F_PROC (GLuint index, GLfloat x, GLfloat y)); +typedef void (APIENTRY PFNGLVERTEXATTRIB2FV_PROC (GLuint index, const GLfloat * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB2S_PROC (GLuint index, GLshort x, GLshort y)); +typedef void (APIENTRY PFNGLVERTEXATTRIB2SV_PROC (GLuint index, const GLshort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB3D_PROC (GLuint index, GLdouble x, GLdouble y, GLdouble z)); +typedef void (APIENTRY PFNGLVERTEXATTRIB3DV_PROC (GLuint index, const GLdouble * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB3F_PROC (GLuint index, GLfloat x, GLfloat y, GLfloat z)); +typedef void (APIENTRY PFNGLVERTEXATTRIB3FV_PROC (GLuint index, const GLfloat * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB3S_PROC (GLuint index, GLshort x, GLshort y, GLshort z)); +typedef void (APIENTRY PFNGLVERTEXATTRIB3SV_PROC (GLuint index, const GLshort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NBV_PROC (GLuint index, const GLbyte * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NIV_PROC (GLuint index, const GLint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NSV_PROC (GLuint index, const GLshort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NUB_PROC (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NUBV_PROC (GLuint index, const GLubyte * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NUIV_PROC (GLuint index, const GLuint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NUSV_PROC (GLuint index, const GLushort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4BV_PROC (GLuint index, const GLbyte * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4D_PROC (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4DV_PROC (GLuint index, const GLdouble * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4F_PROC (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4FV_PROC (GLuint index, const GLfloat * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4IV_PROC (GLuint index, const GLint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4S_PROC (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4SV_PROC (GLuint index, const GLshort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4UBV_PROC (GLuint index, const GLubyte * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4UIV_PROC (GLuint index, const GLuint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4USV_PROC (GLuint index, const GLushort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBPOINTER_PROC (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer)); + +GLAPI PFNGLBLENDEQUATIONSEPARATE_PROC* glpfBlendEquationSeparate; +GLAPI PFNGLDRAWBUFFERS_PROC* glpfDrawBuffers; +GLAPI PFNGLSTENCILOPSEPARATE_PROC* glpfStencilOpSeparate; +GLAPI PFNGLSTENCILFUNCSEPARATE_PROC* glpfStencilFuncSeparate; +GLAPI PFNGLSTENCILMASKSEPARATE_PROC* glpfStencilMaskSeparate; +GLAPI PFNGLATTACHSHADER_PROC* glpfAttachShader; +GLAPI PFNGLBINDATTRIBLOCATION_PROC* glpfBindAttribLocation; +GLAPI PFNGLCOMPILESHADER_PROC* glpfCompileShader; +GLAPI PFNGLCREATEPROGRAM_PROC* glpfCreateProgram; +GLAPI PFNGLCREATESHADER_PROC* glpfCreateShader; +GLAPI PFNGLDELETEPROGRAM_PROC* glpfDeleteProgram; +GLAPI PFNGLDELETESHADER_PROC* glpfDeleteShader; +GLAPI PFNGLDETACHSHADER_PROC* glpfDetachShader; +GLAPI PFNGLDISABLEVERTEXATTRIBARRAY_PROC* glpfDisableVertexAttribArray; +GLAPI PFNGLENABLEVERTEXATTRIBARRAY_PROC* glpfEnableVertexAttribArray; +GLAPI PFNGLGETACTIVEATTRIB_PROC* glpfGetActiveAttrib; +GLAPI PFNGLGETACTIVEUNIFORM_PROC* glpfGetActiveUniform; +GLAPI PFNGLGETATTACHEDSHADERS_PROC* glpfGetAttachedShaders; +GLAPI PFNGLGETATTRIBLOCATION_PROC* glpfGetAttribLocation; +GLAPI PFNGLGETPROGRAMIV_PROC* glpfGetProgramiv; +GLAPI PFNGLGETPROGRAMINFOLOG_PROC* glpfGetProgramInfoLog; +GLAPI PFNGLGETSHADERIV_PROC* glpfGetShaderiv; +GLAPI PFNGLGETSHADERINFOLOG_PROC* glpfGetShaderInfoLog; +GLAPI PFNGLGETSHADERSOURCE_PROC* glpfGetShaderSource; +GLAPI PFNGLGETUNIFORMLOCATION_PROC* glpfGetUniformLocation; +GLAPI PFNGLGETUNIFORMFV_PROC* glpfGetUniformfv; +GLAPI PFNGLGETUNIFORMIV_PROC* glpfGetUniformiv; +GLAPI PFNGLGETVERTEXATTRIBDV_PROC* glpfGetVertexAttribdv; +GLAPI PFNGLGETVERTEXATTRIBFV_PROC* glpfGetVertexAttribfv; +GLAPI PFNGLGETVERTEXATTRIBIV_PROC* glpfGetVertexAttribiv; +GLAPI PFNGLGETVERTEXATTRIBPOINTERV_PROC* glpfGetVertexAttribPointerv; +GLAPI PFNGLISPROGRAM_PROC* glpfIsProgram; +GLAPI PFNGLISSHADER_PROC* glpfIsShader; +GLAPI PFNGLLINKPROGRAM_PROC* glpfLinkProgram; +GLAPI PFNGLSHADERSOURCE_PROC* glpfShaderSource; +GLAPI PFNGLUSEPROGRAM_PROC* glpfUseProgram; +GLAPI PFNGLUNIFORM1F_PROC* glpfUniform1f; +GLAPI PFNGLUNIFORM2F_PROC* glpfUniform2f; +GLAPI PFNGLUNIFORM3F_PROC* glpfUniform3f; +GLAPI PFNGLUNIFORM4F_PROC* glpfUniform4f; +GLAPI PFNGLUNIFORM1I_PROC* glpfUniform1i; +GLAPI PFNGLUNIFORM2I_PROC* glpfUniform2i; +GLAPI PFNGLUNIFORM3I_PROC* glpfUniform3i; +GLAPI PFNGLUNIFORM4I_PROC* glpfUniform4i; +GLAPI PFNGLUNIFORM1FV_PROC* glpfUniform1fv; +GLAPI PFNGLUNIFORM2FV_PROC* glpfUniform2fv; +GLAPI PFNGLUNIFORM3FV_PROC* glpfUniform3fv; +GLAPI PFNGLUNIFORM4FV_PROC* glpfUniform4fv; +GLAPI PFNGLUNIFORM1IV_PROC* glpfUniform1iv; +GLAPI PFNGLUNIFORM2IV_PROC* glpfUniform2iv; +GLAPI PFNGLUNIFORM3IV_PROC* glpfUniform3iv; +GLAPI PFNGLUNIFORM4IV_PROC* glpfUniform4iv; +GLAPI PFNGLUNIFORMMATRIX2FV_PROC* glpfUniformMatrix2fv; +GLAPI PFNGLUNIFORMMATRIX3FV_PROC* glpfUniformMatrix3fv; +GLAPI PFNGLUNIFORMMATRIX4FV_PROC* glpfUniformMatrix4fv; +GLAPI PFNGLVALIDATEPROGRAM_PROC* glpfValidateProgram; +GLAPI PFNGLVERTEXATTRIB1D_PROC* glpfVertexAttrib1d; +GLAPI PFNGLVERTEXATTRIB1DV_PROC* glpfVertexAttrib1dv; +GLAPI PFNGLVERTEXATTRIB1F_PROC* glpfVertexAttrib1f; +GLAPI PFNGLVERTEXATTRIB1FV_PROC* glpfVertexAttrib1fv; +GLAPI PFNGLVERTEXATTRIB1S_PROC* glpfVertexAttrib1s; +GLAPI PFNGLVERTEXATTRIB1SV_PROC* glpfVertexAttrib1sv; +GLAPI PFNGLVERTEXATTRIB2D_PROC* glpfVertexAttrib2d; +GLAPI PFNGLVERTEXATTRIB2DV_PROC* glpfVertexAttrib2dv; +GLAPI PFNGLVERTEXATTRIB2F_PROC* glpfVertexAttrib2f; +GLAPI PFNGLVERTEXATTRIB2FV_PROC* glpfVertexAttrib2fv; +GLAPI PFNGLVERTEXATTRIB2S_PROC* glpfVertexAttrib2s; +GLAPI PFNGLVERTEXATTRIB2SV_PROC* glpfVertexAttrib2sv; +GLAPI PFNGLVERTEXATTRIB3D_PROC* glpfVertexAttrib3d; +GLAPI PFNGLVERTEXATTRIB3DV_PROC* glpfVertexAttrib3dv; +GLAPI PFNGLVERTEXATTRIB3F_PROC* glpfVertexAttrib3f; +GLAPI PFNGLVERTEXATTRIB3FV_PROC* glpfVertexAttrib3fv; +GLAPI PFNGLVERTEXATTRIB3S_PROC* glpfVertexAttrib3s; +GLAPI PFNGLVERTEXATTRIB3SV_PROC* glpfVertexAttrib3sv; +GLAPI PFNGLVERTEXATTRIB4NBV_PROC* glpfVertexAttrib4Nbv; +GLAPI PFNGLVERTEXATTRIB4NIV_PROC* glpfVertexAttrib4Niv; +GLAPI PFNGLVERTEXATTRIB4NSV_PROC* glpfVertexAttrib4Nsv; +GLAPI PFNGLVERTEXATTRIB4NUB_PROC* glpfVertexAttrib4Nub; +GLAPI PFNGLVERTEXATTRIB4NUBV_PROC* glpfVertexAttrib4Nubv; +GLAPI PFNGLVERTEXATTRIB4NUIV_PROC* glpfVertexAttrib4Nuiv; +GLAPI PFNGLVERTEXATTRIB4NUSV_PROC* glpfVertexAttrib4Nusv; +GLAPI PFNGLVERTEXATTRIB4BV_PROC* glpfVertexAttrib4bv; +GLAPI PFNGLVERTEXATTRIB4D_PROC* glpfVertexAttrib4d; +GLAPI PFNGLVERTEXATTRIB4DV_PROC* glpfVertexAttrib4dv; +GLAPI PFNGLVERTEXATTRIB4F_PROC* glpfVertexAttrib4f; +GLAPI PFNGLVERTEXATTRIB4FV_PROC* glpfVertexAttrib4fv; +GLAPI PFNGLVERTEXATTRIB4IV_PROC* glpfVertexAttrib4iv; +GLAPI PFNGLVERTEXATTRIB4S_PROC* glpfVertexAttrib4s; +GLAPI PFNGLVERTEXATTRIB4SV_PROC* glpfVertexAttrib4sv; +GLAPI PFNGLVERTEXATTRIB4UBV_PROC* glpfVertexAttrib4ubv; +GLAPI PFNGLVERTEXATTRIB4UIV_PROC* glpfVertexAttrib4uiv; +GLAPI PFNGLVERTEXATTRIB4USV_PROC* glpfVertexAttrib4usv; +GLAPI PFNGLVERTEXATTRIBPOINTER_PROC* glpfVertexAttribPointer; + +#define glBlendEquationSeparate glpfBlendEquationSeparate +#define glDrawBuffers glpfDrawBuffers +#define glStencilOpSeparate glpfStencilOpSeparate +#define glStencilFuncSeparate glpfStencilFuncSeparate +#define glStencilMaskSeparate glpfStencilMaskSeparate +#define glAttachShader glpfAttachShader +#define glBindAttribLocation glpfBindAttribLocation +#define glCompileShader glpfCompileShader +#define glCreateProgram glpfCreateProgram +#define glCreateShader glpfCreateShader +#define glDeleteProgram glpfDeleteProgram +#define glDeleteShader glpfDeleteShader +#define glDetachShader glpfDetachShader +#define glDisableVertexAttribArray glpfDisableVertexAttribArray +#define glEnableVertexAttribArray glpfEnableVertexAttribArray +#define glGetActiveAttrib glpfGetActiveAttrib +#define glGetActiveUniform glpfGetActiveUniform +#define glGetAttachedShaders glpfGetAttachedShaders +#define glGetAttribLocation glpfGetAttribLocation +#define glGetProgramiv glpfGetProgramiv +#define glGetProgramInfoLog glpfGetProgramInfoLog +#define glGetShaderiv glpfGetShaderiv +#define glGetShaderInfoLog glpfGetShaderInfoLog +#define glGetShaderSource glpfGetShaderSource +#define glGetUniformLocation glpfGetUniformLocation +#define glGetUniformfv glpfGetUniformfv +#define glGetUniformiv glpfGetUniformiv +#define glGetVertexAttribdv glpfGetVertexAttribdv +#define glGetVertexAttribfv glpfGetVertexAttribfv +#define glGetVertexAttribiv glpfGetVertexAttribiv +#define glGetVertexAttribPointerv glpfGetVertexAttribPointerv +#define glIsProgram glpfIsProgram +#define glIsShader glpfIsShader +#define glLinkProgram glpfLinkProgram +#define glShaderSource glpfShaderSource +#define glUseProgram glpfUseProgram +#define glUniform1f glpfUniform1f +#define glUniform2f glpfUniform2f +#define glUniform3f glpfUniform3f +#define glUniform4f glpfUniform4f +#define glUniform1i glpfUniform1i +#define glUniform2i glpfUniform2i +#define glUniform3i glpfUniform3i +#define glUniform4i glpfUniform4i +#define glUniform1fv glpfUniform1fv +#define glUniform2fv glpfUniform2fv +#define glUniform3fv glpfUniform3fv +#define glUniform4fv glpfUniform4fv +#define glUniform1iv glpfUniform1iv +#define glUniform2iv glpfUniform2iv +#define glUniform3iv glpfUniform3iv +#define glUniform4iv glpfUniform4iv +#define glUniformMatrix2fv glpfUniformMatrix2fv +#define glUniformMatrix3fv glpfUniformMatrix3fv +#define glUniformMatrix4fv glpfUniformMatrix4fv +#define glValidateProgram glpfValidateProgram +#define glVertexAttrib1d glpfVertexAttrib1d +#define glVertexAttrib1dv glpfVertexAttrib1dv +#define glVertexAttrib1f glpfVertexAttrib1f +#define glVertexAttrib1fv glpfVertexAttrib1fv +#define glVertexAttrib1s glpfVertexAttrib1s +#define glVertexAttrib1sv glpfVertexAttrib1sv +#define glVertexAttrib2d glpfVertexAttrib2d +#define glVertexAttrib2dv glpfVertexAttrib2dv +#define glVertexAttrib2f glpfVertexAttrib2f +#define glVertexAttrib2fv glpfVertexAttrib2fv +#define glVertexAttrib2s glpfVertexAttrib2s +#define glVertexAttrib2sv glpfVertexAttrib2sv +#define glVertexAttrib3d glpfVertexAttrib3d +#define glVertexAttrib3dv glpfVertexAttrib3dv +#define glVertexAttrib3f glpfVertexAttrib3f +#define glVertexAttrib3fv glpfVertexAttrib3fv +#define glVertexAttrib3s glpfVertexAttrib3s +#define glVertexAttrib3sv glpfVertexAttrib3sv +#define glVertexAttrib4Nbv glpfVertexAttrib4Nbv +#define glVertexAttrib4Niv glpfVertexAttrib4Niv +#define glVertexAttrib4Nsv glpfVertexAttrib4Nsv +#define glVertexAttrib4Nub glpfVertexAttrib4Nub +#define glVertexAttrib4Nubv glpfVertexAttrib4Nubv +#define glVertexAttrib4Nuiv glpfVertexAttrib4Nuiv +#define glVertexAttrib4Nusv glpfVertexAttrib4Nusv +#define glVertexAttrib4bv glpfVertexAttrib4bv +#define glVertexAttrib4d glpfVertexAttrib4d +#define glVertexAttrib4dv glpfVertexAttrib4dv +#define glVertexAttrib4f glpfVertexAttrib4f +#define glVertexAttrib4fv glpfVertexAttrib4fv +#define glVertexAttrib4iv glpfVertexAttrib4iv +#define glVertexAttrib4s glpfVertexAttrib4s +#define glVertexAttrib4sv glpfVertexAttrib4sv +#define glVertexAttrib4ubv glpfVertexAttrib4ubv +#define glVertexAttrib4uiv glpfVertexAttrib4uiv +#define glVertexAttrib4usv glpfVertexAttrib4usv +#define glVertexAttribPointer glpfVertexAttribPointer + + +/* GL_VERSION_2_1 */ + +typedef void (APIENTRY PFNGLUNIFORMMATRIX2X3FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX3X2FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX2X4FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX4X2FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX3X4FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX4X3FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); + +GLAPI PFNGLUNIFORMMATRIX2X3FV_PROC* glpfUniformMatrix2x3fv; +GLAPI PFNGLUNIFORMMATRIX3X2FV_PROC* glpfUniformMatrix3x2fv; +GLAPI PFNGLUNIFORMMATRIX2X4FV_PROC* glpfUniformMatrix2x4fv; +GLAPI PFNGLUNIFORMMATRIX4X2FV_PROC* glpfUniformMatrix4x2fv; +GLAPI PFNGLUNIFORMMATRIX3X4FV_PROC* glpfUniformMatrix3x4fv; +GLAPI PFNGLUNIFORMMATRIX4X3FV_PROC* glpfUniformMatrix4x3fv; + +#define glUniformMatrix2x3fv glpfUniformMatrix2x3fv +#define glUniformMatrix3x2fv glpfUniformMatrix3x2fv +#define glUniformMatrix2x4fv glpfUniformMatrix2x4fv +#define glUniformMatrix4x2fv glpfUniformMatrix4x2fv +#define glUniformMatrix3x4fv glpfUniformMatrix3x4fv +#define glUniformMatrix4x3fv glpfUniformMatrix4x3fv + + +/* GL_VERSION_3_0 */ + +typedef void (APIENTRY PFNGLCOLORMASKI_PROC (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a)); +typedef void (APIENTRY PFNGLGETBOOLEANI_V_PROC (GLenum target, GLuint index, GLboolean * data)); +typedef void (APIENTRY PFNGLGETINTEGERI_V_PROC (GLenum target, GLuint index, GLint * data)); +typedef void (APIENTRY PFNGLENABLEI_PROC (GLenum target, GLuint index)); +typedef void (APIENTRY PFNGLDISABLEI_PROC (GLenum target, GLuint index)); +typedef GLboolean (APIENTRY PFNGLISENABLEDI_PROC (GLenum target, GLuint index)); +typedef void (APIENTRY PFNGLBEGINTRANSFORMFEEDBACK_PROC (GLenum primitiveMode)); +typedef void (APIENTRY PFNGLENDTRANSFORMFEEDBACK_PROC (void)); +typedef void (APIENTRY PFNGLBINDBUFFERRANGE_PROC (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)); +typedef void (APIENTRY PFNGLBINDBUFFERBASE_PROC (GLenum target, GLuint index, GLuint buffer)); +typedef void (APIENTRY PFNGLTRANSFORMFEEDBACKVARYINGS_PROC (GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode)); +typedef void (APIENTRY PFNGLGETTRANSFORMFEEDBACKVARYING_PROC (GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name)); +typedef void (APIENTRY PFNGLCLAMPCOLOR_PROC (GLenum target, GLenum clamp)); +typedef void (APIENTRY PFNGLBEGINCONDITIONALRENDER_PROC (GLuint id, GLenum mode)); +typedef void (APIENTRY PFNGLENDCONDITIONALRENDER_PROC (void)); +typedef void (APIENTRY PFNGLVERTEXATTRIBIPOINTER_PROC (GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer)); +typedef void (APIENTRY PFNGLGETVERTEXATTRIBIIV_PROC (GLuint index, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETVERTEXATTRIBIUIV_PROC (GLuint index, GLenum pname, GLuint * params)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI1I_PROC (GLuint index, GLint x)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI2I_PROC (GLuint index, GLint x, GLint y)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI3I_PROC (GLuint index, GLint x, GLint y, GLint z)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4I_PROC (GLuint index, GLint x, GLint y, GLint z, GLint w)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI1UI_PROC (GLuint index, GLuint x)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI2UI_PROC (GLuint index, GLuint x, GLuint y)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI3UI_PROC (GLuint index, GLuint x, GLuint y, GLuint z)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4UI_PROC (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI1IV_PROC (GLuint index, const GLint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI2IV_PROC (GLuint index, const GLint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI3IV_PROC (GLuint index, const GLint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4IV_PROC (GLuint index, const GLint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI1UIV_PROC (GLuint index, const GLuint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI2UIV_PROC (GLuint index, const GLuint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI3UIV_PROC (GLuint index, const GLuint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4UIV_PROC (GLuint index, const GLuint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4BV_PROC (GLuint index, const GLbyte * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4SV_PROC (GLuint index, const GLshort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4UBV_PROC (GLuint index, const GLubyte * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4USV_PROC (GLuint index, const GLushort * v)); +typedef void (APIENTRY PFNGLGETUNIFORMUIV_PROC (GLuint program, GLint location, GLuint * params)); +typedef void (APIENTRY PFNGLBINDFRAGDATALOCATION_PROC (GLuint program, GLuint color, const GLchar * name)); +typedef GLint (APIENTRY PFNGLGETFRAGDATALOCATION_PROC (GLuint program, const GLchar * name)); +typedef void (APIENTRY PFNGLUNIFORM1UI_PROC (GLint location, GLuint v0)); +typedef void (APIENTRY PFNGLUNIFORM2UI_PROC (GLint location, GLuint v0, GLuint v1)); +typedef void (APIENTRY PFNGLUNIFORM3UI_PROC (GLint location, GLuint v0, GLuint v1, GLuint v2)); +typedef void (APIENTRY PFNGLUNIFORM4UI_PROC (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)); +typedef void (APIENTRY PFNGLUNIFORM1UIV_PROC (GLint location, GLsizei count, const GLuint * value)); +typedef void (APIENTRY PFNGLUNIFORM2UIV_PROC (GLint location, GLsizei count, const GLuint * value)); +typedef void (APIENTRY PFNGLUNIFORM3UIV_PROC (GLint location, GLsizei count, const GLuint * value)); +typedef void (APIENTRY PFNGLUNIFORM4UIV_PROC (GLint location, GLsizei count, const GLuint * value)); +typedef void (APIENTRY PFNGLTEXPARAMETERIIV_PROC (GLenum target, GLenum pname, const GLint * params)); +typedef void (APIENTRY PFNGLTEXPARAMETERIUIV_PROC (GLenum target, GLenum pname, const GLuint * params)); +typedef void (APIENTRY PFNGLGETTEXPARAMETERIIV_PROC (GLenum target, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETTEXPARAMETERIUIV_PROC (GLenum target, GLenum pname, GLuint * params)); +typedef void (APIENTRY PFNGLCLEARBUFFERIV_PROC (GLenum buffer, GLint drawbuffer, const GLint * value)); +typedef void (APIENTRY PFNGLCLEARBUFFERUIV_PROC (GLenum buffer, GLint drawbuffer, const GLuint * value)); +typedef void (APIENTRY PFNGLCLEARBUFFERFV_PROC (GLenum buffer, GLint drawbuffer, const GLfloat * value)); +typedef void (APIENTRY PFNGLCLEARBUFFERFI_PROC (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)); +typedef const GLubyte * (APIENTRY PFNGLGETSTRINGI_PROC (GLenum name, GLuint index)); +typedef GLboolean (APIENTRY PFNGLISRENDERBUFFER_PROC (GLuint renderbuffer)); +typedef void (APIENTRY PFNGLBINDRENDERBUFFER_PROC (GLenum target, GLuint renderbuffer)); +typedef void (APIENTRY PFNGLDELETERENDERBUFFERS_PROC (GLsizei n, const GLuint * renderbuffers)); +typedef void (APIENTRY PFNGLGENRENDERBUFFERS_PROC (GLsizei n, GLuint * renderbuffers)); +typedef void (APIENTRY PFNGLRENDERBUFFERSTORAGE_PROC (GLenum target, GLenum internalformat, GLsizei width, GLsizei height)); +typedef void (APIENTRY PFNGLGETRENDERBUFFERPARAMETERIV_PROC (GLenum target, GLenum pname, GLint * params)); +typedef GLboolean (APIENTRY PFNGLISFRAMEBUFFER_PROC (GLuint framebuffer)); +typedef void (APIENTRY PFNGLBINDFRAMEBUFFER_PROC (GLenum target, GLuint framebuffer)); +typedef void (APIENTRY PFNGLDELETEFRAMEBUFFERS_PROC (GLsizei n, const GLuint * framebuffers)); +typedef void (APIENTRY PFNGLGENFRAMEBUFFERS_PROC (GLsizei n, GLuint * framebuffers)); +typedef GLenum (APIENTRY PFNGLCHECKFRAMEBUFFERSTATUS_PROC (GLenum target)); +typedef void (APIENTRY PFNGLFRAMEBUFFERTEXTURE1D_PROC (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)); +typedef void (APIENTRY PFNGLFRAMEBUFFERTEXTURE2D_PROC (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)); +typedef void (APIENTRY PFNGLFRAMEBUFFERTEXTURE3D_PROC (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)); +typedef void (APIENTRY PFNGLFRAMEBUFFERRENDERBUFFER_PROC (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)); +typedef void (APIENTRY PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIV_PROC (GLenum target, GLenum attachment, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGENERATEMIPMAP_PROC (GLenum target)); +typedef void (APIENTRY PFNGLBLITFRAMEBUFFER_PROC (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)); +typedef void (APIENTRY PFNGLRENDERBUFFERSTORAGEMULTISAMPLE_PROC (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)); +typedef void (APIENTRY PFNGLFRAMEBUFFERTEXTURELAYER_PROC (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)); +typedef void * (APIENTRY PFNGLMAPBUFFERRANGE_PROC (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)); +typedef void (APIENTRY PFNGLFLUSHMAPPEDBUFFERRANGE_PROC (GLenum target, GLintptr offset, GLsizeiptr length)); +typedef void (APIENTRY PFNGLBINDVERTEXARRAY_PROC (GLuint array)); +typedef void (APIENTRY PFNGLDELETEVERTEXARRAYS_PROC (GLsizei n, const GLuint * arrays)); +typedef void (APIENTRY PFNGLGENVERTEXARRAYS_PROC (GLsizei n, GLuint * arrays)); +typedef GLboolean (APIENTRY PFNGLISVERTEXARRAY_PROC (GLuint array)); + +GLAPI PFNGLCOLORMASKI_PROC* glpfColorMaski; +GLAPI PFNGLGETBOOLEANI_V_PROC* glpfGetBooleani_v; +GLAPI PFNGLGETINTEGERI_V_PROC* glpfGetIntegeri_v; +GLAPI PFNGLENABLEI_PROC* glpfEnablei; +GLAPI PFNGLDISABLEI_PROC* glpfDisablei; +GLAPI PFNGLISENABLEDI_PROC* glpfIsEnabledi; +GLAPI PFNGLBEGINTRANSFORMFEEDBACK_PROC* glpfBeginTransformFeedback; +GLAPI PFNGLENDTRANSFORMFEEDBACK_PROC* glpfEndTransformFeedback; +GLAPI PFNGLBINDBUFFERRANGE_PROC* glpfBindBufferRange; +GLAPI PFNGLBINDBUFFERBASE_PROC* glpfBindBufferBase; +GLAPI PFNGLTRANSFORMFEEDBACKVARYINGS_PROC* glpfTransformFeedbackVaryings; +GLAPI PFNGLGETTRANSFORMFEEDBACKVARYING_PROC* glpfGetTransformFeedbackVarying; +GLAPI PFNGLCLAMPCOLOR_PROC* glpfClampColor; +GLAPI PFNGLBEGINCONDITIONALRENDER_PROC* glpfBeginConditionalRender; +GLAPI PFNGLENDCONDITIONALRENDER_PROC* glpfEndConditionalRender; +GLAPI PFNGLVERTEXATTRIBIPOINTER_PROC* glpfVertexAttribIPointer; +GLAPI PFNGLGETVERTEXATTRIBIIV_PROC* glpfGetVertexAttribIiv; +GLAPI PFNGLGETVERTEXATTRIBIUIV_PROC* glpfGetVertexAttribIuiv; +GLAPI PFNGLVERTEXATTRIBI1I_PROC* glpfVertexAttribI1i; +GLAPI PFNGLVERTEXATTRIBI2I_PROC* glpfVertexAttribI2i; +GLAPI PFNGLVERTEXATTRIBI3I_PROC* glpfVertexAttribI3i; +GLAPI PFNGLVERTEXATTRIBI4I_PROC* glpfVertexAttribI4i; +GLAPI PFNGLVERTEXATTRIBI1UI_PROC* glpfVertexAttribI1ui; +GLAPI PFNGLVERTEXATTRIBI2UI_PROC* glpfVertexAttribI2ui; +GLAPI PFNGLVERTEXATTRIBI3UI_PROC* glpfVertexAttribI3ui; +GLAPI PFNGLVERTEXATTRIBI4UI_PROC* glpfVertexAttribI4ui; +GLAPI PFNGLVERTEXATTRIBI1IV_PROC* glpfVertexAttribI1iv; +GLAPI PFNGLVERTEXATTRIBI2IV_PROC* glpfVertexAttribI2iv; +GLAPI PFNGLVERTEXATTRIBI3IV_PROC* glpfVertexAttribI3iv; +GLAPI PFNGLVERTEXATTRIBI4IV_PROC* glpfVertexAttribI4iv; +GLAPI PFNGLVERTEXATTRIBI1UIV_PROC* glpfVertexAttribI1uiv; +GLAPI PFNGLVERTEXATTRIBI2UIV_PROC* glpfVertexAttribI2uiv; +GLAPI PFNGLVERTEXATTRIBI3UIV_PROC* glpfVertexAttribI3uiv; +GLAPI PFNGLVERTEXATTRIBI4UIV_PROC* glpfVertexAttribI4uiv; +GLAPI PFNGLVERTEXATTRIBI4BV_PROC* glpfVertexAttribI4bv; +GLAPI PFNGLVERTEXATTRIBI4SV_PROC* glpfVertexAttribI4sv; +GLAPI PFNGLVERTEXATTRIBI4UBV_PROC* glpfVertexAttribI4ubv; +GLAPI PFNGLVERTEXATTRIBI4USV_PROC* glpfVertexAttribI4usv; +GLAPI PFNGLGETUNIFORMUIV_PROC* glpfGetUniformuiv; +GLAPI PFNGLBINDFRAGDATALOCATION_PROC* glpfBindFragDataLocation; +GLAPI PFNGLGETFRAGDATALOCATION_PROC* glpfGetFragDataLocation; +GLAPI PFNGLUNIFORM1UI_PROC* glpfUniform1ui; +GLAPI PFNGLUNIFORM2UI_PROC* glpfUniform2ui; +GLAPI PFNGLUNIFORM3UI_PROC* glpfUniform3ui; +GLAPI PFNGLUNIFORM4UI_PROC* glpfUniform4ui; +GLAPI PFNGLUNIFORM1UIV_PROC* glpfUniform1uiv; +GLAPI PFNGLUNIFORM2UIV_PROC* glpfUniform2uiv; +GLAPI PFNGLUNIFORM3UIV_PROC* glpfUniform3uiv; +GLAPI PFNGLUNIFORM4UIV_PROC* glpfUniform4uiv; +GLAPI PFNGLTEXPARAMETERIIV_PROC* glpfTexParameterIiv; +GLAPI PFNGLTEXPARAMETERIUIV_PROC* glpfTexParameterIuiv; +GLAPI PFNGLGETTEXPARAMETERIIV_PROC* glpfGetTexParameterIiv; +GLAPI PFNGLGETTEXPARAMETERIUIV_PROC* glpfGetTexParameterIuiv; +GLAPI PFNGLCLEARBUFFERIV_PROC* glpfClearBufferiv; +GLAPI PFNGLCLEARBUFFERUIV_PROC* glpfClearBufferuiv; +GLAPI PFNGLCLEARBUFFERFV_PROC* glpfClearBufferfv; +GLAPI PFNGLCLEARBUFFERFI_PROC* glpfClearBufferfi; +GLAPI PFNGLGETSTRINGI_PROC* glpfGetStringi; +GLAPI PFNGLISRENDERBUFFER_PROC* glpfIsRenderbuffer; +GLAPI PFNGLBINDRENDERBUFFER_PROC* glpfBindRenderbuffer; +GLAPI PFNGLDELETERENDERBUFFERS_PROC* glpfDeleteRenderbuffers; +GLAPI PFNGLGENRENDERBUFFERS_PROC* glpfGenRenderbuffers; +GLAPI PFNGLRENDERBUFFERSTORAGE_PROC* glpfRenderbufferStorage; +GLAPI PFNGLGETRENDERBUFFERPARAMETERIV_PROC* glpfGetRenderbufferParameteriv; +GLAPI PFNGLISFRAMEBUFFER_PROC* glpfIsFramebuffer; +GLAPI PFNGLBINDFRAMEBUFFER_PROC* glpfBindFramebuffer; +GLAPI PFNGLDELETEFRAMEBUFFERS_PROC* glpfDeleteFramebuffers; +GLAPI PFNGLGENFRAMEBUFFERS_PROC* glpfGenFramebuffers; +GLAPI PFNGLCHECKFRAMEBUFFERSTATUS_PROC* glpfCheckFramebufferStatus; +GLAPI PFNGLFRAMEBUFFERTEXTURE1D_PROC* glpfFramebufferTexture1D; +GLAPI PFNGLFRAMEBUFFERTEXTURE2D_PROC* glpfFramebufferTexture2D; +GLAPI PFNGLFRAMEBUFFERTEXTURE3D_PROC* glpfFramebufferTexture3D; +GLAPI PFNGLFRAMEBUFFERRENDERBUFFER_PROC* glpfFramebufferRenderbuffer; +GLAPI PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIV_PROC* glpfGetFramebufferAttachmentParameteriv; +GLAPI PFNGLGENERATEMIPMAP_PROC* glpfGenerateMipmap; +GLAPI PFNGLBLITFRAMEBUFFER_PROC* glpfBlitFramebuffer; +GLAPI PFNGLRENDERBUFFERSTORAGEMULTISAMPLE_PROC* glpfRenderbufferStorageMultisample; +GLAPI PFNGLFRAMEBUFFERTEXTURELAYER_PROC* glpfFramebufferTextureLayer; +GLAPI PFNGLMAPBUFFERRANGE_PROC* glpfMapBufferRange; +GLAPI PFNGLFLUSHMAPPEDBUFFERRANGE_PROC* glpfFlushMappedBufferRange; +GLAPI PFNGLBINDVERTEXARRAY_PROC* glpfBindVertexArray; +GLAPI PFNGLDELETEVERTEXARRAYS_PROC* glpfDeleteVertexArrays; +GLAPI PFNGLGENVERTEXARRAYS_PROC* glpfGenVertexArrays; +GLAPI PFNGLISVERTEXARRAY_PROC* glpfIsVertexArray; + +#define glColorMaski glpfColorMaski +#define glGetBooleani_v glpfGetBooleani_v +#define glGetIntegeri_v glpfGetIntegeri_v +#define glEnablei glpfEnablei +#define glDisablei glpfDisablei +#define glIsEnabledi glpfIsEnabledi +#define glBeginTransformFeedback glpfBeginTransformFeedback +#define glEndTransformFeedback glpfEndTransformFeedback +#define glBindBufferRange glpfBindBufferRange +#define glBindBufferBase glpfBindBufferBase +#define glTransformFeedbackVaryings glpfTransformFeedbackVaryings +#define glGetTransformFeedbackVarying glpfGetTransformFeedbackVarying +#define glClampColor glpfClampColor +#define glBeginConditionalRender glpfBeginConditionalRender +#define glEndConditionalRender glpfEndConditionalRender +#define glVertexAttribIPointer glpfVertexAttribIPointer +#define glGetVertexAttribIiv glpfGetVertexAttribIiv +#define glGetVertexAttribIuiv glpfGetVertexAttribIuiv +#define glVertexAttribI1i glpfVertexAttribI1i +#define glVertexAttribI2i glpfVertexAttribI2i +#define glVertexAttribI3i glpfVertexAttribI3i +#define glVertexAttribI4i glpfVertexAttribI4i +#define glVertexAttribI1ui glpfVertexAttribI1ui +#define glVertexAttribI2ui glpfVertexAttribI2ui +#define glVertexAttribI3ui glpfVertexAttribI3ui +#define glVertexAttribI4ui glpfVertexAttribI4ui +#define glVertexAttribI1iv glpfVertexAttribI1iv +#define glVertexAttribI2iv glpfVertexAttribI2iv +#define glVertexAttribI3iv glpfVertexAttribI3iv +#define glVertexAttribI4iv glpfVertexAttribI4iv +#define glVertexAttribI1uiv glpfVertexAttribI1uiv +#define glVertexAttribI2uiv glpfVertexAttribI2uiv +#define glVertexAttribI3uiv glpfVertexAttribI3uiv +#define glVertexAttribI4uiv glpfVertexAttribI4uiv +#define glVertexAttribI4bv glpfVertexAttribI4bv +#define glVertexAttribI4sv glpfVertexAttribI4sv +#define glVertexAttribI4ubv glpfVertexAttribI4ubv +#define glVertexAttribI4usv glpfVertexAttribI4usv +#define glGetUniformuiv glpfGetUniformuiv +#define glBindFragDataLocation glpfBindFragDataLocation +#define glGetFragDataLocation glpfGetFragDataLocation +#define glUniform1ui glpfUniform1ui +#define glUniform2ui glpfUniform2ui +#define glUniform3ui glpfUniform3ui +#define glUniform4ui glpfUniform4ui +#define glUniform1uiv glpfUniform1uiv +#define glUniform2uiv glpfUniform2uiv +#define glUniform3uiv glpfUniform3uiv +#define glUniform4uiv glpfUniform4uiv +#define glTexParameterIiv glpfTexParameterIiv +#define glTexParameterIuiv glpfTexParameterIuiv +#define glGetTexParameterIiv glpfGetTexParameterIiv +#define glGetTexParameterIuiv glpfGetTexParameterIuiv +#define glClearBufferiv glpfClearBufferiv +#define glClearBufferuiv glpfClearBufferuiv +#define glClearBufferfv glpfClearBufferfv +#define glClearBufferfi glpfClearBufferfi +#define glGetStringi glpfGetStringi +#define glIsRenderbuffer glpfIsRenderbuffer +#define glBindRenderbuffer glpfBindRenderbuffer +#define glDeleteRenderbuffers glpfDeleteRenderbuffers +#define glGenRenderbuffers glpfGenRenderbuffers +#define glRenderbufferStorage glpfRenderbufferStorage +#define glGetRenderbufferParameteriv glpfGetRenderbufferParameteriv +#define glIsFramebuffer glpfIsFramebuffer +#define glBindFramebuffer glpfBindFramebuffer +#define glDeleteFramebuffers glpfDeleteFramebuffers +#define glGenFramebuffers glpfGenFramebuffers +#define glCheckFramebufferStatus glpfCheckFramebufferStatus +#define glFramebufferTexture1D glpfFramebufferTexture1D +#define glFramebufferTexture2D glpfFramebufferTexture2D +#define glFramebufferTexture3D glpfFramebufferTexture3D +#define glFramebufferRenderbuffer glpfFramebufferRenderbuffer +#define glGetFramebufferAttachmentParameteriv glpfGetFramebufferAttachmentParameteriv +#define glGenerateMipmap glpfGenerateMipmap +#define glBlitFramebuffer glpfBlitFramebuffer +#define glRenderbufferStorageMultisample glpfRenderbufferStorageMultisample +#define glFramebufferTextureLayer glpfFramebufferTextureLayer +#define glMapBufferRange glpfMapBufferRange +#define glFlushMappedBufferRange glpfFlushMappedBufferRange +#define glBindVertexArray glpfBindVertexArray +#define glDeleteVertexArrays glpfDeleteVertexArrays +#define glGenVertexArrays glpfGenVertexArrays +#define glIsVertexArray glpfIsVertexArray + + +/* GL_VERSION_3_1 */ + +typedef void (APIENTRY PFNGLDRAWARRAYSINSTANCED_PROC (GLenum mode, GLint first, GLsizei count, GLsizei instancecount)); +typedef void (APIENTRY PFNGLDRAWELEMENTSINSTANCED_PROC (GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount)); +typedef void (APIENTRY PFNGLTEXBUFFER_PROC (GLenum target, GLenum internalformat, GLuint buffer)); +typedef void (APIENTRY PFNGLPRIMITIVERESTARTINDEX_PROC (GLuint index)); +typedef void (APIENTRY PFNGLCOPYBUFFERSUBDATA_PROC (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)); +typedef void (APIENTRY PFNGLGETUNIFORMINDICES_PROC (GLuint program, GLsizei uniformCount, const GLchar *const* uniformNames, GLuint * uniformIndices)); +typedef void (APIENTRY PFNGLGETACTIVEUNIFORMSIV_PROC (GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETACTIVEUNIFORMNAME_PROC (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformName)); +typedef GLuint (APIENTRY PFNGLGETUNIFORMBLOCKINDEX_PROC (GLuint program, const GLchar * uniformBlockName)); +typedef void (APIENTRY PFNGLGETACTIVEUNIFORMBLOCKIV_PROC (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETACTIVEUNIFORMBLOCKNAME_PROC (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName)); +typedef void (APIENTRY PFNGLUNIFORMBLOCKBINDING_PROC (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)); + +GLAPI PFNGLDRAWARRAYSINSTANCED_PROC* glpfDrawArraysInstanced; +GLAPI PFNGLDRAWELEMENTSINSTANCED_PROC* glpfDrawElementsInstanced; +GLAPI PFNGLTEXBUFFER_PROC* glpfTexBuffer; +GLAPI PFNGLPRIMITIVERESTARTINDEX_PROC* glpfPrimitiveRestartIndex; +GLAPI PFNGLCOPYBUFFERSUBDATA_PROC* glpfCopyBufferSubData; +GLAPI PFNGLGETUNIFORMINDICES_PROC* glpfGetUniformIndices; +GLAPI PFNGLGETACTIVEUNIFORMSIV_PROC* glpfGetActiveUniformsiv; +GLAPI PFNGLGETACTIVEUNIFORMNAME_PROC* glpfGetActiveUniformName; +GLAPI PFNGLGETUNIFORMBLOCKINDEX_PROC* glpfGetUniformBlockIndex; +GLAPI PFNGLGETACTIVEUNIFORMBLOCKIV_PROC* glpfGetActiveUniformBlockiv; +GLAPI PFNGLGETACTIVEUNIFORMBLOCKNAME_PROC* glpfGetActiveUniformBlockName; +GLAPI PFNGLUNIFORMBLOCKBINDING_PROC* glpfUniformBlockBinding; + +#define glDrawArraysInstanced glpfDrawArraysInstanced +#define glDrawElementsInstanced glpfDrawElementsInstanced +#define glTexBuffer glpfTexBuffer +#define glPrimitiveRestartIndex glpfPrimitiveRestartIndex +#define glCopyBufferSubData glpfCopyBufferSubData +#define glGetUniformIndices glpfGetUniformIndices +#define glGetActiveUniformsiv glpfGetActiveUniformsiv +#define glGetActiveUniformName glpfGetActiveUniformName +#define glGetUniformBlockIndex glpfGetUniformBlockIndex +#define glGetActiveUniformBlockiv glpfGetActiveUniformBlockiv +#define glGetActiveUniformBlockName glpfGetActiveUniformBlockName +#define glUniformBlockBinding glpfUniformBlockBinding + + +/* GL_VERSION_3_2 */ + +typedef void (APIENTRY PFNGLDRAWELEMENTSBASEVERTEX_PROC (GLenum mode, GLsizei count, GLenum type, const void * indices, GLint basevertex)); +typedef void (APIENTRY PFNGLDRAWRANGEELEMENTSBASEVERTEX_PROC (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices, GLint basevertex)); +typedef void (APIENTRY PFNGLDRAWELEMENTSINSTANCEDBASEVERTEX_PROC (GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex)); +typedef void (APIENTRY PFNGLMULTIDRAWELEMENTSBASEVERTEX_PROC (GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount, const GLint * basevertex)); +typedef void (APIENTRY PFNGLPROVOKINGVERTEX_PROC (GLenum mode)); +typedef GLsync (APIENTRY PFNGLFENCESYNC_PROC (GLenum condition, GLbitfield flags)); +typedef GLboolean (APIENTRY PFNGLISSYNC_PROC (GLsync sync)); +typedef void (APIENTRY PFNGLDELETESYNC_PROC (GLsync sync)); +typedef GLenum (APIENTRY PFNGLCLIENTWAITSYNC_PROC (GLsync sync, GLbitfield flags, GLuint64 timeout)); +typedef void (APIENTRY PFNGLWAITSYNC_PROC (GLsync sync, GLbitfield flags, GLuint64 timeout)); +typedef void (APIENTRY PFNGLGETINTEGER64V_PROC (GLenum pname, GLint64 * data)); +typedef void (APIENTRY PFNGLGETSYNCIV_PROC (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values)); +typedef void (APIENTRY PFNGLGETINTEGER64I_V_PROC (GLenum target, GLuint index, GLint64 * data)); +typedef void (APIENTRY PFNGLGETBUFFERPARAMETERI64V_PROC (GLenum target, GLenum pname, GLint64 * params)); +typedef void (APIENTRY PFNGLFRAMEBUFFERTEXTURE_PROC (GLenum target, GLenum attachment, GLuint texture, GLint level)); +typedef void (APIENTRY PFNGLTEXIMAGE2DMULTISAMPLE_PROC (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations)); +typedef void (APIENTRY PFNGLTEXIMAGE3DMULTISAMPLE_PROC (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations)); +typedef void (APIENTRY PFNGLGETMULTISAMPLEFV_PROC (GLenum pname, GLuint index, GLfloat * val)); +typedef void (APIENTRY PFNGLSAMPLEMASKI_PROC (GLuint maskNumber, GLbitfield mask)); + +GLAPI PFNGLDRAWELEMENTSBASEVERTEX_PROC* glpfDrawElementsBaseVertex; +GLAPI PFNGLDRAWRANGEELEMENTSBASEVERTEX_PROC* glpfDrawRangeElementsBaseVertex; +GLAPI PFNGLDRAWELEMENTSINSTANCEDBASEVERTEX_PROC* glpfDrawElementsInstancedBaseVertex; +GLAPI PFNGLMULTIDRAWELEMENTSBASEVERTEX_PROC* glpfMultiDrawElementsBaseVertex; +GLAPI PFNGLPROVOKINGVERTEX_PROC* glpfProvokingVertex; +GLAPI PFNGLFENCESYNC_PROC* glpfFenceSync; +GLAPI PFNGLISSYNC_PROC* glpfIsSync; +GLAPI PFNGLDELETESYNC_PROC* glpfDeleteSync; +GLAPI PFNGLCLIENTWAITSYNC_PROC* glpfClientWaitSync; +GLAPI PFNGLWAITSYNC_PROC* glpfWaitSync; +GLAPI PFNGLGETINTEGER64V_PROC* glpfGetInteger64v; +GLAPI PFNGLGETSYNCIV_PROC* glpfGetSynciv; +GLAPI PFNGLGETINTEGER64I_V_PROC* glpfGetInteger64i_v; +GLAPI PFNGLGETBUFFERPARAMETERI64V_PROC* glpfGetBufferParameteri64v; +GLAPI PFNGLFRAMEBUFFERTEXTURE_PROC* glpfFramebufferTexture; +GLAPI PFNGLTEXIMAGE2DMULTISAMPLE_PROC* glpfTexImage2DMultisample; +GLAPI PFNGLTEXIMAGE3DMULTISAMPLE_PROC* glpfTexImage3DMultisample; +GLAPI PFNGLGETMULTISAMPLEFV_PROC* glpfGetMultisamplefv; +GLAPI PFNGLSAMPLEMASKI_PROC* glpfSampleMaski; + +#define glDrawElementsBaseVertex glpfDrawElementsBaseVertex +#define glDrawRangeElementsBaseVertex glpfDrawRangeElementsBaseVertex +#define glDrawElementsInstancedBaseVertex glpfDrawElementsInstancedBaseVertex +#define glMultiDrawElementsBaseVertex glpfMultiDrawElementsBaseVertex +#define glProvokingVertex glpfProvokingVertex +#define glFenceSync glpfFenceSync +#define glIsSync glpfIsSync +#define glDeleteSync glpfDeleteSync +#define glClientWaitSync glpfClientWaitSync +#define glWaitSync glpfWaitSync +#define glGetInteger64v glpfGetInteger64v +#define glGetSynciv glpfGetSynciv +#define glGetInteger64i_v glpfGetInteger64i_v +#define glGetBufferParameteri64v glpfGetBufferParameteri64v +#define glFramebufferTexture glpfFramebufferTexture +#define glTexImage2DMultisample glpfTexImage2DMultisample +#define glTexImage3DMultisample glpfTexImage3DMultisample +#define glGetMultisamplefv glpfGetMultisamplefv +#define glSampleMaski glpfSampleMaski + + +/* GL_VERSION_3_3 */ + +typedef void (APIENTRY PFNGLBINDFRAGDATALOCATIONINDEXED_PROC (GLuint program, GLuint colorNumber, GLuint index, const GLchar * name)); +typedef GLint (APIENTRY PFNGLGETFRAGDATAINDEX_PROC (GLuint program, const GLchar * name)); +typedef void (APIENTRY PFNGLGENSAMPLERS_PROC (GLsizei count, GLuint * samplers)); +typedef void (APIENTRY PFNGLDELETESAMPLERS_PROC (GLsizei count, const GLuint * samplers)); +typedef GLboolean (APIENTRY PFNGLISSAMPLER_PROC (GLuint sampler)); +typedef void (APIENTRY PFNGLBINDSAMPLER_PROC (GLuint unit, GLuint sampler)); +typedef void (APIENTRY PFNGLSAMPLERPARAMETERI_PROC (GLuint sampler, GLenum pname, GLint param)); +typedef void (APIENTRY PFNGLSAMPLERPARAMETERIV_PROC (GLuint sampler, GLenum pname, const GLint * param)); +typedef void (APIENTRY PFNGLSAMPLERPARAMETERF_PROC (GLuint sampler, GLenum pname, GLfloat param)); +typedef void (APIENTRY PFNGLSAMPLERPARAMETERFV_PROC (GLuint sampler, GLenum pname, const GLfloat * param)); +typedef void (APIENTRY PFNGLSAMPLERPARAMETERIIV_PROC (GLuint sampler, GLenum pname, const GLint * param)); +typedef void (APIENTRY PFNGLSAMPLERPARAMETERIUIV_PROC (GLuint sampler, GLenum pname, const GLuint * param)); +typedef void (APIENTRY PFNGLGETSAMPLERPARAMETERIV_PROC (GLuint sampler, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETSAMPLERPARAMETERIIV_PROC (GLuint sampler, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETSAMPLERPARAMETERFV_PROC (GLuint sampler, GLenum pname, GLfloat * params)); +typedef void (APIENTRY PFNGLGETSAMPLERPARAMETERIUIV_PROC (GLuint sampler, GLenum pname, GLuint * params)); +typedef void (APIENTRY PFNGLQUERYCOUNTER_PROC (GLuint id, GLenum target)); +typedef void (APIENTRY PFNGLGETQUERYOBJECTI64V_PROC (GLuint id, GLenum pname, GLint64 * params)); +typedef void (APIENTRY PFNGLGETQUERYOBJECTUI64V_PROC (GLuint id, GLenum pname, GLuint64 * params)); +typedef void (APIENTRY PFNGLVERTEXATTRIBDIVISOR_PROC (GLuint index, GLuint divisor)); +typedef void (APIENTRY PFNGLVERTEXATTRIBP1UI_PROC (GLuint index, GLenum type, GLboolean normalized, GLuint value)); +typedef void (APIENTRY PFNGLVERTEXATTRIBP1UIV_PROC (GLuint index, GLenum type, GLboolean normalized, const GLuint * value)); +typedef void (APIENTRY PFNGLVERTEXATTRIBP2UI_PROC (GLuint index, GLenum type, GLboolean normalized, GLuint value)); +typedef void (APIENTRY PFNGLVERTEXATTRIBP2UIV_PROC (GLuint index, GLenum type, GLboolean normalized, const GLuint * value)); +typedef void (APIENTRY PFNGLVERTEXATTRIBP3UI_PROC (GLuint index, GLenum type, GLboolean normalized, GLuint value)); +typedef void (APIENTRY PFNGLVERTEXATTRIBP3UIV_PROC (GLuint index, GLenum type, GLboolean normalized, const GLuint * value)); +typedef void (APIENTRY PFNGLVERTEXATTRIBP4UI_PROC (GLuint index, GLenum type, GLboolean normalized, GLuint value)); +typedef void (APIENTRY PFNGLVERTEXATTRIBP4UIV_PROC (GLuint index, GLenum type, GLboolean normalized, const GLuint * value)); + +GLAPI PFNGLBINDFRAGDATALOCATIONINDEXED_PROC* glpfBindFragDataLocationIndexed; +GLAPI PFNGLGETFRAGDATAINDEX_PROC* glpfGetFragDataIndex; +GLAPI PFNGLGENSAMPLERS_PROC* glpfGenSamplers; +GLAPI PFNGLDELETESAMPLERS_PROC* glpfDeleteSamplers; +GLAPI PFNGLISSAMPLER_PROC* glpfIsSampler; +GLAPI PFNGLBINDSAMPLER_PROC* glpfBindSampler; +GLAPI PFNGLSAMPLERPARAMETERI_PROC* glpfSamplerParameteri; +GLAPI PFNGLSAMPLERPARAMETERIV_PROC* glpfSamplerParameteriv; +GLAPI PFNGLSAMPLERPARAMETERF_PROC* glpfSamplerParameterf; +GLAPI PFNGLSAMPLERPARAMETERFV_PROC* glpfSamplerParameterfv; +GLAPI PFNGLSAMPLERPARAMETERIIV_PROC* glpfSamplerParameterIiv; +GLAPI PFNGLSAMPLERPARAMETERIUIV_PROC* glpfSamplerParameterIuiv; +GLAPI PFNGLGETSAMPLERPARAMETERIV_PROC* glpfGetSamplerParameteriv; +GLAPI PFNGLGETSAMPLERPARAMETERIIV_PROC* glpfGetSamplerParameterIiv; +GLAPI PFNGLGETSAMPLERPARAMETERFV_PROC* glpfGetSamplerParameterfv; +GLAPI PFNGLGETSAMPLERPARAMETERIUIV_PROC* glpfGetSamplerParameterIuiv; +GLAPI PFNGLQUERYCOUNTER_PROC* glpfQueryCounter; +GLAPI PFNGLGETQUERYOBJECTI64V_PROC* glpfGetQueryObjecti64v; +GLAPI PFNGLGETQUERYOBJECTUI64V_PROC* glpfGetQueryObjectui64v; +GLAPI PFNGLVERTEXATTRIBDIVISOR_PROC* glpfVertexAttribDivisor; +GLAPI PFNGLVERTEXATTRIBP1UI_PROC* glpfVertexAttribP1ui; +GLAPI PFNGLVERTEXATTRIBP1UIV_PROC* glpfVertexAttribP1uiv; +GLAPI PFNGLVERTEXATTRIBP2UI_PROC* glpfVertexAttribP2ui; +GLAPI PFNGLVERTEXATTRIBP2UIV_PROC* glpfVertexAttribP2uiv; +GLAPI PFNGLVERTEXATTRIBP3UI_PROC* glpfVertexAttribP3ui; +GLAPI PFNGLVERTEXATTRIBP3UIV_PROC* glpfVertexAttribP3uiv; +GLAPI PFNGLVERTEXATTRIBP4UI_PROC* glpfVertexAttribP4ui; +GLAPI PFNGLVERTEXATTRIBP4UIV_PROC* glpfVertexAttribP4uiv; + +#define glBindFragDataLocationIndexed glpfBindFragDataLocationIndexed +#define glGetFragDataIndex glpfGetFragDataIndex +#define glGenSamplers glpfGenSamplers +#define glDeleteSamplers glpfDeleteSamplers +#define glIsSampler glpfIsSampler +#define glBindSampler glpfBindSampler +#define glSamplerParameteri glpfSamplerParameteri +#define glSamplerParameteriv glpfSamplerParameteriv +#define glSamplerParameterf glpfSamplerParameterf +#define glSamplerParameterfv glpfSamplerParameterfv +#define glSamplerParameterIiv glpfSamplerParameterIiv +#define glSamplerParameterIuiv glpfSamplerParameterIuiv +#define glGetSamplerParameteriv glpfGetSamplerParameteriv +#define glGetSamplerParameterIiv glpfGetSamplerParameterIiv +#define glGetSamplerParameterfv glpfGetSamplerParameterfv +#define glGetSamplerParameterIuiv glpfGetSamplerParameterIuiv +#define glQueryCounter glpfQueryCounter +#define glGetQueryObjecti64v glpfGetQueryObjecti64v +#define glGetQueryObjectui64v glpfGetQueryObjectui64v +#define glVertexAttribDivisor glpfVertexAttribDivisor +#define glVertexAttribP1ui glpfVertexAttribP1ui +#define glVertexAttribP1uiv glpfVertexAttribP1uiv +#define glVertexAttribP2ui glpfVertexAttribP2ui +#define glVertexAttribP2uiv glpfVertexAttribP2uiv +#define glVertexAttribP3ui glpfVertexAttribP3ui +#define glVertexAttribP3uiv glpfVertexAttribP3uiv +#define glVertexAttribP4ui glpfVertexAttribP4ui +#define glVertexAttribP4uiv glpfVertexAttribP4uiv + + +/* GL_ARB_debug_output */ + +typedef void (APIENTRY PFNGLDEBUGMESSAGECONTROLARB_PROC (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled)); +typedef void (APIENTRY PFNGLDEBUGMESSAGEINSERTARB_PROC (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf)); +typedef void (APIENTRY PFNGLDEBUGMESSAGECALLBACKARB_PROC (GLDEBUGPROCARB callback, const void * userParam)); +typedef GLuint (APIENTRY PFNGLGETDEBUGMESSAGELOGARB_PROC (GLuint count, GLsizei bufSize, GLenum * sources, GLenum * types, GLuint * ids, GLenum * severities, GLsizei * lengths, GLchar * messageLog)); + +GLAPI PFNGLDEBUGMESSAGECONTROLARB_PROC* glpfDebugMessageControlARB; +GLAPI PFNGLDEBUGMESSAGEINSERTARB_PROC* glpfDebugMessageInsertARB; +GLAPI PFNGLDEBUGMESSAGECALLBACKARB_PROC* glpfDebugMessageCallbackARB; +GLAPI PFNGLGETDEBUGMESSAGELOGARB_PROC* glpfGetDebugMessageLogARB; + +#define glDebugMessageControlARB glpfDebugMessageControlARB +#define glDebugMessageInsertARB glpfDebugMessageInsertARB +#define glDebugMessageCallbackARB glpfDebugMessageCallbackARB +#define glGetDebugMessageLogARB glpfGetDebugMessageLogARB + + +/* --------------------------- CATEGORY DEFINES ------------------------------ */ + +#define GL_VERSION_1_0 +#define GL_VERSION_1_1 +#define GL_VERSION_1_2 +#define GL_VERSION_1_3 +#define GL_VERSION_1_4 +#define GL_VERSION_1_5 +#define GL_VERSION_2_0 +#define GL_VERSION_2_1 +#define GL_VERSION_3_0 +#define GL_VERSION_3_1 +#define GL_VERSION_3_2 +#define GL_VERSION_3_3 +#define GL_ARB_debug_output + +void ExtGLLoadFunctions(); + +#ifdef __cplusplus +} +#endif + +inline const char* translateError(GLenum glError) { +#define GL_ERROR_TRANSLATE(e) case e: return #e; + switch (glError) { + /* openGL errors */ + GL_ERROR_TRANSLATE(GL_INVALID_ENUM) + GL_ERROR_TRANSLATE(GL_INVALID_VALUE) + GL_ERROR_TRANSLATE(GL_INVALID_OPERATION) + GL_ERROR_TRANSLATE(GL_OUT_OF_MEMORY) + default: + return "UNKNOWN"; + } +#undef GL_ERROR_TRANSLATE +} + +inline int OpenGLStateHandlerCheckError(const char *file, int line, const char *function) { + int ret = 0; + /* check gl errors (can return multiple errors) */ + for (;;) { + const GLenum glError = glGetError(); + if (glError == GL_NO_ERROR) + break; + + Log::error("openGL err: %s (%i): %s %s => %i", file, line, function, translateError(glError), glError); + ret++; + } + return ret; +} + +#define GL_checkError() OpenGLStateHandlerCheckError(__FILE__, __LINE__, __PRETTY_FUNCTION__) diff --git a/src/modules/video/GLMeshData.h b/src/modules/video/GLMeshData.h new file mode 100644 index 000000000..ae96a526f --- /dev/null +++ b/src/modules/video/GLMeshData.h @@ -0,0 +1,21 @@ +#pragma once + +#include "GLFunc.h" +#include + +namespace video { + +struct GLMeshData { + GLuint noOfIndices = 0; + GLenum indexType = 0; + GLuint indexBuffer = 0; + GLuint vertexBuffer = 0; + GLuint vertexArrayObject = 0; + GLuint baseVertex = 0u; + GLuint baseIndex = 0u; + GLuint materialIndex = 0u; + glm::ivec2 translation; + float scale = 1.0f; +}; + +} diff --git a/src/modules/video/Image.cpp b/src/modules/video/Image.cpp new file mode 100644 index 000000000..7e1dbafe0 --- /dev/null +++ b/src/modules/video/Image.cpp @@ -0,0 +1,47 @@ +#include "Image.h" +#include "core/Log.h" +#include "core/App.h" +#include "io/Filesystem.h" +#include + +namespace video { + +Image::Image(const std::string& filename) : + io::IOResource(), _filename(filename), _width(-1), _height(-1), _depth(-1), _data(nullptr) { +} + +Image::~Image() { + if (_data) { + stbi_image_free(_data); + } +} + +void Image::load(const io::FilePtr& file) { + uint8_t* buffer; + const int length = file->read((void**) &buffer); + std::unique_ptr p(buffer); + if (!buffer || length <= 0) { + _state = io::IOSTATE_FAILED; + return; + } + _data = stbi_load_from_memory(buffer, length, &_width, &_height, &_depth, STBI_rgb_alpha); + if (_data == nullptr) + _state = io::IOSTATE_FAILED; + else + _state = io::IOSTATE_LOADED; +} + +bool Image::loadSync() { + loadAsync(); + while (isLoading()) { + } + return isLoaded(); +} + +void Image::loadAsync() { + // TODO: push into io thread + const io::FilePtr& file = core::App::getInstance()->filesystem()->open(_filename); + load(file); +} + +} diff --git a/src/modules/video/Image.h b/src/modules/video/Image.h new file mode 100644 index 000000000..e28a2cfbe --- /dev/null +++ b/src/modules/video/Image.h @@ -0,0 +1,45 @@ +#pragma once + +#include "io/IOResource.h" +#include "io/File.h" +#include + +namespace video { + +class Image: public io::IOResource { +private: + std::string _filename; + int _width; + int _height; + int _depth; + uint8_t* _data; + + void load(const io::FilePtr& file); +public: + Image(const std::string& filename); + ~Image(); + + void loadAsync(); + + bool loadSync(); + + const uint8_t* data() const { + return _data; + } + + inline int width() const { + return _width; + } + + inline int height() const { + return _height; + } + + inline bool hasAlpha() const { + return true; + } +}; + +typedef std::shared_ptr ImagePtr; + +} diff --git a/src/modules/video/Mesh.cpp b/src/modules/video/Mesh.cpp new file mode 100644 index 000000000..463b10595 --- /dev/null +++ b/src/modules/video/Mesh.cpp @@ -0,0 +1,183 @@ +#include "Mesh.h" +#include "GLFunc.h" +#include "core/Common.h" +#include "core/Log.h" + +namespace video { + +namespace { +const aiVector3D VECZERO(0.0f, 0.0f, 0.0f); +} + +Mesh::Mesh() : + io::IOResource(), _vertexArrayObject(0u), _posBuffer(0u), _uvBuffer(0u), _normalBuffer(0u), _indexBuffer(0u) { +} + +Mesh::~Mesh() { + _textures.clear(); + // destroy all the 4 buffers at once + glDeleteBuffers(4, &_posBuffer); + glDeleteVertexArrays(1, &_vertexArrayObject); +} + +bool Mesh::loadMesh(const std::string& filename) { + Assimp::Importer importer; +#if 0 + // TODO: implement custom io handler to support meshes that are split over several files (like obj) + class MeshIOSystem : public Assimp::IOSystem { + }; + MeshIOSystem iosystem; + importer.SetIOHandler(&iosystem); +#endif + const aiScene* scene = importer.ReadFile(filename, aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs | aiProcess_FindDegenerates); + if (scene == nullptr) { + Log::error("Error parsing '%s': '%s'\n", filename.c_str(), importer.GetErrorString()); + _state = io::IOSTATE_FAILED; + return false; + } + + _meshData.resize(scene->mNumMeshes); + + uint32_t numIndices = 0u; + uint32_t numVertices = 0u; + + for (uint32_t i = 0; i < _meshData.size(); ++i) { + const aiMesh* mesh = scene->mMeshes[i]; + GLMeshData& meshData = _meshData[i]; + meshData.materialIndex = mesh->mMaterialIndex; + meshData.noOfIndices = mesh->mNumFaces * 3; + meshData.baseVertex = numVertices; + meshData.baseIndex = numIndices; + + numVertices += mesh->mNumVertices; + numIndices += meshData.noOfIndices; + } + + _positions.reserve(numVertices); + _normals.reserve(numVertices); + _texCoords.reserve(numVertices); + _indices.reserve(numIndices); + + for (uint32_t i = 0; i < _meshData.size(); i++) { + const aiMesh* mesh = scene->mMeshes[i]; + for (uint32_t i = 0; i < mesh->mNumFaces; ++i) { + const aiFace& face = mesh->mFaces[i]; + core_assert(face.mNumIndices == 3); + _indices.push_back(face.mIndices[0]); + _indices.push_back(face.mIndices[1]); + _indices.push_back(face.mIndices[2]); + } + + for (uint32_t i = 0; i < mesh->mNumVertices; ++i) { + const aiVector3D* pos = &mesh->mVertices[i]; + const aiVector3D* normal = &mesh->mNormals[i]; + const aiVector3D* texCoord = mesh->HasTextureCoords(0) ? &mesh->mTextureCoords[0][i] : &VECZERO; + + _positions.push_back(glm::vec3(pos->x, pos->y, pos->z)); + _normals.push_back(glm::vec3(normal->x, normal->y, normal->z)); + _texCoords.push_back(glm::vec2(texCoord->x, texCoord->y)); + } + } + + loadTextures(scene, filename); + _state = io::IOSTATE_LOADED; + return true; +} + +bool Mesh::initMesh(const ShaderPtr& shader) { + if (_shader) + return true; + if (!shader) + return false; + + if (_state != io::IOSTATE_LOADED) + return false; + + _shader = shader; + for (const TexturePtr& t : _textures) { + if (!t) + continue; + t->load(); + } + + glGenVertexArrays(1, &_vertexArrayObject); + // generate all the 4 needed buffers at once + glGenBuffers(4, &_posBuffer); + + glBindVertexArray(_vertexArrayObject); + + glBindBuffer(GL_ARRAY_BUFFER, _posBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(_positions[0]) * _positions.size(), &_positions[0], GL_STATIC_DRAW); + const int locPos = _shader->enableVertexAttribute("a_pos"); + core_assert(locPos >= 0); + glVertexAttribPointer(locPos, 3, GL_FLOAT, GL_FALSE, 0, 0); + + glBindBuffer(GL_ARRAY_BUFFER, _uvBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(_texCoords[0]) * _texCoords.size(), &_texCoords[0], GL_STATIC_DRAW); + const int locTexCoords = _shader->enableVertexAttribute("a_texcoords"); + core_assert(locTexCoords >= 0); + glVertexAttribPointer(locTexCoords, 2, GL_FLOAT, GL_FALSE, 0, 0); + + glBindBuffer(GL_ARRAY_BUFFER, _normalBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(_normals[0]) * _normals.size(), &_normals[0], GL_STATIC_DRAW); + const int locNorm = _shader->enableVertexAttribute("a_norm"); + core_assert(locNorm >= 0); + glVertexAttribPointer(locNorm, 3, GL_FLOAT, GL_FALSE, 0, 0); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(_indices[0]) * _indices.size(), &_indices[0], GL_STATIC_DRAW); + + glBindVertexArray(0); + + return GL_checkError() == 0; +} + +void Mesh::loadTextures(const aiScene* scene, const std::string& filename) { + std::string::size_type slashIndex = filename.find_last_of("/"); + std::string dir; + + if (slashIndex == std::string::npos) { + dir = "."; + } else if (slashIndex == 0) { + dir = "/"; + } else { + dir = filename.substr(0, slashIndex); + } + + _textures.resize(scene->mNumMaterials); + for (uint32_t i = 0; i < scene->mNumMaterials; i++) { + const aiMaterial* material = scene->mMaterials[i]; + const aiTextureType texType = aiTextureType_DIFFUSE; + if (material->GetTextureCount(texType) <= 0) + continue; + + aiString path; + if (!material->GetTexture(texType, 0, &path, nullptr, nullptr, nullptr, nullptr, nullptr) == AI_SUCCESS) + continue; + + std::string p(path.data); + + if (p.substr(0, 2) == ".\\") { + p = p.substr(2, p.size() - 2); + } + + const std::string fullPath = dir + "/" + p; + _textures[i] = TexturePtr(new Texture(fullPath)); + } +} + +void Mesh::render() { + glBindVertexArray(_vertexArrayObject); + uint32_t lastMatIdx = 0u; + for (const GLMeshData& mesh : _meshData) { + const uint32_t matIdx = mesh.materialIndex; + core_assert(matIdx < _textures.size()); + if (/*lastMatIdx != matIdx &&*/ _textures[matIdx]) { + _textures[matIdx]->bind(); + lastMatIdx = matIdx; + } + glDrawElementsBaseVertex(GL_TRIANGLES, mesh.noOfIndices, GL_UNSIGNED_INT, GL_OFFSET(sizeof(uint32_t) * mesh.baseIndex), mesh.baseVertex); + } +} + +} diff --git a/src/modules/video/Mesh.h b/src/modules/video/Mesh.h new file mode 100644 index 000000000..2bdebb17e --- /dev/null +++ b/src/modules/video/Mesh.h @@ -0,0 +1,50 @@ +#pragma once + +#include "io/IOResource.h" +#include "video/Shader.h" +#include "video/Texture.h" +#include "video/GLMeshData.h" +#include +#include +#include +#include +#include + +namespace video { + +class Mesh : public io::IOResource { +private: + typedef std::vector Indices; + typedef std::vector TexCoords; + typedef std::vector Vertices; + + void loadTextures(const aiScene* scene, const std::string& filename); + + GLuint _vertexArrayObject; + // 4 buffers - don't change the order - don't add anything in between these four buffers + GLuint _posBuffer; + GLuint _uvBuffer; + GLuint _normalBuffer; + GLuint _indexBuffer; + + std::vector _meshData; + std::vector _textures; + + Vertices _positions; + Vertices _normals; + TexCoords _texCoords; + Indices _indices; + + ShaderPtr _shader; +public: + Mesh(); + ~Mesh(); + + bool loadMesh(const std::string& filename); + bool initMesh(const ShaderPtr& shader); + void render(); +}; + +typedef std::shared_ptr MeshPtr; + +} diff --git a/src/modules/video/MeshPool.cpp b/src/modules/video/MeshPool.cpp new file mode 100644 index 000000000..a041746ec --- /dev/null +++ b/src/modules/video/MeshPool.cpp @@ -0,0 +1,38 @@ +#include "MeshPool.h" +#include "io/Filesystem.h" +#include "core/App.h" + +namespace video { + +static const char* supportedFormats[] = { "dae", "fbx", nullptr }; + +MeshPool::MeshPool() : + _threadPool(2) { +} + +MeshPool::~MeshPool() { +} + +std::string MeshPool::getName(const std::string& id) const { + for (const char **format = supportedFormats; *format != nullptr; format++) { + const std::string name = "mesh/" + id + "." + *format; + if (core::App::getInstance()->filesystem()->open(name)->exists()) + return name; + } + + return id; +} + +MeshPtr MeshPool::getMesh(const std::string& id) { + const std::string name = getName(id); + auto i = _meshes.find(name); + if (i != _meshes.end()) + return i->second; + + const MeshPtr mesh(new Mesh()); + _threadPool.push([=]() {mesh->loadMesh(name);}); + _meshes[name] = mesh; + return mesh; +} + +} diff --git a/src/modules/video/MeshPool.h b/src/modules/video/MeshPool.h new file mode 100644 index 000000000..dc68f4c76 --- /dev/null +++ b/src/modules/video/MeshPool.h @@ -0,0 +1,26 @@ +#pragma once + +#include "Mesh.h" +#include "core/ThreadPool.h" +#include +#include + +namespace video { + +class MeshPool { +private: + typedef std::unordered_map Meshes; + Meshes _meshes; + core::ThreadPool _threadPool; + + std::string getName(const std::string& id) const; +public: + MeshPool(); + ~MeshPool(); + + MeshPtr getMesh(const std::string& name); +}; + +typedef std::shared_ptr MeshPoolPtr; + +} diff --git a/src/modules/video/Shader.cpp b/src/modules/video/Shader.cpp new file mode 100644 index 000000000..c700397b9 --- /dev/null +++ b/src/modules/video/Shader.cpp @@ -0,0 +1,283 @@ +#include "Shader.h" + +#include "core/App.h" +#include "io/Filesystem.h" + +#ifndef MAX_SHADER_VAR_NAME +#define MAX_SHADER_VAR_NAME 128 +#endif + +#ifndef VERTEX_POSTFIX +#define VERTEX_POSTFIX ".vert" +#endif + +#ifndef FRAGMENT_POSTFIX +#define FRAGMENT_POSTFIX ".frag" +#endif + +#ifdef _DEBUG +#define checkError() CheckErrorState(__FILE__, __LINE__, __PRETTY_FUNCTION__, _name.c_str()); +#else +#define checkError() +#endif + +namespace video { + +Shader::Shader() : + _program(0), _initialized(false), _active(false), _time(0) { + for (int i = 0; i < SHADER_MAX; ++i) { + _shader[i] = 0; + } +} + +Shader::~Shader() { + for (int i = 0; i < SHADER_MAX; ++i) { + glDeleteShader(_shader[i]); + } + glDeleteProgram(_program); +} + +bool Shader::load(const std::string& name, const std::string& buffer, ShaderType shaderType) { + _name = name; + const std::string& source = getSource(shaderType, buffer); + const GLenum glType = shaderType == SHADER_VERTEX ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER; + checkError(); + + _shader[shaderType] = glCreateShader(glType); + const char *s = source.c_str(); + glShaderSource(_shader[shaderType], 1, (const GLchar**) &s, nullptr); + glCompileShader(_shader[shaderType]); + + GLint status; + glGetShaderiv(_shader[shaderType], GL_COMPILE_STATUS, &status); + if (status != GL_TRUE || glGetError() != GL_NO_ERROR) { + GLint infoLogLength; + glGetShaderiv(_shader[shaderType], GL_INFO_LOG_LENGTH, &infoLogLength); + + std::unique_ptr strInfoLog(new GLchar[infoLogLength + 1]); + glGetShaderInfoLog(_shader[shaderType], infoLogLength, nullptr, strInfoLog.get()); + const std::string errorLog(strInfoLog.get(), static_cast(infoLogLength)); + + const char *strShaderType; + switch (glType) { + case GL_VERTEX_SHADER: + strShaderType = "vertex"; + break; + case GL_FRAGMENT_SHADER: + strShaderType = "fragment"; + break; + default: + strShaderType = "unknown"; + break; + } + + Log::error("compile failure in %s (type: %s) shader:\n%s", name.c_str(), strShaderType, errorLog.c_str()); + return false; + } + + return true; +} + +bool Shader::loadFromFile(const std::string& filename, ShaderType shaderType) { + const std::string& buffer = core::App::getInstance()->filesystem()->load(filename); + if (buffer.empty()) { + Log::error("could not load shader %s", filename.c_str()); + return false; + } + + return load(filename, buffer, shaderType); +} + +/** + * @brief Loads a vertex and fragment shader for the given base filename. + * + * The filename is hand over to your @c Context implementation with the appropriate filename postfixes + * + * @see VERTEX_POSTFIX + * @see FRAGMENT_POSTFIX + */ +bool Shader::loadProgram(const std::string& filename) { + const bool vertex = loadFromFile(filename + VERTEX_POSTFIX, SHADER_VERTEX); + if (!vertex) + return false; + + const bool fragment = loadFromFile(filename + FRAGMENT_POSTFIX, SHADER_FRAGMENT); + if (!fragment) + return false; + + return init(); +} + +bool Shader::init() { + createProgramFromShaders(); + fetchAttributes(); + fetchUniforms(); + const bool success = _program != 0; + _initialized = success; + return success; +} + +GLuint Shader::getShader(ShaderType shaderType) const { + return _shader[shaderType]; +} + +void Shader::update(uint32_t deltaTime) { + _time += deltaTime; +} + +bool Shader::activate() const { + glUseProgram(_program); + checkError(); + _active = true; + return _active; +} + +bool Shader::deactivate() const { + if (!_active) { + return false; + } + + glUseProgram(0); + checkError(); + _active = false; + _time = 0; + return _active; +} + +int Shader::getAttributeLocation(const std::string& name) const { + ShaderVariables::const_iterator i = _attributes.find(name); + if (i == _attributes.end()) { + Log::error("can't find attribute %s in shader %s", name.c_str(), _name.c_str()); + return -1; + } + return i->second; +} + +int Shader::getUniformLocation(const std::string& name) const { + ShaderVariables::const_iterator i = _uniforms.find(name); + if (i == _uniforms.end()) { + Log::error("can't find uniform %s in shader %s", name.c_str(), _name.c_str()); + return -1; + } + return i->second; +} + +int Shader::fetchUniforms() { + char name[MAX_SHADER_VAR_NAME]; + int numUniforms = 0; + glGetProgramiv(_program, GL_ACTIVE_UNIFORMS, &numUniforms); + checkError(); + + _uniforms.clear(); + for (int i = 0; i < numUniforms; i++) { + GLsizei length; + GLint size; + GLenum type; + glGetActiveUniform(_program, i, MAX_SHADER_VAR_NAME - 1, &length, &size, &type, name); + const int location = glGetUniformLocation(_program, name); + _uniforms[name] = location; + Log::debug("uniform location for %s is %i (shader %s)", name, location, _name.c_str()); + } + return numUniforms; +} + +int Shader::fetchAttributes() { + char name[MAX_SHADER_VAR_NAME]; + int numAttributes = 0; + glGetProgramiv(_program, GL_ACTIVE_ATTRIBUTES, &numAttributes); + checkError(); + + _attributes.clear(); + for (int i = 0; i < numAttributes; i++) { + GLsizei length; + GLint size; + GLenum type; + glGetActiveAttrib(_program, i, MAX_SHADER_VAR_NAME - 1, &length, &size, &type, name); + const int location = glGetAttribLocation(_program, name); + _attributes[name] = location; + Log::debug("attribute location for %s is %i (shader %s)", name, location, _name.c_str()); + } + return numAttributes; +} + +std::string Shader::getSource(ShaderType shaderType, const std::string& buffer) const { + std::string src; +#ifdef GL_ES_VERSION_2_0 + src.append("#version 300\n"); +#else + src.append("#version 130\n"); +#endif + + std::string append(buffer); + + const std::string include = "#include"; + int index = 0; + for (std::string::iterator i = append.begin(); i != append.end(); ++i, ++index) { + const char *c = &append[index]; + if (*c != '#') { + src.append(c, 1); + continue; + } + if (::strncmp(include.c_str(), c, include.length())) { + src.append(c, 1); + continue; + } + for (; i != append.end(); ++i, ++index) { + const char *cStart = &append[index]; + if (*cStart != '"') + continue; + + ++index; + ++i; + for (; i != append.end(); ++i, ++index) { + const char *cEnd = &append[index]; + if (*cEnd != '"') + continue; + + const std::string includeFile(cStart + 1, cEnd); + const std::string& includeBuffer = core::App::getInstance()->filesystem()->load(includeFile); + if (!includeBuffer.empty()) { + Log::error("could not load shader include %s (shader %s)", includeFile.c_str(), _name.c_str()); + break; + } + src.append(includeBuffer); + break; + } + break; + } + } + + return src; +} + +void Shader::createProgramFromShaders() { + checkError(); + _program = glCreateProgram(); + checkError(); + + const GLuint vert = _shader[SHADER_VERTEX]; + const GLuint frag = _shader[SHADER_FRAGMENT]; + + glAttachShader(_program, vert); + glAttachShader(_program, frag); + checkError(); + + glLinkProgram(_program); + GLint status; + glGetProgramiv(_program, GL_LINK_STATUS, &status); + checkError(); + if (status == GL_TRUE) + return; + GLint infoLogLength; + glGetProgramiv(_program, GL_INFO_LOG_LENGTH, &infoLogLength); + + GLchar* strInfoLog = new GLchar[infoLogLength + 1]; + glGetProgramInfoLog(_program, infoLogLength, nullptr, strInfoLog); + strInfoLog[infoLogLength] = '\0'; + Log::error("linker failure: %s", strInfoLog); + glDeleteProgram(_program); + _program = 0; + delete[] strInfoLog; +} + +} diff --git a/src/modules/video/Shader.h b/src/modules/video/Shader.h new file mode 100644 index 000000000..a580bc456 --- /dev/null +++ b/src/modules/video/Shader.h @@ -0,0 +1,424 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include "GLFunc.h" +#include "core/Log.h" + +namespace video { + +class CheckErrorState { +protected: + const char* _file; + const int _line; + const char* _function; + const char* _shader; + + inline const char* translateError(GLenum glError) const { +#define GL_ERROR_TRANSLATE(e) case e: return #e; + switch (glError) { + GL_ERROR_TRANSLATE(GL_INVALID_ENUM) + GL_ERROR_TRANSLATE(GL_INVALID_VALUE) + GL_ERROR_TRANSLATE(GL_INVALID_OPERATION) + GL_ERROR_TRANSLATE(GL_OUT_OF_MEMORY) +#ifdef GL_STACK_OVERFLOW + GL_ERROR_TRANSLATE(GL_STACK_OVERFLOW) +#endif +#ifdef GL_STACK_UNDERFLOW + GL_ERROR_TRANSLATE(GL_STACK_UNDERFLOW) +#endif + default: + return "UNKNOWN"; + } +#undef GL_ERROR_TRANSLATE + } + +public: + CheckErrorState(const char *file, int line, const char *function, const char* shader) : + _file(file), _line(line), _function(function), _shader(shader) { + } + + ~CheckErrorState() { + for (;;) { + const GLenum glError = glGetError(); + if (glError == GL_NO_ERROR) + break; + Log::error("openGL err: %s (%i): %s %s => %i (%s)", _file, _line, _function, translateError(glError), glError, _shader); + } + } +}; + +#ifdef _DEBUG +#define checkError() CheckErrorState(__FILE__, __LINE__, __PRETTY_FUNCTION__, _name.c_str()); +#else +#define checkError() +#endif + +enum ShaderType { + SHADER_VERTEX, SHADER_FRAGMENT, + + SHADER_MAX +}; + +class Shader { +protected: + GLuint _shader[SHADER_MAX]; + GLuint _program; + bool _initialized; + mutable bool _active; + + typedef std::unordered_map ShaderVariables; + ShaderVariables _uniforms; + ShaderVariables _attributes; + + mutable uint32_t _time; + + std::string _name; + + int fetchUniforms(); + + int fetchAttributes(); + + std::string getSource(ShaderType shaderType, const std::string& buffer) const; + + void createProgramFromShaders(); + +public: + Shader(); + + virtual ~Shader(); + + bool load(const std::string& name, const std::string& buffer, ShaderType shaderType); + + /** + * If the shaders were loaded manually via @c ::load, then you have to initialize the shader manually, too + */ + bool init(); + + bool loadFromFile(const std::string& filename, ShaderType shaderType); + + /** + * @brief Loads a vertex and fragment shader for the given base filename. + * + * The filename is hand over to your @c Context implementation with the appropriate filename postfixes + * + * @see VERTEX_POSTFIX + * @see FRAGMENT_POSTFIX + */ + bool loadProgram(const std::string& filename); + + /** + * @brief Returns the raw shader handle + */ + GLuint getShader(ShaderType shaderType) const; + + /** + * @brief Ticks the shader + */ + virtual void update(uint32_t deltaTime); + + /** + * @brief Bind the shader program + * + * @return @c true if is is useable now, @c false if not + * + * @see + */ + virtual bool activate() const; + + virtual bool deactivate() const; + + int getAttributeLocation(const std::string& name) const; + + int getUniformLocation(const std::string& name) const; + + void setUniformi(const std::string& name, int value) const; + void setUniformi(int location, int value) const; + void setUniformi(const std::string& name, int value1, int value2) const; + void setUniformi(int location, int value1, int value2) const; + void setUniformi(const std::string& name, int value1, int value2, int value3) const; + void setUniformi(int location, int value1, int value2, int value3) const; + void setUniformi(const std::string& name, int value1, int value2, int value3, int value4) const; + void setUniformi(int location, int value1, int value2, int value3, int value4) const; + void setUniformf(const std::string& name, float value) const; + void setUniformf(int location, float value) const; + void setUniformf(const std::string& name, float value1, float value2) const; + void setUniformf(int location, float value1, float value2) const; + void setUniformf(const std::string& name, float value1, float value2, float value3) const; + void setUniformf(int location, float value1, float value2, float value3) const; + void setUniformf(const std::string& name, float value1, float value2, float value3, float value4) const; + void setUniformf(int location, float value1, float value2, float value3, float value4) const; + void setUniform1fv(const std::string& name, const float* values, int length) const; + void setUniform1fv(int location, const float* values, int length) const; + void setUniform2fv(const std::string& name, const float* values, int length) const; + void setUniform2fv(int location, const float* values, int length) const; + void setUniform3fv(const std::string& name, const float* values, int length) const; + void setUniformVec3(const std::string& name, const glm::vec3& value) const; + void setUniform3fv(int location, const float* values, int length) const; + void setUniform4fv(const std::string& name, const float* values, int length) const; + void setUniform4fv(int location, const float* values, int length) const; + void setUniformMatrix(const std::string& name, const glm::mat4& matrix, bool transpose = false) const; + void setUniformMatrix(int location, const glm::mat4& matrix, bool transpose = false) const; + void setUniformMatrix(const std::string& name, const glm::mat3& matrix, bool transpose = false) const; + void setUniformMatrix(int location, const glm::mat3& matrix, bool transpose = false) const; + void setUniformf(const std::string& name, const glm::vec2& values) const; + void setUniformf(int location, const glm::vec2& values) const; + void setUniformf(const std::string& name, const glm::vec3& values) const; + void setUniformf(int location, const glm::vec3& values) const; + void setUniformf(const std::string& name, const glm::vec4& values) const; + void setUniformf(int location, const glm::vec4& values) const; + void setVertexAttribute(const std::string& name, int size, int type, bool normalize, int stride, void* buffer) const; + void setVertexAttribute(int location, int size, int type, bool normalize, int stride, void* buffer) const; + void setAttributef(const std::string& name, float value1, float value2, float value3, float value4) const; + void disableVertexAttribute(const std::string& name) const; + void disableVertexAttribute(int location) const; + int enableVertexAttribute(const std::string& name) const; + void enableVertexAttribute(int location) const; + bool hasAttribute(const std::string& name) const; + bool hasUniform(const std::string& name) const; +}; + +inline void Shader::setUniformi(const std::string& name, int value) const { + const int location = getUniformLocation(name); + setUniformi(location, value); +} + +inline void Shader::setUniformi(int location, int value) const { + glUniform1i(location, value); + checkError(); +} + +inline void Shader::setUniformi(const std::string& name, int value1, int value2) const { + const int location = getUniformLocation(name); + setUniformi(location, value1, value2); +} + +inline void Shader::setUniformi(int location, int value1, int value2) const { + glUniform2i(location, value1, value2); + checkError(); +} + +inline void Shader::setUniformi(const std::string& name, int value1, int value2, int value3) const { + const int location = getUniformLocation(name); + setUniformi(location, value1, value2, value3); +} + +inline void Shader::setUniformi(int location, int value1, int value2, int value3) const { + glUniform3i(location, value1, value2, value3); + checkError(); +} + +inline void Shader::setUniformi(const std::string& name, int value1, int value2, int value3, int value4) const { + const int location = getUniformLocation(name); + setUniformi(location, value1, value2, value3, value4); +} + +inline void Shader::setUniformi(int location, int value1, int value2, int value3, int value4) const { + glUniform4i(location, value1, value2, value3, value4); + checkError(); +} + +inline void Shader::setUniformf(const std::string& name, float value) const { + const int location = getUniformLocation(name); + setUniformf(location, value); +} + +inline void Shader::setUniformf(int location, float value) const { + glUniform1f(location, value); + checkError(); +} + +inline void Shader::setUniformf(const std::string& name, float value1, float value2) const { + const int location = getUniformLocation(name); + setUniformf(location, value1, value2); +} + +inline void Shader::setUniformf(int location, float value1, float value2) const { + glUniform2f(location, value1, value2); + checkError(); +} + +inline void Shader::setUniformf(const std::string& name, float value1, float value2, float value3) const { + const int location = getUniformLocation(name); + setUniformf(location, value1, value2, value3); +} + +inline void Shader::setUniformf(int location, float value1, float value2, float value3) const { + glUniform3f(location, value1, value2, value3); + checkError(); +} + +inline void Shader::setUniformf(const std::string& name, float value1, float value2, float value3, float value4) const { + const int location = getUniformLocation(name); + setUniformf(location, value1, value2, value3, value4); +} + +inline void Shader::setUniformf(int location, float value1, float value2, float value3, float value4) const { + glUniform4f(location, value1, value2, value3, value4); + checkError(); +} + +inline void Shader::setUniform1fv(const std::string& name, const float* values, int length) const { + const int location = getUniformLocation(name); + setUniform1fv(location, values, length); +} + +inline void Shader::setUniform1fv(int location, const float* values, int length) const { + glUniform1fv(location, length, values); + checkError(); +} + +inline void Shader::setUniform2fv(const std::string& name, const float* values, int length) const { + const int location = getUniformLocation(name); + setUniform2fv(location, values, length); +} + +inline void Shader::setUniform2fv(int location, const float* values, int length) const { + glUniform2fv(location, length / 2, values); + checkError(); +} + +inline void Shader::setUniform3fv(const std::string& name, const float* values, int length) const { + const int location = getUniformLocation(name); + setUniform3fv(location, values, length); +} + +inline void Shader::setUniformVec3(const std::string& name, const glm::vec3& value) const { + const int location = getUniformLocation(name); + glUniform3fv(location, 1, glm::value_ptr(value)); +} + +inline void Shader::setUniform3fv(int location, const float* values, int length) const { + glUniform3fv(location, length / 3, values); + checkError(); +} + +inline void Shader::setUniform4fv(const std::string& name, const float* values, int length) const { + int location = getUniformLocation(name); + setUniform4fv(location, values, length); +} + +inline void Shader::setUniform4fv(int location, const float* values, int length) const { + glUniform4fv(location, length / 4, values); + checkError(); +} + +inline void Shader::setUniformMatrix(const std::string& name, const glm::mat4& matrix, bool transpose) const { + const int location = getUniformLocation(name); + setUniformMatrix(location, matrix, transpose); +} + +inline void Shader::setUniformMatrix(int location, const glm::mat4& matrix, bool transpose) const { + glUniformMatrix4fv(location, 1, transpose ? GL_TRUE : GL_FALSE, glm::value_ptr(matrix)); + checkError(); +} + +inline void Shader::setUniformMatrix(const std::string& name, const glm::mat3& matrix, bool transpose) const { + const int location = getUniformLocation(name); + setUniformMatrix(location, matrix, transpose); +} + +inline void Shader::setUniformMatrix(int location, const glm::mat3& matrix, bool transpose) const { + glUniformMatrix3fv(location, 1, transpose ? GL_TRUE : GL_FALSE, glm::value_ptr(matrix)); + checkError(); +} + +inline void Shader::setUniformf(const std::string& name, const glm::vec2& values) const { + setUniformf(name, values.x, values.y); +} + +inline void Shader::setUniformf(int location, const glm::vec2& values) const { + setUniformf(location, values.x, values.y); +} + +inline void Shader::setUniformf(const std::string& name, const glm::vec3& values) const { + setUniformf(name, values.x, values.y, values.z); +} + +inline void Shader::setUniformf(int location, const glm::vec3& values) const { + setUniformf(location, values.x, values.y, values.z); +} + +inline void Shader::setUniformf(const std::string& name, const glm::vec4& values) const { + setUniformf(name, values.x, values.y, values.z, values.w); +} + +inline void Shader::setUniformf(int location, const glm::vec4& values) const { + setUniformf(location, values.x, values.y, values.z, values.w); +} + +inline void Shader::setVertexAttribute(const std::string& name, int size, int type, bool normalize, int stride, void* buffer) const { + const int location = getAttributeLocation(name); + if (location == -1) + return; + setVertexAttribute(location, size, type, normalize, stride, buffer); +} + +inline void Shader::setVertexAttribute(int location, int size, int type, bool normalize, int stride, void* buffer) const { + glVertexAttribPointer(location, size, type, normalize, stride, buffer); + checkError(); +} + +inline void Shader::setAttributef(const std::string& name, float value1, float value2, float value3, float value4) const { + const int location = getAttributeLocation(name); + glVertexAttrib4f(location, value1, value2, value3, value4); + checkError(); +} + +inline void Shader::disableVertexAttribute(const std::string& name) const { + const int location = getAttributeLocation(name); + if (location == -1) + return; + disableVertexAttribute(location); +} + +inline void Shader::disableVertexAttribute(int location) const { + glDisableVertexAttribArray(location); + checkError(); +} + +inline int Shader::enableVertexAttribute(const std::string& name) const { + int location = getAttributeLocation(name); + if (location == -1) + return -1; + enableVertexAttribute(location); + return location; +} + +inline void Shader::enableVertexAttribute(int location) const { + glEnableVertexAttribArray(location); + checkError(); +} + +inline bool Shader::hasAttribute(const std::string& name) const { + return _attributes.find(name) != _attributes.end(); +} + +inline bool Shader::hasUniform(const std::string& name) const { + return _uniforms.find(name) != _uniforms.end(); +} + +class ShaderScope { +private: + const Shader& _shader; +public: + ShaderScope(const Shader& shader) : + _shader(shader) { + _shader.activate(); + } + + virtual ~ShaderScope() { + _shader.deactivate(); + } +}; + +#undef checkError + +typedef std::shared_ptr ShaderPtr; + +} diff --git a/src/modules/video/Texture.cpp b/src/modules/video/Texture.cpp new file mode 100644 index 000000000..515cf167f --- /dev/null +++ b/src/modules/video/Texture.cpp @@ -0,0 +1,51 @@ +#include "Texture.h" +#include "core/Log.h" +#include "core/String.h" + +namespace video { + +Texture::Texture(const std::string& filename) : + io::IOResource(), _filename(filename), _textureHandle(0u) { +} + +Texture::~Texture() { + if (_textureHandle != 0) { + glDeleteTextures(1, &_textureHandle); + } +} + +void Texture::upload() { + if (!_img) + return; + if (_img->isLoaded()) { + const GLenum mode = _img->hasAlpha() ? GL_RGBA : GL_RGB; + glTexImage2D(GL_TEXTURE_2D, 0, mode, _img->width(), _img->height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, _img->data()); + _img = ImagePtr(); + _state = io::IOSTATE_LOADED; + } else if (_img->isFailed()) { + _state = io::IOSTATE_FAILED; + _img = ImagePtr(); + } +} + +void Texture::load() { + glGenTextures(1, &_textureHandle); + glBindTexture(GL_TEXTURE_2D, _textureHandle); + static const int empty = 0x00000000; + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &empty); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + _img = ImagePtr(new Image(_filename)); + _img->loadAsync(); +} + +void Texture::bind() { + glBindTexture(GL_TEXTURE_2D, _textureHandle); + upload(); +} + +void Texture::unbind() { + glBindTexture(GL_TEXTURE_2D, 0); +} + +} diff --git a/src/modules/video/Texture.h b/src/modules/video/Texture.h new file mode 100644 index 000000000..e40c9c841 --- /dev/null +++ b/src/modules/video/Texture.h @@ -0,0 +1,29 @@ +#pragma once + +#include "video/GLFunc.h" +#include "io/IOResource.h" +#include "video/Image.h" + +#include + +namespace video { + +class Texture: public io::IOResource { +private: + std::string _filename; + GLuint _textureHandle; + video::ImagePtr _img; + + void upload(); +public: + Texture(const std::string& filename); + ~Texture(); + + void load(); + void bind(); + void unbind(); +}; + +typedef std::shared_ptr TexturePtr; + +} diff --git a/src/modules/video/VertexBuffer.cpp b/src/modules/video/VertexBuffer.cpp new file mode 100644 index 000000000..feaf21049 --- /dev/null +++ b/src/modules/video/VertexBuffer.cpp @@ -0,0 +1,77 @@ +#include "VertexBuffer.h" +#include "core/Common.h" + +namespace video { + +VertexBuffer::VertexBuffer(const void* data, GLsizeiptr size, GLenum target) : + _handle(GL_INVALID_VALUE), _target(target), _vao(0) { + create(data, size, target); +} + +VertexBuffer::VertexBuffer() : + _handle(GL_INVALID_VALUE), _target(GL_INVALID_VALUE), _vao(0) { +} + +bool VertexBuffer::addAttribute(uint32_t index, int size, GLenum type, bool normalized, int stride, intptr_t offset) { + // if we already have a buffer, we don't accept new attributes + if (isValid()) + return false; + _attributes.push_back(Attribute{index, size, type, normalized, stride, offset}); + return true; +} + +bool VertexBuffer::bind() { + if (!isValid()) + return false; + if (_vao != 0) { + glBindVertexArray(_vao); + return true; + } + + glGenVertexArrays(1, &_vao); + glBindVertexArray(_vao); + glBindBuffer(_target, _handle); + const int size = _attributes.size(); + for (int i = 0; i < size; i++) { + const Attribute& a = _attributes[i]; + glVertexAttribPointer(i, a.size, a.type, a.normalized, a.stride, GL_OFFSET(a.offset)); + glEnableVertexAttribArray(i); + } + return true; +} + +void VertexBuffer::unbind() { + if (_vao != 0) + glBindVertexArray(0); + else + glBindBuffer(_target, 0); +} + +bool VertexBuffer::create(const void* data, GLsizeiptr size, GLenum target) { + // we already have a buffer + if (isValid()) { + core_assert(_target == target); + glBindBuffer(target, _handle); + glBufferData(target, size, data, GL_STATIC_DRAW); + glBindBuffer(target, 0); + return true; + } + _target = target; + glGenBuffers(1, &_handle); + if (!isValid()) + return false; + glBindBuffer(target, _handle); + glBufferData(target, size, data, GL_STATIC_DRAW); + glBindBuffer(target, 0); + return true; +} + +VertexBuffer::~VertexBuffer() { + if (!isValid()) + return; + if (_vao != 0) + glDeleteVertexArrays(1, &_vao); + glDeleteBuffers(1, &_handle); +} + +} diff --git a/src/modules/video/VertexBuffer.h b/src/modules/video/VertexBuffer.h new file mode 100644 index 000000000..ddbd1741f --- /dev/null +++ b/src/modules/video/VertexBuffer.h @@ -0,0 +1,44 @@ +#pragma once + +#include "GLFunc.h" +#include + +namespace video { + +class VertexBuffer { +private: + GLuint _handle; + GLenum _target; + struct Attribute { + uint32_t index; + int size; + GLenum type; + bool normalized; + int stride; + intptr_t offset; + }; + std::vector _attributes; + GLuint _vao; +public: + VertexBuffer(const void* data, GLsizeiptr size, GLenum target = GL_ARRAY_BUFFER); + VertexBuffer(); + ~VertexBuffer(); + + bool addAttribute(uint32_t index, int size, GLenum type, bool normalized, int stride, intptr_t offset); + + bool create(const void* data, GLsizeiptr size, GLenum target = GL_ARRAY_BUFFER); + bool bind(); + void unbind(); + bool isValid() const; + GLuint handle() const; +}; + +inline bool VertexBuffer::isValid() const { + return _handle != GL_INVALID_VALUE && _handle > 0; +} + +inline GLuint VertexBuffer::handle() const { + return _handle; +} + +} diff --git a/src/modules/video/WindowedApp.cpp b/src/modules/video/WindowedApp.cpp new file mode 100644 index 000000000..165cfb136 --- /dev/null +++ b/src/modules/video/WindowedApp.cpp @@ -0,0 +1,150 @@ +#include "WindowedApp.h" +#include "core/Common.h" +#include "core/Singleton.h" +#include "GLFunc.h" + +#include + +namespace video { + +namespace { +inline void checkError(const char *file, unsigned int line, const char *function) { + const char *error = SDL_GetError(); + if (*error != '\0') { + Log::error("%s (%s:%i => %s)", error, file, line, function); + SDL_ClearError(); + } else { + Log::error("unknown error (%s:%i => %s)", file, line, function); + } +} +#define sdlCheckError() checkError(__FILE__, __LINE__, __PRETTY_FUNCTION__) +} + +WindowedApp::WindowedApp(const io::FilesystemPtr& filesystem, const core::EventBusPtr& eventBus) : + App(filesystem, eventBus, 15679), _window(nullptr), _glcontext(nullptr), _width(-1), _height(-1), _aspect(1.0f), _clearColor(0.0, 0.0, 0.0) { +} + +void WindowedApp::onAfterRunning() { + SDL_GL_SwapWindow(_window); +} + +core::AppState WindowedApp::onRunning() { + App::onRunning(); + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_QUIT: + return core::AppState::Cleanup; + default: { + const bool running = core::Singleton::getInstance().handleEvent(event); + if (!running) { + return core::AppState::Cleanup; + } + break; + } + } + } + + SDL_GL_MakeCurrent(_window, _glcontext); + glClearColor(_clearColor.r, _clearColor.g, _clearColor.b, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glViewport(0, 0, _width, _height); + + return core::AppState::Running; +} + +core::AppState WindowedApp::onInit() { + return App::onInit(); +} + +core::AppState WindowedApp::onConstruct() { + if (SDL_Init(SDL_INIT_VIDEO) == -1) { + sdlCheckError(); + return core::AppState::Cleanup; + } + + core::Singleton::getInstance().registerObserver(this); + + SDL_DisplayMode displayMode; + SDL_GetDesktopDisplayMode(0, &displayMode); + const char *name = SDL_GetPixelFormatName(displayMode.format); + int width = displayMode.w; + int height = displayMode.h; + + SDL_ClearError(); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest"); + SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); + + const bool fullscreen = core::Var::get("cl_fullscreen", "true")->boolVal(); + + int flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN; + if (fullscreen) + flags |= SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_BORDERLESS; + const int videoDrivers = SDL_GetNumVideoDrivers(); + for (int i = 0; i < videoDrivers; ++i) { + Log::info("available driver: %s", SDL_GetVideoDriver(i)); + } + + Log::info("driver: %s", SDL_GetCurrentVideoDriver()); + const int displays = SDL_GetNumVideoDisplays(); + Log::info("found %i displays", displays); + if (fullscreen && displays > 1) { + width = displayMode.w; + height = displayMode.h; + Log::info("use fake fullscreen for the first display: %i:%i", width, height); + } + + _window = SDL_CreateWindow("Client", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, flags); + if (!_window) { + sdlCheckError(); + return core::AppState::Cleanup; + } + + _glcontext = SDL_GL_CreateContext(_window); + + SDL_DisableScreenSaver(); + + if (SDL_SetWindowBrightness(_window, 1.0f) == -1) + sdlCheckError(); + + const bool grabMouse = false; + if (grabMouse && (!fullscreen || displays > 1)) { + SDL_SetWindowGrab(_window, SDL_TRUE); + } + + int screen = 0; + int modes = SDL_GetNumDisplayModes(screen); + Log::info("possible display modes:"); + for (int i = 0; i < modes; i++) { + SDL_GetDisplayMode(screen, i, &displayMode); + name = SDL_GetPixelFormatName(displayMode.format); + Log::info("%ix%i@%iHz %s", displayMode.w, displayMode.h, displayMode.refresh_rate, name); + } + + // some platforms may override or hardcode the resolution - so + // we have to query it here to get the actual resolution + SDL_GetWindowSize(_window, &_width, &_height); + _aspect = _width / static_cast(_height); + + ExtGLLoadFunctions(); + + return App::onConstruct(); +} + +core::AppState WindowedApp::onCleanup() { + core::Singleton::getInstance().removeObserver(this); + SDL_GL_DeleteContext(_glcontext); + SDL_DestroyWindow(_window); + SDL_Quit(); + return App::onCleanup(); +} + +} diff --git a/src/modules/video/WindowedApp.h b/src/modules/video/WindowedApp.h new file mode 100644 index 000000000..6dd6fd639 --- /dev/null +++ b/src/modules/video/WindowedApp.h @@ -0,0 +1,34 @@ +#pragma once + +#include "core/App.h" +#include "io/IEventObserver.h" +#include "io/EventHandler.h" +#include + +struct SDL_Window; +typedef void *SDL_GLContext; + +namespace video { + +class WindowedApp: public core::App, public io::IEventObserver { +protected: + SDL_Window* _window; + SDL_GLContext _glcontext; + int _width; + int _height; + float _aspect; + glm::vec3 _clearColor; + + WindowedApp(const io::FilesystemPtr& filesystem, const core::EventBusPtr& eventBus); + + virtual ~WindowedApp() { + } +public: + virtual core::AppState onRunning() override; + virtual void onAfterRunning() override; + virtual core::AppState onConstruct() override; + virtual core::AppState onInit() override; + virtual core::AppState onCleanup() override; +}; + +} diff --git a/src/modules/voxel/CMakeLists.txt b/src/modules/voxel/CMakeLists.txt new file mode 100644 index 000000000..95dda6513 --- /dev/null +++ b/src/modules/voxel/CMakeLists.txt @@ -0,0 +1,22 @@ +fips_begin_module(voxel) + fips_files( + Raycast.cpp Raycast.h + World.cpp World.h + WorldEvents.h + WorldData.h + Voxel.h + ) + find_package(SDL2 REQUIRED) + include_directories(${SDL2_INCLUDE_DIRS}) + fips_deps(core io noise zlib ${SDL2_LIBRARIES}) +fips_end_module() + +begin_googleunittest(voxel) + fips_dir(tests) + fips_files( + WorldTest.cpp + ) + find_package(SDL2 REQUIRED) + include_directories(${SDL2_INCLUDE_DIRS}) + fips_deps(voxel ${SDL2_LIBRARIES}) +end_googleunittest() diff --git a/src/modules/voxel/Raycast.cpp b/src/modules/voxel/Raycast.cpp new file mode 100644 index 000000000..ff6cec217 --- /dev/null +++ b/src/modules/voxel/Raycast.cpp @@ -0,0 +1,15 @@ +#include "Raycast.h" + +namespace voxel { + +bool Raycast::operator()(const WorldData::Sampler& sampler) { + if (sampler.getVoxel().getMaterial() != AIR) { + _voxel = sampler.getVoxel(); + _position = glm::vec3(sampler.getPosition().getX(), sampler.getPosition().getY(), sampler.getPosition().getZ()); + return false; + } + + return true; +} + +} diff --git a/src/modules/voxel/Raycast.h b/src/modules/voxel/Raycast.h new file mode 100644 index 000000000..4daf80759 --- /dev/null +++ b/src/modules/voxel/Raycast.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include "WorldData.h" + +namespace voxel { + +class Raycast { +private: + glm::vec3 _position; + voxel::Voxel _voxel; +public: + inline glm::vec3 position() const { + return _position; + } + + inline Voxel voxel() const { + return _voxel; + } + + bool operator()(const WorldData::Sampler& sampler); +}; + +} diff --git a/src/modules/voxel/Spiral.h b/src/modules/voxel/Spiral.h new file mode 100644 index 000000000..69cfad2ba --- /dev/null +++ b/src/modules/voxel/Spiral.h @@ -0,0 +1,55 @@ +#pragma once + +namespace voxel { + +/** + * @brief Two dimensional spiral + * + * The call to @c Spiral::next() will advance the coordinates that are then accessible via @c Spiral::x() and @c Spiral::y(). + */ +class Spiral { +protected: + int _layer = 1; + int _leg = 0; + int _x = 0; + int _y = 0; +public: + Spiral() : + _layer(1), _leg(0), _x(0), _y(0) { + } + void next() { + switch (_leg) { + case 0: + ++_x; + if (_x == _layer) + ++_leg; + break; + case 1: + ++_y; + if (_y == _layer) + ++_leg; + break; + case 2: + --_x; + if (-_x == _layer) + ++_leg; + break; + case 3: + --_y; + if (-_y == _layer) { + _leg = 0; + ++_layer; + } + break; + } + } + + inline int x() const { + return _x; + } + inline int y() const { + return _y; + } +}; + +} diff --git a/src/modules/voxel/Voxel.h b/src/modules/voxel/Voxel.h new file mode 100644 index 000000000..96157938c --- /dev/null +++ b/src/modules/voxel/Voxel.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace voxel { + +// this must be 0 +const int AIR = 0; +const int DIRT = 1; +const int GRASS = 2; +const int CLOUD = 3; +const int WATER = 4; +const int LEAVES = 5; +const int TRUNK = 6; +const int CLOUDS = 7; + +// density 0 - 255 (8 bits) +// material types 0 - 255 (8 bits) +typedef PolyVox::MaterialDensityPair88 Voxel; + +typedef PolyVox::CubicVertex VoxelVertex; +typedef PolyVox::Mesh CubicMesh; +typedef PolyVox::Vertex VoxelVertexDecoded; +typedef PolyVox::Mesh DecodedMesh; + +struct DecodedMeshData { + DecodedMesh mesh; + // translation on the x and z axis + glm::ivec2 translation; +}; + +} diff --git a/src/modules/voxel/World.cpp b/src/modules/voxel/World.cpp new file mode 100644 index 000000000..ad6e5f009 --- /dev/null +++ b/src/modules/voxel/World.cpp @@ -0,0 +1,493 @@ +#include "World.h" +#include "core/App.h" +#include "core/ByteStream.h" +#include "core/Var.h" +#include "core/Log.h" +#include "core/Common.h" +#include "core/Trace.h" +#include "io/File.h" +#include "Raycast.h" +#include "Voxel.h" +#include +#include +#include +#include +#include +#include +#include + +namespace voxel { + +#define MAX_HEIGHT 256 +#define WORLD_FILE_VERSION 1 + +// http://code.google.com/p/fortressoverseer/source/browse/Overseer/PolyVoxGenerator.cpp +World::World() : + _volumeData(nullptr), _seed(0), _size(0), _noise(), _worldShapeNoise(), _threadPool(1), _rwLock("World") { + _chunkSize = core::Var::get("cl_chunksize", "16", core::CV_READONLY); +} + +World::~World() { + if (_volumeData) + delete _volumeData; + _volumeData = nullptr; +} + +int World::internalFindFloor(int x, int z) const { + for (int i = MAX_HEIGHT - 1; i >= 0; i--) { + const int material = getMaterial(x, i, z); + if (material != AIR && material != CLOUDS) { + return i + 1; + } + } + return -1; +} + +glm::ivec3 World::internalRandomPos(int border) const { + const glm::ivec2& pos = randomPosWithoutHeight(border); + const int y = internalFindFloor(pos.x, pos.y); + return glm::ivec3(pos.x, y, pos.y); +} + +glm::ivec2 World::randomPosWithoutHeight(int border) const { + if (_size <= 2 * border) { + Log::warn("Border %i exceeds size %i", border, _size); + return glm::ivec2(0); + } + std::uniform_int_distribution distribution(border, _size - border); + const int x = distribution(_engine); + const int z = distribution(_engine); + return glm::ivec2(x, z); +} + +glm::ivec3 World::randomPos(int border) const { + const glm::ivec2& pos = randomPosWithoutHeight(border); + const int y = findFloor(pos.x, pos.y); + return glm::ivec3(pos.x, y, pos.y); +} + +// Extract the surface for the specified region of the volume. +// The surface extractor outputs the mesh in an efficient compressed format which +// is not directly suitable for rendering. +void World::scheduleMeshExtraction(const glm::ivec2& p) { + if (p.x < 0 || p.y < 0 || p.x >= _size || p.y >= _size) { + Log::debug("skip mesh extraction for %i:%i (%i)", p.x, p.y, _size); + return; + } + + const int size = _chunkSize->intVal(); + const glm::ivec2& pos = getGridPos(p); + if (_meshesExtracted.find(pos) != _meshesExtracted.end()) { + Log::debug("mesh is already extracted for %i:%i (%i)", p.x, p.y, _size); + return; + } + _meshesExtracted.insert(pos); + + const int delta = size - 1; + _threadPool.push([=] () { + core_trace_scoped("MeshExtraction"); + const PolyVox::Vector3DInt32 mins(pos.x, 0, pos.y); + const PolyVox::Vector3DInt32 maxs(mins.getX() + delta, MAX_HEIGHT, mins.getZ() + delta); + const PolyVox::Region region(mins, maxs); + DecodedMeshData data; + { + std::lock_guard lock(_mutex); + data.mesh = PolyVox::decodeMesh(PolyVox::extractCubicMesh(_volumeData, region)); + } + + data.translation = pos; + core::ScopedWriteLock lock(_rwLock); + _meshQueue.push_back(std::move(data)); + }); +} + +int World::findFloor(int x, int z) const { + std::lock_guard lock(_mutex); + return internalFindFloor(x, z); +} + +void World::allowReExtraction(const glm::ivec2& pos) { + _meshesExtracted.erase(getGridPos(pos)); +} + +World::Result World::raycast(const glm::vec3& start, const glm::vec3& end, voxel::Raycast& raycast) { + if (_volumeData == nullptr) + return World::FAILED; + std::lock_guard lock(_mutex); + PolyVox::RaycastResult result = PolyVox::raycastWithEndpoints(_volumeData, PolyVox::Vector3DFloat(start.x, start.y, start.z), + PolyVox::Vector3DFloat(end.x, end.y, end.z), raycast); + if (result == PolyVox::RaycastResults::Completed) + return World::COMPLETED; + return World::INTERUPTED; +} + +bool World::findPath(const PolyVox::Vector3DInt32& start, const PolyVox::Vector3DInt32& end, + std::list& listResult) { + if (_volumeData == nullptr) + return false; + + static auto f = [] (const voxel::WorldData* volData, const PolyVox::Vector3DInt32& v3dPos) { + voxel::Voxel voxel = volData->getVoxel(v3dPos); + return voxel.getDensity() != 0; + }; + + std::lock_guard lock(_mutex); + const PolyVox::AStarPathfinderParams params(_volumeData, start, end, &listResult, 1.0f, 10000, + PolyVox::TwentySixConnected, std::bind(f, std::placeholders::_1, std::placeholders::_2)); + PolyVox::AStarPathfinder pf(params); + // TODO: move into threadpool + pf.execute(); + return true; +} + +void World::destroy() { + if (!_volumeData) + return; + std::lock_guard lock(_mutex); + if (!_volumeData) + return; + Log::info("flush the world"); + delete _volumeData; + _volumeData = nullptr; +} + +void World::createCirclePlane(const glm::ivec3& center, int width, int depth, double radius, const Voxel& voxel) { + const double xRadius = (width - 1) / 2.0; + const double zRadius = (depth - 1) / 2.0; + const double minRadius = std::min(xRadius, zRadius); + const double xRatio = xRadius / (float) minRadius; + const double zRatio = zRadius / (float) minRadius; + + for (double z = -zRadius; z <= zRadius; ++z) { + for (double x = -xRadius; x <= xRadius; ++x) { + const double xP = x / xRatio; + const double zP = z / zRatio; + const double distance = sqrt(pow(xP, 2) + pow(zP, 2)); + if (distance < radius) { + if (_volumeData->getEnclosingRegion().containsPoint(center.x + x, center.y, center.z + z)) + _volumeData->setVoxel(center.x + x, center.y, center.z + z, voxel); + } + } + } +} + +void World::createCube(const glm::ivec3& pos, int width, int height, int depth, const Voxel& voxel) { + for (int x = 0; x < width; ++x) { + for (int y = 0; y < height; ++y) { + for (int z = 0; z < depth; ++z) { + if (_volumeData->getEnclosingRegion().containsPoint(pos.x + x, pos.y + y, pos.z + z)) { + _volumeData->setVoxel(pos.x + x, pos.y + y, pos.z + z, voxel); + } + } + } + } +} + +void World::createPlane(const glm::ivec3& pos, int width, int depth, const Voxel& voxel) { + createCube(pos, width, 1, depth, voxel); +} + +void World::createEllipse(const glm::ivec3& pos, int width, int height, int depth, const Voxel& voxel) { + const double heightRadius = (height - 1.0) / 2.0; + const double minDimension = std::min(width, depth); + const double adjustedMinRadius = (minDimension - 1.0) / 2.0; + const double heightFactor = heightRadius / adjustedMinRadius; + for (double y = -heightRadius; y <= heightRadius; ++y) { + const double adjustedHeight = abs(y / heightFactor); + const double circleRadius = sqrt(pow(adjustedMinRadius + 0.5, 2.0) - pow(adjustedHeight, 2.0)); + const glm::ivec3 planePos(pos.x, pos.y + y, pos.z); + createCirclePlane(planePos, width, depth, circleRadius, voxel); + } +} + +void World::createCone(const glm::ivec3& pos, int width, int height, int depth, const Voxel& voxel) { + const double heightRadius = height - 0.5; + const double minDimension = std::min(width, depth); + const double minRadius = minDimension / 2.0; + for (double y = 0.5; y <= heightRadius; y++) { + const double percent = 1 - (y / height); + const double circleRadius = percent * minRadius; + const glm::ivec3 planePos(pos.x, pos.y + y, pos.z); + createCirclePlane(planePos, width, depth, circleRadius, voxel); + } +} + +void World::createDome(const glm::ivec3& pos, int width, int height, int depth, const Voxel& voxel) { + // TODO: +} + +void World::addTree(const glm::ivec3& pos, TreeType type, int trunkHeight) { + const int top = (int) pos.y + trunkHeight; + const int sizeX = _volumeData->getWidth(); + const int sizeY = _volumeData->getDepth(); + const int sizeZ = _volumeData->getHeight(); + const Voxel voxel(TRUNK, Voxel::getMaxDensity()); + + Log::trace("generate tree at %i:%i:%i", pos.x, pos.y, pos.z); + + for (int y = pos.y; y < top; ++y) { + const int width = std::max(1, 3 - (y - pos.y)); + for (int x = pos.x - width; x < pos.x + width; ++x) { + for (int z = pos.z - width; z < pos.z + width; ++z) { + if ((x >= pos.x + 1 || x < pos.x - 1) && (z >= pos.z + 1 || z < pos.z - 1)) + continue; + if (x < 0 || y < 0 || z < 0 || x >= sizeX || y >= sizeY || z >= sizeZ) + continue; + + _volumeData->setVoxel(x, y, z, voxel); + } + } + } + + const int width = 16; + const int depth = 16; + const int height = 12; + const Voxel leavesVoxel(LEAVES, 1); + if (type == TreeType::ELLIPSIS) { + const int centerLeavesPos = top + height / 2; + const glm::ivec3 leafesPos(pos.x, centerLeavesPos, pos.z); + createEllipse(leafesPos, width, height, depth, leavesVoxel); + } else if (type == TreeType::CONE) { + const glm::ivec3 leafesPos(pos.x, top, pos.z); + createCone(leafesPos, width, height, depth, leavesVoxel); + } else if (type == TreeType::DOME) { + const glm::ivec3 leafesPos(pos.x, top, pos.z); + createDome(leafesPos, width, height, depth, leavesVoxel); + } +} + +void World::createTrees() { + const int amount = 4; + Log::debug("generate %i trees", amount); + // TODO: don't place trees on top of other trees + // TODO: don't use random positions, but decide on the material of some positions + for (int i = 0; i < amount; ++i) { + const glm::ivec3& pos = internalRandomPos(10); + addTree(pos, TreeType::ELLIPSIS); + } + for (int i = 0; i < amount; ++i) { + const glm::ivec3& pos = internalRandomPos(10); + addTree(pos, TreeType::CONE); + } +} + +void World::createClouds() { + const int amount = 4; + Log::debug("generate %i clouds", amount); + + const Voxel voxel(CLOUDS, Voxel::getMinDensity()); + for (int i = 0; i < amount; ++i) { + const int height = 10; + const glm::ivec2& pos = randomPosWithoutHeight(); + glm::ivec3 cloudCenterPos(pos.x, _size - height, pos.y); + createEllipse(cloudCenterPos, 10, height, 10, voxel); + cloudCenterPos.x -= 5; + cloudCenterPos.y -= 5 + i; + createEllipse(cloudCenterPos, 20, height, 35, voxel); + } +} + +void World::createUnderground() { + glm::ivec3 startPos(1, 1, 1); + const Voxel voxel(DIRT, Voxel::getMaxDensity()); + createPlane(startPos, 10, 10, voxel); +} + +bool World::load(long seed, util::IProgressMonitor* progressMonitor) { + const core::App* app = core::App::getInstance(); + const io::FilesystemPtr& filesystem = app->filesystem(); + const std::string filename = "world-" + std::to_string(seed) + ".wld"; + const io::FilePtr& f = filesystem->open(filename); + if (!f) + return false; + destroy(); + Log::trace("Try to load world %s", f->getName().c_str()); + uint8_t *fileBuf; + // TODO: load async, put world into state loading, and do the real loading in onFrame if the file is fully loaded + const int fileLen = f->read((void **) &fileBuf); + if (!fileBuf || fileLen <= 0) { + Log::error("Failed to load the world from %s", f->getName().c_str()); + return false; + } + std::unique_ptr smartBuf(fileBuf); + + core::ByteStream bs; + bs.append(fileBuf, fileLen); + int len; + int version; + bs.readFormat("ibli", &len, &version, &_seed, &_size); + + if (progressMonitor) + progressMonitor->init(_size * MAX_HEIGHT * _size); + + if (version != WORLD_FILE_VERSION) { + Log::error("file %s has a wrong version number %i (expected %i)", f->getName().c_str(), version, WORLD_FILE_VERSION); + return false; + } + if (_seed != seed) { + Log::error("file %s has a wrong seed %li (expected %li)", f->getName().c_str(), _seed, seed); + return false; + } + if (_size <= 0) { + Log::error("file %s has invalid size: %i", f->getName().c_str(), _size); + return false; + } + const int sizeLimit = 256; + if (len > 1000l * 1000l * sizeLimit) { + Log::error("extracted memory would be more than %i MB for the file %s", sizeLimit, f->getName().c_str()); + return false; + } + + _engine.seed(_seed); + Log::info("Loading a world with size %i from file %s,uncompressing to %i", _size, f->getName().c_str(), (int) len); + + uint8_t* targetBuf = new uint8_t[len]; + std::unique_ptr smartTargetBuf(targetBuf); + + uLongf targetBufSize = len; + const int res = uncompress(targetBuf, &targetBufSize, bs.getBuffer(), bs.getSize()); + if (res != Z_OK) { + Log::error("Failed to uncompress the world data with len %i", len); + return false; + } + + core::ByteStream voxelBuf(len); + voxelBuf.append(targetBuf, len); + + const PolyVox::Region region(0, 0, 0, _size, MAX_HEIGHT, _size); + WorldData* volumeData = new WorldData(region); + const PolyVox::Vector3DInt32& lower = region.getLowerCorner(); + const PolyVox::Vector3DInt32& upper = region.getUpperCorner(); + const int lowerZ = lower.getZ(); + const int upperZ = upper.getZ(); + const int lowerY = lower.getY(); + const int upperY = upper.getY(); + const int lowerX = lower.getX(); + const int upperX = upper.getX(); + for (int z = lowerZ; z < upperZ; ++z) { + for (int y = lowerY; y < upperY; ++y) { + for (int x = lowerX; x < upperX; ++x) { + core_assert(voxelBuf.getSize() >= 2); + const uint8_t material = voxelBuf.readByte(); + const uint8_t density = voxelBuf.readByte(); + const Voxel voxel(material, density); + volumeData->setVoxel(x, y, z, voxel); + if (progressMonitor) + progressMonitor->step(); + } + } + } + if (progressMonitor) + progressMonitor->done(); + _volumeData = volumeData; + return true; +} + +bool World::save(long seed) { + if (_volumeData == nullptr) { + Log::error("No world created yet"); + return false; + } + if (seed != _seed) { + Log::error("Seeds don't match"); + return false; + } + core::ByteStream voxelStream; + const PolyVox::Region region(0, 0, 0, _size, MAX_HEIGHT, _size); + const PolyVox::Vector3DInt32& lower = region.getLowerCorner(); + const PolyVox::Vector3DInt32& upper = region.getUpperCorner(); + const int lowerZ = lower.getZ(); + const int upperZ = upper.getZ(); + const int lowerY = lower.getY(); + const int upperY = upper.getY(); + const int lowerX = lower.getX(); + const int upperX = upper.getX(); + for (int z = lowerZ; z < upperZ; ++z) { + for (int y = lowerY; y < upperY; ++y) { + for (int x = lowerX; x < upperX; ++x) { + const Voxel& voxel = _volumeData->getVoxel(x, y, z); + voxelStream.addByte(voxel.getMaterial()); + voxelStream.addByte(voxel.getDensity()); + } + } + } + + // save the stuff + const std::string filename = "world-" + std::to_string(seed) + ".wld"; + const core::App* app = core::App::getInstance(); + const io::FilesystemPtr& filesystem = app->filesystem(); + + const uint8_t* voxelBuf = voxelStream.getBuffer(); + const int voxelSize = voxelStream.getSize(); + uLongf neededVoxelBufLen = compressBound(voxelSize); + uint8_t* compressedVoxelBuf = new uint8_t[neededVoxelBufLen]; + std::unique_ptr smartBuf(compressedVoxelBuf); + const int res = compress(compressedVoxelBuf, &neededVoxelBufLen, voxelBuf, voxelSize); + if (res != Z_OK) { + Log::error("Failed to compress the voxel data"); + return false; + } + core::ByteStream final; + final.addFormat("ibli", voxelSize, WORLD_FILE_VERSION, _seed, _size); + final.append(compressedVoxelBuf, neededVoxelBufLen); + if (!filesystem->write(filename, final.getBuffer(), final.getSize())) { + Log::error("Failed to write file %s", filename.c_str()); + return false; + } + Log::info("Wrote file %s (%i)", filename.c_str(), voxelSize); + return true; +} + +void World::create(long seed, int size, util::IProgressMonitor* progressMonitor) { + if (_seed == seed) + return; + _seed = seed; + _engine.seed(_seed); + _size = size; + Log::info("Using seed %li with size %i", seed, size); + { + std::lock_guard lock(_mutex); + if (_volumeData != nullptr) { + Log::info("Create a new world"); + destroy(); + } + + _noise.setSeed(seed); + _noise.init(); + const PolyVox::Region region(0, 0, 0, size - 1, MAX_HEIGHT - 1, size - 1); + WorldData* volumeData = new WorldData(region); + if (progressMonitor) + progressMonitor->init(size * MAX_HEIGHT * size + 2); + const PolyVox::Vector3DInt32& lower = region.getLowerCorner(); + const PolyVox::Vector3DInt32& upper = region.getUpperCorner(); + for (double z = lower.getZ(); z < upper.getZ(); ++z) { + for (double x = lower.getX(); x < upper.getX(); ++x) { + const int height = (_noise.get(x, z, 0, 256.0) + 1) * 128; + + for (double h = 0; h <= height; ++h) { + if (progressMonitor) { + progressMonitor->step(); + } + const Voxel voxel(DIRT, DIRT); + volumeData->setVoxel(x, h, z, voxel); + } + } + } + _volumeData = volumeData; + createTrees(); + if (progressMonitor) { + progressMonitor->step(); + } + createClouds(); + if (progressMonitor) { + progressMonitor->step(); + progressMonitor->done(); + } + } + core::App::getInstance()->eventBus()->publish(WorldCreatedEvent(this)); +} + +void World::onFrame(long dt) { +} + +} diff --git a/src/modules/voxel/World.h b/src/modules/voxel/World.h new file mode 100644 index 000000000..5ce5f5ec5 --- /dev/null +++ b/src/modules/voxel/World.h @@ -0,0 +1,160 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "noise/AccidentalNoise.h" +#include "noise/WorldShapeNoise.h" +#include "noise/NoisePPNoise.h" +#include "noise/PerlinNoise.h" +#include "io/Filesystem.h" +#include "WorldData.h" +#include "WorldEvents.h" +#include "Voxel.h" +#include "Raycast.h" +#include "util/IProgressMonitor.h" +#include "core/ThreadPool.h" +#include "core/ReadWriteLock.h" +#include "core/Var.h" + +namespace voxel { + +class World { +public: + enum Result { + COMPLETED, ///< If the ray passed through the volume without being interupted + INTERUPTED, ///< If the ray was interupted while travelling + FAILED + }; + + World(); + ~World(); + + void create(long seed, int size, util::IProgressMonitor* progressMonitor = nullptr); + bool load(long seed, util::IProgressMonitor* progressMonitor = nullptr); + bool save(long seed); + void destroy(); + + inline bool isCreated() const { + return _volumeData != nullptr; + } + + Result raycast(const glm::vec3& start, const glm::vec3& end, voxel::Raycast& raycast); + bool findPath(const PolyVox::Vector3DInt32& start, const PolyVox::Vector3DInt32& end, std::list& listResult); + int findFloor(int x, int z) const; + int getMaterial(int x, int y, int z) const; + + /** + * @brief Returns a random position inside the boundaries of the world (on the surface) + */ + glm::ivec3 randomPos(int border = 0) const; + glm::ivec2 randomPosWithoutHeight(int border = 0) const; + + /** + * @brief Cuts the given world coordinate down to mesh tile vectors + */ + inline glm::ivec2 getGridPos(const glm::vec3& pos) { + return getGridPos(glm::ivec2(static_cast(pos.x), static_cast(pos.z))); + } + + /** + * @brief Cuts the given world coordinate down to mesh tile vectors + */ + inline glm::ivec2 getGridPos(const glm::ivec2& pos) const { + const int size = _chunkSize->intVal(); + return glm::ivec2(pos.x / size * size, pos.y / size * size); + } + + /** + * @brief We need to pop the mesh extractor queue to find out if there are new and ready to use meshes for us + */ + inline bool pop(DecodedMeshData& item) { + core::ScopedWriteLock lock(_rwLock); + if (_meshQueue.empty()) + return false; + item = std::move(_meshQueue.front()); + _meshQueue.pop_front(); + return true; + } + + /** + * @brief If you don't need an extracted mesh anymore, make sure to allow the reextraction at a later time. + * @param[in] pos A World vector that is automatically converted into a mesh tile vector + */ + void allowReExtraction(const glm::ivec2& pos); + + /** + * @brief Performs async mesh extraction. You need to call @c pop in order to see if some extraction is ready. + * + * @param[in] pos A World vector that is automatically converted into a mesh tile vector + * @note This will not allow to reschedule an extraction for the same area until @c allowReExtraction was called. + */ + void scheduleMeshExtraction(const glm::ivec2& pos); + + void onFrame(long dt); + + inline int size() const { return _size; } + inline long seed() const { return _seed; } + +private: + enum class TreeType { + DOME, + CONE, + ELLIPSIS + }; + + WorldData* _volumeData; + mutable std::mt19937 _engine; + long _seed; + int _size; + noise::NoisePPNoise _noise; + noise::WorldShapeNoise _worldShapeNoise; + + struct IVec2HashEquals { + size_t operator()(const glm::ivec2& k) const { + // TODO: find a better hash function - we have a lot of collisions here + return std::hash()(k.x) ^ std::hash()(k.y); + } + + bool operator()(const glm::ivec2& a, const glm::ivec2& b) const { + return a.x == b.x && a.y == b.y; + } + }; + + // assumes that the mutex is already locked + glm::ivec3 internalRandomPos(int border = 0) const; + int internalFindFloor(int x, int y) const; + + void createCirclePlane(const glm::ivec3& center, int width, int depth, double radius, const Voxel& voxel); + void createEllipse(const glm::ivec3& pos, int width, int height, int depth, const Voxel& voxel); + void createCone(const glm::ivec3& pos, int width, int height, int depth, const Voxel& voxel); + void createDome(const glm::ivec3& pos, int width, int height, int depth, const Voxel& voxel); + void createCube(const glm::ivec3& pos, int width, int height, int depth, const Voxel& voxel); + void createPlane(const glm::ivec3& pos, int width, int depth, const Voxel& voxel); + + void addTree(const glm::ivec3& pos, TreeType type, int trunkHeight = 10); + void createTrees(); + void createClouds(); + void createUnderground(); + + core::ThreadPool _threadPool; + mutable std::mutex _mutex; + core::ReadWriteLock _rwLock; + std::deque _meshQueue; + // fast lookup for positions that are already extracted and available in the _meshData vector + std::unordered_set _meshesExtracted; + core::VarPtr _chunkSize; +}; + +inline int World::getMaterial(int x, int y, int z) const { + return _volumeData->getVoxel(x, y, z).getMaterial(); +} + +typedef std::shared_ptr WorldPtr; + +} diff --git a/src/modules/voxel/WorldData.h b/src/modules/voxel/WorldData.h new file mode 100644 index 000000000..e98729fd8 --- /dev/null +++ b/src/modules/voxel/WorldData.h @@ -0,0 +1,10 @@ +#pragma once + +#include +#include "Voxel.h" + +namespace voxel { + +typedef PolyVox::RawVolume WorldData; + +} diff --git a/src/modules/voxel/WorldEvents.h b/src/modules/voxel/WorldEvents.h new file mode 100644 index 000000000..249575cbe --- /dev/null +++ b/src/modules/voxel/WorldEvents.h @@ -0,0 +1,22 @@ +#pragma once + +#include "core/EventBus.h" + +namespace voxel { + +class World; + +class WorldCreatedEvent: public core::IEventBusEvent { +private: + World* _world; +public: + WorldCreatedEvent(World* world) : + _world(world) { + } + + inline World* world() const { + return _world; + } +}; + +} diff --git a/src/modules/voxel/tests/WorldTest.cpp b/src/modules/voxel/tests/WorldTest.cpp new file mode 100644 index 000000000..a08858892 --- /dev/null +++ b/src/modules/voxel/tests/WorldTest.cpp @@ -0,0 +1,36 @@ +#include "core/tests/AbstractTest.h" +#include "voxel/World.h" + +namespace voxel { +namespace { +const long seed = 1L; +const int size = 32; +} + +class WorldTest: public core::AbstractTest { +}; + +TEST_F(WorldTest, testCreateSaveLoad) { + World world; + world.create(seed, size); + ASSERT_TRUE(world.isCreated()); + ASSERT_EQ(seed, world.seed()); + ASSERT_EQ(size, world.size()); + ASSERT_TRUE(world.save(seed)); + ASSERT_EQ(seed, world.seed()); + ASSERT_EQ(size, world.size()); + ASSERT_TRUE(world.load(seed)); + ASSERT_TRUE(world.isCreated()); + ASSERT_EQ(seed, world.seed()); + ASSERT_EQ(size, world.size()); +} + +TEST_F(WorldTest, testLoad) { + World world; + ASSERT_TRUE(world.load(seed)); + ASSERT_TRUE(world.isCreated()); + ASSERT_EQ(seed, world.seed()); + ASSERT_EQ(size, world.size()); +} + +} diff --git a/src/rcon/AIApplication.cpp b/src/rcon/AIApplication.cpp new file mode 100644 index 000000000..091df9f3d --- /dev/null +++ b/src/rcon/AIApplication.cpp @@ -0,0 +1,75 @@ +#include "AIApplication.h" +#include "AIDebugger.h" +#include "AINodeStaticResolver.h" +#include "AIDebuggerWidget.h" +#include "Version.h" + +#include +#include +#include +#include +#include + +namespace ai { +namespace debug { + +AIApplication::AIApplication(int argc, char** argv) : + QApplication(argc, argv) { +#ifdef Q_WS_X11 + QApplication::setGraphicsSystem(QLatin1String("raster")); +#endif + setOrganizationDomain("engine"); + setApplicationName("rcon"); + setApplicationVersion(VERSION); +#ifdef Q_WS_MAC + a.setAttribute(Qt::AA_DontShowIconsInMenus); +#endif + + _resolver = new AINodeStaticResolver(); + _debugger = new AIDebugger(*_resolver); + _widget = new AIDebuggerWidget(*_debugger, *_resolver); + + _window.setCentralWidget(_widget); + + QToolBar* _toolbar = _window.addToolBar(""); + _toolbar->setMovable(false); + _toolbar->setFloatable(false); + _window.addToolBar(Qt::TopToolBarArea, _toolbar); + + _widget->contributeToStatusBar(_window.statusBar()); + _widget->contributeToToolBar(_toolbar); + QMenu* menuBar = _window.menuBar()->addMenu(tr("&File")); + _widget->contributeToFileMenu(menuBar); + _widget->contributeToHelpMenu(_window.menuBar()->addMenu(tr("&Help"))); + _window.showMaximized(); + _window.show(); + + const QList& args = QCoreApplication::arguments(); + if (args.size() == 3) { + const QString hostname = args.at(1); + const short port = args.at(2).toShort(); + qDebug() << "connect to " << hostname << " on port " << port; + _widget->connectToAIServer(hostname, port); + } else { + qDebug() << "connect to 127.0.0.1 on port 11338"; + _widget->connectToAIServer("127.0.0.1", 11338); + } + + QTranslator qtTranslator; + qtTranslator.load("qt_" + QLocale::system().name(), + QLibraryInfo::location(QLibraryInfo::TranslationsPath)); + installTranslator(&qtTranslator); + + QTranslator simpleaiTranslator; + simpleaiTranslator.load(applicationName() + "_" + QLocale::system().name(), ":/data/"); + installTranslator(&simpleaiTranslator); +} + +AIApplication::~AIApplication() { + delete _debugger; + delete _resolver; + delete _widget; +} + +} +} diff --git a/src/rcon/AIApplication.h b/src/rcon/AIApplication.h new file mode 100644 index 000000000..578429c2a --- /dev/null +++ b/src/rcon/AIApplication.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +namespace ai { +namespace debug { + +class AIDebugger; +class AIDebuggerWidget; +class AINodeStaticResolver; + +/** + * @brief Use this class to run the debugger as a stand-alone application. + * + * @note If you embed the debugger into an already exsting QT application, you of course + * don't need this. + */ +class AIApplication: public QApplication { +protected: + AIDebugger* _debugger; + AINodeStaticResolver* _resolver; + AIDebuggerWidget* _widget; + QMainWindow _window; +public: + AIApplication(int argc, char** argv); + virtual ~AIApplication(); +}; + +} +} diff --git a/src/rcon/AIDebugger.cpp b/src/rcon/AIDebugger.cpp new file mode 100644 index 000000000..751700105 --- /dev/null +++ b/src/rcon/AIDebugger.cpp @@ -0,0 +1,319 @@ +#include "AIDebugger.h" +#include "AIDebuggerWidget.h" +#include "AINodeStaticResolver.h" +#include "MapView.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Version.h" + +namespace ai { +namespace debug { + +PROTOCOL_HANDLER(AIStateMessage); +PROTOCOL_HANDLER(AICharacterDetailsMessage); +PROTOCOL_HANDLER(AICharacterStaticMessage); +PROTOCOL_HANDLER(AIPauseMessage); +PROTOCOL_HANDLER(AINamesMessage); + +class StateHandler: public AIStateMessageHandler { +private: + AIDebugger& _aiDebugger; +public: + StateHandler (AIDebugger& aiDebugger) : + _aiDebugger(aiDebugger) { + } + + void executeAIStateMessage(const ai::AIStateMessage& msg) override { + _aiDebugger.setEntities(msg.getStates()); + emit _aiDebugger.onEntitiesUpdated(); + } +}; + +class CharacterHandler: public AICharacterDetailsMessageHandler { +private: + AIDebugger& _aiDebugger; +public: + CharacterHandler (AIDebugger& aiDebugger) : + _aiDebugger(aiDebugger) { + } + + void executeAICharacterDetailsMessage(const ai::AICharacterDetailsMessage& msg) override { + _aiDebugger.setCharacterDetails(msg.getCharacterId(), msg.getAggro(), msg.getNode()); + emit _aiDebugger.onSelected(); + } +}; + +class CharacterStaticHandler: public AICharacterStaticMessageHandler { +private: + AIDebugger& _aiDebugger; +public: + CharacterStaticHandler (AIDebugger& aiDebugger) : + _aiDebugger(aiDebugger) { + } + + void executeAICharacterStaticMessage(const ai::AICharacterStaticMessage& msg) override { + _aiDebugger.addCharacterStaticData(msg); + emit _aiDebugger.onSelected(); + } +}; + +class NamesHandler: public AINamesMessageHandler { +private: + AIDebugger& _aiDebugger; +public: + NamesHandler (AIDebugger& aiDebugger) : + _aiDebugger(aiDebugger) { + } + + void executeAINamesMessage(const ai::AINamesMessage& msg) override { + _aiDebugger.setNames(msg.getNames()); + emit _aiDebugger.onNamesReceived(); + } +}; + +class PauseHandler: public AIPauseMessageHandler { +private: + AIDebugger& _aiDebugger; +public: + PauseHandler (AIDebugger& aiDebugger) : + _aiDebugger(aiDebugger) { + } + + void executeAIPauseMessage(const ai::AIPauseMessage& msg) override { + _aiDebugger._pause = msg.isPause(); + emit _aiDebugger.onPause(msg.isPause()); + } +}; + +AIDebugger::AIDebugger(AINodeStaticResolver& resolver) : + QObject(), _stateHandler(new StateHandler(*this)), _characterHandler(new CharacterHandler(*this)), _characterStaticHandler( + new CharacterStaticHandler(*this)), _pauseHandler(new PauseHandler(*this)), _namesHandler(new NamesHandler(*this)), _nopHandler( + new NopHandler()), _selectedId(-1), _socket(this), _pause(false), _resolver(resolver) { + connect(&_socket, SIGNAL(readyRead()), SLOT(readTcpData())); + connect(&_socket, SIGNAL(disconnected()), SLOT(onDisconnect())); + + ai::ProtocolHandlerRegistry& r = ai::ProtocolHandlerRegistry::get(); + r.registerHandler(ai::PROTO_STATE, _stateHandler); + r.registerHandler(ai::PROTO_CHARACTER_DETAILS, _characterHandler); + r.registerHandler(ai::PROTO_CHARACTER_STATIC, _characterStaticHandler); + r.registerHandler(ai::PROTO_PAUSE, _pauseHandler); + r.registerHandler(ai::PROTO_NAMES, _namesHandler); + r.registerHandler(ai::PROTO_PING, _nopHandler); +} + +AIDebugger::~AIDebugger() { + _socket.close(); + delete _stateHandler; + delete _characterHandler; + delete _characterStaticHandler; + delete _pauseHandler; + delete _namesHandler; +} + +bool AIDebugger::isSelected(const ai::AIStateWorld& ai) const { + return _selectedId == ai.getId(); +} + +void AIDebugger::setCharacterDetails(const CharacterId& id, const AIStateAggro& aggro, const AIStateNode& node) { + _selectedId = id; + _aggro = std::move(aggro.getAggro()); + _node = std::move(node); + _attributes.clear(); + const AIStateWorld& state = _entities.value(id); + const CharacterAttributes& attributes = state.getAttributes(); + for (CharacterAttributes::const_iterator i = attributes.begin(); i != attributes.end(); ++i) { + _attributes[QString::fromStdString(i->first)] = QString::fromStdString(i->second); + } +} + +void AIDebugger::addCharacterStaticData(const AICharacterStaticMessage& msg) { + const std::vector& data = msg.getStaticNodeData(); + _resolver.set(data); +} + +const CharacterId& AIDebugger::getSelected() const { + return _selectedId; +} + +void AIDebugger::togglePause() { + const bool newPauseMode = !_pause; + writeMessage(AIPauseMessage(newPauseMode)); +} + +void AIDebugger::select(const ai::AIStateWorld& ai) { + writeMessage(AISelectMessage(ai.getId())); +} + +bool AIDebugger::writeMessage(const IProtocolMessage& msg) { + if (_socket.state() != QAbstractSocket::ConnectedState) { + return false; + } + // serialize into streamcontainer to get the final size + streamContainer out; + msg.serialize(out); + // now put the serialized message into the byte array + QByteArray temp; + QDataStream data(&temp, QIODevice::ReadWrite); + // add the framing size int + const uint32_t size = out.size(); + streamContainer sizeC; + IProtocolMessage::addInt(sizeC, size); + for (streamContainer::iterator i = sizeC.begin(); i != sizeC.end(); ++i) { + const uint8_t byte = *i; + data << byte; + } + // add the real message + for (streamContainer::iterator i = out.begin(); i != out.end(); ++i) { + const uint8_t byte = *i; + data << byte; + } + // now write everything to the socket + _socket.write(temp); + return true; +} + +void AIDebugger::unselect() { + writeMessage(AISelectMessage(-1)); + _selectedId = -1; + _aggro.clear(); + _node = AIStateNode(); + qDebug() << "unselect entity"; +} + +void AIDebugger::step() { + writeMessage(AIStepMessage(1L)); +} + +void AIDebugger::reset() { + writeMessage(AIResetMessage()); +} + +void AIDebugger::change(const QString& name) { + writeMessage(AIChangeMessage(name.toStdString())); +} + +void AIDebugger::updateNode(int32_t nodeId, const QVariant& name, const QVariant& type, const QVariant& condition) { + writeMessage(AIUpdateNodeMessage(nodeId, _selectedId, name.toString().toStdString(), type.toString().toStdString(), condition.toString().toStdString())); +} + +void AIDebugger::deleteNode(int32_t nodeId) { + writeMessage(AIDeleteNodeMessage(nodeId, _selectedId)); +} + +void AIDebugger::addNode(int32_t parentNodeId, const QVariant& name, const QVariant& type, const QVariant& condition) { + writeMessage(AIAddNodeMessage(parentNodeId, _selectedId, name.toString().toStdString(), type.toString().toStdString(), condition.toString().toStdString())); +} + +bool AIDebugger::connectToAIServer(const QString& hostname, short port) { + _socket.disconnectFromHost(); + _socket.connectToHost(hostname, port, QAbstractSocket::ReadWrite, QAbstractSocket::AnyIPProtocol); + if (_socket.waitForConnected()) { + qDebug() << "Connection established " << _socket.state(); + return true; + } + const QAbstractSocket::SocketError socketError = _socket.error(); + switch (socketError) { + case QAbstractSocket::RemoteHostClosedError: + qDebug() << "The connection was closed by the host"; + break; + case QAbstractSocket::HostNotFoundError: + qDebug() << "The host was not found. Please check the host name and port settings"; + break; + case QAbstractSocket::ConnectionRefusedError: + qDebug() << "The connection was refused by the peer"; + break; + default: + qDebug() << "Socket error: " << socketError; + break; + } + return false; +} + +void AIDebugger::onDisconnect() { + qDebug() << "disconnect from server: " << _socket.state(); + { + _pause = false; + emit onPause(_pause); + } + { + _selectedId = -1; + _aggro.clear(); + _attributes.clear(); + _node = AIStateNode(); + emit onSelected(); + } + if (!_names.empty()) { + _names.clear(); + emit onNamesReceived(); + } + if (!_entities.empty()) { + _entities.clear(); + emit onEntitiesUpdated(); + } + emit disconnect(); +} + +void AIDebugger::readTcpData() { + while (_socket.bytesAvailable() > 0) { + const QByteArray& data = _socket.readAll(); + // read everything that is currently available from the socket + // and store it in our buffer + const int n = data.count(); + for (int i = 0; i < n; ++i) { + _stream.push_back(data[i]); + } + ai::ProtocolMessageFactory& mf = ai::ProtocolMessageFactory::get(); + for (;;) { + if (!mf.isNewMessageAvailable(_stream)) + break; + std::unique_ptr msg(mf.create(_stream)); + if (!msg) { + qDebug() << "unknown server message - disconnecting"; + _socket.disconnectFromHost(); + break; + } + ai::ProtocolHandlerRegistry& r = ai::ProtocolHandlerRegistry::get(); + ai::IProtocolHandler* handler = r.getHandler(*msg); + if (handler) { + handler->execute(1, *msg); + } else { + qDebug() << "no handler for " << msg->getId(); + _socket.disconnectFromHost(); + break; + } + } + } +} + +MapView* AIDebugger::createMapWidget() { + return new MapView(*this); +} + +void AIDebugger::setNames(const std::vector& names) { + _names.clear(); + for (std::vector::const_iterator i = names.begin(); i != names.end(); ++i) { + _names << QString::fromStdString(*i); + } +} + +void AIDebugger::setEntities(const std::vector& entities) { + _entities.clear(); + for (std::vector::const_iterator i = entities.begin(); i != entities.end(); ++i) { + _entities.insert(i->getId(), *i); + } +} + +} +} diff --git a/src/rcon/AIDebugger.h b/src/rcon/AIDebugger.h new file mode 100644 index 000000000..c2c98d4b2 --- /dev/null +++ b/src/rcon/AIDebugger.h @@ -0,0 +1,152 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ai { +namespace debug { + +class MapView; +class AIDebuggerWidget; +class AINodeStaticResolver; + +/** + * @brief This is the remote debugger for the ai entities. + * + * You can extend this class and override AIDebugger::createMapWidget to create our own @c MapView instance + * to render additional details to your characters or even the map the entities are spawned on. + */ +class AIDebugger: public QObject { + Q_OBJECT +friend class PauseHandler; +public: + typedef QMap Entities; + typedef Entities::const_iterator EntitiesIter; + typedef QMap CharacterAttributesMap; +protected: + typedef Entities::iterator Iter; + // all the entities that are send by the ai debug server + Entities _entities; + + // the network protocol message handlers + ai::IProtocolHandler *_stateHandler; + ai::IProtocolHandler *_characterHandler; + ai::IProtocolHandler *_characterStaticHandler; + ai::IProtocolHandler *_pauseHandler; + ai::IProtocolHandler *_namesHandler; + ai::IProtocolHandler *_nopHandler; + + // The buffer where we store our network data until we can read one complete protocol message. + ai::streamContainer _stream; + + // the current selected entity id + ai::CharacterId _selectedId; + // the aggro list of the current selected entity + std::vector _aggro; + // the behaviour tree states of the current selected entity + AIStateNode _node; + // the attributes of the current selected entity + CharacterAttributesMap _attributes; + // the socket of the ai debug server + QTcpSocket _socket; + bool _pause; + QStringList _names; + AINodeStaticResolver& _resolver; + + bool writeMessage(const IProtocolMessage& msg); + +private slots: + void readTcpData(); + void onDisconnect(); +public: + AIDebugger(AINodeStaticResolver& resolver); + virtual ~AIDebugger(); + + /** + * @return The list of ai controlled entities + */ + const Entities& getEntities() const; + void setEntities(const std::vector& entities); + void setCharacterDetails(const CharacterId& id, const AIStateAggro& aggro, const AIStateNode& node); + void addCharacterStaticData(const AICharacterStaticMessage& msg); + void setNames(const std::vector& names); + const QStringList& getNames() const; + /** + * @return The behaviour tree node that is assigned to the selected entity + */ + const AIStateNode& getNode() const; + /** + * @return The key/value pairs of attributes that are assigned on the server side to the selected ai entity + */ + const CharacterAttributesMap& getAttributes() const; + const std::vector& getAggro() const; + + /** + * @brief Start the debugger - call this from your main method + */ + int run(); + bool connectToAIServer(const QString& hostname, short port); + + bool isSelected(const ai::AIStateWorld& ai) const; + const CharacterId& getSelected() const; + void select(const ai::AIStateWorld& ai); + void togglePause(); + void unselect(); + void step(); + void reset(); + void change(const QString& name); + void updateNode(int32_t nodeId, const QVariant& name, const QVariant& type, const QVariant& condition); + void deleteNode(int32_t nodeId); + void addNode(int32_t parentNodeId, const QVariant& name, const QVariant& type, const QVariant& condition); + + /** + * @brief override this if you would like to create your own @c MapView implementation that renders + * for example more details of your map. + */ + virtual MapView* createMapWidget(); + +signals: + void onPause(bool pause); + void disconnected(); + // signal that is triggered whenever the entity details for the current selected entity arrived + void onSelected(); + // new names list was received + void onNamesReceived(); + // entities on the map were updated + void onEntitiesUpdated(); +}; + +inline const std::vector& AIDebugger::getAggro() const { + return _aggro; +} + +inline const AIStateNode& AIDebugger::getNode() const { + return _node; +} + +inline const AIDebugger::CharacterAttributesMap& AIDebugger::getAttributes() const { + return _attributes; +} + +inline const AIDebugger::Entities& AIDebugger::getEntities() const { + return _entities; +} + +inline const QStringList& AIDebugger::getNames() const { + return _names; +} + +} +} diff --git a/src/rcon/CMakeLists.txt b/src/rcon/CMakeLists.txt new file mode 100644 index 000000000..4f98846a6 --- /dev/null +++ b/src/rcon/CMakeLists.txt @@ -0,0 +1,77 @@ +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) + +find_package(Qt5Widgets) +find_package(Qt5Network) +find_package(Qt5Gui) +find_package(Qt5LinguistTools) + +if (${Qt5Widgets_FOUND} AND ${Qt5Network_FOUND} AND ${Qt5Gui_FOUND} AND ${Qt5LinguistTools_FOUND}) + +qt5_add_resources(rcon_RESOURCES data/resources.qrc) + +fips_begin_app(rcon windowed) + fips_files( + Main.cpp + AIApplication.cpp + AIDebugger.cpp + gui/AICompressorProxy.h + gui/action/AddAction.h + gui/action/DeleteAction.h + gui/AIDebuggerWidget.cpp + gui/AINodeStaticResolver.cpp + gui/dialog/AddDialog.cpp + gui/dialog/ConnectDialog.cpp + gui/dialog/IDialog.cpp + gui/view/list/EntityList.cpp + gui/view/list/EntityListModel.cpp + gui/view/map/MapView.cpp + gui/view/map/MapItem.cpp + gui/view/tree/BehaviourTreeModel.cpp + gui/view/tree/BehaviourTreeModelItem.cpp + gui/view/tree/NodeTreeItem.cpp + gui/view/tree/NodeTreeView.cpp + gui/view/tree/TreeViewCommon.cpp + gui/view/state/StateTable.cpp + gui/view/state/StateTableModel.cpp + gui/view/aggro/AggroTable.cpp + gui/view/aggro/AggroTableModel.cpp + gui/widget/ZoomFrame.cpp + gui/widget/ZoomWidget.cpp + gui/widget/IComboBox.cpp + gui/widget/IGraphicsView.cpp + data/resources.qrc + ) + + fips_include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${AUTOGEN_TARGETS_FOLDER} + ${AUTOMOC_TARGETS_FOLDER} + ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_CURRENT_SOURCE_DIR}/gui + ${CMAKE_CURRENT_SOURCE_DIR}/gui/action + ${CMAKE_CURRENT_SOURCE_DIR}/gui/dialog + ${CMAKE_CURRENT_SOURCE_DIR}/gui/widget + ${CMAKE_CURRENT_SOURCE_DIR}/gui/view/map + ${CMAKE_CURRENT_SOURCE_DIR}/gui/view/tree + ${CMAKE_CURRENT_SOURCE_DIR}/gui/view/aggro + ${CMAKE_CURRENT_SOURCE_DIR}/gui/view/state + ${CMAKE_CURRENT_SOURCE_DIR}/gui/view/list + ${CMAKE_CURRENT_SOURCE_DIR}/common + ) + + if (FIPS_LINUX) + check_function_exists(__atomic_fetch_add_4 HAVE___ATOMIC_FETCH_ADD_4) + if (NOT HAVE___ATOMIC_FETCH_ADD_4) + check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC) + if (HAVE_LIBATOMIC) + fips_libs("atomic") + endif() + endif() + endif() + + fips_deps(simpleai) +fips_end_app() +qt5_use_modules(rcon Widgets Gui Network) + +endif() # NO QT diff --git a/src/rcon/Main.cpp b/src/rcon/Main.cpp new file mode 100644 index 000000000..65dc585e4 --- /dev/null +++ b/src/rcon/Main.cpp @@ -0,0 +1,16 @@ +#include "AIApplication.h" +#include "AIDebugger.h" +#include "AIDebuggerWidget.h" + +#ifdef AI_PROFILER +#include +#endif + +int main(int argc, char **argv) { +#ifdef AI_PROFILER + ProfilerStart("simpleai-debugger.prof"); +#endif + + ai::debug::AIApplication app(argc, argv); + return app.exec(); +} diff --git a/src/rcon/README.md b/src/rcon/README.md new file mode 100644 index 000000000..0843bd78d --- /dev/null +++ b/src/rcon/README.md @@ -0,0 +1,4 @@ +To compile this on a debian based linux, you will need +some qt related packages installed: + +sudo apt-get install qt5-default qttools5-dev qttools5-dev-tools diff --git a/src/rcon/Version.h b/src/rcon/Version.h new file mode 100644 index 000000000..27575720c --- /dev/null +++ b/src/rcon/Version.h @@ -0,0 +1,3 @@ +#pragma once + +#define VERSION "0.1" diff --git a/src/rcon/app.rc b/src/rcon/app.rc new file mode 100644 index 000000000..a125fd419 --- /dev/null +++ b/src/rcon/app.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "simpleai-debugger.ico" diff --git a/src/rcon/common/Common.h b/src/rcon/common/Common.h new file mode 100644 index 000000000..d3d9b659c --- /dev/null +++ b/src/rcon/common/Common.h @@ -0,0 +1,4 @@ +#pragma once + +#define COMPILE_TIME_ASSERT(statement) extern int COMPILE_TIME_ASSERT_ARRAY[((statement) != 0) * 2 - 1] +#define ARRAY_LENGTH(array) (sizeof(array) / sizeof(*(array))) diff --git a/src/rcon/common/Settings.h b/src/rcon/common/Settings.h new file mode 100644 index 000000000..1d938934a --- /dev/null +++ b/src/rcon/common/Settings.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +class Settings { +private: + QSettings _settings; + Settings() : + _settings("simpleai", "simpleai") { + } + +public: + static QSettings& getSettings() { + static Settings s; + return s._settings; + } + + static void setIfAbsent(const QString& key, const QString& value) { + if (getSettings().allKeys().contains(key)) + return; + getSettings().setValue(key, value); + } + +}; diff --git a/src/rcon/data/images/about.png b/src/rcon/data/images/about.png new file mode 100644 index 000000000..8c423a8ec Binary files /dev/null and b/src/rcon/data/images/about.png differ diff --git a/src/rcon/data/images/connect.png b/src/rcon/data/images/connect.png new file mode 100644 index 000000000..a06d13014 Binary files /dev/null and b/src/rcon/data/images/connect.png differ diff --git a/src/rcon/data/images/continue.png b/src/rcon/data/images/continue.png new file mode 100644 index 000000000..569ad23f6 Binary files /dev/null and b/src/rcon/data/images/continue.png differ diff --git a/src/rcon/data/images/exit.png b/src/rcon/data/images/exit.png new file mode 100644 index 000000000..2c6d72401 Binary files /dev/null and b/src/rcon/data/images/exit.png differ diff --git a/src/rcon/data/images/node.png b/src/rcon/data/images/node.png new file mode 100644 index 000000000..08a920e79 Binary files /dev/null and b/src/rcon/data/images/node.png differ diff --git a/src/rcon/data/images/pause.png b/src/rcon/data/images/pause.png new file mode 100644 index 000000000..8a39b78a1 Binary files /dev/null and b/src/rcon/data/images/pause.png differ diff --git a/src/rcon/data/images/priorityselector.png b/src/rcon/data/images/priorityselector.png new file mode 100644 index 000000000..7b770cec4 Binary files /dev/null and b/src/rcon/data/images/priorityselector.png differ diff --git a/src/rcon/data/images/reset.png b/src/rcon/data/images/reset.png new file mode 100644 index 000000000..15deae018 Binary files /dev/null and b/src/rcon/data/images/reset.png differ diff --git a/src/rcon/data/images/selector.png b/src/rcon/data/images/selector.png new file mode 100644 index 000000000..ce8e9660c Binary files /dev/null and b/src/rcon/data/images/selector.png differ diff --git a/src/rcon/data/images/splash.png b/src/rcon/data/images/splash.png new file mode 100644 index 000000000..7959af327 Binary files /dev/null and b/src/rcon/data/images/splash.png differ diff --git a/src/rcon/data/images/step.png b/src/rcon/data/images/step.png new file mode 100644 index 000000000..ac0c63d48 Binary files /dev/null and b/src/rcon/data/images/step.png differ diff --git a/src/rcon/data/images/switch.png b/src/rcon/data/images/switch.png new file mode 100644 index 000000000..78b06b49d Binary files /dev/null and b/src/rcon/data/images/switch.png differ diff --git a/src/rcon/data/images/zoomin.png b/src/rcon/data/images/zoomin.png new file mode 100644 index 000000000..2c876792d Binary files /dev/null and b/src/rcon/data/images/zoomin.png differ diff --git a/src/rcon/data/images/zoomout.png b/src/rcon/data/images/zoomout.png new file mode 100644 index 000000000..689e321de Binary files /dev/null and b/src/rcon/data/images/zoomout.png differ diff --git a/src/rcon/data/resources.qrc b/src/rcon/data/resources.qrc new file mode 100644 index 000000000..db57e9e0c --- /dev/null +++ b/src/rcon/data/resources.qrc @@ -0,0 +1,21 @@ + + + images/splash.png + images/connect.png + images/step.png + images/reset.png + images/continue.png + images/exit.png + images/about.png + images/pause.png + images/zoomin.png + images/zoomout.png + images/switch.png + images/node.png + images/selector.png + images/priorityselector.png + + + diff --git a/src/rcon/gui/AICompressorProxy.h b/src/rcon/gui/AICompressorProxy.h new file mode 100644 index 000000000..73e971537 --- /dev/null +++ b/src/rcon/gui/AICompressorProxy.h @@ -0,0 +1,58 @@ +#pragma once + +#include +#include +#include + +class CompressorProxy: public QObject { +Q_OBJECT +private: + inline bool emitCheck(bool & flag) { + flag = true; + QCoreApplication::sendPostedEvents(this, QEvent::MetaCall); // recurse + bool result = flag; + flag = false; + return result; + } + + bool _selected; + bool _entitiesUpdated; + bool _namesReceived; + +private slots: + void selected() { + if (!emitCheck(_selected)) { + return; + } + emit onSelected(); + } + + void entitiesUpdated() { + if (!emitCheck(_entitiesUpdated)) { + return; + } + emit onEntitiesUpdated(); + } + + void namesReceived() { + if (!emitCheck(_namesReceived)) { + return; + } + emit onNamesReceived(); + } + +signals: + // signal that is triggered whenever the entity details for the current selected entity arrived + void onSelected(); + // new names list was received + void onNamesReceived(); + // entities on the map were updated + void onEntitiesUpdated(); + +public: + // No default constructor, since the proxy must be a child of the + // target object. + explicit CompressorProxy(QObject * parent) : + QObject(parent), _selected(false), _entitiesUpdated(false), _namesReceived(false) { + } +}; diff --git a/src/rcon/gui/AIDebuggerWidget.cpp b/src/rcon/gui/AIDebuggerWidget.cpp new file mode 100644 index 000000000..56815fe55 --- /dev/null +++ b/src/rcon/gui/AIDebuggerWidget.cpp @@ -0,0 +1,396 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "AIDebugger.h" +#include "AIDebuggerWidget.h" +#include "ConnectDialog.h" +#include "StateTable.h" +#include "EntityList.h" +#include "AggroTable.h" +#include "MapView.h" +#include "ZoomFrame.h" +#include "NodeTreeView.h" +#include "AddAction.h" +#include "DeleteAction.h" + +namespace ai { +namespace debug { + +AIDebuggerWidget::AIDebuggerWidget(AIDebugger& debugger, AINodeStaticResolver& resolver) : + QWidget(), _resolver(resolver), _model(debugger, resolver), _debugger(debugger), _proxy(this) { + createView(); + createActions(); + + _statusBarLabel = new QLabel(tr("not connected")); + _selectedLabel = new QLabel(tr("nothing selected")); + + connect(_namesComboBox, SIGNAL(currentIndexChanged(const QString &)), SLOT(change(const QString &))); + connect(&_debugger, SIGNAL(onPause(bool)), SLOT(setPause(bool))); + connect(&_debugger, SIGNAL(disconnected()), SLOT(onDisconnect())); + + connect(&_debugger, SIGNAL(onSelected()), &_proxy, SLOT(selected()), Qt::QueuedConnection); + connect(&_debugger, SIGNAL(onNamesReceived()), &_proxy, SLOT(namesReceived()), Qt::QueuedConnection); + connect(&_debugger, SIGNAL(onEntitiesUpdated()), &_proxy, SLOT(entitiesUpdated()), Qt::QueuedConnection); + + connect(&_proxy, SIGNAL(onSelected()), this, SLOT(onSelected())); + connect(&_proxy, SIGNAL(onEntitiesUpdated()), this, SLOT(onEntitiesUpdated())); + connect(&_proxy, SIGNAL(onNamesReceived()), this, SLOT(onNamesReceived())); +} + +AIDebuggerWidget::~AIDebuggerWidget() { + delete _nodeTree; + delete _nodeTreeFrame; + delete _mapFrame; + delete _entityList; + delete _statusBarLabel; + delete _selectedLabel; + delete _stateTable; + delete _aggroTable; + delete _pauseAction; + delete _resetAction; + delete _stepAction; + delete _connectAction; + delete _aboutAction; + delete _documentationAction; + delete _bugAction; + delete _namesComboBox; + delete _tree; +} + +void AIDebuggerWidget::onEntitiesUpdated() { + _entityList->updateEntityList(); + _mapWidget->updateMapView(); +} + +void AIDebuggerWidget::onSelected() { + const ai::CharacterId& id = _debugger.getSelected(); + if (id == -1) { + _selectedLabel->setText(tr("nothing selected")); + } else { + _selectedLabel->setText(tr("selected %1").arg(id)); + } + _stateTable->updateStateTable(); + _nodeTree->updateTreeWidget(); + _model.setRootNode(const_cast(&_debugger.getNode())); + _tree->expandAll(); + _aggroTable->updateAggroTable(); +} + +void AIDebuggerWidget::onNamesReceived() { + const QString name = _namesComboBox->currentText(); + _namesComboBox->clear(); + const QStringList& names = _debugger.getNames(); + if (names.empty()) { + _namesComboBox->insertItem(0, tr("None")); + _namesComboBox->setEnabled(false); + } else { + _namesComboBox->insertItems(0, names); + _namesComboBox->setEnabled(true); + } + const int index = _namesComboBox->findText(name); + if (index == -1) { + if (!names.empty()) + _namesComboBox->setCurrentIndex(0); + return; + } + + _namesComboBox->setCurrentIndex(index); +} + +void AIDebuggerWidget::contributeToStatusBar(QStatusBar* statusBar) { + statusBar->addWidget(_statusBarLabel); + statusBar->addWidget(_selectedLabel); +} + +void AIDebuggerWidget::contributeToToolBar(QToolBar* toolBar) { + toolBar->addAction(_connectAction); + toolBar->addAction(_pauseAction); + toolBar->addAction(_stepAction); + toolBar->addAction(_resetAction); +} + +void AIDebuggerWidget::contributeToFileMenu(QMenu *fileMenu) { + fileMenu->addAction(_connectAction); +} + +void AIDebuggerWidget::contributeToHelpMenu(QMenu *helpMenu) { + helpMenu->addAction(_documentationAction); + helpMenu->addAction(_bugAction); + helpMenu->addAction(_aboutAction); +} + +void AIDebuggerWidget::removeFromStatusBar(QStatusBar* statusBar) { + statusBar->removeWidget(_statusBarLabel); + statusBar->removeWidget(_selectedLabel); +} + +void AIDebuggerWidget::removeFromToolBar(QToolBar* toolBar) { + toolBar->removeAction(_connectAction); + toolBar->removeAction(_pauseAction); + toolBar->removeAction(_stepAction); + toolBar->removeAction(_resetAction); +} + +void AIDebuggerWidget::removeFromFileMenu(QMenu *fileMenu) { + fileMenu->removeAction(_connectAction); +} + +void AIDebuggerWidget::removeFromHelpMenu(QMenu *helpMenu) { + helpMenu->removeAction(_bugAction); + helpMenu->removeAction(_documentationAction); + helpMenu->removeAction(_aboutAction); +} + +void AIDebuggerWidget::createView() { + QVBoxLayout *layout = new QVBoxLayout; + QSplitter* splitter = new QSplitter(Qt::Orientation::Vertical); + splitter->addWidget(createTopWidget()); + splitter->addWidget(createBottomWidget()); + layout->addWidget(splitter); + setLayout(layout); +} + +QWidget *AIDebuggerWidget::createTopWidget() { + QSplitter *splitter = new QSplitter; + + _mapWidget = _debugger.createMapWidget(); + _mapFrame = new ZoomFrame(_mapWidget); + + _entityFilter = new QLineEdit(); + _entityList = new EntityList(_debugger, _entityFilter); + _namesComboBox = new QComboBox(); + _namesComboBox->setFixedWidth(_entityList->width()); + _namesComboBox->setInsertPolicy(QComboBox::InsertAlphabetically); + _namesComboBox->addItem(tr("None")); + + splitter->addWidget(_mapFrame); + + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->setMargin(0); + vbox->addWidget(_namesComboBox); + vbox->addWidget(_entityFilter); + vbox->addWidget(_entityList); + + QWidget *widget = new QWidget(); + widget->setFixedWidth(_entityList->width()); + widget->setLayout(vbox); + splitter->addWidget(widget); + + return splitter; +} + +void AIDebuggerWidget::onDeleteNode(int nodeId) { + _debugger.deleteNode(nodeId); +} + +void AIDebuggerWidget::onAddNode(int parentNodeId, const QVariant& name, const QVariant& type, const QVariant& condition) { + _debugger.addNode(parentNodeId, name, type, condition); +} + +void AIDebuggerWidget::showContextMenu(const QPoint &pos) { + const QModelIndex& index = _tree->indexAt(pos); + BehaviourTreeModelItem* item = _model.item(index); + if (item == nullptr) { + qDebug() << "No item found for index: " << index; + return; + } + const AIStateNode* node = item->node(); + QMenu *menu = new QMenu(this); + AddAction* addAction = new AddAction(node->getNodeId(), this); + connect(addAction, SIGNAL(triggered(int, const QVariant&, const QVariant&, const QVariant&)), this, + SLOT(onAddNode(int, const QVariant&, const QVariant&, const QVariant&))); + QAction* deleteAction = new DeleteAction(node->getNodeId(), this); + connect(deleteAction, SIGNAL(triggered(int)), this, + SLOT(onDeleteNode(int))); + menu->addAction(addAction); + menu->addAction(deleteAction); + menu->popup(_tree->viewport()->mapToGlobal(pos)); +} + +QWidget *AIDebuggerWidget::createTreePanelWidget() { + QWidget* treePanel = new QWidget(); + treePanel->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding); + + _nodeTree = new NodeTreeView(_debugger, _resolver); + _nodeTreeFrame = new ZoomFrame(_nodeTree, treePanel); + _nodeTreeFrame->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + _nodeTreeFrame->setVisible(false); + _aggroTable = new AggroTable(_debugger); + _stateTable = new StateTable(_debugger); + + _tree = new QTreeView(treePanel); + _tree->setUniformRowHeights(true); + _tree->setAlternatingRowColors(true); + _tree->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + _tree->setModel(&_model); + _tree->setContextMenuPolicy(Qt::CustomContextMenu); + + connect(_tree, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(showContextMenu(const QPoint &))); + + QHeaderView *header = _tree->header(); + header->setStretchLastSection(false); + header->setSectionResizeMode(COL_NAME, QHeaderView::Stretch); + header->setSectionResizeMode(COL_TYPE, QHeaderView::Stretch); + header->setSectionResizeMode(COL_CONDITION, QHeaderView::Stretch); + header->setSectionResizeMode(COL_STATE, QHeaderView::ResizeToContents); + header->setSectionResizeMode(COL_LASTRUN, QHeaderView::ResizeToContents); + + QPushButton *toggle = new QPushButton(QIcon(":/images/switch.png"), "", treePanel); + toggle->setFlat(true); + toggle->setCheckable(true); + toggle->setFixedSize(16, 16); + toggle->setToolTip(tr("Switch between tree views")); + connect(toggle, SIGNAL(released()), this, SLOT(toggleTreeView())); + toggle->raise(); + + QGridLayout *treeLayout = new QGridLayout(); + treeLayout->setColumnStretch(0, 10); + treeLayout->setRowStretch(0, 10); + treeLayout->addWidget(_nodeTreeFrame, 0, 0); + treeLayout->addWidget(_tree, 0, 0); + treeLayout->addWidget(toggle, 0, 0, Qt::AlignRight | Qt::AlignTop); + + treePanel->setLayout(treeLayout); + treePanel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + return treePanel; +} + +QWidget *AIDebuggerWidget::createBottomWidget() { + QSplitter *splitter = new QSplitter; + + QWidget* treePanel = createTreePanelWidget(); + splitter->addWidget(treePanel); + splitter->setStretchFactor(splitter->indexOf(treePanel), 5); + splitter->addWidget(_aggroTable); + splitter->setStretchFactor(splitter->indexOf(_aggroTable), 1); + splitter->addWidget(_stateTable); + splitter->setStretchFactor(splitter->indexOf(_stateTable), 1); + return splitter; +} + +void AIDebuggerWidget::onDisconnect() { + _statusBarLabel->setText(tr("not connected")); +} + +void AIDebuggerWidget::change(const QString &name) { + _name = name; + _debugger.change(name); +} + +void AIDebuggerWidget::setPause(bool pause) { + if (pause) { + _pauseAction->setIcon(QIcon(":/images/continue.png")); + } else { + _pauseAction->setIcon(QIcon(":/images/pause.png")); + } +} + +void AIDebuggerWidget::requestStep() { + _debugger.step(); +} + +void AIDebuggerWidget::requestReset() { + _debugger.reset(); +} + +void AIDebuggerWidget::requestPause() { + _debugger.togglePause(); +} + +void AIDebuggerWidget::connectToAIServer(const QString& hostname, short port) { + if (_debugger.connectToAIServer(hostname, port)) { + _statusBarLabel->setText(tr("connected to %1:%2").arg(hostname).arg(port)); + } else { + _statusBarLabel->setText(tr("connection to %1:%2 failed").arg(hostname).arg(port)); + } +} + +void AIDebuggerWidget::connectToAIServer() { + ConnectDialog d; + const int state = d.run(); + if (state != QDialog::Accepted) { + _statusBarLabel->setText(tr("not connected")); + return; + } + const short port = d.getPort(); + const QString& hostname = d.getHostname(); + connectToAIServer(hostname, port); +} + +void AIDebuggerWidget::about() { + QMessageBox::about(this, tr("About"), tr("AI debug visualization for libsimpleai.
Grab the latest version at github")); +} + +void AIDebuggerWidget::documentation() { + QDesktopServices::openUrl(QUrl("https://github.com/mgerhardy/simpleai/wiki")); +} + +void AIDebuggerWidget::bug() { + QDesktopServices::openUrl(QUrl("https://github.com/mgerhardy/simpleai/issues")); +} + +void AIDebuggerWidget::toggleTreeView() { + if (_nodeTreeFrame->isVisible()) { + _nodeTreeFrame->setVisible(false); + _tree->setVisible(true); + } else { + _nodeTreeFrame->setVisible(true); + _tree->setVisible(false); + } +} + +void AIDebuggerWidget::createActions() { + _connectAction = new QAction(tr("C&onnect"), this); + _connectAction->setShortcuts(QKeySequence::Open); + _connectAction->setStatusTip(tr("Connect to AI server")); + _connectAction->setIcon(QIcon(":/images/connect.png")); + connect(_connectAction, SIGNAL(triggered()), this, SLOT(connectToAIServer())); + + _pauseAction = new QAction(tr("Pause"), this); + _pauseAction->setStatusTip(tr("Freeze the ai controlled entities")); + _pauseAction->setIcon(QIcon(":/images/pause.png")); + connect(_pauseAction, SIGNAL(triggered()), this, SLOT(requestPause())); + + _stepAction = new QAction(tr("Step"), this); + _stepAction->setStatusTip(tr("Performs one step while ai is in pause mode")); + _stepAction->setIcon(QIcon(":/images/step.png")); + connect(_stepAction, SIGNAL(triggered()), this, SLOT(requestStep())); + + _resetAction = new QAction(tr("Reset"), this); + _resetAction->setStatusTip(tr("Resets the states of the ai")); + _resetAction->setIcon(QIcon(":/images/reset.png")); + connect(_resetAction, SIGNAL(triggered()), this, SLOT(requestReset())); + + _aboutAction = new QAction(tr("&About"), this); + _aboutAction->setStatusTip(tr("Show the application's About box")); + _aboutAction->setIcon(QIcon(":/images/about.png")); + connect(_aboutAction, SIGNAL(triggered()), this, SLOT(about())); + + _documentationAction = new QAction(tr("&Documentation"), this); + _documentationAction->setStatusTip(tr("Open the libsimpleai documentation")); + _documentationAction->setIcon(QIcon(":/images/docs.png")); + connect(_documentationAction, SIGNAL(triggered()), this, SLOT(documentation())); + + _bugAction = new QAction(tr("&Report a bug"), this); + _bugAction->setStatusTip(tr("Report a bug")); + _bugAction->setIcon(QIcon(":/images/bug.png")); + connect(_bugAction, SIGNAL(triggered()), this, SLOT(bug())); +} + +QLabel *AIDebuggerWidget::createLabel(const QString &text) const { + QLabel *label = new QLabel(text); + label->setAlignment(Qt::AlignCenter); + label->setMargin(2); + label->setFrameStyle(QFrame::Box | QFrame::Sunken); + return label; +} + +} +} diff --git a/src/rcon/gui/AIDebuggerWidget.h b/src/rcon/gui/AIDebuggerWidget.h new file mode 100644 index 000000000..8d821f6be --- /dev/null +++ b/src/rcon/gui/AIDebuggerWidget.h @@ -0,0 +1,129 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "BehaviourTreeModel.h" +#include "AICompressorProxy.h" +#include "AINodeStaticResolver.h" +#include "BehaviourTreeModelItem.h" + +namespace ai { +namespace debug { + +class StateTable; +class EntityList; +class AggroTable; +class NodeTreeView; +class ZoomFrame; +class MapView; +class AIDebugger; + +/** + * @brief The widget that represents the whole ai debugger + */ +class AIDebuggerWidget: public QWidget { +Q_OBJECT +public: + AIDebuggerWidget(AIDebugger& debugger, AINodeStaticResolver& resolver); + virtual ~AIDebuggerWidget(); + + void connectToAIServer(const QString& hostname, short port); + + /** + * @brief Call this with an existing @c QStatusBar to add additional ai debugger information to it + */ + void contributeToStatusBar(QStatusBar* statusBar); + /** + * @brief Call this with an existing @c QToolbar to add addition ai debugger buttons to it + */ + void contributeToToolBar(QToolBar* toolBar); + /** + * @brief Call this with an existing @c QToolbar to add addition ai debugger entries to it + */ + void contributeToFileMenu(QMenu *fileMenu); + /** + * @brief Call this with an existing @c QToolbar to add addition ai debugger entries to it + */ + void contributeToHelpMenu(QMenu *helpMenu); + + /** + * @brief If you let the ai debugger contribute to the status bar, call if to remove the contribution + */ + void removeFromStatusBar(QStatusBar* statusBar); + /** + * @brief If you let the ai debugger contribute to the tool bar, call if to remove the contribution + */ + void removeFromToolBar(QToolBar* toolBar); + /** + * @brief If you let the ai debugger contribute to the file menu, call if to remove the contribution + */ + void removeFromFileMenu(QMenu *fileMenu); + /** + * @brief If you let the ai debugger contribute to the help menu, call if to remove the contribution + */ + void removeFromHelpMenu(QMenu *helpMenu); + +private slots: + void about(); + void documentation(); + void bug(); + void toggleTreeView(); + void connectToAIServer(); + void requestPause(); + void requestStep(); + void requestReset(); + void setPause(bool pause); + void change(const QString &); + void onNamesReceived(); + void onDisconnect(); + void onEntitiesUpdated(); + void onSelected(); + void showContextMenu(const QPoint& pos); + void onDeleteNode(int nodeId); + void onAddNode(int parentNodeId, const QVariant& name, const QVariant& type, const QVariant& condition); + +private: + void createView(); + void createActions(); + + QWidget *createTopWidget(); + QWidget *createBottomWidget(); + QWidget *createTreePanelWidget(); + QLabel *createLabel(const QString &text) const; + + NodeTreeView *_nodeTree; + ZoomFrame *_nodeTreeFrame; + StateTable *_stateTable; + ZoomFrame *_mapFrame; + MapView *_mapWidget; + EntityList *_entityList; + QLineEdit *_entityFilter; + AggroTable *_aggroTable; + QAction *_connectAction; + QAction *_pauseAction; + QAction *_stepAction; + QAction *_resetAction; + QAction *_aboutAction; + QAction *_documentationAction; + QAction *_bugAction; + QLabel *_statusBarLabel; + QLabel *_selectedLabel; + QComboBox *_namesComboBox; + QTreeView *_tree; + AINodeStaticResolver& _resolver; + BehaviourTreeModel _model; + + AIDebugger& _debugger; + QString _name; + CompressorProxy _proxy; +}; + +} +} diff --git a/src/rcon/gui/AINodeStaticResolver.cpp b/src/rcon/gui/AINodeStaticResolver.cpp new file mode 100644 index 000000000..1031bb205 --- /dev/null +++ b/src/rcon/gui/AINodeStaticResolver.cpp @@ -0,0 +1,35 @@ +#include "AINodeStaticResolver.h" +#include +#include +#include + +namespace ai { +namespace debug { + +namespace { +const AIStateNodeStatic UNKNOWN(-1, "unknown", "unknown", "unknown", "unknown", "unknown"); +} + +AINodeStaticResolver::AINodeStaticResolver() { +} + +void AINodeStaticResolver::set(const std::vector& data) { + _data = data; + _hash.clear(); + for (const AIStateNodeStatic& s : _data) { + _hash[s.getId()] = &s; + } + qDebug() << "received " << _hash.size() << " entries"; +} + +const AIStateNodeStatic& AINodeStaticResolver::get(int32_t id) const { + const AIStateNodeStatic* s = _hash[id]; + if (s == nullptr) { + qDebug() << "entry for " << id << " wasn't found"; + return UNKNOWN; + } + return *s; +} + +} +} diff --git a/src/rcon/gui/AINodeStaticResolver.h b/src/rcon/gui/AINodeStaticResolver.h new file mode 100644 index 000000000..f661a3d49 --- /dev/null +++ b/src/rcon/gui/AINodeStaticResolver.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +namespace ai { + +class AIStateNodeStatic; + +namespace debug { + +class AINodeStaticResolver { +private: + std::vector _data; + QHash _hash; +public: + AINodeStaticResolver(); + + void set(const std::vector& data); + const AIStateNodeStatic& get(int32_t id) const; +}; + +} +} diff --git a/src/rcon/gui/action/AddAction.h b/src/rcon/gui/action/AddAction.h new file mode 100644 index 000000000..44ce41883 --- /dev/null +++ b/src/rcon/gui/action/AddAction.h @@ -0,0 +1,32 @@ +#include +#include +#include "AddDialog.h" + +namespace ai { +namespace debug { + +class BehaviourTreeModelItem; + +class AddAction: public QAction { +Q_OBJECT +private: + int _parentId; + +private slots: + void onTriggered() { + AddDialog d; + d.run(); + emit triggered(_parentId, d.getName(), d.getType(), d.getCondition()); + } +public: + AddAction(int parentId, QObject* parent) : + QAction(parent), _parentId(parentId) { + setText(tr("Add node")); + connect(this, SIGNAL(triggered()), this, SLOT(onTriggered())); + } +signals: + void triggered(int parentId, const QVariant& name, const QVariant& type, const QVariant& condition); +}; + +} +} diff --git a/src/rcon/gui/action/DeleteAction.h b/src/rcon/gui/action/DeleteAction.h new file mode 100644 index 000000000..8c2ccd84a --- /dev/null +++ b/src/rcon/gui/action/DeleteAction.h @@ -0,0 +1,29 @@ +#include +#include +#include "AddDialog.h" + +namespace ai { +namespace debug { + +class BehaviourTreeModelItem; + +class DeleteAction: public QAction { +Q_OBJECT +private: + int _nodeId; +private slots: + void onTriggered() { + emit triggered(_nodeId); + } +public: + DeleteAction(int nodeId, QObject* parent) : + QAction(parent), _nodeId(nodeId) { + setText(tr("Delete node")); + connect(this, SIGNAL(triggered()), this, SLOT(onTriggered())); + } +signals: + void triggered(int nodeId); +}; + +} +} diff --git a/src/rcon/gui/dialog/AddDialog.cpp b/src/rcon/gui/dialog/AddDialog.cpp new file mode 100644 index 000000000..7132a9473 --- /dev/null +++ b/src/rcon/gui/dialog/AddDialog.cpp @@ -0,0 +1,39 @@ +#include "AddDialog.h" +#include +#include + +AddDialog::AddDialog() : + IDialog(tr("Create new node")), _nameText(nullptr), _typeText(nullptr), _conditionText(nullptr), _group( + nullptr) { +} + +AddDialog::~AddDialog() { + delete _nameText; + delete _typeText; + delete _conditionText; + delete _group; +} + +void AddDialog::addMainWidgets(QBoxLayout& layout) { + _group = new QGroupBox(tr("Node")); + QGridLayout *innerLayout = new QGridLayout; + _nameText = new QLineEdit("NewNode"); + innerLayout->addWidget(new QLabel(tr("Name")), 0, 0); + innerLayout->addWidget(_nameText, 0, 1); + _typeText = new QLineEdit("PrioritySelector"); + innerLayout->addWidget(new QLabel(tr("Type")), 1, 0); + innerLayout->addWidget(_typeText, 1, 1); + _conditionText = new QLineEdit("True"); + innerLayout->addWidget(new QLabel(tr("Condition")), 2, 0); + innerLayout->addWidget(_conditionText, 2, 1); + _group->setLayout(innerLayout); + layout.addWidget(_group); +} + +void AddDialog::onApply() { + _condition = _conditionText->text(); + _name = _nameText->text(); + _type = _typeText->text(); + + close(); +} diff --git a/src/rcon/gui/dialog/AddDialog.h b/src/rcon/gui/dialog/AddDialog.h new file mode 100644 index 000000000..17b91dc3e --- /dev/null +++ b/src/rcon/gui/dialog/AddDialog.h @@ -0,0 +1,38 @@ +#pragma once + +#include "IDialog.h" + +#include +#include + +class AddDialog: public IDialog { +Q_OBJECT +private: + QLineEdit *_nameText; + QLineEdit *_typeText; + QLineEdit *_conditionText; + QGroupBox *_group; + + QString _name; + QString _type; + QString _condition; + +public: + AddDialog(); + virtual ~AddDialog(); + + virtual void onApply() override; + virtual void addMainWidgets(QBoxLayout& layout) override; + + inline const QString& getName() const { + return _name; + } + + inline const QString& getType() const { + return _type; + } + + inline const QString& getCondition() const { + return _condition; + } +}; diff --git a/src/rcon/gui/dialog/ConnectDialog.cpp b/src/rcon/gui/dialog/ConnectDialog.cpp new file mode 100644 index 000000000..a9fce96f4 --- /dev/null +++ b/src/rcon/gui/dialog/ConnectDialog.cpp @@ -0,0 +1,45 @@ +#include "ConnectDialog.h" +#include +#include "Settings.h" + +#define S_HOSTNAME "hostname" +#define S_PORT "port" + +ConnectDialog::ConnectDialog(const QString& defaultHostname, short defaultPort) : + IDialog(tr("Connect to AI server")), _hostnameText(nullptr), _portText(nullptr), _group( + nullptr) { + Settings::setIfAbsent(S_HOSTNAME, defaultHostname); + Settings::setIfAbsent(S_PORT, QString::number(defaultPort)); + + const QSettings& settings = Settings::getSettings(); + _hostname = settings.value(S_HOSTNAME).toString(); + _port = settings.value(S_PORT).toInt(); +} + +ConnectDialog::~ConnectDialog() { + delete _hostnameText; + delete _portText; + delete _group; +} + +void ConnectDialog::addMainWidgets(QBoxLayout& layout) { + _group = new QGroupBox(tr("Server")); + QVBoxLayout *boxLayout = new QVBoxLayout; + _hostnameText = new QLineEdit(_hostname); + boxLayout->addWidget(_hostnameText); + _portText = new QLineEdit(QString::number(_port)); + boxLayout->addWidget(_portText); + _group->setLayout(boxLayout); + layout.addWidget(_group); +} + +void ConnectDialog::onApply() { + _hostname = _hostnameText->text(); + _port = _portText->text().toShort(); + + QSettings& settings = Settings::getSettings(); + settings.setValue(S_HOSTNAME, _hostname); + settings.setValue(S_PORT, _portText->text()); + + close(); +} diff --git a/src/rcon/gui/dialog/ConnectDialog.h b/src/rcon/gui/dialog/ConnectDialog.h new file mode 100644 index 000000000..3bafcb4b7 --- /dev/null +++ b/src/rcon/gui/dialog/ConnectDialog.h @@ -0,0 +1,30 @@ +#pragma once + +#include "IDialog.h" + +#include +#include + +class ConnectDialog: public IDialog { +Q_OBJECT +private: + QLineEdit *_hostnameText; + QLineEdit *_portText; + QGroupBox *_group; + QString _hostname; + short _port; +public: + ConnectDialog(const QString& defaultHostname = "0.0.0.0", short defaultPort = 12345); + virtual ~ConnectDialog(); + + virtual void onApply() override; + virtual void addMainWidgets(QBoxLayout& layout) override; + + inline const QString& getHostname() const { + return _hostname; + } + + inline short getPort() const { + return _port; + } +}; diff --git a/src/rcon/gui/dialog/IDialog.cpp b/src/rcon/gui/dialog/IDialog.cpp new file mode 100644 index 000000000..de8b6b153 --- /dev/null +++ b/src/rcon/gui/dialog/IDialog.cpp @@ -0,0 +1,54 @@ +#include "IDialog.h" + +#include +#include +#include +#include +#include + +IDialog::IDialog(const QString &title, int flags) : + QDialog(nullptr, 0), _title(title), _applyButton( + nullptr), _closeButton(nullptr), _buttonLayout(nullptr), _buttons( + nullptr), _mainLayout(nullptr), _flags(flags) { + setWindowTitle(_title); + setModal(false); +} + +IDialog::~IDialog() { + if (!(_flags & DIALOG_NO_APPLY_BUTTON)) { + delete _applyButton; + } + delete _closeButton; + delete _buttonLayout; + delete _buttons; + delete _mainLayout; +} + +int IDialog::run() { + _buttonLayout = new QHBoxLayout; + _buttons = new QWidget; + addButtons(*_buttonLayout); + _buttons->setLayout(_buttonLayout); + + _mainLayout = new QVBoxLayout; + addMainWidgets(*_mainLayout); + _mainLayout->addSpacing(12); + _mainLayout->addWidget(_buttons); + _mainLayout->addStretch(1); + setLayout(_mainLayout); + + show(); + exec(); + return result(); +} + +void IDialog::addButtons(QBoxLayout& layout) { + if (!(_flags & DIALOG_NO_APPLY_BUTTON)) { + _applyButton = new QPushButton(tr("Apply")); + connect(_applyButton, SIGNAL(clicked()), this, SLOT(apply())); + layout.addWidget(_applyButton); + } + _closeButton = new QPushButton(tr("Close")); + connect(_closeButton, SIGNAL(clicked()), this, SLOT(reject())); + layout.addWidget(_closeButton); +} diff --git a/src/rcon/gui/dialog/IDialog.h b/src/rcon/gui/dialog/IDialog.h new file mode 100644 index 000000000..81afc4e81 --- /dev/null +++ b/src/rcon/gui/dialog/IDialog.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include +#include +#include + +#define DIALOG_NO_APPLY_BUTTON (1 << 0) + +class IDialog: public QDialog { +Q_OBJECT +protected: + QString _title; + + QPushButton *_applyButton; + QPushButton *_closeButton; + QHBoxLayout *_buttonLayout; + QWidget *_buttons; + QVBoxLayout *_mainLayout; + int _flags; + +private slots: + void apply() { + onApply(); + emit accept(); + } + +public: + IDialog(const QString &title, int flags = 0); + virtual ~IDialog(); + const QString& getTitle() const; + + int run(); + + virtual void addButtons(QBoxLayout& layout); + virtual void onApply() {} + virtual void addMainWidgets(QBoxLayout& /* layout */) = 0; +}; + +inline const QString& IDialog::getTitle() const { + return _title; +} diff --git a/src/rcon/gui/view/aggro/AggroTable.cpp b/src/rcon/gui/view/aggro/AggroTable.cpp new file mode 100644 index 000000000..379fea5c7 --- /dev/null +++ b/src/rcon/gui/view/aggro/AggroTable.cpp @@ -0,0 +1,30 @@ +#include "AggroTable.h" +#include + +namespace ai { +namespace debug { + +AggroTable::AggroTable(AIDebugger& debugger) : + QTableView(), _model(debugger, this), _debugger(debugger) { + _proxyModel.setSourceModel(&_model); + setModel(&_proxyModel); + setAlternatingRowColors(true); + resizeColumnsToContents(); + setSortingEnabled(false); + setSelectionMode(QAbstractItemView::NoSelection); + verticalHeader()->hide(); + setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding); + for (int c = 0; c < horizontalHeader()->count(); ++c) { + horizontalHeader()->setSectionResizeMode(c, QHeaderView::Stretch); + } +} + +AggroTable::~AggroTable() { +} + +void AggroTable::updateAggroTable() { + _model.update(); +} + +} +} diff --git a/src/rcon/gui/view/aggro/AggroTable.h b/src/rcon/gui/view/aggro/AggroTable.h new file mode 100644 index 000000000..c7a589ede --- /dev/null +++ b/src/rcon/gui/view/aggro/AggroTable.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +#include "AIDebugger.h" +#include "AggroTableModel.h" + +namespace ai { +namespace debug { + +/** + * @brief Shows a key value pair of values for the selected entity + */ +class AggroTable: public QTableView { +private: + AggroTableModel _model; + QSortFilterProxyModel _proxyModel; + AIDebugger& _debugger; +public: + AggroTable(AIDebugger& debugger); + virtual ~AggroTable(); + + void updateAggroTable(); +}; + +} +} diff --git a/src/rcon/gui/view/aggro/AggroTableModel.cpp b/src/rcon/gui/view/aggro/AggroTableModel.cpp new file mode 100644 index 000000000..15d1b3cd8 --- /dev/null +++ b/src/rcon/gui/view/aggro/AggroTableModel.cpp @@ -0,0 +1,62 @@ +#include "AggroTableModel.h" +#include + +namespace ai { +namespace debug { + +AggroTableModel::AggroTableModel(const AIDebugger& debugger, QTableView *parent) : + QAbstractTableModel(nullptr), _debugger(debugger), _parent(parent) { +} + +AggroTableModel::~AggroTableModel() { +} + +void AggroTableModel::update() { + beginResetModel(); + endResetModel(); +} + +int AggroTableModel::rowCount(const QModelIndex & /*parent*/) const { + const std::vector& aggro = _debugger.getAggro(); + return aggro.size(); +} + +int AggroTableModel::columnCount(const QModelIndex & /*parent*/) const { + return 2; +} + +QVariant AggroTableModel::headerData(int section, Qt::Orientation orientation, + int role) const { + if (orientation != Qt::Horizontal) + return QVariant(); + + if (role == Qt::DisplayRole) { + switch (section) { + case 0: + return tr("ID"); + case 1: + return tr("Aggro"); + default: + break; + } + } + return QVariant(); +} + +QVariant AggroTableModel::data(const QModelIndex &index, int role) const { + const std::vector& aggro = _debugger.getAggro(); + if (role == Qt::DisplayRole) { + switch (index.column()) { + case 0: + return aggro.at(index.row()).id; + case 1: + return aggro.at(index.row()).aggro; + default: + break; + } + } + return QVariant(); +} + +} +} diff --git a/src/rcon/gui/view/aggro/AggroTableModel.h b/src/rcon/gui/view/aggro/AggroTableModel.h new file mode 100644 index 000000000..de40ec64a --- /dev/null +++ b/src/rcon/gui/view/aggro/AggroTableModel.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include + +#include "AIDebugger.h" + +namespace ai { +namespace debug { + +class AggroTableModel: public QAbstractTableModel { +Q_OBJECT +private: + const AIDebugger& _debugger; + QTableView* _parent; +public: + AggroTableModel(const AIDebugger& debugger, QTableView *parent); + ~AggroTableModel(); + + inline const AIDebugger::Entities& getEntities() const { + return _debugger.getEntities(); + } + + inline const AIStateWorld* getEntity(const QModelIndex &index) const { + const int size = getEntities().size(); + if (size > index.row() && index.row() >= 0) + return &getEntities().values().at(index.row()); + return nullptr; + } + + void update(); + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation orientation, + int role) const override; +}; + +} +} diff --git a/src/rcon/gui/view/list/EntityList.cpp b/src/rcon/gui/view/list/EntityList.cpp new file mode 100644 index 000000000..a4237b213 --- /dev/null +++ b/src/rcon/gui/view/list/EntityList.cpp @@ -0,0 +1,39 @@ +#include "EntityList.h" +#include + +namespace ai { +namespace debug { + +EntityList::EntityList(AIDebugger& debugger, QLineEdit* entityFilter) : + QTableView(), _model(debugger, this), _debugger(debugger), _entityFilter(entityFilter) { + setFixedWidth(200); + _proxyModel.setSourceModel(&_model); + setModel(&_proxyModel); + setAlternatingRowColors(true); + setSortingEnabled(true); + setSelectionMode(QAbstractItemView::SingleSelection); + setSelectionBehavior(QAbstractItemView::SelectRows); + setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding); + verticalHeader()->hide(); + horizontalHeader()->setStretchLastSection(true); + + connect(_entityFilter, SIGNAL(textChanged(QString)), &_proxyModel, SLOT(setFilterWildcard(QString))); + connect(selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)), this, SLOT(selectEntity(QModelIndex,QModelIndex))); +} + +EntityList::~EntityList() { +} + +void EntityList::updateEntityList() { + _model.update(); + _model.sort(0); +} + +void EntityList::selectEntity(const QModelIndex ¤t, const QModelIndex &previous) { + Q_UNUSED(previous); + const AIStateWorld& state = _model.getEntities().at(_proxyModel.mapToSource(current).row()); + _debugger.select(state); +} + +} +} diff --git a/src/rcon/gui/view/list/EntityList.h b/src/rcon/gui/view/list/EntityList.h new file mode 100644 index 000000000..7842da8dc --- /dev/null +++ b/src/rcon/gui/view/list/EntityList.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include + +#include "AIDebugger.h" +#include "EntityListModel.h" + +namespace ai { +namespace debug { + +/** + * @brief Shows a list of all entities that are handled on the server we are connected to + */ +class EntityList: public QTableView { +Q_OBJECT +private: + EntityListModel _model; + QSortFilterProxyModel _proxyModel; + AIDebugger& _debugger; + QLineEdit* _entityFilter; +private slots: + void selectEntity(const QModelIndex ¤t, const QModelIndex &previous); +public: + EntityList(AIDebugger& debugger, QLineEdit *entityFilter); + virtual ~EntityList(); + + void updateEntityList(); +}; + +} +} diff --git a/src/rcon/gui/view/list/EntityListModel.cpp b/src/rcon/gui/view/list/EntityListModel.cpp new file mode 100644 index 000000000..d290ad732 --- /dev/null +++ b/src/rcon/gui/view/list/EntityListModel.cpp @@ -0,0 +1,58 @@ +#include "EntityListModel.h" +#include + +namespace ai { +namespace debug { + +EntityListModel::EntityListModel(AIDebugger& debugger, QTableView *parent) : + QAbstractTableModel(parent), _debugger(debugger), _parent(parent) { +} + +EntityListModel::~EntityListModel() { +} + +void EntityListModel::update() { + beginResetModel(); + _list = _debugger.getEntities().values(); + endResetModel(); +} + +int EntityListModel::rowCount(const QModelIndex & /*parent*/) const { + return _list.size(); +} + +int EntityListModel::columnCount(const QModelIndex & /*parent*/) const { + return 1; +} + +QVariant EntityListModel::headerData(int section, Qt::Orientation orientation, + int role) const { + if (orientation != Qt::Horizontal) + return QVariant(); + if (section != 0) + return QVariant(); + + if (role == Qt::DisplayRole) { + return tr("Entities"); + } else if (role == Qt::ToolTipRole) { + return tr("The character id"); + } + return QVariant(); +} + +QVariant EntityListModel::data(const QModelIndex &index, int role) const { + const AIStateWorld& state = _list.at(index.row()); + if (role == Qt::DisplayRole) { + if (index.column() == 0) { + return state.getId(); + } + } else if (role == Qt::BackgroundColorRole) { + if (_debugger.isSelected(state)) { + return QColor(Qt::gray); + } + } + return QVariant(); +} + +} +} diff --git a/src/rcon/gui/view/list/EntityListModel.h b/src/rcon/gui/view/list/EntityListModel.h new file mode 100644 index 000000000..56129a6ed --- /dev/null +++ b/src/rcon/gui/view/list/EntityListModel.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +#include "AIDebugger.h" + +namespace ai { +namespace debug { + +class EntityListModel: public QAbstractTableModel { +Q_OBJECT +private: + AIDebugger& _debugger; + QTableView* _parent; + QList _list; +public: + EntityListModel(AIDebugger& debugger, QTableView *parent); + ~EntityListModel(); + + inline const QList& getEntities() const { + return _list; + } + + void update(); + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation orientation, + int role) const override; +}; + +} +} diff --git a/src/rcon/gui/view/map/MapItem.cpp b/src/rcon/gui/view/map/MapItem.cpp new file mode 100644 index 000000000..84fcd59da --- /dev/null +++ b/src/rcon/gui/view/map/MapItem.cpp @@ -0,0 +1,76 @@ +#include "MapItem.h" +#include "AIDebugger.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ai { +namespace debug { + +MapItem::MapItem(QGraphicsItem* parent, const AIStateWorld& state, AIDebugger& aiDebugger) : + QGraphicsItemGroup(parent), _state(state), _aiDebugger(aiDebugger) { + const bool selected = _aiDebugger.isSelected(state); + setFlag(QGraphicsItem::ItemIsSelectable); + + const qreal size = 30.0; + QColor color = selected ? QColor::fromRgb(200, 200, 0, 255) : QColor::fromRgb(255, 0, 0, 128); + QGraphicsEllipseItem *body = new QGraphicsEllipseItem(0.0, 0.0, size, size); + addToGroup(body); + + QVector2D end(::cosf(state.getOrientation()), ::sinf(state.getOrientation())); + end.normalize(); + const qreal center = size / 2.0; + QGraphicsLineItem *direction = new QGraphicsLineItem(center, center, center + center * end.x(), center + center * end.y()); + addToGroup(direction); + + direction->setSelected(selected); + body->setSelected(selected); + + setAcceptHoverEvents(true); + setAcceptedMouseButtons(Qt::AllButtons); + const CharacterAttributes& attributes = _state.getAttributes(); + CharacterAttributes::const_iterator name = attributes.find(attributes::NAME); + if (name != attributes.end()) { + setToolTip(QString::fromStdString(name->second)); + } else { + setToolTip(QString::number(_state.getId())); + } + CharacterAttributes::const_iterator group = attributes.find(attributes::GROUP); + if (group != attributes.end()) { + const int groupId = atoi(group->second.c_str()); + if (groupId > 0) { + const int b = groupId * 113 % 255; + const int component = groupId % 3; + switch (component) { + case 0: + color.setRed(b); + break; + case 1: + color.setGreen(b); + break; + default: + color.setBlue(b); + break; + } + } + } + + body->setBrush(color); +} + +MapItem::~MapItem() { +} + +void MapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { + QGraphicsItem::mouseDoubleClickEvent(event); + _aiDebugger.select(_state); + update(); +} + +} +} diff --git a/src/rcon/gui/view/map/MapItem.h b/src/rcon/gui/view/map/MapItem.h new file mode 100644 index 000000000..04e640bf4 --- /dev/null +++ b/src/rcon/gui/view/map/MapItem.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include + +namespace ai { +namespace debug { + +class AIDebugger; + +/** + * @brief Represents one entity in the world + * + * @note If you want to show additional details for an entity, see the @c MapView class + */ +class MapItem: public QGraphicsItemGroup { +protected: + const AIStateWorld _state; + AIDebugger& _aiDebugger; +public: + MapItem(QGraphicsItem* parent, const AIStateWorld& state, AIDebugger& aiDebugger); + virtual ~MapItem(); + +protected: + virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override; +}; + +} +} diff --git a/src/rcon/gui/view/map/MapView.cpp b/src/rcon/gui/view/map/MapView.cpp new file mode 100644 index 000000000..b1be93ba1 --- /dev/null +++ b/src/rcon/gui/view/map/MapView.cpp @@ -0,0 +1,43 @@ +#include "MapView.h" +#include "AIDebugger.h" +#include "MapItem.h" + +namespace ai { +namespace debug { + +MapView::MapView(AIDebugger& debugger) : + IGraphicsView(true, true), _debugger(debugger) { + _scene.setItemIndexMethod(QGraphicsScene::NoIndex); + setViewportUpdateMode(QGraphicsView::FullViewportUpdate); + setCacheMode(QGraphicsView::CacheBackground); + setRenderHint(QPainter::Antialiasing, false); + setInteractive(true); + setScene(&_scene); +} + +MapView::~MapView() { + _scene.clear(); +} + +MapItem* MapView::createMapItem(const AIStateWorld& state) { + MapItem* item = new MapItem(nullptr, state, _debugger); + item->setPos((qreal)state.getPosition().x, (qreal)state.getPosition().z); + if (_debugger.isSelected(state)) { + item->setZValue(std::numeric_limits::max()); + } else { + item->setZValue((qreal)state.getPosition().y); + } + return item; +} + +void MapView::updateMapView() { + _scene.clear(); + const AIDebugger::Entities& e = _debugger.getEntities(); + for (AIDebugger::EntitiesIter i = e.begin(); i != e.end(); ++i) { + MapItem* item = createMapItem(*i); + _scene.addItem(item); + } +} + +} +} diff --git a/src/rcon/gui/view/map/MapView.h b/src/rcon/gui/view/map/MapView.h new file mode 100644 index 000000000..1badb86a5 --- /dev/null +++ b/src/rcon/gui/view/map/MapView.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include +#include "IGraphicsView.h" + +namespace ai { +namespace debug { + +class AIDebugger; +class MapItem; + +/** + * @brief The view that renders your map with all the ai controlled entities. + * + * @note If you want to render additional details to an entity, extend this class to override + * MapView::createMapItem and provide your own @c MapItem there. + */ +class MapView: public IGraphicsView { + Q_OBJECT +protected: + QGraphicsScene _scene; + AIDebugger& _debugger; +public: + MapView(AIDebugger& debugger); + virtual ~MapView(); + + virtual void updateMapView(); + + /** + * @brief Creates a @c MapItem and allows you to create your own instances to render extra details + */ + virtual MapItem* createMapItem(const AIStateWorld& state); +}; + +} +} diff --git a/src/rcon/gui/view/state/StateTable.cpp b/src/rcon/gui/view/state/StateTable.cpp new file mode 100644 index 000000000..ec578319a --- /dev/null +++ b/src/rcon/gui/view/state/StateTable.cpp @@ -0,0 +1,30 @@ +#include "StateTable.h" +#include + +namespace ai { +namespace debug { + +StateTable::StateTable(AIDebugger& debugger) : + QTableView(), _model(debugger), _debugger(debugger) { + _proxyModel.setSourceModel(&_model); + setModel(&_proxyModel); + setAlternatingRowColors(true); + resizeColumnsToContents(); + setSortingEnabled(true); + setSelectionMode(QAbstractItemView::NoSelection); + verticalHeader()->hide(); + setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding); + for (int c = 0; c < horizontalHeader()->count(); ++c) { + horizontalHeader()->setSectionResizeMode(c, QHeaderView::Stretch); + } +} + +StateTable::~StateTable() { +} + +void StateTable::updateStateTable() { + _model.update(); +} + +} +} diff --git a/src/rcon/gui/view/state/StateTable.h b/src/rcon/gui/view/state/StateTable.h new file mode 100644 index 000000000..70083f3f1 --- /dev/null +++ b/src/rcon/gui/view/state/StateTable.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +#include "AIDebugger.h" +#include "StateTableModel.h" + +namespace ai { +namespace debug { + +/** + * @brief Shows a key value pair of values for the selected entity + */ +class StateTable: public QTableView { +private: + StateTableModel _model; + QSortFilterProxyModel _proxyModel; + AIDebugger& _debugger; +public: + StateTable(AIDebugger& debugger); + virtual ~StateTable(); + + void updateStateTable(); +}; + +} +} diff --git a/src/rcon/gui/view/state/StateTableModel.cpp b/src/rcon/gui/view/state/StateTableModel.cpp new file mode 100644 index 000000000..777fe10b7 --- /dev/null +++ b/src/rcon/gui/view/state/StateTableModel.cpp @@ -0,0 +1,66 @@ +#include "StateTableModel.h" +#include + +namespace ai { +namespace debug { + +StateTableModel::StateTableModel(const AIDebugger& debugger) : + QAbstractTableModel(nullptr), _debugger(debugger) { +} + +StateTableModel::~StateTableModel() { +} + +void StateTableModel::update() { + beginResetModel(); + const AIDebugger::CharacterAttributesMap& a = _debugger.getAttributes(); + _list.clear(); + for (AIDebugger::CharacterAttributesMap::const_iterator i = a.begin(); i != a.end(); ++i) { + _list << i.key(); + } + endResetModel(); +} + +int StateTableModel::rowCount(const QModelIndex & /*parent*/) const { + return _list.size(); +} + +int StateTableModel::columnCount(const QModelIndex & /*parent*/) const { + return 2; +} + +QVariant StateTableModel::headerData(int section, Qt::Orientation orientation, + int role) const { + if (orientation != Qt::Horizontal) + return QVariant(); + + if (role == Qt::DisplayRole) { + switch (section) { + case 0: + return tr("Key"); + case 1: + return tr("Value"); + default: + break; + } + } + return QVariant(); +} + +QVariant StateTableModel::data(const QModelIndex &index, int role) const { + const QString& key = _list[index.row()]; + if (role == Qt::DisplayRole) { + switch (index.column()) { + case 0: + return key; + case 1: + return _debugger.getAttributes().value(key); + default: + break; + } + } + return QVariant(); +} + +} +} diff --git a/src/rcon/gui/view/state/StateTableModel.h b/src/rcon/gui/view/state/StateTableModel.h new file mode 100644 index 000000000..8af214904 --- /dev/null +++ b/src/rcon/gui/view/state/StateTableModel.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include +#include + +#include "AIDebugger.h" + +namespace ai { +namespace debug { + +class StateTableModel: public QAbstractTableModel { +Q_OBJECT +private: + const AIDebugger& _debugger; + QList _list; +public: + StateTableModel(const AIDebugger& debugger); + ~StateTableModel(); + + inline const AIDebugger::Entities& getEntities() const { + return _debugger.getEntities(); + } + + inline const AIStateWorld* getEntity(const QModelIndex &index) const { + const int size = getEntities().size(); + if (size > index.row() && index.row() >= 0) + return &getEntities().values().at(index.row()); + return nullptr; + } + + void update(); + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation orientation, + int role) const override; +}; + +} +} diff --git a/src/rcon/gui/view/tree/BehaviourTreeModel.cpp b/src/rcon/gui/view/tree/BehaviourTreeModel.cpp new file mode 100644 index 000000000..e2a7ab579 --- /dev/null +++ b/src/rcon/gui/view/tree/BehaviourTreeModel.cpp @@ -0,0 +1,162 @@ +#include "BehaviourTreeModel.h" +#include "BehaviourTreeModelItem.h" +#include "AIDebugger.h" + +#include +#include + +namespace ai { +namespace debug { + +BehaviourTreeModel::BehaviourTreeModel(AIDebugger& debugger, AINodeStaticResolver& resolver, QObject *parent) : + QAbstractItemModel(parent), _rootItem(nullptr), _resolver(resolver), _debugger(debugger), _allowUpdate(true) { + connect(this, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(onDataChanged(const QModelIndex&, const QModelIndex&))); +} + +BehaviourTreeModel::~BehaviourTreeModel() { + delete _rootItem; +} + +void BehaviourTreeModel::onDataChanged(const QModelIndex& topLeft, const QModelIndex& /*bottomRight*/) { + BehaviourTreeModelItem *nodeItem = item(topLeft); + if (nodeItem == nullptr) { + qDebug() << "No item found at: " << topLeft; + return; + } + + const QVariant& name = nodeItem->data(COL_NAME); + const QVariant& type = nodeItem->data(COL_TYPE); + const QVariant& condition = nodeItem->data(COL_CONDITION); + _debugger.updateNode(nodeItem->node()->getNodeId(), name, type, condition); + nodeItem->resetEdit(); +} + +QModelIndex BehaviourTreeModel::index(int row, int column, const QModelIndex &parent) const { + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + BehaviourTreeModelItem *parentItem; + if (!parent.isValid()) + parentItem = _rootItem; + else + parentItem = item(parent); + + BehaviourTreeModelItem *childItem = parentItem->child(row); + if (childItem) + return createIndex(row, column, childItem); + return QModelIndex(); +} + +QModelIndex BehaviourTreeModel::parent(const QModelIndex &index) const { + if (!index.isValid()) + return QModelIndex(); + + BehaviourTreeModelItem *childItem = item(index); + BehaviourTreeModelItem *parentItem = childItem->parent(); + if (parentItem == nullptr || parentItem == _rootItem) + return QModelIndex(); + + return createIndex(parentItem->row(), 0, parentItem); +} + +int BehaviourTreeModel::rowCount(const QModelIndex &parent) const { + BehaviourTreeModelItem *parentItem; + if (parent.column() > 0) + return 0; + + if (!parent.isValid()) + parentItem = _rootItem; + else + parentItem = item(parent); + + if (parentItem == nullptr) + return 0; + + return parentItem->childCount(); +} + +int BehaviourTreeModel::columnCount(const QModelIndex &parent) const { + if (parent.isValid()) + return item(parent)->columnCount(); + return _rootItem->columnCount(); +} + +QVariant BehaviourTreeModel::data(const QModelIndex &index, int role) const { + if (!index.isValid()) + return QVariant(); + + BehaviourTreeModelItem *nodeItem = item(index); + if (nodeItem == nullptr) + return QVariant(); + + if (role == Qt::DecorationRole) { + if (index.column() == COL_NAME) + return nodeItem->icon(); + } else if (role == Qt::TextColorRole) { + return nodeItem->color(); + } + + if (role == Qt::EditRole && _allowUpdate) { + qDebug() << "start editing"; + _allowUpdate = false; + } + + if (role == Qt::DisplayRole || role == Qt::EditRole) + return nodeItem->data(index.column()); + else if (role == Qt::ToolTipRole) + return nodeItem->tooltip(index.column()); + return QVariant(); +} + +bool BehaviourTreeModel::submit() { + if (!_allowUpdate) { + emit behaviourUpdated(); + qDebug() << "end editing"; + } + _allowUpdate = true; + return QAbstractItemModel::submit(); +} + +Qt::ItemFlags BehaviourTreeModel::flags(const QModelIndex &index) const { + if (!index.isValid()) + return Qt::ItemIsEnabled; + + Qt::ItemFlags flags = QAbstractItemModel::flags(index); + switch (index.column()) { + case COL_NAME: + case COL_TYPE: + case COL_CONDITION: + flags |= Qt::ItemIsEditable; + } + return flags; +} + +bool BehaviourTreeModel::setData(const QModelIndex &index, const QVariant &value, int role) { + if (index.isValid() && role == Qt::EditRole) { + _rootItem->child(index.row())->setData(index.column(), value); + emit dataChanged(index, index); + return true; + } + return false; +} + +QVariant BehaviourTreeModel::headerData(int section, Qt::Orientation orientation, int role) const { + if (orientation == Qt::Horizontal && role == Qt::DisplayRole && _rootItem != nullptr) + return _rootItem->headerData(section); + + return QVariant(); +} + +void BehaviourTreeModel::setRootNode(AIStateNode* node) { + if (!_allowUpdate) + return; + beginResetModel(); + if (_rootItem) { + delete _rootItem; + } + _rootItem = new BehaviourTreeModelItem(node, _resolver); + endResetModel(); +} + +} +} diff --git a/src/rcon/gui/view/tree/BehaviourTreeModel.h b/src/rcon/gui/view/tree/BehaviourTreeModel.h new file mode 100644 index 000000000..38ac386b3 --- /dev/null +++ b/src/rcon/gui/view/tree/BehaviourTreeModel.h @@ -0,0 +1,51 @@ +#pragma once + +#include "AINodeStaticResolver.h" +#include +#include + +namespace ai { +namespace debug { + +class AIDebugger; +class BehaviourTreeModelItem; + +class BehaviourTreeModel: public QAbstractItemModel { +Q_OBJECT +private: + BehaviourTreeModelItem *_rootItem; + AINodeStaticResolver& _resolver; + AIDebugger& _debugger; + mutable bool _allowUpdate; +public: + explicit BehaviourTreeModel(AIDebugger& debugger, AINodeStaticResolver& resolver, QObject *parent = nullptr); + ~BehaviourTreeModel(); + + inline BehaviourTreeModelItem* item(const QModelIndex& index) const { + if (!index.isValid()) + return nullptr; + + return static_cast(index.internalPointer()); + } + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex &child) const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; + Qt::ItemFlags flags(const QModelIndex &index) const override; + + void setRootNode(AIStateNode* node); + +public slots: + bool submit() override; + void onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); + +signals: + void behaviourUpdated(); +}; + +} +} diff --git a/src/rcon/gui/view/tree/BehaviourTreeModelItem.cpp b/src/rcon/gui/view/tree/BehaviourTreeModelItem.cpp new file mode 100644 index 000000000..5b3841576 --- /dev/null +++ b/src/rcon/gui/view/tree/BehaviourTreeModelItem.cpp @@ -0,0 +1,135 @@ +#include "BehaviourTreeModelItem.h" +#include "TreeViewCommon.h" +#include "AINodeStaticResolver.h" +#include + +namespace ai { +namespace debug { + +BehaviourTreeModelItem::BehaviourTreeModelItem(AIStateNode* node, AINodeStaticResolver& resolver, BehaviourTreeModelItem* parent) : + _node(node), _staticNodeData(resolver.get(node->getNodeId())), _populated(false), _rowCount(0), _parent(parent) { + if (_parent == nullptr) { + _rows.push_back(new BehaviourTreeModelItem(_node, resolver, this)); + } else { + for (const AIStateNode& node : _node->getChildren()) { + _rows.push_back(new BehaviourTreeModelItem(const_cast(&node), resolver, this)); + } + } + const QString type = QString::fromStdString(_staticNodeData.getType()).toLower(); + const QString path = ":/images/" + type + ".png"; + if (QFile::exists(path)) + _icon = QIcon(path); + else if (type.contains("selector")) + _icon = QIcon(":/images/selector.png"); + else + _icon = QIcon(":/images/node.png"); +} + +BehaviourTreeModelItem::~BehaviourTreeModelItem() { + qDeleteAll(_rows); +} + +void BehaviourTreeModelItem::resetEdit() { + _editedName = ""; + _editedCondition = ""; + _editedType = ""; +} + +BehaviourTreeModelItem* BehaviourTreeModelItem::child(int row) { + return _rows.value(row); +} + +QVariant BehaviourTreeModelItem::color() const { + const TreeNodeStatus status = _node->getStatus(); + switch (status) { + case UNKNOWN: + case CANNOTEXECUTE: + return QColor(Qt::gray); + case RUNNING: + case FINISHED: + return QColor(Qt::darkGreen); + case FAILED: + case EXCEPTION: + return QColor(Qt::red); + case MAX_TREENODESTATUS: + break; + } + return QVariant(); +} + +int BehaviourTreeModelItem::row() { + if (_parent != nullptr) + return _parent->_rows.indexOf(this); + return 0; +} + +QIcon BehaviourTreeModelItem::icon() const { + return _icon; +} + +QString BehaviourTreeModelItem::tooltip(int column) const { + if (column == COL_NAME) + return QString::fromStdString(_staticNodeData.getType()); + if (column == COL_CONDITION) + return QString::fromStdString(_staticNodeData.getCondition()); + return QString(); +} + +void BehaviourTreeModelItem::setData(int column, const QVariant& data) { + switch (column) { + case COL_NAME: + _editedName = data.toString(); + break; + case COL_TYPE: + _editedType = data.toString(); + break; + case COL_CONDITION: + _editedCondition = data.toString(); + break; + } +} + +QVariant BehaviourTreeModelItem::headerData(int column) const { + switch (column) { + case COL_NAME: + return QObject::tr("Name"); + case COL_TYPE: + return QObject::tr("Type"); + case COL_CONDITION: + return QObject::tr("Condition"); + case COL_STATE: + return QObject::tr("State"); + case COL_LASTRUN: + return QObject::tr("Last run"); + } + return QVariant(); +} + +QVariant BehaviourTreeModelItem::data(int column) const { + switch (column) { + case COL_NAME: + if (!_editedName.isEmpty()) + return _editedName; + return QString::fromStdString(_staticNodeData.getName()); + case COL_TYPE: + if (!_editedType.isEmpty()) + return _editedType; + return QString::fromStdString(_staticNodeData.getType()); + case COL_CONDITION: + if (!_editedCondition.isEmpty()) + return _editedCondition; + return QString::fromStdString(_node->getCondition()); + case COL_STATE: { + const TreeNodeStatus status = _node->getStatus(); + if (status >= UNKNOWN && status < MAX_TREENODESTATUS) + return stateNames[status]; + return stateNames[UNKNOWN]; + } + case COL_LASTRUN: + return QString::number(_node->getLastRun() / 1000); + } + return QVariant(); +} + +} +} diff --git a/src/rcon/gui/view/tree/BehaviourTreeModelItem.h b/src/rcon/gui/view/tree/BehaviourTreeModelItem.h new file mode 100644 index 000000000..6c0ff2028 --- /dev/null +++ b/src/rcon/gui/view/tree/BehaviourTreeModelItem.h @@ -0,0 +1,73 @@ +#pragma once + +#include +#include +#include + +namespace ai { +namespace debug { + +enum { + COL_NAME, + COL_TYPE, + COL_CONDITION, + COL_STATE, + COL_LASTRUN, + + COL_MAX +}; + +class AINodeStaticResolver; + +class BehaviourTreeModelItem { +private: + AIStateNode* _node; + const AIStateNodeStatic& _staticNodeData; + bool _populated; + int _rowCount; + QList _rows; + BehaviourTreeModelItem* _parent; + QIcon _icon; + + QString _editedType; + QString _editedName; + QString _editedCondition; + +public: + BehaviourTreeModelItem(AIStateNode* node, AINodeStaticResolver& resolver, BehaviourTreeModelItem* parent = nullptr); + virtual ~BehaviourTreeModelItem(); + + void setData(int column, const QVariant& data); + + void resetEdit(); + + QVariant headerData(int column) const; + QVariant data(int column) const; + QString tooltip(int column) const; + QIcon icon() const; + + QVariant color() const; + + inline int columnCount() const { + return COL_MAX; + } + + inline int childCount() const { + return _rows.size(); + } + + int row(); + + BehaviourTreeModelItem* child(int row); + + inline BehaviourTreeModelItem* parent() { + return _parent; + } + + inline AIStateNode* node() { + return _node; + } +}; + +} +} diff --git a/src/rcon/gui/view/tree/NodeTreeItem.cpp b/src/rcon/gui/view/tree/NodeTreeItem.cpp new file mode 100644 index 000000000..f1e422634 --- /dev/null +++ b/src/rcon/gui/view/tree/NodeTreeItem.cpp @@ -0,0 +1,154 @@ +#include "NodeTreeItem.h" +#include "AIDebugger.h" +#include "TreeViewCommon.h" +#include +#include +#include +#include + +namespace ai { +namespace debug { + +namespace { +const qreal padding = 1; +const qreal fontSize = 10; +const QColor backgroundColor = QColor::fromRgb(32, 32, 32, 64); +const QColor runningBackgroundColor = QColor::fromRgb(255, 0, 0, 128); +const QFont font("Times", fontSize); +const QFontMetrics fontMetrics(font); +} + +NodeTreeItem::NodeTreeItem (QGraphicsItem* parentItem, const AIStateNode& node, const AIStateNodeStatic& staticNodeData, NodeTreeItem* parent, int height, int horizontalSpacing, int verticalSpacing) : + QGraphicsItem(parentItem), _node(node), _parent(parent), _height(height), _horizontalSpacing( + horizontalSpacing), _verticalSpacing(verticalSpacing) { + _condition = QString::fromStdString(_node.getCondition()); + _name = QString::fromStdString(staticNodeData.getName()); + _type = QString::fromStdString(staticNodeData.getType()); + _width = std::max(130, std::max(fontMetrics.width(_name), fontMetrics.width(_condition))); + _lineHeight = fontMetrics.lineSpacing(); +} + +NodeTreeItem::~NodeTreeItem () { +} + +void NodeTreeItem::init() { + setOffset(QPointF(100.0f, fullSize().height() / 2.0f - _height)); +} + +void NodeTreeItem::setOffset (const QPointF& offset) { + _offset = offset; + + if (_parent == nullptr){ + setPos(_offset); + } else { + setPos(_parent->pos() + _offset); + } + + float yOffset = 0.0f; + foreach (NodeTreeItem* node, _children) { + const float halfHeight = node->fullSize().height() / 2.0f; + yOffset += halfHeight; + float heightOffset = -_size.height() / 2.0f + yOffset; + yOffset += halfHeight + _verticalSpacing; + const QPointF offsetF(_width + _horizontalSpacing, heightOffset); + node->setOffset(offsetF); + } +} + +QRectF NodeTreeItem::boundingRect () const { + return _size; +} + +QRectF NodeTreeItem::fullSize() { + if (!_size.isEmpty()) + return _size; + + _size = QRectF(0.0f, 0.0f, _width + _horizontalSpacing, _height + _verticalSpacing); + + if (_children.empty()) { + return _size; + } + + QRectF total; + foreach (NodeTreeItem* node, _children) { + QRectF childDimension = node->fullSize(); + childDimension.translate(node->_width + _horizontalSpacing, total.height() + childDimension.height() / 2.0f); + total |= childDimension; + } + + total.moveTo(total.x(), _size.center().y() - total.height() / 2.0f); + + _size |= total; + + return _size; +} + +QPointF NodeTreeItem::getChildPos (NodeTreeItem* child) const { + const QPointF& childPos = child->pos() - pos(); + const float childRelX = childPos.x(); + const float childRelY = childPos.y() + child->boundingRect().center().y(); + return QPointF(childRelX, childRelY); +} + +void NodeTreeItem::paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + Q_UNUSED(option); + Q_UNUSED(widget); + //painter->setClipRect(option->exposedRect); + const qreal lod = option->levelOfDetailFromTransform(painter->worldTransform()); + const bool running = _node.isRunning(); + QBrush b = painter->brush(); + if (running) + painter->setBrush(runningBackgroundColor); + else + painter->setBrush(backgroundColor); + painter->drawRect(0.0f, 0.0f, _width, _height); + + if (!_children.empty()) { + // location of the vertical line + const float seperatorX = _width + _horizontalSpacing / 2.0f; + // draw the (right) vertical line for connecting the parent with the separator vertical line + painter->drawLine(_width, _height / 2.0f, seperatorX, _height / 2.0f); + foreach (NodeTreeItem* child, _children) { + const QPointF& childPos = getChildPos(child); + // draw the (left) vertical line for connecting the separator with the children's left side + painter->drawLine(seperatorX, childPos.y(), childPos.x(), childPos.y()); + } + // draw the vertical connection line + if (_children.size() >= 2) { + const QPointF& firstChildPos = getChildPos(_children.first()); + const QPointF& lastChildPos = getChildPos(_children.last()); + painter->drawLine(seperatorX, firstChildPos.y(), seperatorX, lastChildPos.y()); + } + } + + painter->setBrush(b); + + if (lod < 0.4) + return; + + painter->setFont(font); + painter->save(); + const int radius = 4; + QRect rect(padding + 2 * radius, padding, _width - 2 * padding - 2 * radius, _height - 2 * padding); + painter->drawText(rect, _name); + rect.setY(rect.y() + _lineHeight); + const TreeNodeStatus status = _node.getStatus(); + const QString stateString = stateNames[status]; + const int64_t lastRun = _node.getLastRun(); + painter->drawText(rect, stateString); + QPoint center(padding + radius, padding + radius); + rect.setY(rect.y() + _lineHeight); + painter->drawText(rect, _condition); + int seconds; + if (lastRun == -1) + seconds = 255; + else + seconds = lastRun / 1000; + QColor activityColor(std::max(0, 255 - seconds), 0, 0, 255); + painter->setBrush(activityColor); + painter->drawEllipse(center, radius, radius); + painter->restore(); +} + +} +} diff --git a/src/rcon/gui/view/tree/NodeTreeItem.h b/src/rcon/gui/view/tree/NodeTreeItem.h new file mode 100644 index 000000000..dd19f10e7 --- /dev/null +++ b/src/rcon/gui/view/tree/NodeTreeItem.h @@ -0,0 +1,54 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include + +namespace ai { +namespace debug { + +class AIDebugger; + +// TODO use QGraphicsPathItem +class NodeTreeItem : public QGraphicsItem { +protected: + AIStateNode _node; + NodeTreeItem* _parent; + QList _children; + QString _condition; + QString _name; + QString _type; + int _width; + int _height; + int _lineHeight; + int _horizontalSpacing; + int _verticalSpacing; + QRectF _size; + QPointF _offset; + + QRectF fullSize(); + inline QPointF getChildPos (NodeTreeItem* child) const; + void setOffset(const QPointF& offset); + QRectF boundingRect() const override; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget) override; + +public: + NodeTreeItem (QGraphicsItem* parentItem, const AIStateNode& node, const AIStateNodeStatic& staticNodeData, NodeTreeItem* parent, int height, int horizontalSpacing, int verticalSpacing); + virtual ~NodeTreeItem (); + + void init(); + + inline NodeTreeItem* getParent() { return _parent; } + inline const AIStateNode& getNode() { return _node; } + inline int width() const { return _width; } + inline int height() const { return _height; } + inline int getSize() const { return _node.getChildren().size(); } + inline void addChildren(NodeTreeItem* node) { _children.append(node); } +}; + +} +} diff --git a/src/rcon/gui/view/tree/NodeTreeView.cpp b/src/rcon/gui/view/tree/NodeTreeView.cpp new file mode 100644 index 000000000..b065d11b4 --- /dev/null +++ b/src/rcon/gui/view/tree/NodeTreeView.cpp @@ -0,0 +1,52 @@ +#include "NodeTreeView.h" +#include "AINodeStaticResolver.h" +#include + +namespace { +const int horizontalSpacing = 40; +const int verticalSpacing = 10; +const int nodeHeight = 60; +} + +namespace ai { +namespace debug { + +NodeTreeView::NodeTreeView(AIDebugger& debugger, AINodeStaticResolver& resolver, QWidget* parent) : + IGraphicsView(false, false, parent), _debugger(debugger), _scene(this), _resolver(resolver) { + _scene.setItemIndexMethod(QGraphicsScene::NoIndex); + // because the connection lines are not included in the bounding box... + setViewportUpdateMode(QGraphicsView::FullViewportUpdate); + setCacheMode(QGraphicsView::CacheBackground); + setRenderHint(QPainter::Antialiasing, false); + setScene(&_scene); +} + +NodeTreeView::~NodeTreeView() { + setScene(nullptr); +} + +void NodeTreeView::updateTreeWidget() { + _scene.clear(); + const ai::CharacterId& id = _debugger.getSelected(); + if (id == -1) { + return; + } + const AIStateNode& node = _debugger.getNode(); + NodeTreeItem* item = buildTreeItems(node, nullptr); + item->init(); + _scene.setSceneRect(QRectF()); +} + +NodeTreeItem* NodeTreeView::buildTreeItems(const AIStateNode& node, NodeTreeItem* parent) { + NodeTreeItem* thisNode = new NodeTreeItem(nullptr, node, _resolver.get(node.getNodeId()), parent, nodeHeight, horizontalSpacing, verticalSpacing); + _scene.addItem(thisNode); + const std::vector& children = node.getChildren(); + for (std::vector::const_iterator i = children.begin(); i != children.end(); ++i) { + NodeTreeItem* childNode = buildTreeItems(*i, thisNode); + thisNode->addChildren(childNode); + } + return thisNode; +} + +} +} diff --git a/src/rcon/gui/view/tree/NodeTreeView.h b/src/rcon/gui/view/tree/NodeTreeView.h new file mode 100644 index 000000000..81d608bb3 --- /dev/null +++ b/src/rcon/gui/view/tree/NodeTreeView.h @@ -0,0 +1,34 @@ +#pragma once + +#include "IGraphicsView.h" +#include + +#include "NodeTreeItem.h" +#include "AIDebugger.h" +#include + +namespace ai { +namespace debug { + +class AINodeStaticResolver; + +/** + * @brief Shows the behaviour tree for the current selected entity + */ +class NodeTreeView: public IGraphicsView { +Q_OBJECT +private: + AIDebugger& _debugger; + QGraphicsScene _scene; + AINodeStaticResolver& _resolver; + + NodeTreeItem* buildTreeItems(const AIStateNode& node, NodeTreeItem* parent); +public: + NodeTreeView(AIDebugger& debugger, AINodeStaticResolver& resolver, QWidget* parent = nullptr); + virtual ~NodeTreeView(); + + void updateTreeWidget(); +}; + +} +} diff --git a/src/rcon/gui/view/tree/TreeViewCommon.cpp b/src/rcon/gui/view/tree/TreeViewCommon.cpp new file mode 100644 index 000000000..e2280b4a8 --- /dev/null +++ b/src/rcon/gui/view/tree/TreeViewCommon.cpp @@ -0,0 +1,19 @@ +#include "TreeViewCommon.h" + +namespace ai { +namespace debug { + +#define E(x) #x +const char *stateNames[] = { +E(UNKNOWN), +E(CANNOTEXECUTE), +E(RUNNING), +E(FINISHED), +E(FAILED), +E(EXCEPTION) +}; +#undef E +COMPILE_TIME_ASSERT(ARRAY_LENGTH(stateNames) == MAX_TREENODESTATUS); + +} +} diff --git a/src/rcon/gui/view/tree/TreeViewCommon.h b/src/rcon/gui/view/tree/TreeViewCommon.h new file mode 100644 index 000000000..feec2e1ac --- /dev/null +++ b/src/rcon/gui/view/tree/TreeViewCommon.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include "Common.h" + +namespace ai { +namespace debug { + +extern const char *stateNames[]; + +} +} diff --git a/src/rcon/gui/widget/IComboBox.cpp b/src/rcon/gui/widget/IComboBox.cpp new file mode 100644 index 000000000..c146ae730 --- /dev/null +++ b/src/rcon/gui/widget/IComboBox.cpp @@ -0,0 +1,119 @@ +#include "IComboBox.h" + +#include +#include +#include +#include +#include + +DetailsClickFilter::DetailsClickFilter(QLabel* label, IComboBox* comboBox) : + _label(label), _comboBox(comboBox) { +} + +bool DetailsClickFilter::eventFilter(QObject* watched, QEvent* event) { + if (watched != _label) + return false; + if (event->type() != QEvent::MouseButtonPress) + return false; + const QMouseEvent* const me = static_cast(event); + _clickedPoint = me->pos(); + + _comboBox->onChangeDetails(); + + if (_label->pixmap() == nullptr) + return false; + + QImage tmp(_label->pixmap()->toImage()); + QPainter painter(&tmp); + QPen paintpen(Qt::red); + paintpen.setWidth(4); + painter.setPen(paintpen); + painter.drawPoint(_clickedPoint); + _label->setPixmap(QPixmap::fromImage(tmp)); + _comboBox->onClickedDetails(_clickedPoint); + return false; +} + +const QPoint& DetailsClickFilter::getClickedPoint() const { + return _clickedPoint; +} + +IComboBox::IComboBox(const QString& title, const QString& detailImageSubdir, int flags, QWidget* parent) : + QWidget(parent), _proxy(&_comboBox), _detailsClickFilter(&_details, + this), _flags(flags), _detailImageSubdir( + detailImageSubdir) { + setLayout(&_vLayout); + if (_flags & COMBOBOX_DETAILS) { + connect(&_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(changeDetails())); + _vLayout.addWidget(&_details); + _details.installEventFilter(&_detailsClickFilter); + } + _vLayout.addWidget(&_container); + _container.setLayout(&_hLayout); + _hLayout.addWidget(&_comboBox, 1); +#if 0 + QSizePolicy sp = _comboBox.view()->sizePolicy(); + sp.setHorizontalPolicy(QSizePolicy::Minimum); + _comboBox.view()->setSizePolicy(sp); +#endif + _comboBox.setDuplicatesEnabled(false); + _comboBox.setEditable(true); + _proxy.setSourceModel(_comboBox.model()); + _comboBox.model()->setParent(&_proxy); + _comboBox.setModel(&_proxy); + _refresh = new QPushButton(QIcon(":/images/refresh.png"), ""); + _refresh->setToolTip(title); + if (!(_flags & COMBOBOX_NO_REFRESH)) { + connect(_refresh, SIGNAL(clicked()), this, SLOT(onRefresh())); + _hLayout.addWidget(_refresh); + } +} + +IComboBox::~IComboBox() { + delete _refresh; +} + +void IComboBox::clear() { + _comboBox.clear(); + _uniqueSet.clear(); +} + +void IComboBox::changeDetails() { + onChangeDetails(); +} + +void IComboBox::sort() { + _comboBox.model()->sort(0); +} + +bool IComboBox::insert(int key, const QString& value) { + const QString unique = QString::number(key) + "-" + value; + if (!_uniqueSet.contains(unique)) { + _comboBox.addItem(value, QVariant(key)); + _uniqueSet.insert(unique); + return true; + } + return false; +} + +void IComboBox::onRefresh() { + clear(); + load(); + sort(); +} + +void IComboBox::onChangeDetails() { + if (_detailImageSubdir.isEmpty()) + return; + const int id = getId(); + const QString& imagePath(_detailImageSubdir + QDir::separator() + id + ".png"); + const QPixmap pixmap(imagePath); + _details.setPixmap(pixmap); +} + +int IComboBox::getId() const { + if (_comboBox.count() == 0 || _comboBox.currentIndex() == -1) + return -1; + const int id = _comboBox.itemData(_comboBox.currentIndex()).toString().toInt(); + return id; +} diff --git a/src/rcon/gui/widget/IComboBox.h b/src/rcon/gui/widget/IComboBox.h new file mode 100644 index 000000000..9998fe4e9 --- /dev/null +++ b/src/rcon/gui/widget/IComboBox.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#define COMBOBOX_NO_REFRESH (1 << 0) +#define COMBOBOX_DETAILS (1 << 1) + +class IComboBox; + +class DetailsClickFilter: public QObject { +Q_OBJECT +protected: + QLabel* _label; + IComboBox* _comboBox; + QPoint _clickedPoint; + +public: + DetailsClickFilter(QLabel* label, IComboBox* comboBox); + bool eventFilter(QObject* watched, QEvent* event) override; + + const QPoint& getClickedPoint () const; +}; + +class IComboBox: public QWidget { +Q_OBJECT +protected: + QWidget _container; + QComboBox _comboBox; + QSortFilterProxyModel _proxy; + QHBoxLayout _hLayout; + QVBoxLayout _vLayout; + QLabel _details; + DetailsClickFilter _detailsClickFilter; + QPushButton *_refresh; + int _flags; + QSet _uniqueSet; + QString _detailImageSubdir; + +private slots: + void onRefresh(); + void changeDetails(); +public: + IComboBox(const QString& title, const QString& detailImageSubdir, int flags = 0, QWidget* parent = nullptr); + virtual ~IComboBox(); + + // inserts an object and eliminate duplicates, returns true if the item was really inserted + bool insert(int key, const QString& value); + void sort(); + void clear(); + // loads the data from the given server. Before calling this manually you should also invoke @c clear + virtual void load() = 0; + virtual void onChangeDetails(); + virtual void onClickedDetails(const QPoint& /* pos */) {} + // returns the id of the current selected item + int getId() const; +}; diff --git a/src/rcon/gui/widget/IGraphicsView.cpp b/src/rcon/gui/widget/IGraphicsView.cpp new file mode 100644 index 000000000..aeb7d4e91 --- /dev/null +++ b/src/rcon/gui/widget/IGraphicsView.cpp @@ -0,0 +1,45 @@ +#include "IGraphicsView.h" + +namespace ai { +namespace debug { + +IGraphicsView::IGraphicsView(bool renderGrid, bool renderBackground, QWidget* parent) : + QGraphicsView(parent), _renderGrid(renderGrid), _renderBackground(renderBackground) { + setRenderHint(QPainter::Antialiasing, true); +} + +IGraphicsView::~IGraphicsView() { +} + +void IGraphicsView::drawBackground(QPainter* painter, const QRectF& rect) { + QGraphicsView::drawBackground(painter, rect); + if (_renderBackground) { + painter->fillRect(rect, QBrush(QColor(50, 50, 50))); + } + + if (_renderGrid) { + QPen linePen(QColor(80, 80, 80), 1, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin); + linePen.setCosmetic(true); + painter->setPen(linePen); + + const int gridInterval = 100; + const qreal left = static_cast(rect.left()) + - (static_cast(rect.left()) % gridInterval); + const qreal top = static_cast(rect.top()) + - (static_cast(rect.top()) % gridInterval); + + QVarLengthArray linesX; + for (qreal x = left; x < rect.right(); x += gridInterval) + linesX.append(QLineF(x, rect.top(), x, rect.bottom())); + + QVarLengthArray linesY; + for (qreal y = top; y < rect.bottom(); y += gridInterval) + linesY.append(QLineF(rect.left(), y, rect.right(), y)); + + painter->drawLines(linesX.data(), linesX.size()); + painter->drawLines(linesY.data(), linesY.size()); + } +} + +} +} diff --git a/src/rcon/gui/widget/IGraphicsView.h b/src/rcon/gui/widget/IGraphicsView.h new file mode 100644 index 000000000..2a46f6500 --- /dev/null +++ b/src/rcon/gui/widget/IGraphicsView.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +namespace ai { +namespace debug { + +class IGraphicsView : public QGraphicsView { +private: + bool _renderGrid; + bool _renderBackground; +public: + IGraphicsView(bool renderGrid = false, bool renderBackground = false, QWidget* parent = nullptr); + virtual ~IGraphicsView(); + + virtual void drawBackground(QPainter* painter, const QRectF& rect) override; +}; + +} +} diff --git a/src/rcon/gui/widget/ZoomFrame.cpp b/src/rcon/gui/widget/ZoomFrame.cpp new file mode 100644 index 000000000..e161354ec --- /dev/null +++ b/src/rcon/gui/widget/ZoomFrame.cpp @@ -0,0 +1,41 @@ +#include "ZoomFrame.h" +#include "MapView.h" +#include "ZoomWidget.h" +#include "AIDebugger.h" + +namespace ai { +namespace debug { + +ZoomFrame::ZoomFrame(QGraphicsView* graphicsView, QWidget* parent) : + QFrame(parent), _zoomWidget(nullptr), _graphicsView(graphicsView) { + setFrameStyle(Sunken | StyledPanel); + _graphicsView->setRenderHint(QPainter::Antialiasing, false); + _graphicsView->setOptimizationFlags(QGraphicsView::DontSavePainterState); + //_graphicsView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate); + _graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); + _graphicsView->setDragMode(QGraphicsView::ScrollHandDrag); + _graphicsView->setCacheMode(QGraphicsView::CacheBackground); + _zoomWidget = new ZoomWidget(*_graphicsView); + + setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding); + + QHBoxLayout* topLayout = new QHBoxLayout; + topLayout->addWidget(_graphicsView); + topLayout->addWidget(_zoomWidget); + setLayout(topLayout); +} + +ZoomFrame::~ZoomFrame() { + delete _zoomWidget; +} + +void ZoomFrame::zoomIn(int level) { + _zoomWidget->zoomIn(level); +} + +void ZoomFrame::zoomOut(int level) { + _zoomWidget->zoomOut(level); +} + +} +} diff --git a/src/rcon/gui/widget/ZoomFrame.h b/src/rcon/gui/widget/ZoomFrame.h new file mode 100644 index 000000000..773bed864 --- /dev/null +++ b/src/rcon/gui/widget/ZoomFrame.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +namespace ai { +namespace debug { + +class ZoomWidget; + +class ZoomFrame: public QFrame { + Q_OBJECT +protected: + ZoomWidget* _zoomWidget; + QGraphicsView* _graphicsView; +public: + ZoomFrame(QGraphicsView* graphicsView, QWidget* parent = nullptr); + virtual ~ZoomFrame(); + + void zoomIn(int level); + void zoomOut(int level); +}; + +} +} diff --git a/src/rcon/gui/widget/ZoomWidget.cpp b/src/rcon/gui/widget/ZoomWidget.cpp new file mode 100644 index 000000000..a8eccc32e --- /dev/null +++ b/src/rcon/gui/widget/ZoomWidget.cpp @@ -0,0 +1,80 @@ +#include "ZoomWidget.h" + +#include +#include + +namespace ai { +namespace debug { + +ZoomWidget::ZoomWidget(QGraphicsView& gview, QWidget* parent) : + QWidget(parent), _graphicsView(gview), _zoomSlider(), _zoomInButton(), _zoomOutButton() { + const int size = style()->pixelMetric(QStyle::PM_ToolBarIconSize); + QSize icosize(size, size); + + _zoomInButton.setAutoRepeat(true); + _zoomInButton.setAutoRepeatInterval(33); + _zoomInButton.setAutoRepeatDelay(0); + _zoomInButton.setIcon(QPixmap(":/images/zoomin.png")); + _zoomInButton.setIconSize(icosize); + + _zoomOutButton.setAutoRepeat(true); + _zoomOutButton.setAutoRepeatInterval(33); + _zoomOutButton.setAutoRepeatDelay(0); + _zoomOutButton.setIcon(QPixmap(":/images/zoomout.png")); + _zoomOutButton.setIconSize(icosize); + + _zoomSlider.setMinimum(0); + _zoomSlider.setMaximum(200); + _zoomSlider.setValue(100); + _zoomSlider.setTickPosition(QSlider::TicksRight); + + setupZoomMatrix(); + + QVBoxLayout* layout = new QVBoxLayout(); + layout->addWidget(&_zoomInButton); + layout->addWidget(&_zoomSlider); + layout->addWidget(&_zoomOutButton); + + connect(&_zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(setupZoomMatrix())); + connect(&_zoomInButton, SIGNAL(clicked()), this, SLOT(zoomIn())); + connect(&_zoomOutButton, SIGNAL(clicked()), this, SLOT(zoomOut())); + setLayout(layout); +} + +ZoomWidget::~ZoomWidget() { + disconnect(&_zoomSlider, 0, this, SLOT(setupZoomMatrix())); + disconnect(&_zoomInButton, 0, this, SLOT(zoomIn())); + disconnect(&_zoomOutButton, 0, this, SLOT(zoomOut())); +} + +void ZoomWidget::setupZoomMatrix() { + const qreal scale = _zoomSlider.value() / 100.0; + QMatrix matrix; + matrix.scale(scale, scale); + _graphicsView.setMatrix(matrix); +} + +void ZoomWidget::setAutoRepeatInterval(int interval) { + _zoomInButton.setAutoRepeatInterval(interval); + _zoomOutButton.setAutoRepeatInterval(interval); +} + +void ZoomWidget::setValueRange(int min, int max) { + _zoomSlider.setMinimum(min); + _zoomSlider.setMaximum(max); +} + +void ZoomWidget::setValue(int value) { + _zoomSlider.setValue(value); +} + +void ZoomWidget::zoomIn(int level) { + _zoomSlider.setValue(_zoomSlider.value() + level); +} + +void ZoomWidget::zoomOut(int level) { + _zoomSlider.setValue(_zoomSlider.value() - level); +} + +} +} diff --git a/src/rcon/gui/widget/ZoomWidget.h b/src/rcon/gui/widget/ZoomWidget.h new file mode 100644 index 000000000..35bc04ff7 --- /dev/null +++ b/src/rcon/gui/widget/ZoomWidget.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace ai { +namespace debug { + +class ZoomWidget: public QWidget { + Q_OBJECT +public: + ZoomWidget(QGraphicsView& gview, QWidget* parent = nullptr); + ~ZoomWidget(); + + void setAutoRepeatInterval(int interval); + void setValueRange(int min, int max); + void setValue(int value); + +public slots: + void zoomIn(int level = 1); + void zoomOut(int level = 1); + +private slots: + void setupZoomMatrix(); + +private: + QGraphicsView& _graphicsView; + QSlider _zoomSlider; + QToolButton _zoomInButton; + QToolButton _zoomOutButton; +}; + +} +} diff --git a/src/rcon/simpleai-debugger.ico b/src/rcon/simpleai-debugger.ico new file mode 100644 index 000000000..28a94e7c1 Binary files /dev/null and b/src/rcon/simpleai-debugger.ico differ diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt new file mode 100644 index 000000000..9c5531fd6 --- /dev/null +++ b/src/server/CMakeLists.txt @@ -0,0 +1,21 @@ +fips_begin_app(server cmdline) + fips_files( + Server.cpp Server.h + ) + + fips_dir(sauce) + fips_files( + ServerModule.h + ServerInjector.h + ) + + find_package(SDL2 REQUIRED) + include_directories(${SDL2_INCLUDE_DIRS} .) + if (FIPS_LINUX) + list(APPEND DEPS "-latomic") + endif() + fips_deps(backend ${DEPS} ${SDL2_LIBRARIES}) + copy_data_files(server) +fips_end_app() +check_lua_files(server behaviourtrees.lua) +check_lua_files(server attributes.lua) diff --git a/src/server/Server.cpp b/src/server/Server.cpp new file mode 100644 index 000000000..95fb764f8 --- /dev/null +++ b/src/server/Server.cpp @@ -0,0 +1,52 @@ +#include "Server.h" +#include "core/Var.h" +#include "core/Command.h" +#include "sauce/ServerInjector.h" +#include "backend/storage/StoreCmd.h" +#include + +Server::Server(network::NetworkPtr network, backend::ServerLoopPtr serverLoop, core::TimeProviderPtr timeProvider, io::FilesystemPtr filesystem, core::EventBusPtr eventBus) : + App(filesystem, eventBus, 15678), _quit(false), _network(network), _serverLoop(serverLoop), _timeProvider(timeProvider) { + init("engine", "server"); +} + +core::AppState Server::onInit() { + const core::AppState state = core::App::onInit(); + if (!_network->start()) { + Log::error("Failed to start the server"); + return core::Cleanup; + } + + if (!_serverLoop->onInit()) { + Log::error("Failed to init the main loop"); + return core::Cleanup; + } + + core::Command::registerCommand("quit", [&] (const core::CmdArgs& args) {_quit = true;}); + StoreCmd SCmd; + SCmd.addComd(); + + const core::VarPtr& port = core::Var::get("sv_port", "11337"); + const core::VarPtr& host = core::Var::get("sv_host", ""); + const core::VarPtr& maxclients = core::Var::get("sv_maxclients", "1024"); + if (!_network->bind(port->intVal(), host->strVal(), maxclients->intVal(), 2)) { + Log::error("Failed to bind the server socket on %s:%i", host->strVal().c_str(), port->intVal()); + return core::Cleanup; + } + Log::error("Server socket is up at %s:%i", host->strVal().c_str(), port->intVal()); + return state; +} + +core::AppState Server::onRunning() { + if (_quit) + return core::Cleanup; + _timeProvider->update(_now); + core::App::onRunning(); + _serverLoop->onFrame(_deltaFrame); + return core::Running; +} + +int main(int argc, char *argv[]) { + getInjector()->get()->startMainLoop(argc, argv); + return EXIT_SUCCESS; +} diff --git a/src/server/Server.h b/src/server/Server.h new file mode 100644 index 000000000..c8fbc7dfb --- /dev/null +++ b/src/server/Server.h @@ -0,0 +1,20 @@ +#pragma once + +#include "core/App.h" +#include "backend/loop/ServerLoop.h" +#include "core/TimeProvider.h" +#include "network/Network.h" + +class Server: public core::App { +private: + bool _quit; + network::NetworkPtr _network; + backend::ServerLoopPtr _serverLoop; + core::TimeProviderPtr _timeProvider; +public: + Server(network::NetworkPtr network, backend::ServerLoopPtr serverLoop, core::TimeProviderPtr timeProvider, io::FilesystemPtr filesystem, core::EventBusPtr eventBus); + + core::AppState onInit() override; + + core::AppState onRunning() override; +}; diff --git a/src/server/sauce/ServerInjector.h b/src/server/sauce/ServerInjector.h new file mode 100644 index 000000000..fb8991f37 --- /dev/null +++ b/src/server/sauce/ServerInjector.h @@ -0,0 +1,11 @@ +#pragma once + +#include "ServerModule.h" +#include "backend/network/ServerNetworkModule.h" + +inline sauce::shared_ptr getInjector() { + sauce::Modules modules; + modules.add(); + modules.add(); + return modules.createInjector(); +} diff --git a/src/server/sauce/ServerModule.h b/src/server/sauce/ServerModule.h new file mode 100644 index 000000000..095382a6b --- /dev/null +++ b/src/server/sauce/ServerModule.h @@ -0,0 +1,42 @@ +#pragma once + +#include + +#include "core/AbstractModule.h" +#include "voxel/World.h" +#include "network/MessageSender.h" +#include "Server.h" + +#include "backend/poi/PoiProvider.h" +#include "backend/entity/EntityStorage.h" +#include "backend/entity/ai/AIRegistry.h" +#include "backend/entity/ai/AILoader.h" +#include "backend/loop/ServerLoop.h" +#include "backend/spawn/SpawnMgr.h" +#include "backend/poi/PoiProvider.h" + +#include "attrib/ContainerProvider.h" + +using namespace backend; +using namespace sauce; +using namespace core; +using namespace network; +using namespace voxel; +using namespace attrib; +using namespace io; + +class ServerModule: public core::AbstractModule { + void configure() const override { + core::AbstractModule::configure(); + bind().in().to(); + + bind().in().to(); + bind().in().to(); + bind().in().to(); + bind().in().to(); + bind().in().to(); + bind().in().to(); + bind().in().to(); + bind().in().to(); + } +}; diff --git a/src/worldgenerator/CMakeLists.txt b/src/worldgenerator/CMakeLists.txt new file mode 100644 index 000000000..db37c6bc8 --- /dev/null +++ b/src/worldgenerator/CMakeLists.txt @@ -0,0 +1,14 @@ +fips_begin_app(worldgenerator cmdline) + fips_files( + WorldGenerator.cpp WorldGenerator.h + ) + + fips_dir(sauce) + fips_files( + WorldGeneratorModule.h + WorldGeneratorInjector.h + ) + + fips_deps(voxel core io) + copy_data_files(worldgenerator) +fips_end_app() diff --git a/src/worldgenerator/WorldGenerator.cpp b/src/worldgenerator/WorldGenerator.cpp new file mode 100644 index 000000000..ec6d526ca --- /dev/null +++ b/src/worldgenerator/WorldGenerator.cpp @@ -0,0 +1,57 @@ +#include "WorldGenerator.h" +#include "sauce/WorldGeneratorInjector.h" +#include "core/Var.h" + +WorldGenerator::WorldGenerator(voxel::WorldPtr world, core::EventBusPtr eventBus, core::TimeProviderPtr timeProvider, io::FilesystemPtr filesystem) : + App(filesystem, eventBus, 15681), _world(world), _timeProvider(timeProvider), _seed(0L), _size(0) { + init("engine", "worldgenerator"); +} + +core::AppState WorldGenerator::onInit() { + core::AppState state = App::onInit(); + const core::VarPtr& seed = core::Var::get("seed"); + const core::VarPtr& size = core::Var::get("size"); + + if (size->strVal().empty()) { + Log::error("No size specified: -set size "); + return core::AppState::Cleanup; + } else if (seed->strVal().empty()) { + Log::error("No seed specified: -set seed "); + return core::AppState::Cleanup; + } + _seed = seed->longVal(); + _size = size->intVal(); + return state; +} + +core::AppState WorldGenerator::onRunning() { + core::AppState state = core::App::onRunning(); + + class ProgressMonitor: public util::IProgressMonitor { + public: + void step(int steps = 1) override { + IProgressMonitor::step(steps); + Log::info("max: %i, steps: %i => %f\r", _max, _steps, progress()); + } + void done() override { + Log::info("\ndone"); + } + } monitor; + + unsigned long start = _timeProvider->currentTime(); + _world->create(_seed, _size, &monitor); + if (!_world->save(_seed)) { + Log::error("Failed to save the world for seed %li", _seed); + } else { + Log::info("World for seed %li created", _seed); + } + unsigned long end = _timeProvider->currentTime(); + unsigned long delta = end - start; + Log::info("World generating process took %lu milliseconds", delta); + return state; +} + +int main(int argc, char *argv[]) { + getInjector()->get()->startMainLoop(argc, argv); + return EXIT_SUCCESS; +} diff --git a/src/worldgenerator/WorldGenerator.h b/src/worldgenerator/WorldGenerator.h new file mode 100644 index 000000000..9094e38a4 --- /dev/null +++ b/src/worldgenerator/WorldGenerator.h @@ -0,0 +1,18 @@ +#pragma once + +#include "core/App.h" +#include "voxel/World.h" +#include "core/TimeProvider.h" + +class WorldGenerator: public core::App { +private: + voxel::WorldPtr _world; + core::TimeProviderPtr _timeProvider; + long _seed; + int _size; +public: + WorldGenerator(voxel::WorldPtr world, core::EventBusPtr eventBus, core::TimeProviderPtr timeProvider, io::FilesystemPtr filesystem); + + core::AppState onInit() override; + core::AppState onRunning() override; +}; diff --git a/src/worldgenerator/sauce/WorldGeneratorInjector.h b/src/worldgenerator/sauce/WorldGeneratorInjector.h new file mode 100644 index 000000000..3c7e40a36 --- /dev/null +++ b/src/worldgenerator/sauce/WorldGeneratorInjector.h @@ -0,0 +1,9 @@ +#pragma once + +#include "WorldGeneratorModule.h" + +inline sauce::shared_ptr getInjector() { + sauce::Modules modules; + modules.add(); + return modules.createInjector(); +} diff --git a/src/worldgenerator/sauce/WorldGeneratorModule.h b/src/worldgenerator/sauce/WorldGeneratorModule.h new file mode 100644 index 000000000..aecfc3a1d --- /dev/null +++ b/src/worldgenerator/sauce/WorldGeneratorModule.h @@ -0,0 +1,12 @@ +#pragma once + +#include "core/AbstractModule.h" +#include "voxel/World.h" + +class WorldGeneratorModule: public core::AbstractModule { + void configure() const override { + core::AbstractModule::configure(); + bind().in().to(); + bind().in().to(); + } +};