├── LICENSE ├── README.md ├── img ├── features.png ├── g2_elo.png └── ranking.jpg ├── manage.py ├── mysite ├── __init__.py ├── asgi.py ├── settings.py ├── urls.py └── wsgi.py ├── notebooks ├── aggregation.ipynb ├── auto_betting_simu.ipynb ├── feature_engineering.ipynb ├── paris ├── populate_db.ipynb ├── strategy_analysis.ipynb └── var ├── paris ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── admin.cpython-36.pyc │ ├── apps.cpython-36.pyc │ ├── forms.cpython-36.pyc │ ├── models.cpython-36.pyc │ ├── module_api.cpython-36.pyc │ ├── module_data.cpython-36.pyc │ ├── urls.cpython-36.pyc │ ├── utils.cpython-36.pyc │ └── views.cpython-36.pyc ├── admin.py ├── apps.py ├── forms.py ├── migrations │ └── .gitignore ├── models.py ├── module_api.py ├── module_data.py ├── module_scrapping.py ├── static │ └── paris │ │ ├── base.html │ │ ├── item.html │ │ ├── matches.json │ │ ├── rankings.json │ │ └── style.css ├── templates │ └── paris │ │ ├── base.html │ │ ├── bet_form.html │ │ ├── bet_history.html │ │ ├── bet_history2.html │ │ ├── day.html │ │ ├── history.html │ │ ├── index.html │ │ ├── pred.html │ │ ├── team_match_list.html │ │ └── upcoming.html ├── tests.py ├── urls.py ├── utils.py └── views.py ├── report.pdf ├── requirements.txt └── var ├── .gitignore ├── history.db ├── history_elo.csv ├── logit.joblib ├── ranking.csv └── teams_map.csv /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSGO Odds forecasting 2 | 3 | The goal of this project is to build an application that provides an interface for forecasting the outcome of Counter Strige: Global Offensive competitive games. 4 | It includes : 5 | - a theoretical approach of gambling theory in the case of betting on competitve games. 6 | - a way to aggregate different sources available online to build features to predict the outcomes of the matches. 7 | - a model and a decision rule that is supposed to beat a particular bookmaker, only using the latter features. 8 | - some tools and simulations of what can be done in the field of Counter Strike odds prediction. 9 | 10 | You can find a whole detailled explanation of the content of the project [here](report.pdf). 11 | 12 | If you have any questions feel free to contact me ! 13 | 14 | ### If you want to test it yourself 15 | - Make sure you use shell_plus when you run the notebooks (see : [how-to-use-django-in-jupyter-notebook](https://medium.com/ayuth/how-to-use-django-in-jupyter-notebook-561ea2401852)) 16 | ```python 17 | python manage.py shell_plus --notebook 18 | ``` 19 | - Make sure you git is configured to keep symbolic links 20 | ``` 21 | git config --global core.symlinks true 22 | ``` 23 | 24 | - Make sure you have a good version of chromedriver in your PATH (see : [chromedriver](https://chromedriver.chromium.org/)) 25 | - When you run migrations for the first time use: 26 | ```python 27 | python manage.py migrate --run-syncdb 28 | ``` 29 | -------------------------------------------------------------------------------- /img/features.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/img/features.png -------------------------------------------------------------------------------- /img/g2_elo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/img/g2_elo.png -------------------------------------------------------------------------------- /img/ranking.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/img/ranking.jpg -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 9 | try: 10 | from django.core.management import execute_from_command_line 11 | except ImportError as exc: 12 | raise ImportError( 13 | "Couldn't import Django. Are you sure it's installed and " 14 | "available on your PYTHONPATH environment variable? Did you " 15 | "forget to activate a virtual environment?" 16 | ) from exc 17 | execute_from_command_line(sys.argv) 18 | 19 | 20 | if __name__ == '__main__': 21 | main() 22 | -------------------------------------------------------------------------------- /mysite/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/mysite/__init__.py -------------------------------------------------------------------------------- /mysite/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for mysite project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /mysite/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for mysite project. 3 | 4 | Generated by 'django-admin startproject' using Django 3.0.6. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/3.0/ref/settings/ 11 | """ 12 | 13 | import os 14 | 15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | PROJECT_DIR = os.path.dirname(os.path.realpath(__file__)) 18 | ROOT_DIR = os.path.dirname(PROJECT_DIR) 19 | STATIC_ROOT = os.path.join(PROJECT_DIR, 'static') 20 | STATICFILES_DIRS = [ 21 | os.path.join(BASE_DIR, "\\"), 22 | ] 23 | 24 | # Quick-start development settings - unsuitable for production 25 | # See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/ 26 | 27 | # SECURITY WARNING: keep the secret key used in production secret! 28 | SECRET_KEY ='YOUR DJANGO SECRET KEY' 29 | 30 | # SECURITY WARNING: don't run with debug turned on in production! 31 | DEBUG = True 32 | 33 | ALLOWED_HOSTS = [] 34 | 35 | 36 | # Application definition 37 | 38 | INSTALLED_APPS = [ 39 | "django_cron", 40 | 'paris.apps.ParisConfig', 41 | 'django.contrib.admin', 42 | 'django.contrib.auth', 43 | 'django.contrib.contenttypes', 44 | 'django.contrib.sessions', 45 | 'django.contrib.messages', 46 | 'django.contrib.staticfiles', 47 | 'django_extensions' 48 | ] 49 | 50 | CRON_CLASSES = [ 51 | "paris.cron.UpdateFinishedMatches", 52 | "paris.cron.UpdateRankingAndHistory", 53 | "paris.cron.AutoBet" 54 | 55 | ] 56 | 57 | MIDDLEWARE = [ 58 | 'django.middleware.security.SecurityMiddleware', 59 | 'django.contrib.sessions.middleware.SessionMiddleware', 60 | 'django.middleware.common.CommonMiddleware', 61 | 'django.middleware.csrf.CsrfViewMiddleware', 62 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 63 | 'django.contrib.messages.middleware.MessageMiddleware', 64 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 65 | ] 66 | 67 | ROOT_URLCONF = 'mysite.urls' 68 | 69 | TEMPLATES = [ 70 | { 71 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 72 | 'DIRS': [], 73 | 'APP_DIRS': True, 74 | 'OPTIONS': { 75 | 'context_processors': [ 76 | 'django.template.context_processors.debug', 77 | 'django.template.context_processors.request', 78 | 'django.contrib.auth.context_processors.auth', 79 | 'django.contrib.messages.context_processors.messages', 80 | ], 81 | }, 82 | }, 83 | ] 84 | 85 | WSGI_APPLICATION = 'mysite.wsgi.application' 86 | 87 | 88 | # Database 89 | # https://docs.djangoproject.com/en/3.0/ref/settings/#databases 90 | 91 | DATABASES = { 92 | 'default': { 93 | 'ENGINE': 'django.db.backends.sqlite3', 94 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 95 | } 96 | } 97 | 98 | 99 | # Password validation 100 | # https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators 101 | 102 | AUTH_PASSWORD_VALIDATORS = [ 103 | { 104 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 105 | }, 106 | { 107 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 108 | }, 109 | { 110 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 111 | }, 112 | { 113 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 114 | }, 115 | ] 116 | 117 | 118 | # Internationalization 119 | # https://docs.djangoproject.com/en/3.0/topics/i18n/ 120 | 121 | LANGUAGE_CODE = 'en-us' 122 | 123 | TIME_ZONE = 'Europe/Paris' 124 | 125 | USE_I18N = True 126 | 127 | USE_L10N = True 128 | 129 | USE_TZ = True 130 | 131 | 132 | # Static files (CSS, JavaScript, Images) 133 | # https://docs.djangoproject.com/en/3.0/howto/static-files/ 134 | 135 | STATIC_URL = '/static/' 136 | -------------------------------------------------------------------------------- /mysite/urls.py: -------------------------------------------------------------------------------- 1 | """mysite URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.0/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import include, path 18 | 19 | urlpatterns = [ 20 | path('paris/', include('paris.urls')), 21 | path('admin/', admin.site.urls), 22 | ] -------------------------------------------------------------------------------- /mysite/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for mysite project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /notebooks/auto_betting_simu.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import os\n", 10 | "from paris.models import Match\n", 11 | "from paris.module_data import FeaturesBuilder, parse_team_name\n", 12 | "from paris.utils import AutoBettor\n", 13 | "import pandas as pd\n", 14 | "\n", 15 | "import joblib\n", 16 | "\n", 17 | "os.environ[\"DJANGO_ALLOW_ASYNC_UNSAFE\"] = \"true\"" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": null, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "#the first time you run it, you should log yourself on csgolounge manually, afterwards it will remember you\n", 27 | "ab = AutoBettor(clf = joblib.load('var/logit.joblib'))" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": null, 33 | "metadata": { 34 | "scrolled": true 35 | }, 36 | "outputs": [], 37 | "source": [ 38 | "ab.auto_bet()" 39 | ] 40 | } 41 | ], 42 | "metadata": { 43 | "kernelspec": { 44 | "display_name": "Django Shell-Plus", 45 | "language": "python", 46 | "name": "django_extensions" 47 | }, 48 | "language_info": { 49 | "codemirror_mode": { 50 | "name": "ipython", 51 | "version": 3 52 | }, 53 | "file_extension": ".py", 54 | "mimetype": "text/x-python", 55 | "name": "python", 56 | "nbconvert_exporter": "python", 57 | "pygments_lexer": "ipython3", 58 | "version": "3.6.12" 59 | }, 60 | "toc": { 61 | "base_numbering": 1, 62 | "nav_menu": {}, 63 | "number_sections": true, 64 | "sideBar": true, 65 | "skip_h1_title": false, 66 | "title_cell": "Table of Contents", 67 | "title_sidebar": "Contents", 68 | "toc_cell": false, 69 | "toc_position": {}, 70 | "toc_section_display": true, 71 | "toc_window_display": false 72 | } 73 | }, 74 | "nbformat": 4, 75 | "nbformat_minor": 4 76 | } 77 | -------------------------------------------------------------------------------- /notebooks/paris: -------------------------------------------------------------------------------- 1 | ./../paris -------------------------------------------------------------------------------- /notebooks/populate_db.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from paris.module_scrapping import MatchPageScrapper\n", 10 | "import os\n", 11 | "os.environ[\"DJANGO_ALLOW_ASYNC_UNSAFE\"] = \"true\"" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 6, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "scrapper = MatchPageScrapper()" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": null, 26 | "metadata": { 27 | "scrolled": true 28 | }, 29 | "outputs": [], 30 | "source": [ 31 | "#you can start from whatever seed(s) and it will add to database related matches,\n", 32 | "#it's infinite unless you have alrealy scrapped the whole website\n", 33 | "scrapper.recursive_scrap(['https://csgolounge.com/fr/match/265846/'])" 34 | ] 35 | } 36 | ], 37 | "metadata": { 38 | "kernelspec": { 39 | "display_name": "Django Shell-Plus", 40 | "language": "python", 41 | "name": "django_extensions" 42 | }, 43 | "language_info": { 44 | "codemirror_mode": { 45 | "name": "ipython", 46 | "version": 3 47 | }, 48 | "file_extension": ".py", 49 | "mimetype": "text/x-python", 50 | "name": "python", 51 | "nbconvert_exporter": "python", 52 | "pygments_lexer": "ipython3", 53 | "version": "3.6.12" 54 | }, 55 | "toc": { 56 | "base_numbering": 1, 57 | "nav_menu": {}, 58 | "number_sections": true, 59 | "sideBar": true, 60 | "skip_h1_title": false, 61 | "title_cell": "Table of Contents", 62 | "title_sidebar": "Contents", 63 | "toc_cell": false, 64 | "toc_position": {}, 65 | "toc_section_display": true, 66 | "toc_window_display": false 67 | } 68 | }, 69 | "nbformat": 4, 70 | "nbformat_minor": 4 71 | } 72 | -------------------------------------------------------------------------------- /notebooks/var: -------------------------------------------------------------------------------- 1 | ./../var -------------------------------------------------------------------------------- /paris/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/paris/__init__.py -------------------------------------------------------------------------------- /paris/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/paris/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /paris/__pycache__/admin.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/paris/__pycache__/admin.cpython-36.pyc -------------------------------------------------------------------------------- /paris/__pycache__/apps.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/paris/__pycache__/apps.cpython-36.pyc -------------------------------------------------------------------------------- /paris/__pycache__/forms.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/paris/__pycache__/forms.cpython-36.pyc -------------------------------------------------------------------------------- /paris/__pycache__/models.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/paris/__pycache__/models.cpython-36.pyc -------------------------------------------------------------------------------- /paris/__pycache__/module_api.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/paris/__pycache__/module_api.cpython-36.pyc -------------------------------------------------------------------------------- /paris/__pycache__/module_data.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/paris/__pycache__/module_data.cpython-36.pyc -------------------------------------------------------------------------------- /paris/__pycache__/urls.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/paris/__pycache__/urls.cpython-36.pyc -------------------------------------------------------------------------------- /paris/__pycache__/utils.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/paris/__pycache__/utils.cpython-36.pyc -------------------------------------------------------------------------------- /paris/__pycache__/views.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/paris/__pycache__/views.cpython-36.pyc -------------------------------------------------------------------------------- /paris/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from .models import Match,Bet,Prediction 4 | 5 | admin.site.register(Match) 6 | admin.site.register(Bet) 7 | admin.site.register(Prediction) -------------------------------------------------------------------------------- /paris/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ParisConfig(AppConfig): 5 | name = 'paris' 6 | -------------------------------------------------------------------------------- /paris/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from .models import Bet,Match 3 | 4 | from django.db.models import Q 5 | 6 | class BetForm(forms.ModelForm): 7 | 8 | 9 | def __init__(self, *args, **kwargs): 10 | super().__init__(*args, **kwargs) 11 | self.fields['match'].queryset = Match.objects.filter(Q(status='Scheduled')|Q(status='Live')).order_by('date') 12 | 13 | '''if 'match' in self.data: 14 | try: 15 | 16 | match_id = int(self.data.get('match')) 17 | team1 = Match.objects.filter(match_id=match_id)[0].team1.strip() 18 | team2 = Match.objects.filter(match_id=match_id)[0].team2.strip() 19 | self.fields['winner'].choices = [(team1,team1),(team2,team2)] 20 | print([(team1,team1),(team2,team2)]) 21 | 22 | 23 | except (ValueError, TypeError): 24 | pass # invalid input from the client; ignore and fallback to empty City queryset 25 | ''' 26 | 27 | 28 | class Meta: 29 | model = Bet 30 | fields = ['amount','match','winner'] 31 | 32 | 33 | -------------------------------------------------------------------------------- /paris/migrations/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/paris/migrations/.gitignore -------------------------------------------------------------------------------- /paris/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | 4 | MATCH_STATUS = [('Scheduled', 'Scheduled'), 5 | ('Live', 'Live'), 6 | ('Results', 'Results'), 7 | ('Rescheduled', 'Rescheduled'), 8 | ('Canceled', 'Canceled'), 9 | ('Expired', 'Expired'), 10 | ('Empty', 'Empty')] 11 | 12 | BET_STATUS = [('Pending', 'Pending'), 13 | ('Finished', 'Finished'), 14 | ('Canceled', 'Canceled')] 15 | 16 | WINNER = [('Team 1', 'Team 1'), 17 | ('Team 2', 'Team 2'), 18 | ('None', 'None')] 19 | 20 | BET_STRATEGY = [('Naive', 'Naive'), 21 | ('EV', 'EV'), 22 | ('HLTV', 'HLTV')] 23 | 24 | MODELS = [('LOGREG', 'LOGREG')] 25 | 26 | 27 | class Match(models.Model): 28 | team1 = models.CharField(max_length=200) 29 | team2 = models.CharField(max_length=200) 30 | odd1 = models.DecimalField(max_digits=10, decimal_places=2) 31 | odd2 = models.DecimalField(max_digits=10, decimal_places=2) 32 | date = models.DateTimeField('date scheduled') 33 | logo1 = models.CharField(max_length=200) 34 | logo2 = models.CharField(max_length=200) 35 | status = models.CharField(max_length=200, choices=MATCH_STATUS) 36 | bo = models.CharField(max_length=200) 37 | match_id = models.IntegerField(primary_key=True) 38 | winner = models.CharField(max_length=200, choices=WINNER) 39 | time_to_go = models.CharField(max_length=200) 40 | 41 | def __str__(self): 42 | return "%s vs %s" % (self.team1, self.team2) 43 | 44 | 45 | class Prediction(models.Model): 46 | match = models.OneToOneField(Match, 47 | on_delete=models.CASCADE, 48 | primary_key=True) 49 | odd1 = models.DecimalField(max_digits=100, decimal_places=2) 50 | odd2 = models.DecimalField(max_digits=100, decimal_places=2) 51 | delta_ev_1 = models.DecimalField(max_digits=100, 52 | decimal_places=2, 53 | default=0) 54 | delta_ev_2 = models.DecimalField(max_digits=100, 55 | decimal_places=2, 56 | default=0) 57 | model = models.CharField(max_length=200, choices=MODELS) 58 | 59 | def __str__(self): 60 | return "Prediction of %s" % (self.match) 61 | 62 | 63 | class Bet(models.Model): 64 | class Meta: 65 | constraints = [models.UniqueConstraint(fields=['match', 'strategy'], 66 | name='unique strat')] 67 | match = models.ForeignKey(Match, on_delete=models.CASCADE) 68 | winner = models.CharField(max_length=200, choices=WINNER, default='None') 69 | amount = models.DecimalField(max_digits=10, decimal_places=2, default=0) 70 | status = models.CharField(max_length=200, 71 | choices=BET_STATUS, 72 | default='Pending') 73 | gain = models.DecimalField(max_digits=10, decimal_places=5, default=0) 74 | real = models.BooleanField(default=False) 75 | strategy = models.CharField(max_length=200, 76 | choices=BET_STRATEGY, 77 | default='EV') 78 | bet_id = models.AutoField(primary_key=True) 79 | 80 | def __str__(self): 81 | return f"{self.amount:.2f}€ on {self.winner} ({self.match.team1} vs {self.match.team2}), strat : {self.strategy}" 82 | -------------------------------------------------------------------------------- /paris/module_api.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from urllib.request import urlopen 3 | import json 4 | from . import module_data 5 | from io import StringIO 6 | 7 | 8 | def get_teams(token): 9 | """ 10 | Calls PandasScore API following endpoints : /csgo/teams 11 | return the response as a jsons 12 | """ 13 | per_page = 100 14 | response=[] 15 | for i in range(50): 16 | page=i 17 | request = urlopen(f"https://api.pandascore.co/csgo/teams?token={token}&per_page={per_page}&page={page}") 18 | response += json.load(request) 19 | return response 20 | 21 | def get_matches_history(token,page_number=300): 22 | """ 23 | Calls PandasScore API following endpoints : /csgo/matches 24 | return the response as a jsons 25 | """ 26 | per_page = 100 27 | response=[] 28 | for i in range(page_number): 29 | page = i 30 | request = urlopen(f"https://api.pandascore.co/csgo/matches?token={token}&page={page}&per_page={per_page}") 31 | response += json.load(request) 32 | return response 33 | 34 | 35 | def update_history(token): 36 | matches_json = get_matches_history(token) 37 | matches = pd.read_json(StringIO(json.dumps(matches_json))) 38 | module_data.add_to_history(matches) 39 | -------------------------------------------------------------------------------- /paris/module_data.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | import sqlite3 4 | import datetime 5 | import pytz 6 | from . import module_api 7 | 8 | DATA_DIR = './var/' 9 | 10 | 11 | def add_to_history(matches, verbose=0): 12 | n = matches.shape[0] 13 | for i in range(n): 14 | match = matches.iloc[i] 15 | if match['status'] != 'finished': 16 | if verbose: 17 | print("Match not finished yet, can't add to history") 18 | else: 19 | row = [0]*5 20 | row[0], found_1 = parse_team_name(match['opponents'][0]['opponent']['name'], 21 | return_found=True) 22 | row[1], found_2 = parse_team_name(match['opponents'][1]['opponent']['name'], 23 | return_found=True) 24 | if not found_1: 25 | with open('var/teams_map.csv', 'a', encoding = 'utf-8') as f: 26 | f.write(row[0]+';\n') 27 | print(f'{row[0]} added to map') 28 | f.close() 29 | if not found_2: 30 | with open('var/teams_map.csv', 'a', encoding = 'utf-8') as f: 31 | f.write(row[1]+';\n') 32 | f.close() 33 | print(f'{row[1]} added to map') 34 | 35 | row[2] = match['scheduled_at'].to_pydatetime() 36 | score = str(match['results'][0]['score']) 37 | score += " - " + str(match['results'][1]['score']) 38 | row[3] = (score) 39 | 40 | try: 41 | row[4] = parse_team_name(match['winner']['name']) 42 | 43 | except Exception: 44 | #print(match['winner']) 45 | row[4] = None 46 | finally: 47 | with sqlite3.connect(DATA_DIR + 'history.db') as conn: 48 | c = conn.cursor() 49 | infos = tuple(row) 50 | query = """INSERT or IGNORE INTO 51 | history VALUES (?,?,?,?,?)""" 52 | c.execute(query, infos) 53 | conn.commit() 54 | conn.close() 55 | 56 | 57 | 58 | def parse_team_name(el, return_found=False): 59 | rem = ['team', 'e-sports', 'esports', 'esport', 60 | 'gaming', 'club', 'clan', 'international'] 61 | my_map = pd.read_csv(DATA_DIR + 'teams_map.csv', sep=';').values.tolist() 62 | 63 | def team_map(x, map_, return_found=False): 64 | x = x.strip() 65 | found = False 66 | for val in map_: 67 | if x in val and not found: 68 | found = True 69 | x = val[0] 70 | if return_found: 71 | return x, found 72 | else: 73 | return x 74 | 75 | l = el.strip().lower().split(' ') 76 | for word in rem: 77 | if word in l: 78 | l.remove(word) 79 | el = " ".join(l) 80 | return team_map(el.lower(), my_map, return_found) 81 | 82 | 83 | def init_db(reboot=False): 84 | if reboot: 85 | query = """DROP TABLE history""" 86 | with sqlite3.connect(DATA_DIR + 'history.db') as conn: 87 | c = conn.cursor() 88 | c.execute(query) 89 | conn.commit() 90 | conn.close() 91 | 92 | query = """ 93 | CREATE TABLE history( 94 | team1 TEXT, 95 | team2 TEXT, 96 | date TEXT, 97 | score TEXT, 98 | winner TEXT, 99 | UNIQUE(team1, team2, date, score, winner) 100 | );""" 101 | with sqlite3.connect(DATA_DIR+'history.db') as conn: 102 | c = conn.cursor() 103 | c.execute(query) 104 | conn.commit() 105 | conn.close() 106 | 107 | 108 | def get_history(): 109 | with sqlite3.connect(DATA_DIR+'history.db') as conn: 110 | history = pd.read_sql_query("SELECT * from history", conn) 111 | conn.close() 112 | return history 113 | 114 | 115 | def parse_date(date): 116 | if type(date) == str: 117 | date = datetime.datetime.strptime(date,'%Y-%m-%d %H:%M:%S%z') 118 | return date 119 | 120 | 121 | 122 | 123 | class FeaturesBuilder: 124 | 125 | def __init__(self, update_history=False, token=None, 126 | recompute_ranking=False, recompute_elo=False): 127 | if update_history: 128 | if not token: 129 | print("Pls specify a token if you want the history to be updated") 130 | return None 131 | module_api.update_history(token) 132 | self.history = get_history().drop_duplicates() 133 | self.history = self.history[~self.history['winner'].isnull()] 134 | self.history.date = pd.to_datetime(self.history.date, utc=True) 135 | self.history = self.history.reset_index(drop=True) 136 | if recompute_ranking: 137 | self.ranking = self.compute_ranking(self.history) 138 | self.ranking.to_csv(DATA_DIR+'ranking.csv') 139 | else: 140 | self.ranking = pd.read_csv(DATA_DIR + 'ranking.csv', index_col=0) 141 | self.ranking.index = pd.to_datetime(self.ranking.index) 142 | 143 | if recompute_elo: 144 | self.history_elo = self.get_matches_elo(self.history) 145 | self.history_elo.to_csv(DATA_DIR + 'history_elo.csv') 146 | else: 147 | self.history_elo = pd.read_csv(DATA_DIR + 'history_elo.csv', 148 | index_col=0).drop_duplicates() 149 | self.history_elo.date = pd.to_datetime(self.history_elo.date, 150 | utc=True) 151 | 152 | # Module elo computing 153 | def find_date(self, date): 154 | dates = self.ranking.index 155 | before = np.where(dates <= date) 156 | if len(before) > 0: 157 | t = before[0][-1] 158 | return dates[t] 159 | 160 | def compute_ranking(self, history): 161 | t0 = history.date.min() 162 | now = datetime.datetime.now(tz=pytz.utc) 163 | weeks = (now-t0).days // 7 164 | dates = ([pd.to_datetime(t0) + 165 | datetime.timedelta(days=i*7) for i in range(weeks)]) 166 | teams = pd.Series(pd.concat((history.team1, 167 | history.team2), axis=0).unique()) 168 | elo = pd.Series(np.ones(len(teams))*1400) 169 | elo_ranking = pd.DataFrame(columns=['team', 'elo', 'date']) 170 | elo_ranking.team = teams 171 | elo_ranking.elo = elo 172 | elo_ranking.date = t0 173 | elo_ranking = elo_ranking.set_index(['date', 'team']) 174 | elo_ranking = elo_ranking.unstack('team').elo 175 | for i in range(weeks-1): 176 | matches = (history[(dates[i] < history['date']) 177 | & (history['date'] < dates[i+1])]) 178 | if dates[i+1] not in elo_ranking.index: 179 | elo_vect = elo_ranking.loc[[dates[i]]].copy() 180 | elo_vect.index = [dates[i+1]] 181 | for j in range(len(matches)): 182 | match = matches.iloc[j] 183 | team1 = match.team1 184 | team2 = match.team2 185 | elo1 = elo_vect[team1] 186 | elo2 = elo_vect[team2] 187 | p1 = 1/(1+10**((elo2-elo1)/400)) 188 | p2 = 1/(1+10**((elo1-elo2)/400)) 189 | S1 = 40*((match['winner'] == team1) - p1) 190 | S2 = 40*((match['winner'] == team2) - p2) 191 | elo1 += S1 192 | elo2 += S2 193 | elo_vect[team1] = elo1 194 | elo_vect[team2] = elo2 195 | elo_ranking = elo_ranking.append(elo_vect) 196 | return elo_ranking 197 | 198 | def get_teams_elo(self, teams, date): 199 | t = self.find_date(date) 200 | try: 201 | teams_elo = self.ranking.loc[t, teams] 202 | except KeyError: 203 | print(f'One or both teams not in the ranking : {teams}') 204 | teams_elo = [-99, -99] 205 | return teams_elo 206 | 207 | def get_match_elo(self, match): 208 | elo1, elo2 = self.get_teams_elo([match.team1, match.team2], match.date) 209 | return elo1, elo2 210 | 211 | def get_matches_elo(self, matches): 212 | elo1 = np.zeros(len(matches)) - 99 213 | elo2 = np.zeros(len(matches)) - 99 214 | for i in range(len(matches)): 215 | elo1[i], elo2[i] = self.get_match_elo(matches.iloc[i]) 216 | mask = (elo1 != -99) & (elo2 != -99) 217 | matches = matches[mask].copy() 218 | elo1 = elo1[mask] 219 | elo2 = elo2[mask] 220 | matches['elo1'] = elo1 221 | matches['elo2'] = elo2 222 | return matches 223 | 224 | # Module fitness computing 225 | def get_team_history(self,team,date,rows=5): 226 | date = datetime.datetime(date.year,date.month,date.day,tzinfo=datetime.timezone.utc) 227 | team_history = self.history_elo[(self.history_elo['date']0 39 | 40 | def scrap_match_page(self,url): 41 | self.driver.get(url) 42 | self.driver.implicitly_wait(1) 43 | if self.is_already_scrapped(url.split('/')[-2]): 44 | return None, [] 45 | elif not self.is_page_empty(): 46 | #matches_data = pd.DataFrame(columns= ["team1",'team2','odd1','odd2','logo1','logo2','bo','date','match_id']) 47 | date = self.driver.find_elements_by_class_name('lounge-match-date__date')[0].get_attribute("innerHTML") 48 | date = datetime.strptime(date.replace(" ","")[:-3],"%d.%m.%Y,%H:%M") 49 | date = pytz.timezone("Europe/Paris").localize(date, is_dst=None) 50 | bo = self.driver.find_elements_by_class_name('sys-bo')[0].get_attribute('innerHTML') 51 | team1 = self.driver.find_elements_by_class_name('lounge-team_left')[0] 52 | team1_name = parse_team_name(team1.find_elements_by_class_name('lounge-team__title')[0].get_attribute('innerHTML').lower()) 53 | team1_odd = team1.find_elements_by_class_name('sys-stat-koef-1')[0].get_attribute('innerHTML') 54 | team2 = self.driver.find_elements_by_class_name('lounge-team_right')[0] 55 | team2_name = parse_team_name(team2.find_elements_by_class_name('lounge-team__title')[0].get_attribute('innerHTML').lower()) 56 | team2_odd = team2.find_elements_by_class_name('sys-stat-koef-2')[0].get_attribute('innerHTML') 57 | team1_logo = team1.find_elements_by_class_name('sys-t1logo')[0].get_attribute('src') 58 | team2_logo = team2.find_elements_by_class_name('sys-t2logo')[0].get_attribute('src') 59 | match_id = self.driver.current_url.split('/')[-2] 60 | is_canceled = len(self.driver.find_elements_by_class_name('lounge-match-date_canceled'))>0 61 | is_rescheduled = len(self.driver.find_elements_by_class_name('lounge-match-date_rescheduled'))>0 62 | is_live = len(self.driver.find_elements_by_class_name('lounge-match-date_live'))>0 63 | winner_element = self.driver.find_elements_by_class_name('lounge-team_win') 64 | urls = list(map(lambda x:x.get_attribute('href'),self.driver.find_elements_by_class_name('match-history-item'))) 65 | if url in urls: 66 | urls.remove(url) 67 | if len(winner_element)>0: 68 | team1_winner = 'lounge-team_left' in self.driver.find_elements_by_class_name('lounge-team_win')[0].get_attribute('class').split() 69 | team2_winner = 'lounge-team_right' in self.driver.find_elements_by_class_name('lounge-team_win')[0].get_attribute('class').split() 70 | else: 71 | team1_winner = False 72 | team2_winner = False 73 | winner = team1_winner * 'Team 1' + team2_winner * 'Team 2' 74 | has_results = len(winner)>0 75 | status = "Rescheduled" * is_rescheduled + "Canceled" * is_canceled + 'Results' * has_results + "Live" * is_live 76 | 77 | if len(team1_odd) > 2 and len(team2_odd) > 2: 78 | team1_odd = float(team1_odd[1:]) 79 | team2_odd = float(team2_odd[1:]) 80 | row = pd.DataFrame([[team1_name,team2_name,team1_odd,team2_odd, 81 | team1_logo,team2_logo,bo,status,winner,date,match_id]], 82 | columns= ["team1",'team2','odd1','odd2', 83 | 'logo1','logo2','bo','status','winner','date','match_id']) 84 | team1,team2,odd1,odd2,logo1,logo2,bo,status,winner,date,match_id=row.iloc[0] 85 | Match(team1=team1,team2=team2,odd1=odd1,odd2=odd2,logo1=logo1,logo2=logo2,status=status,winner=winner,bo=bo,date=date,match_id=match_id).save() 86 | self.already_visited.append(match_id) 87 | return row,urls 88 | else: 89 | return None,[] 90 | 91 | else: 92 | date = datetime.now(pytz.utc) 93 | status = 'Empty' 94 | match_id = self.driver.current_url.split('/')[-2] 95 | row = pd.DataFrame([['','', 0., 0., 96 | '','','',status,'',date,match_id]], 97 | columns= ["team1",'team2','odd1','odd2', 98 | 'logo1','logo2','bo','status','winner','date','match_id']) 99 | team1,team2,odd1,odd2,logo1,logo2,bo,status,winner,date,match_id=row.iloc[0] 100 | Match(team1=team1,team2=team2,odd1=odd1,odd2=odd2,logo1=logo1,logo2=logo2,status=status,winner=winner,bo=bo,date=date,match_id=match_id).save() 101 | self.already_visited.append(match_id) 102 | return row, [] 103 | 104 | def recursive_scrap(self,urls): 105 | if len(urls) == 0: 106 | return 'Done' 107 | else: 108 | for url in urls: 109 | data,new_urls = self.scrap_match_page(url) 110 | print(data) 111 | self.recursive_scrap(new_urls) 112 | 113 | -------------------------------------------------------------------------------- /paris/static/paris/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | My test page 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | {% block content %} 20 | 21 | {% endblock %} 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /paris/static/paris/item.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% if matches_history %} 5 | {% for match in matches_history %} 6 | 7 | {% endfor %} 8 | 9 | {% else %} 10 |

No matches are available.

11 | {% endif %} 12 | -------------------------------------------------------------------------------- /paris/static/paris/matches.json: -------------------------------------------------------------------------------- 1 | {"team1":{"0":"alternate attax","1":"saw","2":"izako boars","3":"k23","4":"sprout","5":"agf","6":"astralis","7":"mibr","8":"new england whalers","9":"secret","10":"depth","11":"avant","12":"espada","13":"project x","14":"ldlc","15":"izako boars","16":"winstrike","17":"thedice","18":"wygers","19":"real betis","20":"hreds","21":"infinity","22":"atheris","23":"chiefs","24":"x6tence","25":"chiefs","26":"teamone","27":"secret","28":"rebirth","29":"new england whalers","30":"furia","31":"sprout","32":"astralis","33":"skade","34":"nemiga","35":"copenhagen flames","36":"virtus.pro","37":"hard legion","38":"heretics","39":"project x","40":"heretics","41":"order","42":"new england whalers","43":"river plate","44":"secret","45":"new england whalers","46":"malvinas","47":"yeah","48":"movistar riders","49":"mad lions","50":"north","51":"skade","52":"virtus.pro","53":"alternate attax","54":"godsent","55":"vexed","56":"k23","57":"north","58":"agf","59":"cyber legacy"},"team2":{"0":"mad lions","1":"nemiga","2":"cyber legacy","3":"wisla krakow","4":"copenhagen flames","5":"singularity","6":"g2","7":"furia","8":"mythic","9":"teamone","10":"rbg","11":"tbd","12":"godsent","13":"sj","14":"movistar riders","15":"sinners","16":"lilmix","17":"agf","18":"sangal","19":"budapest five","20":"lyngby vikings","21":"wolves crew","22":"estral","23":"avant","24":"forze","25":"order","26":"rbg","27":"depth","28":"mythic","29":"russian canadians","30":"g2","31":"north","32":"mibr","33":"navi youth","34":"hellraisers","35":"galaxy racer","36":"k23","37":"mustang crew","38":"gambit","39":"alternate attax","40":"x6tence","41":"vertex","42":"secret","43":"coscu army","44":"rebirth","45":"rbg","46":"detona pound","47":"rebirth","48":"saw","49":"havu","50":"endpoint","51":"lyngby vikings","52":"wisla krakow","53":"singularity","54":"heroic","55":"umx","56":"endpoint","57":"illuminar","58":"espada","59":"nexus"},"odd1":{"0":3.2,"1":3.93,"2":6.16,"3":1.48,"4":1.16,"5":1.15,"6":2.07,"7":1.17,"8":1.3,"9":9.87,"10":6.25,"11":4.6,"12":3.9,"13":1.0,"14":63.26,"15":1.0,"16":1.05,"17":1.0,"18":1.0,"19":1.0,"20":1.0,"21":1.0,"22":1.0,"23":7.85,"24":4.56,"25":2.86,"26":1.13,"27":1.22,"28":1.59,"29":1.14,"30":1.64,"31":1.68,"32":1.09,"33":1.95,"34":1.7,"35":2.12,"36":1.15,"37":1.63,"38":4.42,"39":2.37,"40":1.7,"41":1.24,"42":1.3,"43":1.42,"44":1.57,"45":1.23,"46":2.27,"47":1.63,"48":2.58,"49":1.78,"50":1.42,"51":1.47,"52":1.2,"53":1.33,"54":3.62,"55":1.31,"56":1.99,"57":1.26,"58":2.88,"59":2.33},"odd2":{"0":1.37,"1":1.28,"2":1.16,"3":2.69,"4":6.19,"5":6.27,"6":1.76,"7":5.9,"8":3.72,"9":1.09,"10":1.15,"11":1.23,"12":1.28,"13":1.0,"14":1.01,"15":1.0,"16":17.61,"17":1.0,"18":1.0,"19":1.0,"20":1.0,"21":1.0,"22":1.0,"23":1.12,"24":1.23,"25":1.44,"26":7.41,"27":4.7,"28":2.37,"29":6.89,"30":2.27,"31":2.19,"32":10.06,"33":1.86,"34":2.15,"35":1.72,"36":6.56,"37":2.29,"38":1.24,"39":1.59,"40":2.15,"41":4.36,"42":3.68,"43":2.94,"44":2.43,"45":4.49,"46":1.64,"47":2.28,"48":1.51,"49":2.03,"50":2.94,"51":2.74,"52":4.97,"53":3.46,"54":1.31,"55":3.62,"56":1.82,"57":4.07,"58":1.43,"59":1.61},"logo1":{"0":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/330_5e1f9be12e05e.png","1":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5548_5e98e240e9630.png","2":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1369_59a3323886e25.png","3":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/6103_5f827b2ccafcd.png","4":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1592_5a39e79a82e88.png","5":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1803_5c49060641ebc.png","6":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/368_59440d4ce3b61.png","7":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/32_5df2be1641cf5.png","8":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5454_5e2373d1955f3.png","9":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/TBD.png","10":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/TBD.png","11":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/2627_5cf3ef5cb49d5.png","12":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/2476_5cb357a52dbab.png","13":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5377_5e012822cfce1.png","14":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/140_5926e597249d7.png","15":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1369_59a3323886e25.png","16":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1916_5de59f6de7a60.png","17":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/4810_5ded7586a5bda.png","18":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5772_5ed18c4a6af78.png","19":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5859_5ec714db3426d.png","20":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/2614_5d40951fa0f07.png","21":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/2504_5eab4a82d0c3f.png","22":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/TBD.png","23":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/77_593639ff7e214.png","24":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/441_59933e20840c7.png","25":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/77_593639ff7e214.png","26":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/791_599618822057e.png","27":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/TBD.png","28":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/4874_5dd3397411232.png","29":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5454_5e2373d1955f3.png","30":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1576_5a6a0ff128782.png","31":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1592_5a39e79a82e88.png","32":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/368_59440d4ce3b61.png","33":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/4980_5e07d21d665ff.png","34":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1236_59374e5ae80ad.png","35":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/2247_5c0efa448f68f.png","36":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1293_5df752b5b3454.png","37":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5080_5db6141952705.png","38":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/4618_5f9758725ddbf.png","39":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5377_5e012822cfce1.png","40":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/4618_5f9758725ddbf.png","41":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1652_5b2ae815760bd.png","42":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5454_5e2373d1955f3.png","43":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/6066_5f25ee1312c88.png","44":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/TBD.png","45":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5454_5e2373d1955f3.png","46":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1380_5d128836ba462.png","47":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1725_5ec710e1f333d.png","48":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1397_5c866ccd68a48.png","49":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/382_5df48b42eafc9.png","50":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/973_5e1545660e1ab.png","51":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/4980_5e07d21d665ff.png","52":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1293_5df752b5b3454.png","53":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/330_5e1f9be12e05e.png","54":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/535_59382ba51f073.png","55":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/31_599341811c1d1.png","56":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/6103_5f827b2ccafcd.png","57":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/973_5e1545660e1ab.png","58":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1803_5c49060641ebc.png","59":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5652_5e782a02177eb.png"},"logo2":{"0":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/382_5df48b42eafc9.png","1":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1236_59374e5ae80ad.png","2":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5652_5e782a02177eb.png","3":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5090_5dab7e9f5f3e9.png","4":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/2247_5c0efa448f68f.png","5":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/587_5abcbd068a548.png","6":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/44_5c866ab23875c.png","7":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1576_5a6a0ff128782.png","8":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/997_5936375151aa4.png","9":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/791_599618822057e.png","10":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/4699_5d5735fac8fd6.png","11":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/43_5930e891d1b2a.png","12":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/535_59382ba51f073.png","13":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1501_5c79bf5a45a6b.png","14":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1397_5c866ccd68a48.png","15":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5487_5e35eda201c69.png","16":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/2299_5d844778188ab.png","17":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1803_5c49060641ebc.png","18":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/4859_5de59e4d7539c.png","19":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/2509_5d5736352a1e2.png","20":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/2275_5ca93acaea365.png","21":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/TBD.png","22":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/6010_5f0121b6213b7.png","23":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/2627_5cf3ef5cb49d5.png","24":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1295_5c995b66c78df.png","25":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1652_5b2ae815760bd.png","26":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/4699_5d5735fac8fd6.png","27":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/TBD.png","28":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/997_5936375151aa4.png","29":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/TBD.png","30":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/44_5c866ab23875c.png","31":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/973_5e1545660e1ab.png","32":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/32_5df2be1641cf5.png","33":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5056_5da1df63a234c.png","34":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5055_5f255d28aee4a.png","35":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/6072_5f2c4adf799d0.png","36":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/6103_5f827b2ccafcd.png","37":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5689_5e8685b710959.png","38":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/2485_5f58b04d48315.png","39":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/330_5e1f9be12e05e.png","40":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/441_59933e20840c7.png","41":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5678_5e81481ebc6c9.png","42":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/TBD.png","43":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1863_5afb5e601a140.png","44":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/4874_5dd3397411232.png","45":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/4699_5d5735fac8fd6.png","46":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5766_5f9f2cd34fada.png","47":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/4874_5dd3397411232.png","48":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5548_5e98e240e9630.png","49":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1273_595987b630dc0.png","50":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/833_5e3f3ad3534f0.png","51":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/2275_5ca93acaea365.png","52":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5090_5dab7e9f5f3e9.png","53":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/587_5abcbd068a548.png","54":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/5787_5eab38cc08ce4.png","55":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/TBD.png","56":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/833_5e3f3ad3534f0.png","57":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/1722_5dcddec1cf9bb.png","58":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/2476_5cb357a52dbab.png","59":"https:\/\/csgolounge.com\/images\/teams\/go\/120x120\/136_5f3b0441cfd57.png"},"bo":{"0":" BO3 ","1":" BO3 ","2":" BO3 ","3":" BO3 ","4":" BO3 ","5":" BO3 ","6":" BO3 ","7":" BO3 ","8":" BO3 ","9":" BO3 ","10":" BO3 ","11":" BO5 ","12":" BO3 ","13":" BO3 ","14":" BO3 ","15":" BO3 ","16":" BO3 ","17":" BO3 ","18":" BO3 ","19":" BO3 ","20":" BO3 ","21":" BO3 ","22":" BO3 ","23":" BO5 ","24":" BO3 ","25":" BO3 ","26":" BO3 ","27":" BO3 ","28":" BO3 ","29":" BO3 ","30":" BO3 ","31":" BO3 ","32":" BO3 ","33":" BO3 ","34":" BO3 ","35":" BO3 ","36":" BO3 ","37":" BO3 ","38":" BO3 ","39":" BO3 ","40":" BO3 ","41":" BO3 ","42":" BO3 ","43":" BO3 ","44":" BO3 ","45":" BO3 ","46":" BO3 ","47":" BO3 ","48":" BO3 ","49":" BO3 ","50":" BO3 ","51":" BO3 ","52":" BO3 ","53":" BO3 ","54":" BO3 ","55":" BO3 ","56":" BO3 ","57":" BO3 ","58":" BO3 ","59":" BO3 "},"status":{"0":"Live","1":"Scheduled","2":"Scheduled","3":"Scheduled","4":"Scheduled","5":"Scheduled","6":"Scheduled","7":"Scheduled","8":"Scheduled","9":"Scheduled","10":"Scheduled","11":"Scheduled","12":"Scheduled","13":"Scheduled","14":"Scheduled","15":"Scheduled","16":"Scheduled","17":"Scheduled","18":"Scheduled","19":"Scheduled","20":"Scheduled","21":"Scheduled","22":"Scheduled","23":"Scheduled","24":"Results","25":"Results","26":"Results","27":"Results","28":"Results","29":"Canceled","30":"Results","31":"Results","32":"Results","33":"Results","34":"Results","35":"Results","36":"Results","37":"Results","38":"Results","39":"Results","40":"Results","41":"Results","42":"Rescheduled","43":"Results","44":"Results","45":"Results","46":"Results","47":"Results","48":"Results","49":"Results","50":"Results","51":"Results","52":"Results","53":"Results","54":"Results","55":"Results","56":"Results","57":"Results","58":"Results","59":"Results"},"winner":{"0":"","1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":"","9":"","10":"","11":"","12":"","13":"","14":"","15":"","16":"","17":"","18":"","19":"","20":"","21":"","22":"","23":"","24":"Team 1","25":"Team 2","26":"Team 1","27":"Team 1","28":"Team 2","29":"","30":"Team 2","31":"Team 2","32":"Team 1","33":"Team 1","34":"Team 1","35":"Team 1","36":"Team 2","37":"Team 1","38":"Team 2","39":"Team 2","40":"Team 2","41":"Team 1","42":"","43":"Team 2","44":"Team 1","45":"Team 1","46":"Team 2","47":"Team 2","48":"Team 1","49":"Team 1","50":"Team 1","51":"Team 1","52":"Team 1","53":"Team 1","54":"Team 1","55":"Team 1","56":"Team 2","57":"Team 1","58":"Team 2","59":"Team 1"},"date":{"0":1604390400000,"1":1604400600000,"2":1604400600000,"3":1604401200000,"4":1604401200000,"5":1604413800000,"6":1604417400000,"7":1604428200000,"8":1604451600000,"9":1604451600000,"10":1604451600000,"11":1604480700000,"12":1604487000000,"13":1604518200000,"14":1604518200000,"15":1604518200000,"16":1604518200000,"17":1604518200000,"18":1604518200000,"19":1604518200000,"20":1604518200000,"21":1604527200000,"22":1604538000000,"23":1604563200000,"24":1604390400000,"25":1604387100000,"26":1604365200000,"27":1604365200000,"28":1604365200000,"29":1604365200000,"30":1604352300000,"31":1604342100000,"32":1604337000000,"33":1604328300000,"34":1604327400000,"35":1604314800000,"36":1604314800000,"37":1604314200000,"38":1604314200000,"39":1604304000000,"40":1604304000000,"41":1604300700000,"42":1604284200000,"43":1604272800000,"44":1604271600000,"45":1604264400000,"46":1604260800000,"47":1604260800000,"48":1604253600000,"49":1604253600000,"50":1604250000000,"51":1604250000000,"52":1604241000000,"53":1604241000000,"54":1604239200000,"55":1604235600000,"56":1604228400000,"57":1604228400000,"58":1604227800000,"59":1604227800000},"match_id":{"0":253929,"1":253941,"2":253951,"3":253963,"4":253973,"5":253985,"6":254009,"7":254011,"8":254058,"9":254060,"10":254062,"11":253860,"12":253871,"13":254092,"14":254094,"15":254096,"16":254125,"17":254127,"18":254149,"19":254151,"20":254169,"21":254178,"22":254180,"23":253891,"24":253917,"25":253850,"26":253651,"27":253649,"28":253647,"29":253645,"30":253346,"31":253567,"32":253331,"33":253770,"34":253758,"35":253602,"36":253600,"37":253746,"38":253734,"39":253579,"40":253577,"41":253722,"42":253840,"43":253624,"44":253796,"45":253794,"46":253622,"47":253556,"48":253540,"49":253185,"50":253782,"51":253529,"52":253320,"53":253309,"54":253174,"55":253695,"56":253518,"57":253393,"58":253297,"59":253286}} -------------------------------------------------------------------------------- /paris/static/paris/rankings.json: -------------------------------------------------------------------------------- 1 | {"name":{"0":"astralis","1":"natus vincere","2":"renegades","3":"evil geniuses","4":"big","5":"faze","6":"vitality","7":"heroic","8":"furia","9":"og","10":"sprout","11":"spirit","12":"complexity","13":"liquid","14":"mousesports","15":"fnatic","16":"tyloo","17":"gambit youngsters","18":"forze","19":"order","20":"100 thieves","21":"g2","22":"havu","23":"virtus.pro","24":"nemiga","25":"chaos","26":"vici","27":"nip","28":"ence","29":"saw","30":"godsent","31":"avant","32":"atk","33":"mad lions","34":"gen.g","35":"tricked","36":"chiefs","37":"north","38":"endpoint","39":"alternate attax","40":"mibr","41":"heretics","42":"rooster","43":"boom","44":"nexus","45":"teamone","46":"ago","47":"hellraisers","48":"espada","49":"tiger","50":"invictus","51":"w7m","52":"cr4zy","53":"winstrike","54":"movistar riders","55":"sharks","56":"syman","57":"wisla krakow","58":"isurus","59":"secret","60":"skade","61":"k23","62":"9z","63":"lynn vision","64":"thedice","65":"copenhagen flames","66":"kova","67":"detona","68":"kingzzz","69":"ze pug godz","70":"prima","71":"imperial","72":"flowskola","73":"lilmix","74":"fightclub","75":"cloud9","76":"onethree","77":"paradox","78":"sinners","79":"swole patrol","80":"agf","81":"gamerlegion","82":"hard legion","83":"pain","84":"illuminar","85":"sj","86":"btrg","87":"baecon group","88":"bluejays","89":"red instinct","90":"ldlc","91":"giants","92":"fate","93":"nordavind","94":"intz","95":"gambit","96":"1win","97":"apeks","98":"twa","99":"rugratz","100":"new england whalers","101":"cyber legacy","102":"ubiteam","103":"granit","104":"sons of lennart","105":"bren","106":"rebirth","107":"wings up","108":"supremacy","109":"pact","110":"malvinas","111":"vertex","112":"vinkelparty","113":"hercegnovi","114":"red canids","115":"pelafustanes","116":"rooster 2","117":"los kogutos","118":"100pinggods","119":"secret","120":"third impact","121":"energy","122":"river plate","123":"penta sports","124":"natus vincere junior","125":"tt willhaben","126":"meta","127":"kombucha","128":"wygers","129":"big academy","130":"dignitas female","131":"triumphant song","132":"golden knights","133":"exen","134":"moscow five academy","135":"amsterdam kings","136":"goliath","137":"totem","138":"exploit","139":"z5","140":"kqvthrowar","141":"offmicplz","142":"project f","143":"rfts","144":"come mid","145":"furia inagame","146":"paquet\u00e3\u00a1","147":"rhyno","148":"isellpower","149":"good headshot","150":"global","151":"sixth gear","152":"5epl #1","153":"bravos","154":"s2v","155":"blackbarz","156":"kiisu","157":"tjenarelarry","158":"invictus","159":"seven.gg","160":"furia female","161":"mefron","162":"dr. pepper","163":"lethal divide","164":"skinbaron","165":"sawo","166":"mbappeek","167":"nopurplesattob","168":"radix","169":"nasr","170":"havan liberty","171":"tienaajat","172":"godz1337","173":"grond","174":"accusata","175":"xi'antaichanggui","176":"hirveatilanne","177":"blessed","178":"jointheforce","179":"exaequo italy","180":"4elements","181":"violent roses","182":"\u9ec4\u7116\u9e21","183":"epic dudes","184":"omen attih","185":"avez","186":"really weird","187":"kingslayer","188":"tarantino fan","189":"ex-incept","190":"zigma","191":"kolossus","192":"hsl","193":"for the win evolution","194":"pokemons","195":"9z fem","196":"sampi","197":"hauntedfamily","198":"vicious&evil","199":"checkmate","200":"nomix","201":"kpi","202":"zero","203":"ex-blessed","204":"sera","205":"elites","206":"masonic","207":"eviscerate","208":"jerseyboys","209":"n4meless","210":"integral nation","211":"fengshuii","212":"last name","213":"punch quest","214":"caught off guard","215":"sinister5","216":"galaxy racer","217":"savage","218":"danjoor gang","219":"most valuable players","220":"athena","221":"beyond","222":"valour","223":"epsilon","224":"sport do recife","225":"5ks","226":"savage","227":"dogmination","228":"iraq","229":"hawks","230":"progress g","231":"born of darkness","232":"gosu","233":"knockout","234":"positive vibes only","235":"gobananas","236":"revenant","237":"doraemon","238":"7ds","239":"ballarat bulldogs","240":"maffel","241":"quest","242":"tropadalacoste","243":"success","244":"evidence","245":"prizmv","246":"godnat","247":"boomers","248":"cyberground","249":"unicorns of love","250":"djentlemen","251":"istanbul wildcats","252":"tka","253":"az","254":"cohesive concepts","255":"mercury","256":"\/dab\/","257":"sbudedollars","258":"nyxe","259":"014team","260":"doggers","261":"scape b","262":"axxez","263":"jmt","264":"rhein-neckar","265":"konkrigerne","266":"rpeat","267":"the little bocks","268":"skilled enough","269":"crazy killerz","270":"boomers","271":"olsdfypro","272":"rpg","273":"spacescroll","274":"einheit","275":"bacan","276":"hc","277":"geniuzhard","278":"manguste","279":"mrozonki","280":"ex-warriors int.","281":"after","282":"ttc","283":"triumph","284":"sissi state young punks","285":"fcottond","286":"deportivo","287":"s\u00f8rby flames","288":"frosty","289":"jyysto","290":"tikitakan","291":"h34t","292":"panthers never surrend","293":"quekhi","294":"prodigy","295":"alpha","296":"lbs","297":"fenrir","298":"wer","299":"cavaniagent","300":"cavaniagent","301":"veritas vincit","302":"jyderup enigma","303":"campus vejle * instinct","304":"kizmogamingclub","305":"russian canadians","306":"dignitas","307":"soberano female","308":"destiny","309":"vexed","310":"menestystarina","311":"valoranters","312":"tropa suprema ihosts3","313":"retired5","314":"iso","315":"\u03c0raci","316":"olej nap\u0119dowy","317":"ex-polar ace","318":"excellency","319":"real betis","320":"royal republic","321":"native 2 empire","322":"timbermen","323":"kinship","324":"brazen","325":"izako boars","326":"ethereal","327":"leisure","328":"vp.prodigy","329":"bezotca","330":"fendi","331":"newhappy","332":"lemondogs","333":"ob\u6307\u6325\u5b98","334":"addice inc.","335":"aimcats","336":"sparx","337":"cismix","338":"baecongg.4gaming","339":"brunolopes","340":"sangal","341":"aafk hobbylag","342":"kokonister!","343":"aezakmi","344":"benelux5","345":"invictus","346":"megaballers","347":"loto","348":"eclipse","349":"fly1nghirsch","350":"santos","351":"vslash","352":"kyiv","353":"ground zero","354":"dame time","355":"yalla cs","356":"offset","357":"xdudog","358":"wesports","359":"tur\u00f3w zgorzelec","360":"dnmk","361":"mew","362":"tyloo fe","363":"emme","364":"detona pound","365":"zero.tsg","366":"antofa on laners","367":"ymca","368":"visu","369":"europske cs","370":"dermia","371":"globo gym","372":"wizards","373":"royalty","374":"plan-b","375":"undead","376":"recast","377":"dieux","378":"mythic","379":"umx","380":"entropiq","381":"f!ve","382":"aligon","383":"orgless","384":"honors","385":"high coast","386":"nonamers","387":"portal x","388":"myinsanity","389":"cowana","390":"prifu","391":"sg.pro","392":"divine vendetta","393":"d13","394":"blacklist","395":"hg","396":"ex-recon 5","397":"warthox","398":"l\u00e8s\u00e8","399":"wygers argentina","400":"ucam","401":"saves","402":"teamname kommt","403":"paper rex","404":"fwrd","405":"quantum bellator fire","406":"furious","407":"new pampas","408":"project x","409":"greshjerna","410":"jijiehao","411":"gaminate","412":"pro100","413":"ago nest","414":"online kingdom","415":"falkn","416":"good game pr","417":"apologis","418":"ayb","419":"sparx","420":"fragbox","421":"mustang crew","422":"9ine","423":"majesty.ua","424":"incognito","425":"exdee","426":"eclot","427":"toomuchvideogames","428":"bantz","429":"dzver","430":"alma","431":"coscu army","432":"queso","433":"gtz bulls","434":"yeah","435":"log","436":"e-galo","437":"plmix","438":"huat zai","439":"rebirth","440":"lyngby vikings","441":"scape","442":"tenerife titans","443":"aion","444":"soberano","445":"silhouette","446":"aftermind","447":"c0ntact","448":"mako","449":"killabeez","450":"enterprise","451":"sws","452":"sjk","453":"budapest five","454":"hyper","455":"neverest","456":"alltech","457":"keyd","458":"cex","459":"mazaalai","460":"buffdaddy's paypal","461":"extremum","462":"unique","463":"mens","464":"zer\u00e3\u02dczone","465":"cyberwolves","466":"x6tence","467":"hreds","468":"eeriness.cs","469":"gamefist","470":"singularity","471":"pompa","472":"conquer","473":"r!ot","474":"qlash","475":"no limit","476":"for the win","477":"cream real betis latam","478":"nyyrikki","479":"selectah","480":"overt","481":"level up","482":"exalty","483":"cleantmix","484":"let's quit","485":"thunder logic","486":"rbg","487":"final-gaming","488":"white rabbit","489":"playing ducks","490":"planetkey dynamics","491":"entropy","492":"imperium","493":"lakers","494":"divizon","495":"brute","496":"honoris","497":"sector one","498":"valhalla vikings","499":"esuba","500":"dark tigers","501":"control","502":"downfall","503":"gameagents","504":"infinity","505":"forbidden","506":"pc419","507":"lowlandlions","508":"black dragons female"},"ranking":{"0":1,"1":2,"2":3,"3":4,"4":5,"5":6,"6":7,"7":8,"8":9,"9":10,"10":11,"11":12,"12":13,"13":14,"14":15,"15":16,"16":17,"17":18,"18":19,"19":20,"20":21,"21":22,"22":23,"23":24,"24":25,"25":26,"26":27,"27":28,"28":29,"29":30,"30":31,"31":32,"32":33,"33":34,"34":35,"35":36,"36":37,"37":38,"38":39,"39":40,"40":41,"41":42,"42":43,"43":44,"44":45,"45":46,"46":47,"47":48,"48":49,"49":50,"50":51,"51":52,"52":53,"53":54,"54":55,"55":56,"56":57,"57":58,"58":59,"59":60,"60":61,"61":62,"62":63,"63":64,"64":65,"65":66,"66":67,"67":68,"68":69,"69":70,"70":71,"71":72,"72":73,"73":74,"74":75,"75":76,"76":77,"77":78,"78":79,"79":80,"80":81,"81":82,"82":83,"83":84,"84":85,"85":86,"86":87,"87":88,"88":89,"89":90,"90":91,"91":92,"92":93,"93":94,"94":95,"95":96,"96":97,"97":98,"98":99,"99":100,"100":101,"101":102,"102":103,"103":104,"104":105,"105":106,"106":107,"107":108,"108":109,"109":110,"110":111,"111":112,"112":113,"113":114,"114":115,"115":116,"116":117,"117":118,"118":119,"119":120,"120":121,"121":122,"122":123,"123":124,"124":125,"125":126,"126":127,"127":128,"128":129,"129":130,"130":131,"131":132,"132":133,"133":134,"134":135,"135":136,"136":137,"137":138,"138":139,"139":140,"140":141,"141":142,"142":143,"143":144,"144":145,"145":146,"146":147,"147":148,"148":149,"149":150,"150":151,"151":152,"152":153,"153":154,"154":155,"155":156,"156":157,"157":158,"158":159,"159":160,"160":161,"161":162,"162":163,"163":164,"164":165,"165":166,"166":167,"167":168,"168":169,"169":170,"170":171,"171":172,"172":173,"173":174,"174":175,"175":176,"176":177,"177":178,"178":179,"179":180,"180":181,"181":182,"182":183,"183":184,"184":185,"185":186,"186":187,"187":188,"188":189,"189":190,"190":191,"191":192,"192":193,"193":194,"194":195,"195":196,"196":197,"197":198,"198":199,"199":200,"200":201,"201":202,"202":203,"203":204,"204":205,"205":206,"206":207,"207":208,"208":209,"209":210,"210":211,"211":212,"212":213,"213":214,"214":215,"215":216,"216":217,"217":218,"218":219,"219":220,"220":221,"221":222,"222":223,"223":224,"224":225,"225":226,"226":227,"227":228,"228":229,"229":230,"230":231,"231":232,"232":233,"233":234,"234":235,"235":236,"236":237,"237":238,"238":239,"239":240,"240":241,"241":242,"242":243,"243":244,"244":245,"245":246,"246":247,"247":248,"248":249,"249":250,"250":251,"251":252,"252":253,"253":254,"254":255,"255":256,"256":257,"257":258,"258":259,"259":260,"260":261,"261":262,"262":263,"263":264,"264":265,"265":266,"266":267,"267":268,"268":269,"269":270,"270":271,"271":272,"272":273,"273":274,"274":275,"275":276,"276":277,"277":278,"278":279,"279":280,"280":281,"281":282,"282":283,"283":284,"284":285,"285":286,"286":287,"287":288,"288":289,"289":290,"290":291,"291":292,"292":293,"293":294,"294":295,"295":296,"296":297,"297":298,"298":299,"299":300,"300":301,"301":302,"302":303,"303":304,"304":305,"305":306,"306":307,"307":308,"308":309,"309":310,"310":311,"311":312,"312":313,"313":314,"314":315,"315":316,"316":317,"317":318,"318":319,"319":320,"320":321,"321":322,"322":323,"323":324,"324":325,"325":326,"326":327,"327":328,"328":329,"329":330,"330":331,"331":332,"332":333,"333":334,"334":335,"335":336,"336":337,"337":338,"338":339,"339":340,"340":341,"341":342,"342":343,"343":344,"344":345,"345":346,"346":347,"347":348,"348":349,"349":350,"350":351,"351":352,"352":353,"353":354,"354":355,"355":356,"356":357,"357":358,"358":359,"359":360,"360":361,"361":362,"362":363,"363":364,"364":365,"365":366,"366":367,"367":368,"368":369,"369":370,"370":371,"371":372,"372":373,"373":374,"374":375,"375":376,"376":377,"377":378,"378":379,"379":380,"380":381,"381":382,"382":383,"383":384,"384":385,"385":386,"386":387,"387":388,"388":389,"389":390,"390":391,"391":392,"392":393,"393":394,"394":395,"395":396,"396":397,"397":398,"398":399,"399":400,"400":401,"401":402,"402":403,"403":404,"404":405,"405":406,"406":407,"407":408,"408":409,"409":410,"410":411,"411":412,"412":413,"413":414,"414":415,"415":416,"416":417,"417":418,"418":419,"419":420,"420":421,"421":422,"422":423,"423":424,"424":425,"425":426,"426":427,"427":428,"428":429,"429":430,"430":431,"431":432,"432":433,"433":434,"434":435,"435":436,"436":437,"437":438,"438":439,"439":440,"440":441,"441":442,"442":443,"443":444,"444":445,"445":446,"446":447,"447":448,"448":449,"449":450,"450":451,"451":452,"452":453,"453":454,"454":455,"455":456,"456":457,"457":458,"458":459,"459":460,"460":461,"461":462,"462":463,"463":464,"464":465,"465":466,"466":467,"467":468,"468":469,"469":470,"470":471,"471":472,"472":473,"473":474,"474":475,"475":476,"476":477,"477":478,"478":479,"479":480,"480":481,"481":482,"482":483,"483":484,"484":485,"485":486,"486":487,"487":488,"488":489,"489":490,"490":491,"491":492,"492":493,"493":494,"494":495,"495":496,"496":497,"497":498,"498":499,"499":500,"500":501,"501":502,"502":503,"503":504,"504":505,"505":506,"506":507,"507":508,"508":509},"elo":{"0":1411,"1":1370,"2":1294,"3":1283,"4":1280,"5":1277,"6":1274,"7":1269,"8":1268,"9":1234,"10":1233,"11":1215,"12":1214,"13":1208,"14":1205,"15":1203,"16":1186,"17":1184,"18":1182,"19":1173,"20":1167,"21":1152,"22":1151,"23":1141,"24":1137,"25":1136,"26":1136,"27":1135,"28":1135,"29":1131,"30":1121,"31":1114,"32":1110,"33":1110,"34":1108,"35":1105,"36":1099,"37":1099,"38":1097,"39":1092,"40":1089,"41":1086,"42":1083,"43":1081,"44":1080,"45":1075,"46":1074,"47":1073,"48":1072,"49":1070,"50":1070,"51":1070,"52":1069,"53":1067,"54":1066,"55":1065,"56":1065,"57":1065,"58":1060,"59":1059,"60":1057,"61":1055,"62":1052,"63":1051,"64":1048,"65":1047,"66":1047,"67":1046,"68":1045,"69":1043,"70":1041,"71":1040,"72":1039,"73":1039,"74":1039,"75":1039,"76":1038,"77":1037,"78":1037,"79":1035,"80":1035,"81":1034,"82":1034,"83":1032,"84":1032,"85":1031,"86":1030,"87":1029,"88":1028,"89":1027,"90":1026,"91":1026,"92":1025,"93":1024,"94":1023,"95":1021,"96":1019,"97":1019,"98":1019,"99":1018,"100":1017,"101":1017,"102":1016,"103":1016,"104":1015,"105":1015,"106":1015,"107":1015,"108":1014,"109":1014,"110":1014,"111":1013,"112":1013,"113":1013,"114":1012,"115":1011,"116":1011,"117":1010,"118":1010,"119":1010,"120":1010,"121":1009,"122":1009,"123":1008,"124":1007,"125":1007,"126":1007,"127":1007,"128":1007,"129":1006,"130":1006,"131":1006,"132":1005,"133":1005,"134":1005,"135":1005,"136":1005,"137":1005,"138":1005,"139":1005,"140":1005,"141":1004,"142":1004,"143":1004,"144":1004,"145":1004,"146":1004,"147":1004,"148":1004,"149":1004,"150":1003,"151":1003,"152":1003,"153":1003,"154":1003,"155":1003,"156":1003,"157":1003,"158":1003,"159":1003,"160":1003,"161":1003,"162":1002,"163":1002,"164":1002,"165":1002,"166":1002,"167":1002,"168":1002,"169":1002,"170":1002,"171":1002,"172":1002,"173":1002,"174":1002,"175":1001,"176":1001,"177":1001,"178":1001,"179":1001,"180":1001,"181":1001,"182":1001,"183":1001,"184":1001,"185":1001,"186":1001,"187":1000,"188":1000,"189":1000,"190":1000,"191":1000,"192":1000,"193":1000,"194":1000,"195":1000,"196":1000,"197":1000,"198":1000,"199":1000,"200":1000,"201":1000,"202":1000,"203":1000,"204":1000,"205":1000,"206":1000,"207":1000,"208":1000,"209":1000,"210":1000,"211":1000,"212":1000,"213":999,"214":999,"215":999,"216":999,"217":999,"218":999,"219":999,"220":999,"221":999,"222":999,"223":998,"224":998,"225":998,"226":998,"227":998,"228":998,"229":998,"230":998,"231":998,"232":998,"233":998,"234":998,"235":998,"236":998,"237":998,"238":998,"239":997,"240":997,"241":997,"242":997,"243":997,"244":997,"245":997,"246":997,"247":997,"248":997,"249":997,"250":997,"251":997,"252":997,"253":997,"254":997,"255":997,"256":997,"257":997,"258":997,"259":997,"260":997,"261":997,"262":997,"263":997,"264":997,"265":997,"266":997,"267":997,"268":997,"269":997,"270":997,"271":997,"272":997,"273":997,"274":997,"275":997,"276":997,"277":996,"278":996,"279":996,"280":996,"281":996,"282":996,"283":996,"284":996,"285":996,"286":996,"287":996,"288":996,"289":995,"290":995,"291":995,"292":995,"293":995,"294":995,"295":995,"296":995,"297":995,"298":995,"299":995,"300":995,"301":995,"302":995,"303":995,"304":995,"305":995,"306":995,"307":995,"308":995,"309":994,"310":994,"311":994,"312":994,"313":994,"314":994,"315":994,"316":994,"317":994,"318":994,"319":994,"320":994,"321":994,"322":994,"323":994,"324":994,"325":994,"326":994,"327":994,"328":994,"329":994,"330":994,"331":993,"332":993,"333":993,"334":993,"335":993,"336":993,"337":993,"338":993,"339":993,"340":993,"341":993,"342":993,"343":993,"344":993,"345":993,"346":993,"347":992,"348":992,"349":992,"350":992,"351":992,"352":992,"353":992,"354":992,"355":992,"356":992,"357":992,"358":992,"359":992,"360":991,"361":991,"362":991,"363":991,"364":991,"365":991,"366":991,"367":991,"368":991,"369":991,"370":991,"371":991,"372":990,"373":990,"374":990,"375":990,"376":990,"377":990,"378":990,"379":990,"380":989,"381":989,"382":989,"383":989,"384":989,"385":989,"386":989,"387":988,"388":988,"389":988,"390":987,"391":987,"392":987,"393":987,"394":987,"395":986,"396":986,"397":986,"398":986,"399":986,"400":986,"401":986,"402":986,"403":985,"404":985,"405":985,"406":985,"407":985,"408":985,"409":985,"410":984,"411":984,"412":984,"413":984,"414":984,"415":984,"416":984,"417":984,"418":984,"419":983,"420":982,"421":982,"422":982,"423":981,"424":981,"425":981,"426":980,"427":980,"428":980,"429":980,"430":979,"431":979,"432":979,"433":979,"434":978,"435":977,"436":976,"437":976,"438":976,"439":976,"440":976,"441":975,"442":975,"443":974,"444":974,"445":974,"446":973,"447":973,"448":972,"449":972,"450":971,"451":971,"452":970,"453":969,"454":969,"455":968,"456":968,"457":968,"458":968,"459":968,"460":967,"461":967,"462":967,"463":967,"464":967,"465":966,"466":966,"467":965,"468":965,"469":964,"470":964,"471":962,"472":962,"473":961,"474":961,"475":960,"476":959,"477":958,"478":956,"479":955,"480":955,"481":954,"482":954,"483":954,"484":952,"485":952,"486":951,"487":946,"488":946,"489":945,"490":944,"491":944,"492":943,"493":943,"494":942,"495":942,"496":940,"497":940,"498":937,"499":936,"500":936,"501":931,"502":926,"503":926,"504":918,"505":915,"506":904,"507":902,"508":901}} -------------------------------------------------------------------------------- /paris/templates/paris/base.html: -------------------------------------------------------------------------------- 1 | 2 | {% load static %} 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {% block title %}Base Page {% endblock %} 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 |
30 | {% block matches %}{% endblock %} 31 | 32 |
33 |
34 | 35 | {% block predictions %}{% endblock %} 36 | 37 |
38 | 39 |
40 | 41 | 42 | 43 | {% block script %} 44 | 66 | 67 | {% endblock script %} 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /paris/templates/paris/bet_form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
{% csrf_token %} 4 | {{ form.as_p }} 5 | 6 |
7 | 8 | -------------------------------------------------------------------------------- /paris/templates/paris/bet_history.html: -------------------------------------------------------------------------------- 1 | {% if bets %} 2 | 3 | {% if total >= 0 %} 4 |

5 | 6 | {% else %} 7 |

8 | 9 | {% endif %} 10 | 11 | Gain = {{total}}

12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | {% for bet in bets %} 34 | {% if bet.winner == bet.match.winner %} 35 | 36 | {% elif bet.status == 'Pending' %} 37 | 38 | {% else %} 39 | 40 | {% endif %} 41 | 42 | 43 | 44 | 45 | 46 | 47 | 53 | {% if bet.winner == 'Team 1' %} 54 | 55 | {% elif bet.winner == 'Team 2' %} 56 | 57 | {% endif %} 58 | {% if bet.match.winner == 'Team 1' %} 59 | 60 | {% elif bet.match.winner == 'Team 2' %} 61 | 62 | {% else %} 63 | 64 | {% endif %} 65 | 66 | 67 | 68 | {% endfor %} 69 | 70 |
Team 1Odd 1Team 2Odd 2AmountEVBetResultsStatusGain
{{bet.match.team1}}{{bet.match.odd1}}{{bet.match.team2}}{{bet.match.odd2}}{{bet.amount}}€{% if bet.winner == 'Team 1' %} 48 | {{ bet.match.prediction.delta_ev_1}} 49 | {% else %} 50 | {{bet.match.prediction.delta_ev_2}} 51 | {% endif %} 52 | {{bet.match.team1}}{{bet.match.team2}}{{bet.match.team1}}{{bet.match.team2}}{{bet.status}}{{bet.gain}}
71 | 72 | 73 | {% else %} 74 |

No bet are available.

75 | {% endif %} 76 | 77 | -------------------------------------------------------------------------------- /paris/templates/paris/bet_history2.html: -------------------------------------------------------------------------------- 1 | 2 | {% if total >= 0 %} 3 |

4 | 5 | {% else %} 6 |

7 | 8 | {% endif %} 9 | Gain = {{total}}

10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | {% for date,total in totals.items%} 23 | 24 | 25 | {% if total >= 0 %} 26 | 31 | 32 | 33 | {% endfor %} 34 | 35 |
DateGain
{{date|date:"d M"}} 27 | {% else %} 28 | 29 | {% endif %} 30 | {{total}}
36 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /paris/templates/paris/day.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {% block title %} Day page {% endblock %} 12 | 13 | 14 | 15 | 16 | 19 | 22 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | {% if mbs %} 31 | {% for mb in mbs %} 32 | {% if mb.0.status == "Scheduled" %} 33 | 131 | {% elif mb.0.status == "Live" %} 132 | 226 | 227 | 228 | {% elif mb.0.status == 'Canceled' %} 229 | 230 | 274 | 275 | {% elif mb.0.status == 'Rescheduled' %} 276 | 277 | 321 | 322 | {% elif mb.0.status == 'Results' %} 323 | 324 | 418 | 419 | 420 | 421 | {% elif mb.0.status == 'Expired' %} 422 | 423 | 467 | {% endif %} 468 | 469 | {% endfor %} 470 | 471 | {% else %} 472 |

No matches are available.

473 | {% endif %} 474 | 475 | 476 | 477 | -------------------------------------------------------------------------------- /paris/templates/paris/history.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% if matches_history %} 5 | {% for match in matches_history %} 6 | 7 | {% if match.status == 'Canceled' %} 8 | 9 | 10 | {% elif match.status == 'Rescheduled' %} 11 | 12 | 13 | 14 | {% elif match.status == 'Results' %} 15 | 16 | 51 | 52 | 53 | 54 | {% else%} 55 | 56 | 57 | {% endif %} 58 | 59 | {% endfor %} 60 | 61 | {% else %} 62 |

No matches are available.

63 | {% endif %} 64 | -------------------------------------------------------------------------------- /paris/templates/paris/index.html: -------------------------------------------------------------------------------- 1 | {% extends "paris/base.html" %} 2 | 3 | 4 | 5 | {% block title %} 6 | CSGO auto-bettor 7 | {% endblock %} 8 | 9 | {% block matches %} 10 | 11 | 12 | {% include "paris/upcoming.html" %} 13 | 14 | {% endblock %} 15 | 16 | {% block predictions %} 17 | 18 | 19 |
20 | 23 | 26 | 29 | 30 |
31 | 32 | 42 | 43 | 44 |
45 | 59 |
60 | 61 | 62 |
63 | 64 | 65 | {% endblock %} 66 | 67 | 68 | {% block script %} 69 | 70 | 71 | 130 | 131 | {% endblock %} -------------------------------------------------------------------------------- /paris/templates/paris/pred.html: -------------------------------------------------------------------------------- 1 | {% if pred_list %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | {% for pred in pred_list %} 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | {% endfor %} 31 | 32 | {% else %} 33 |

No predictions are available.

34 | {% endif %} -------------------------------------------------------------------------------- /paris/templates/paris/team_match_list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /paris/templates/paris/upcoming.html: -------------------------------------------------------------------------------- 1 | 2 | {% if matches %} 3 | {% for match in matches %} 4 | 5 | {% if match.status == "Scheduled" %} 6 | 84 | {% elif match.status == "Live" %} 85 | 163 | 164 | {% endif %} 165 | 166 | {% endfor %} 167 | 168 | {% else %} 169 |

No matches are available.

170 | {% endif %} 171 | -------------------------------------------------------------------------------- /paris/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /paris/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | 6 | app_name = 'paris' 7 | urlpatterns = [ 8 | path('', views.IndexView.as_view(), name='index'), 9 | path('history', views.HistoryView.as_view(), name='history'), 10 | path('bet',views.BetView.as_view(),name='bet'), 11 | path('bet_history2//', 12 | views.BetHistory2.as_view(), 13 | name='bet_history2'), 14 | path('pred', views.PredictionView.as_view(), name='pred'), 15 | path('day//', views.DayView.as_view(), name='day') 16 | 17 | ] 18 | -------------------------------------------------------------------------------- /paris/utils.py: -------------------------------------------------------------------------------- 1 | from django.db.models import Q 2 | from django.utils import timezone 3 | 4 | from selenium import webdriver 5 | from selenium.common.exceptions import (StaleElementReferenceException, 6 | NoSuchElementException, 7 | UnexpectedAlertPresentException, 8 | ElementNotInteractableException, 9 | ElementClickInterceptedException) 10 | from selenium.webdriver.support import expected_conditions as EC 11 | from selenium.webdriver.common.by import By 12 | from selenium.webdriver.support.ui import WebDriverWait 13 | 14 | from .models import Match, Prediction, Bet 15 | from .module_data import parse_team_name, FeaturesBuilder 16 | 17 | import pytz 18 | import time 19 | import pandas as pd 20 | import random 21 | 22 | from datetime import datetime 23 | 24 | 25 | # clf = load('xgb.joblib') 26 | 27 | DATA_DIR = 'var/' 28 | 29 | 30 | # rankings= get_rankings() 31 | 32 | 33 | def decision(prediction, strategy): 34 | 35 | if strategy == 'EV' or strategy == 'Kelly': 36 | ev1 = prediction.delta_ev_1 37 | ev2 = prediction.delta_ev_2 38 | if ev1 > ev2 and ev1 > 0: 39 | decision = 1 40 | elif ev2 > ev1 and ev2 > 0: 41 | decision = 0 42 | else: 43 | decision = -1 44 | elif strategy == 'Naive': 45 | odd1 = prediction.odd1 46 | odd2 = prediction.odd2 47 | decision = odd1 < odd2 48 | else: 49 | decision = None 50 | return decision 51 | 52 | 53 | def compute_time_to_go(matches): 54 | """ 55 | Compute the time to go before the match starts 56 | """ 57 | for match in matches: 58 | delta_t = match.date - timezone.now() 59 | match.time_to_go = "" 60 | if delta_t.days > 0: 61 | match.time_to_go += str(int(delta_t.days)) + 'd ' 62 | if delta_t.seconds//3600 > 0: 63 | match.time_to_go += str((delta_t.seconds//3600)) + 'h ' 64 | match.time_to_go += str((delta_t.seconds//60) % 60) + 'm ' 65 | 66 | 67 | class AutoBettor(): 68 | def __init__(self, clf): 69 | options = webdriver.ChromeOptions() 70 | options.add_argument('--ignore-certificate-errors') 71 | options.add_argument("--test-type") 72 | options.add_argument("--user-data-dir="+DATA_DIR+"driver_data") 73 | options.add_argument('--disable-gpu') 74 | options.add_experimental_option("excludeSwitches", ["enable-automation"]) 75 | options.add_experimental_option('useAutomationExtension', False) 76 | options.add_argument("--disable-blink-features=AutomationControlled") 77 | options.add_argument("--remote-debugging-port=9222") 78 | options.add_argument("--no-sandbox") 79 | options.add_argument("--disable-dev-shm-usage") 80 | self.driver = webdriver.Chrome(options=options) 81 | self.driver.get('https://csgolounge.com/fr/') 82 | self.FB = FeaturesBuilder() 83 | self.clf = clf 84 | self.B = 0 85 | 86 | def auto_predict(self, fast=False): 87 | """ 88 | Place bets using decision rules based on different strategies 89 | """ 90 | if fast: 91 | five_min = timezone.now() + timezone.timedelta(seconds=5*60) 92 | predictions = Prediction.objects.filter(match__status='Scheduled', 93 | match__date__lte=five_min) 94 | else: 95 | query = Q(match__status="Scheduled") 96 | predictions = Prediction.objects.filter(query) 97 | 98 | for pred in predictions: 99 | decision_ev = decision(pred, 'EV') 100 | 101 | if decision_ev == 1: 102 | bet, created = Bet.objects.get_or_create(match=pred.match, strategy='EV') 103 | bet.winner = 'Team 1' 104 | bet.amount = 1 105 | bet.save() 106 | pred.save() 107 | print(bet, 108 | "; "+"new"*created + "not new" * (1-created)) 109 | elif decision_ev == 0: 110 | bet, created = Bet.objects.get_or_create(match=pred.match, strategy='EV') 111 | bet.winner = 'Team 2' 112 | bet.amount = 1 113 | bet.save() 114 | pred.save() 115 | print(bet, 116 | "; "+"new"*created + "not new" * (1-created)) 117 | elif decision_ev == -1: 118 | bet, created = Bet.objects.get_or_create(match=pred.match, 119 | strategy='EV') 120 | bet.winner = 'None' 121 | bet.amount = 0 122 | bet.save() 123 | pred.save() 124 | print(f'Not a good bet {pred.match}') 125 | print(bet, 126 | "; "+"new"*created + "not new" * (1-created)) 127 | 128 | if decision_ev == 1: 129 | bet, created = Bet.objects.get_or_create(match=pred.match, 130 | strategy='Kelly') 131 | bet.winner = 'Team 1' 132 | f = pred.delta_ev_1 / pred.match.odd1 133 | bet.amount = self.B * float(f) 134 | 135 | bet.save() 136 | pred.save() 137 | print(bet, 138 | "; "+"new"*created + "not new" * (1-created)) 139 | 140 | elif decision_ev == 0: 141 | bet, created = Bet.objects.get_or_create(match=pred.match, 142 | strategy='Kelly') 143 | bet.winner = 'Team 2' 144 | f = pred.delta_ev_2 / pred.match.odd2 145 | bet.amount = self.B * float(f) 146 | bet.save() 147 | pred.save() 148 | print(bet, 149 | "; "+"new"*created + "not new" * (1-created)) 150 | elif decision_ev == -1: 151 | bet, created = Bet.objects.get_or_create(match=pred.match, 152 | strategy='Kelly') 153 | bet.winner = 'None' 154 | bet.amount = 0 155 | bet.save() 156 | pred.save() 157 | print(f'Not a good bet {pred.match}') 158 | print(bet, 159 | "; "+"new"*created + "not new" * (1-created)) 160 | 161 | decision_naive = decision(pred, 'Naive') 162 | if decision_naive == 1: 163 | bet, created = Bet.objects.get_or_create(match=pred.match, 164 | strategy='Naive') 165 | bet.winner = 'Team 1' 166 | bet.amount = 1 167 | bet.save() 168 | print(bet, 169 | "; "+"new"*created + "not new" * (1-created)) 170 | 171 | elif decision_naive == 0: 172 | bet, created = Bet.objects.get_or_create(match=pred.match, 173 | strategy='Naive') 174 | bet.winner = 'Team 2' 175 | bet.amount = 1 176 | bet.save() 177 | print(bet, 178 | "; "+"new"*created + "not new" * (1-created)) 179 | 180 | bets = Bet.objects.filter(status='Pending') 181 | for bet in bets: 182 | if bet.match.status == 'Canceled' or bet.match.status =='Rescheduled': 183 | bet.delete() 184 | self.update_bet(fast=fast) 185 | 186 | def update_bet(self,fast=False): 187 | """ 188 | Compute the results of bets : the winning team and the gain associated 189 | """ 190 | if fast: 191 | five_min = timezone.now() + timezone.timedelta(seconds=5*60) 192 | bets = Bet.objects.filter(match__status='Results', match__date__lte=five_min) 193 | 194 | else: 195 | query1 = (Q(match__status='Results') | Q(match__status='Expired')) 196 | query2 = Q(status='Finished') | Q(status='Canceled') 197 | bets = Bet.objects.filter(query1).exclude(query2) 198 | for bet in bets: 199 | match = bet.match 200 | if match.status == 'Results': 201 | if len(bet.winner): 202 | if bet.winner == 'Team 1': 203 | win = (match.winner == 'Team 1') 204 | lose = 1-win 205 | bet.gain = bet.amount *((match.odd1-1)* win - lose) 206 | elif bet.winner == 'Team 2': 207 | win = (match.winner == 'Team 2') 208 | lose = 1-win 209 | bet.gain = bet.amount *((match.odd2-1)* win - lose) 210 | bet.status = 'Finished' 211 | elif match.status == 'Expired': 212 | bet.status = 'Canceled' 213 | 214 | bet.save(force_update=True) 215 | self.update_matches() 216 | 217 | def update_matches(self): 218 | """ 219 | Check if matches list is outdated and assign the status 'expired' to outdated matches 220 | """ 221 | history_button = self.driver.find_elements_by_class_name("sys-history-tab")[0] 222 | history_button.click() 223 | matches = self.driver.find_elements_by_class_name("lounge-bets-items__item") 224 | for match in matches: 225 | date = match.find_elements_by_class_name('lounge-match-date__date')[0].get_attribute("innerHTML") 226 | date = datetime.strptime(date.replace(" ","")[:-3], "%d.%m.%Y,%H:%M") 227 | tz = timezone.get_current_timezone() 228 | date = tz.localize(date, is_dst=None) 229 | bo = match.find_elements_by_class_name('sys-bo')[0].get_attribute('innerHTML') 230 | team1 = match.find_elements_by_class_name('lounge-team_left')[0] 231 | team1_name = parse_team_name(team1.find_elements_by_class_name('lounge-team__title')[0].get_attribute('innerHTML')) 232 | team1_logo = team1.find_elements_by_class_name('sys-t1logo')[0].get_attribute('src') 233 | team2 = match.find_elements_by_class_name('lounge-team_right')[0] 234 | team2_name = parse_team_name(team2.find_elements_by_class_name('lounge-team__title')[0].get_attribute('innerHTML')) 235 | team2_logo = team2.find_elements_by_class_name('sys-t2logo')[0].get_attribute('src') 236 | team1_odd = team1.find_elements_by_class_name('sys-stat-koef-1')[0].get_attribute('innerHTML') 237 | team2_odd = team2.find_elements_by_class_name('sys-stat-koef-2')[0].get_attribute('innerHTML') 238 | is_rescheduled = 'bet-rescheduled' in match.get_attribute('class').split() 239 | is_canceled = 'bet-canceled' in match.get_attribute('class').split() 240 | has_results = 'bet-result' in match.get_attribute('class').split() 241 | is_live = 'bet-now' in match.get_attribute('class').split() 242 | status = "Rescheduled" * is_rescheduled + "Canceled" * is_canceled + 'Results' * has_results + "Live" * is_live 243 | if not len(status): 244 | status = 'Scheduled' 245 | right_win = 'bet-winner-right' in match.get_attribute('class').split() 246 | left_win = 'bet-winner-left' in match.get_attribute('class').split() 247 | winner = left_win * 'Team 1' + right_win * 'Team 2' 248 | 249 | if len(team1_odd) > 2 and len(team2_odd) > 2: 250 | team1_odd = float(team1_odd[1:]) 251 | team2_odd = float(team2_odd[1:]) 252 | match_id = int(match.get_attribute('data-id')) 253 | 254 | Match(team1=team1_name,team2=team2_name,odd1=team1_odd,odd2=team2_odd, 255 | logo1=team1_logo,logo2=team2_logo, 256 | status=status, winner=winner, 257 | bo=bo,date=date,match_id=match_id).save() 258 | 259 | twelve_hours_ago = timezone.now() - timezone.timedelta(hours=12) 260 | Match.objects.filter(Q(date__lte = twelve_hours_ago) & (Q(status = "Scheduled")|Q(status="Live"))).update(status='Expired') 261 | total_button = self.driver.find_elements_by_class_name("sys-total-tab")[0] 262 | total_button.click() 263 | 264 | def scrap_upcoming_matches(self): 265 | wait = WebDriverWait(self.driver, 10) 266 | wait.until(EC.presence_of_element_located((By.XPATH, "//a[@href='/fr/checkin/']"))) 267 | matches_data = pd.DataFrame(columns= ["team1",'team2','odd1','odd2','logo1','logo2','bo','status','winner','date','match_id']) 268 | total_button = self.driver.find_elements_by_class_name("sys-total-tab")[0] 269 | total_button.click() 270 | matches = self.driver.find_elements_by_class_name("lounge-bets-items__item") 271 | for match in matches: 272 | date = match.find_elements_by_class_name('lounge-match-date__date')[0].get_attribute("innerHTML") 273 | date = datetime.strptime(date.replace(" ","")[:-3],"%d.%m.%Y,%H:%M") 274 | tz = timezone.get_current_timezone() 275 | date = tz.localize(date, is_dst=None) 276 | bo = match.find_elements_by_class_name('sys-bo')[0].get_attribute('innerHTML') 277 | team1 = match.find_elements_by_class_name('lounge-team_left')[0] 278 | team1_name = parse_team_name(team1.find_elements_by_class_name('lounge-team__title')[0].get_attribute('innerHTML')) 279 | team1_logo = team1.find_elements_by_class_name('sys-t1logo')[0].get_attribute('src') 280 | team2 = match.find_elements_by_class_name('lounge-team_right')[0] 281 | team2_name = parse_team_name(team2.find_elements_by_class_name('lounge-team__title')[0].get_attribute('innerHTML')) 282 | team2_logo = team2.find_elements_by_class_name('sys-t2logo')[0].get_attribute('src') 283 | team1_odd = team1.find_elements_by_class_name('sys-stat-koef-1')[0].get_attribute('innerHTML') 284 | team2_odd = team2.find_elements_by_class_name('sys-stat-koef-2')[0].get_attribute('innerHTML') 285 | is_rescheduled = 'bet-rescheduled' in match.get_attribute('class').split() 286 | is_canceled = 'bet-canceled' in match.get_attribute('class').split() 287 | has_results = 'bet-result' in match.get_attribute('class').split() 288 | is_live = 'bet-now' in match.get_attribute('class').split() 289 | status = "Rescheduled" * is_rescheduled + "Canceled" * is_canceled + 'Results' * has_results + "Live" * is_live 290 | if not len(status): 291 | status = 'Scheduled' 292 | right_win = 'bet-winner-right' in match.get_attribute('class').split() 293 | left_win = 'bet-winner-left' in match.get_attribute('class').split() 294 | winner = left_win* 'Team 1' + right_win* 'Team 2' 295 | 296 | if len(team1_odd) > 2 and len(team2_odd) > 2: 297 | team1_odd = float(team1_odd[1:]) 298 | team2_odd = float(team2_odd[1:]) 299 | match_id = int(match.get_attribute('data-id')) 300 | row = pd.DataFrame([[team1_name,team2_name,team1_odd,team2_odd,team1_logo,team2_logo,bo,status,winner,date,match_id]], 301 | columns= ["team1",'team2','odd1','odd2','logo1','logo2','bo','status','winner','date','match_id']) 302 | matches_data = matches_data.append(row,ignore_index=True) 303 | 304 | return matches_data 305 | 306 | def save_predictions(self, predictions, model='LOGREG'): 307 | for i in range(len(predictions)): 308 | pred = predictions.iloc[i] 309 | match_id = pred['match_id'] 310 | odd_p_1 = float(pred['odd_p_1']) 311 | odd_p_2 = float(pred['odd_p_2']) 312 | match = Match.objects.filter(match_id=match_id)[0] 313 | delta_ev_1 = float(match.odd1)/odd_p_1 - 1 314 | delta_ev_2 = float(match.odd2)/odd_p_2 - 1 315 | 316 | Prediction(match=match, odd1=odd_p_1, odd2=odd_p_2, 317 | delta_ev_1=delta_ev_1, 318 | delta_ev_2=delta_ev_2, model=model).save() 319 | 320 | def predict(self, features): 321 | probas = self.clf.predict_proba(features.drop('match_id', axis=1)) 322 | eps = 1e-8 323 | features['odd_p_1'] = 1/(probas[:, 1] + eps) 324 | features['odd_p_2'] = 1/(probas[:, 0] + eps) 325 | return features 326 | 327 | def get_bankroll(self): 328 | self.B = 50 329 | return 330 | 331 | def real_bet(self): 332 | return 333 | 334 | 335 | 336 | def auto_bet(self, amount='0.5'): 337 | k = 0 338 | refresh_counter = 0 339 | while 1: 340 | self.get_bankroll() 341 | k += 1 342 | now = datetime.now() 343 | minutes = str(now.minute) 344 | if len(minutes) < 2: 345 | minutes = "0" + minutes 346 | print(f'Starting iteration {k} at {now.hour}h{minutes}') 347 | print(f'Bankroll : {self.B:.2f}€') 348 | try: 349 | matches_data = self.scrap_upcoming_matches() 350 | for i in range(matches_data.shape[0]): 351 | match = matches_data.iloc[i] 352 | (team1, team2, odd1, odd2, 353 | logo1, logo2, bo, status, 354 | winner, date, match_id) = match 355 | Match(team1=team1, team2=team2, odd1=odd1, odd2=odd2, 356 | logo1=logo1, logo2=logo2, 357 | status=status, winner=winner, 358 | bo=bo, date=date, match_id=match_id).save() 359 | print('Upcoming matches : ') 360 | print(matches_data.iloc[:10, :4]) 361 | 362 | # m = 5 363 | # to_m_min = timezone.now() + timezone.timedelta(seconds=m*60) 364 | # for_m_min = timezone.now() - timezone.timedelta(seconds=m*60) 365 | 366 | features = self.FB.get_features(matches_data, 367 | features=['match_id', 'odd1', 'odd2', 'date', 'elo1', 368 | 'elo2', 'F_S_team1', 'F_S_team2']) 369 | predictions = self.predict(features) 370 | self.save_predictions(predictions) 371 | 372 | except IndexError: 373 | print("Can't scrap matches") 374 | 375 | self.auto_predict() 376 | self.real_bet(validate=False) 377 | if refresh_counter < 10 + (random.random()-1/2) * 5: 378 | refresh_counter += 1 379 | else: 380 | self.driver.get('https://csgolounge.com/fr/') 381 | refresh_counter = 0 382 | print('Sleeping for 30s') 383 | for j in range(30): 384 | #print('#'*j + ' ' + str((j*100)//30) +'%') 385 | time.sleep(1) 386 | 387 | 388 | print("##################") -------------------------------------------------------------------------------- /paris/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.urls import reverse_lazy 3 | from django.views import generic 4 | from django.db.models import Q 5 | from django.utils import timezone 6 | from datetime import datetime, timedelta 7 | import pytz 8 | from .utils import compute_time_to_go 9 | from .forms import BetForm 10 | from .models import Match, Bet, Prediction 11 | import numpy as np 12 | 13 | 14 | MATCH_NOT_FINISHED = Q(status='Scheduled') | Q(status='Live') 15 | DATA_DIR = 'var/' 16 | 17 | 18 | class IndexView(generic.TemplateView): 19 | template_name = 'paris/index.html' 20 | context_object_name = '' 21 | 22 | def get_context_data(self, **kwargs): 23 | context = super().get_context_data(**kwargs) 24 | matches = Match.objects.filter(MATCH_NOT_FINISHED).order_by('date') 25 | compute_time_to_go(matches) 26 | context['matches'] = matches 27 | context['bets'] = Bet.objects.order_by('-match__date') 28 | context['total'] = np.array(list(map(lambda x: x.gain,Bet.objects.filter(status='Finished')))).sum() 29 | return context 30 | 31 | 32 | def get_bets_list_by_ev(request): 33 | ev_trsh = request.GET.get('ev') 34 | data = {'bets': Bet.objects.filter(ev__gte=ev_trsh)} 35 | return render(request, '/bet_history', data) 36 | 37 | 38 | class DayView(generic.ListView): 39 | template_name = 'paris/day.html' 40 | context_object_name = 'matches' 41 | 42 | def get_context_data(self, **kwargs): 43 | context = super().get_context_data(**kwargs) 44 | strategy = self.kwargs['strat'] 45 | date_ = self.kwargs['date'] 46 | date_ = datetime.strptime(date_, "%d.%m.%Y") 47 | tz = timezone.get_current_timezone() 48 | date_ = tz.localize(date_, is_dst=None) 49 | print(date_) 50 | date_next_day = date_ + timedelta(days=1) 51 | IN_DAY = Q(date__gte=date_, date__lt=date_next_day) 52 | NOT_BET = Q(status='Rescheduled')|Q(status='Canceled')|Q(status='Expired') 53 | matches = Match.objects.filter(IN_DAY).exclude(NOT_BET).filter(prediction__pk__isnull=False).order_by('-date') 54 | compute_time_to_go(matches) 55 | 56 | if strategy == 'ev': 57 | bets = Bet.objects.filter(match__in=matches, 58 | strategy='EV').order_by('-match__date') 59 | elif strategy == 'kelly': 60 | bets = Bet.objects.filter(match__in=matches, 61 | strategy='Kelly').order_by('-match__date') 62 | elif strategy == 'naive': 63 | bets = Bet.objects.filter(match__in=matches, 64 | strategy='Naive').order_by('-match__date') 65 | print(len(bets),len(matches)) 66 | context['mbs'] = zip(matches, bets) 67 | return context 68 | 69 | def get_queryset(self): 70 | 71 | return None 72 | 73 | 74 | class BetView(generic.CreateView): 75 | template_name = 'paris/bet_form.html' 76 | model = Bet 77 | form_class = BetForm 78 | success_url = reverse_lazy('paris:index') 79 | 80 | 81 | class BetHistory2(generic.ListView): 82 | template_name = 'paris/bet_history2.html' 83 | context_object_name = 'bets' 84 | 85 | def get_context_data(self, **kwargs): 86 | context = super().get_context_data(**kwargs) 87 | strategy = self.kwargs['strat'] 88 | context['strategy'] = strategy 89 | ev = self.kwargs['ev'] 90 | if strategy == 'ev': 91 | bets = Bet.objects.filter(strategy='EV') 92 | 93 | elif strategy == 'naive': 94 | bets = Bet.objects.filter(strategy='Naive') 95 | 96 | elif strategy == 'kelly': 97 | bets = Bet.objects.filter(strategy='Kelly') 98 | 99 | n = 20 100 | date_0 = timezone.now().replace(second=0, minute=0, 101 | hour=0, microsecond=0) 102 | dates = [date_0-timezone.timedelta(days=i) 103 | for i in range(-1, n)] 104 | totals = [] 105 | for i in range(0, n+1): 106 | date_next_day = dates[i] + timedelta(days=1) 107 | bets_today = (bets.filter(match__date__lt=date_next_day, 108 | match__date__gte=dates[i]) 109 | .order_by('-match__date')) 110 | totals.append(np.array(list(map(lambda x: x.gain, bets_today))).sum()) 111 | context['totals'] = dict(zip(dates, totals)) 112 | context['total'] = np.array(totals, dtype=np.float).sum() 113 | return context 114 | 115 | def get_queryset(self): 116 | return None 117 | 118 | 119 | class PredictionView(generic.ListView): 120 | template_name = 'paris/pred.html' 121 | context_object_name = 'pred_list' 122 | 123 | def get_queryset(self): 124 | return (Prediction.objects 125 | .order_by('-match__date') 126 | .filter(MATCH_NOT_FINISHED)) 127 | 128 | 129 | class HistoryView(generic.ListView): 130 | template_name = 'paris/history.html' 131 | context_object_name = 'matches_history' 132 | 133 | def get_queryset(self): 134 | return Match.objects.exclude(MATCH_NOT_FINISHED).order_by('-date') 135 | -------------------------------------------------------------------------------- /report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/report.pdf -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # This file may be used to create an environment using: 2 | # $ conda create --name --file 3 | # platform: win-64 4 | _tflow_select=2.2.0=eigen 5 | absl-py=0.11.0=py36haa95532_0 6 | aiohttp=3.6.3=py36he774522_0 7 | asgiref=3.3.1=pyhd3eb1b0_0 8 | astor=0.8.1=py36_0 9 | astunparse=1.6.3=pypi_0 10 | async-timeout=3.0.1=py36_0 11 | async_generator=1.10=py_0 12 | attrs=20.3.0=pyhd3eb1b0_0 13 | autopep8=1.5.4=pypi_0 14 | backcall=0.2.0=py_0 15 | beautifulsoup4=4.9.3=pypi_0 16 | blas=1.0=mkl 17 | bleach=3.2.1=py_0 18 | blinker=1.4=py36_0 19 | brotlipy=0.7.0=py36h2bbff1b_1003 20 | bs4=0.0.1=pypi_0 21 | ca-certificates=2020.10.14=0 22 | cached-property=1.5.2=pypi_0 23 | cachetools=4.1.1=py_0 24 | certifi=2020.11.8=py36haa95532_0 25 | cffi=1.14.3=py36hcd4344a_2 26 | chardet=3.0.4=py36haa95532_1003 27 | click=7.1.2=py_0 28 | colorama=0.4.4=py_0 29 | cryptography=3.2.1=py36hcd4344a_1 30 | cycler=0.10.0=pypi_0 31 | decorator=4.4.2=py_0 32 | defusedxml=0.6.0=py_0 33 | django=3.1.3=pyhd3eb1b0_0 34 | django-common-helpers=0.9.2=pypi_0 35 | django-cron=0.5.1=pypi_0 36 | django-extensions=3.1.0=pypi_0 37 | entrypoints=0.3=py36_0 38 | freetype=2.10.4=hd328e21_0 39 | gast=0.3.3=pypi_0 40 | google-auth=1.23.0=pyhd3eb1b0_0 41 | google-auth-oauthlib=0.4.2=pyhd3eb1b0_2 42 | google-pasta=0.2.0=py_0 43 | grpcio=1.31.0=py36he7da953_0 44 | h5py=2.10.0=py36h5e291fa_0 45 | hdf5=1.10.4=h7ebc959_0 46 | icc_rt=2019.0.0=h0cc432a_1 47 | icu=58.2=ha925a31_3 48 | idna=2.10=py_0 49 | idna_ssl=1.1.0=py36_0 50 | importlib-metadata=2.0.0=py_1 51 | importlib_metadata=2.0.0=1 52 | intel-openmp=2020.2=254 53 | ipykernel=5.3.4=py36h5ca1d4c_0 54 | ipython=7.16.1=py36h5ca1d4c_0 55 | ipython_genutils=0.2.0=py36_0 56 | ipywidgets=7.5.1=py_1 57 | jedi=0.17.2=py36_0 58 | jinja2=2.11.2=py_0 59 | joblib=0.17.0=py_0 60 | jpeg=9b=hb83a4c4_2 61 | json5=0.9.5=pypi_0 62 | jsonschema=3.2.0=py_2 63 | jupyter=1.0.0=py36_7 64 | jupyter-contrib-core=0.3.3=pypi_0 65 | jupyter-http-over-ws=0.0.8=pypi_0 66 | jupyter-nbextensions-configurator=0.4.1=pypi_0 67 | jupyter_client=6.1.7=py_0 68 | jupyter_console=6.2.0=py_0 69 | jupyter_core=4.6.3=py36_0 70 | jupyterlab=2.2.9=pypi_0 71 | jupyterlab-server=1.2.0=pypi_0 72 | jupyterlab_pygments=0.1.2=py_0 73 | kiwisolver=1.3.1=pypi_0 74 | krb5=1.17.1=hc04afaa_0 75 | libpng=1.6.37=h2a8f88b_0 76 | libpq=12.2=h3235a2c_0 77 | libprotobuf=3.13.0.1=h200bbdf_0 78 | libsodium=1.0.18=h62dcd97_0 79 | libtiff=4.1.0=h56a325e_1 80 | lz4-c=1.9.2=hf4a77e7_3 81 | m2w64-gcc-libgfortran=5.3.0=6 82 | m2w64-gcc-libs=5.3.0=7 83 | m2w64-gcc-libs-core=5.3.0=7 84 | m2w64-gmp=6.1.0=2 85 | m2w64-libwinpthread-git=5.0.0.4634.697f757=2 86 | markdown=3.3.3=py36haa95532_0 87 | markupsafe=1.1.1=py36he774522_0 88 | matplotlib=3.3.3=pypi_0 89 | mistune=0.8.4=py36he774522_0 90 | mkl=2020.2=256 91 | mkl-service=2.3.0=py36hb782905_0 92 | mkl_fft=1.2.0=py36h45dec08_0 93 | mkl_random=1.1.1=py36h47e9c7a_0 94 | msys2-conda-epoch=20160418=1 95 | multidict=4.7.6=py36he774522_1 96 | nbclient=0.5.1=py_0 97 | nbconvert=6.0.7=py36_0 98 | nbformat=5.0.8=py_0 99 | nest-asyncio=1.4.2=pyhd3eb1b0_0 100 | notebook=6.0.3=py36_0 101 | numpy=1.18.5=pypi_0 102 | oauthlib=3.1.0=py_0 103 | olefile=0.46=py36_0 104 | openssl=1.1.1h=he774522_0 105 | opt_einsum=3.1.0=py_0 106 | packaging=20.4=py_0 107 | pandas=1.1.3=py36ha925a31_0 108 | pandoc=2.11=h9490d1a_0 109 | pandocfilters=1.4.3=py36haa95532_1 110 | parso=0.7.0=py_0 111 | pickleshare=0.7.5=py36_0 112 | pillow=8.0.1=py36h4fa10fc_0 113 | pip=20.2.4=py36haa95532_0 114 | prometheus_client=0.8.0=py_0 115 | prompt-toolkit=3.0.8=py_0 116 | prompt_toolkit=3.0.8=0 117 | protobuf=3.13.0.1=py36ha925a31_1 118 | psycopg2=2.8.5=py36h7a1dbc1_0 119 | pyasn1=0.4.8=py_0 120 | pyasn1-modules=0.2.8=py_0 121 | pycodestyle=2.6.0=pypi_0 122 | pycparser=2.20=py_2 123 | pygments=2.7.2=pyhd3eb1b0_0 124 | pyjwt=1.7.1=py36_0 125 | pyopenssl=19.1.0=pyhd3eb1b0_1 126 | pyparsing=2.4.7=py_0 127 | pyqt=5.9.2=py36h6538335_2 128 | pyreadline=2.1=py36_1 129 | pyrsistent=0.17.3=py36he774522_0 130 | pysocks=1.7.1=py36haa95532_0 131 | python=3.6.12=h5500b2f_2 132 | python-dateutil=2.8.1=py_0 133 | pytz=2020.1=py_0 134 | pywin32=227=py36he774522_1 135 | pywinpty=0.5.7=py36_0 136 | pyyaml=5.3.1=pypi_0 137 | pyzmq=19.0.2=py36ha925a31_1 138 | qt=5.9.7=vc14h73c81de_0 139 | qtconsole=4.7.7=py_0 140 | qtpy=1.9.0=py_0 141 | requests=2.25.0=pypi_0 142 | requests-oauthlib=1.3.0=py_0 143 | rsa=4.6=py_0 144 | scikit-learn=0.23.2=py36h47e9c7a_0 145 | scipy=1.5.2=py36h9439919_0 146 | seaborn=0.11.0=pypi_0 147 | selenium=3.141.0=py36he774522_0 148 | send2trash=1.5.0=py36_0 149 | setuptools=50.3.1=py36haa95532_1 150 | sip=4.19.8=py36h6538335_0 151 | six=1.15.0=py36haa95532_0 152 | soupsieve=2.0.1=pypi_0 153 | sqlite=3.33.0=h2a8f88b_0 154 | sqlparse=0.4.1=py_0 155 | tensorboard=2.3.0=pyh4dce500_0 156 | tensorboard-plugin-wit=1.6.0=py_0 157 | termcolor=1.1.0=py36_1 158 | terminado=0.9.1=py36_0 159 | testpath=0.4.4=py_0 160 | threadpoolctl=2.1.0=pyh5ca1d4c_0 161 | tk=8.6.10=he774522_0 162 | toml=0.10.2=pypi_0 163 | tornado=6.0.4=py36he774522_1 164 | traitlets=4.3.3=py36_0 165 | typing_extensions=3.7.4.3=py_0 166 | urllib3=1.26.2=pypi_0 167 | vc=14.1=h0510ff6_4 168 | vs2015_runtime=14.16.27012=hf0eaf9b_3 169 | wcwidth=0.2.5=py_0 170 | webencodings=0.5.1=py36_1 171 | werkzeug=0.16.1=py_0 172 | wheel=0.35.1=pyhd3eb1b0_0 173 | widgetsnbextension=3.5.1=py36_0 174 | win_inet_pton=1.1.0=py36haa95532_0 175 | wincertstore=0.2=py36h7fe50ca_0 176 | winpty=0.4.3=4 177 | wrapt=1.12.1=py36he774522_1 178 | xz=5.2.5=h62dcd97_0 179 | yaml=0.2.5=he774522_0 180 | yarl=1.6.2=py36he774522_0 181 | zeromq=4.3.2=ha925a31_3 182 | zipp=3.4.0=pyhd3eb1b0_0 183 | zlib=1.2.11=h62dcd97_4 184 | zstd=1.4.5=h04227a9_0 185 | -------------------------------------------------------------------------------- /var/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/var/.gitignore -------------------------------------------------------------------------------- /var/history.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/var/history.db -------------------------------------------------------------------------------- /var/logit.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Egiob/csgo_forecasting/dd6d4c85788ffc02bbd199b1c259e17def6cb6b0/var/logit.joblib -------------------------------------------------------------------------------- /var/teams_map.csv: -------------------------------------------------------------------------------- 1 | name;name2; 2 | wolsung;; 3 | orgles5;; 4 | project5;; 5 | madeeka;; 6 | navi youth;na'vi junior; 7 | london;; 8 | honoris;; 9 | control;; 10 | prodigy;prodigy (brazil); 11 | generation of miracles;; 12 | mk;; 13 | epikk;; 14 | boca boston;; 15 | nordavind no;; 16 | riddle;; 17 | bitfrost;; 18 | ex-wizards;; 19 | excellency;; 20 | fwrd;; 21 | wizards;; 22 | queso;; 23 | way 2 french;; 24 | morning light;; 25 | justice;; 26 | twa;; 27 | iwis;; 28 | bantz;; 29 | downfall;; 30 | forbidden;; 31 | overt;; 32 | esea open;; 33 | ago nest;; 34 | sangal;; 35 | swedish canadians;; 36 | cyberwolves;; 37 | galactics esc;; 38 | gtz bulls;; 39 | warriors;warriors international; 40 | terro;; 41 | plmix;; 42 | detona pound;; 43 | paqueta;; 44 | ex-airborne;; 45 | nerdrage;; 46 | les petits bouffons;; 47 | ex-vexed;; 48 | keep the comms up;; 49 | orion;; 50 | w2c;; 51 | trvpremeslo;; 52 | trepunktnoll;; 53 | jigadood;; 54 | heartless;; 55 | ztayhome;; 56 | pupsiki squad;; 57 | eidos;; 58 | o2;; 59 | zero.tsg;; 60 | chrome;; 61 | cex;; 62 | the pensioners;; 63 | vac;; 64 | rebel;; 65 | exalty;; 66 | alltech;; 67 | nicecactus;; 68 | one one;; 69 | amsterdam kings;; 70 | lamif;; 71 | reünie;; 72 | sateliti;; 73 | mynec;; 74 | trtrr;; 75 | blink;; 76 | mustang crew;; 77 | bluejays;; 78 | blood, sweat, and tears;blood sweat; 79 | rozu;; 80 | draconic;; 81 | ex-mc academy;; 82 | wygers;; 83 | strange tactics;; 84 | bogatiri;; 85 | nosurrender;; 86 | keymotion;; 87 | coscu army;; 88 | hsl;; 89 | qlash forge;; 90 | hg;; 91 | manguste;; 92 | exaequo italy;; 93 | elites;; 94 | broccoli & chicken;; 95 | sapphirekelownadotcom;; 96 | ex-up;; 97 | brave soldiers;; 98 | red feet;; 99 | utopian;; 100 | rise;; 101 | adastra;; 102 | timbermen;; 103 | dans ta yeule;; 104 | trivium;; 105 | xternal;; 106 | kinship black;; 107 | savage;; 108 | neko paradise;; 109 | raijin;; 110 | front;; 111 | pdhm;; 112 | dogs of war;; 113 | precision;; 114 | polar ace;; 115 | serac;; 116 | lavender;; 117 | luxgaming;; 118 | 303;; 119 | buffdaddy's paypal;buffdaddys;buffdaddys paypal 120 | chetz;; 121 | kingzzz;; 122 | lionz;; 123 | babos;; 124 | silent;; 125 | nonamers;; 126 | myinsanity;; 127 | casa de papel;; 128 | cyber legacy;; 129 | aa;alcoholics anonymous; 130 | campus vejle * flammen;; 131 | aligon;; 132 | infamous;; 133 | funplus phoenix;; 134 | crazycoco;; 135 | nyyrikki;; 136 | vertex;; 137 | district 7;; 138 | ex-eunited;; 139 | i sleep;; 140 | tiger;; 141 | justpassingby;; 142 | markandlarry;; 143 | shidiots;; 144 | entry;; 145 | in the lab;; 146 | lucid;; 147 | penguinsmokeweed;; 148 | electrify;; 149 | rooster;; 150 | lords of plumbing;; 151 | hunkydads;; 152 | braintrust;; 153 | eimi fukada fc;; 154 | aeroplane;; 155 | 4 and a half men;; 156 | umumba;; 157 | levelzero;; 158 | wings;; 159 | nocturns;; 160 | lnd;; 161 | duck nutz;; 162 | sinisters;; 163 | freerox;; 164 | under 21;; 165 | ex-intz;; 166 | stepback;; 167 | kinetic;; 168 | igen;; 169 | wubbalubbadubdub;; 170 | born in mongolia;; 171 | shinelikedemons;; 172 | aim4r;; 173 | updraft;; 174 | ignis;; 175 | d13;; 176 | 2k;; 177 | intz.academy;; 178 | speedrunners;; 179 | dopeclvb;; 180 | atlants;; 181 | ekaterinburg;; 182 | fakedospro;; 183 | fearow;; 184 | hawks;; 185 | up;; 186 | cptl;; 187 | kynyniekat;; 188 | rehti;; 189 | swole identity;; 190 | rysix;; 191 | ex-skullz;; 192 | polar ace south;; 193 | e-gaming;; 194 | nlg;; 195 | brazen;; 196 | gameagents;; 197 | thedabers;; 198 | sinners;sinners (cz); 199 | pax;; 200 | no2b;; 201 | sws;; 202 | rensga;; 203 | slashlevel;; 204 | timechasers;; 205 | alltherage;; 206 | 1337huania;; 207 | sigma;; 208 | yoink;; 209 | deeznuts;; 210 | wildcats;; 211 | ne parsya;; 212 | maslomaslo;; 213 | lapw;; 214 | fbg;; 215 | jijiehao;; 216 | very1zgaming;; 217 | ferox;; 218 | hot ass;; 219 | orgless;; 220 | fakemaquinas;; 221 | unluckers;; 222 | we are orgless;; 223 | new patrol;; 224 | super nova csgo;; 225 | asterius;; 226 | neverest;; 227 | dynasty;; 228 | salamander;; 229 | prima;; 230 | moon daddy;; 231 | klan gadanych głupot;; 232 | dogsclvb;; 233 | unlukoexpress;; 234 | ha masse;; 235 | everybodydance;; 236 | 1win;; 237 | moscow five academy;; 238 | 100pinggods;; 239 | revolt;; 240 | imperium;; 241 | prospects;; 242 | 1820ht;; 243 | akatsuki;; 244 | blinkdagger;; 245 | space jam;; 246 | sgindomix;; 247 | zigma;; 248 | clowns;; 249 | paper rex;; 250 | blank;; 251 | ze pug godz;; 252 | fiveg;; 253 | lyngby vikings;; 254 | bravos;; 255 | skyfire;; 256 | divine vendetta;; 257 | c0ntact;; 258 | freestyle;; 259 | incubus;; 260 | supremacy;; 261 | rsc19;; 262 | cephei;; 263 | jokers;; 264 | agarthas;; 265 | black;; 266 | ex-bizarre;; 267 | hardstuck main;; 268 | fraggin4praze;; 269 | ethereal;ethereal (ru); 270 | s2v;; 271 | euronics;; 272 | cisbots;; 273 | hard4u;; 274 | hz;; 275 | trident;; 276 | formidable;; 277 | avengers;; 278 | no problem!;; 279 | demolition crew;; 280 | esper;; 281 | rock candy;; 282 | skin ogres;; 283 | axis;; 284 | spray'n'pray;; 285 | el'quvet;; 286 | incept;; 287 | airborne;; 288 | yeah;; 289 | station7;; 290 | russian street party;; 291 | 2be continued;; 292 | astro;; 293 | onegodlike.jr;; 294 | dreamseller;; 295 | armory;; 296 | noname.newgen;; 297 | saskatoon warriors;; 298 | maple;; 299 | 7sins;; 300 | ex-intact;; 301 | apeks;; 302 | meandtheboys;; 303 | ex-ambush;; 304 | impunity;; 305 | a point;; 306 | gmcc;; 307 | darkhorse;; 308 | mazaalai;; 309 | saw;; 310 | recon 5;; 311 | just for fun;; 312 | in young ren;; 313 | rocketlauncher$;; 314 | sg.pro;s-gaming; 315 | project x;; 316 | furia inagame;; 317 | ex-intic;; 318 | noorg;; 319 | evolve;; 320 | rejected;; 321 | 9z;; 322 | radnicki;; 323 | nexus;; 324 | budapest five;; 325 | ex-virtus.pro;; 326 | ad hoc;; 327 | big academy;; 328 | empire;; 329 | csgo-mdl;; 330 | j money crew;; 331 | new england whalers;; 332 | call it luck;; 333 | bad news bandits;; 334 | arrow;; 335 | daryl's make a wish;; 336 | rbg;; 337 | third impact;; 338 | gorilla gang;; 339 | big chillin;; 340 | asuna's anime aimers;; 341 | the home of the grave;; 342 | eco fraggers anonymous;; 343 | ucf knights;; 344 | cyberstorm;; 345 | kinship;; 346 | ちんぱんじ~;; 347 | ttc;touch the crown; 348 | reapers;; 349 | evidence;; 350 | l9l;; 351 | 4bowie;; 352 | macau legend;; 353 | dmc;; 354 | superovd;; 355 | shift;; 356 | cataclysm;; 357 | divisionx;; 358 | rebirth;; 359 | oceanus;; 360 | thunder logic;; 361 | faint;; 362 | agf;; 363 | unicorns of love;; 364 | princeadil;; 365 | owned;; 366 | brute;; 367 | real betis;cream real betis;real betis cream 368 | kpi;; 369 | gen.g;; 370 | juggernauts;; 371 | kim kardashians;; 372 | vicious adikta;; 373 | armada;; 374 | nebuloza;; 375 | psychoactive;; 376 | gejming haus aula;; 377 | outlawz;; 378 | avez;; 379 | legion;; 380 | skippy the kangaroo;; 381 | mako;; 382 | instinct china;; 383 | corvidae;; 384 | srry4waht;; 385 | fightclub;; 386 | sons of lennart;; 387 | youclap;; 388 | electronik generation;; 389 | baecon;baecongg; 390 | dream[s]cape;; 391 | og;; 392 | apologis;; 393 | hellside;; 394 | thedice;the dice; 395 | goliath;; 396 | 5orgless;; 397 | arcy;; 398 | finest;; 399 | og3od;; 400 | firemix;; 401 | hub;; 402 | global;; 403 | bl4ze;; 404 | plan a;; 405 | ex-genuine;; 406 | tenerife titans;; 407 | vanguard;; 408 | game fist;; 409 | sector one;sector one.cs; 410 | secret;; 411 | camel riders;; 412 | rvn;; 413 | viboras;; 414 | ratatatata;; 415 | tunisia;; 416 | enrage;; 417 | pompa;; 418 | soberano;; 419 | rufus;; 420 | santos;; 421 | falkol;; 422 | alma;; 423 | maquinas;; 424 | endpoint;; 425 | wind and rain;; 426 | fierce;; 427 | mad lions;; 428 | exile;; 429 | melbet;; 430 | red instinct;; 431 | 2byl9;; 432 | bring me the horizon;; 433 | kryvbas;; 434 | majesty;; 435 | waitfortag;; 436 | navi junior;; 437 | r-stars;; 438 | wild;wild mutigaming; 439 | vodkajuniors;; 440 | revolution;; 441 | uzbekistan;; 442 | project major;; 443 | galkynysh;; 444 | ftw;; 445 | exploit;; 446 | jeste;; 447 | unique;; 448 | vilay;; 449 | 2115;; 450 | extremum;; 451 | triumph;; 452 | fate;; 453 | ex-bluejays;; 454 | rugratz;; 455 | mith.maple;; 456 | august;; 457 | opaa;; 458 | yalla;; 459 | 100 thieves;; 460 | ex-windigo;; 461 | syntax;; 462 | ahq;; 463 | let's quit;; 464 | laze;; 465 | boom;; 466 | ikarus;; 467 | bren;; 468 | brave of warriors;; 469 | d7g;; 470 | aster;; 471 | lynn vision;; 472 | wartex;; 473 | blekingelaget;; 474 | another bad habbit;; 475 | ninjas to be;; 476 | bobbys bjässar;; 477 | man of the year;; 478 | starwish;; 479 | ale fan;; 480 | valorix;; 481 | lilmix;; 482 | marskalk;; 483 | crowns;; 484 | visomvet;; 485 | latchlinan;; 486 | dendd;; 487 | lumens;; 488 | pt1se;; 489 | rova-;; 490 | 9ine;; 491 | no expectation;; 492 | onoff;; 493 | esportsadviser;; 494 | x6tence;; 495 | cleantmix;; 496 | imperial;imperial (brazil); 497 | wisla krakow;; 498 | conquer;; 499 | onethree;onethree.tsg; 500 | ehome;; 501 | mc;; 502 | ex-singularity;; 503 | phoenix;; 504 | asterion;; 505 | hard legion;; 506 | ben's anime;; 507 | catman;; 508 | hukka;; 509 | menacegg;; 510 | ajuri;; 511 | veto;; 512 | kova;; 513 | hreds;; 514 | invictus;ig; 515 | btrg;big time regal; 516 | really weird;; 517 | bpro;; 518 | skade;; 519 | nordavind;; 520 | divine;; 521 | ascent;; 522 | dippers;; 523 | buckets;; 524 | fury;; 525 | syf;; 526 | rewound;; 527 | jade;; 528 | parallax;; 529 | hentai hooligans;; 530 | bizarre;; 531 | zooweemama;; 532 | madlikewizards;; 533 | pc419;; 534 | genuine;; 535 | livid;; 536 | rap gang;; 537 | just swing;; 538 | bushido boyz;; 539 | big frames;; 540 | monstars;; 541 | peeker's advantage;; 542 | new identity;; 543 | riot squad;; 544 | mac-51;; 545 | se7en;; 546 | evil geniuses;eg; 547 | m1x;; 548 | espada;; 549 | red canids;; 550 | ex-luminosity;; 551 | ambush;; 552 | japaleno;; 553 | gamerzone;; 554 | adwokacik;; 555 | e-rivals;; 556 | illuminar;; 557 | smash;; 558 | demise;; 559 | turkey5;; 560 | ex-epsilon;; 561 | warthox;; 562 | gambit youngsters;; 563 | dreameaters;; 564 | ffamix;; 565 | heretics;; 566 | nochance;; 567 | offset;; 568 | cr4zy;; 569 | frenchfrogs;; 570 | instinct;; 571 | aristocracy;; 572 | giants;; 573 | redemption poa;; 574 | w7m;; 575 | infinity;infinity (colomb); 576 | squared;; 577 | avant;; 578 | ground zero;; 579 | lucid dream;; 580 | entity;; 581 | athletico;; 582 | breakaway;; 583 | paradox;; 584 | detona;; 585 | isurus;; 586 | lazarus;; 587 | atk;; 588 | gamerlegion;; 589 | ex-3dmax;; 590 | france fe;; 591 | lazarus fe;; 592 | hysteria;; 593 | arkangel fe;; 594 | those damn canadians;; 595 | tyloo fe;; 596 | intact;; 597 | the quest;; 598 | party astronauts;; 599 | mythic;; 600 | zone;; 601 | final feature;; 602 | chaos;chaos (na); 603 | x-kom;; 604 | ukraine;; 605 | enzo;; 606 | tnc;; 607 | wardell n friends;; 608 | russia;; 609 | panda;; 610 | movistar riders;; 611 | altima;; 612 | viva algeria;; 613 | absolute;; 614 | frostfire;; 615 | furious;; 616 | denial;; 617 | singularity;; 618 | gtv.revolution;; 619 | copenhagen flames;; 620 | havu;; 621 | codewise unicorns;; 622 | izako boars;; 623 | defusekids;; 624 | pact;; 625 | sj;; 626 | massiveimpact;; 627 | ancient;; 628 | devils.one;; 629 | bad news bears;; 630 | pain;; 631 | carnage fe;; 632 | besiktas;; 633 | crowns fe;; 634 | clg red;; 635 | pain fe;; 636 | assassins;; 637 | orgless fe;; 638 | dignitas fe;; 639 | old guys;; 640 | tricked;; 641 | furia;; 642 | gosu;; 643 | beyond;; 644 | aequus;; 645 | runtime;; 646 | syman;; 647 | spirit;; 648 | nemiga;; 649 | nasr;; 650 | ecl;; 651 | energy;; 652 | chosen5;; 653 | forze;; 654 | shotcallers;; 655 | x6tence galaxy;; 656 | 5power;; 657 | pro100;; 658 | teamone;one; 659 | alpha red;; 660 | vitality;; 661 | torqued;; 662 | swole patrol;; 663 | ex-space soldiers;; 664 | spacestation;; 665 | fragsters;; 666 | sprout;; 667 | winstrike;; 668 | não tem como;; 669 | intz;; 670 | windigo;; 671 | rogue;; 672 | eunited;; 673 | azio;; 674 | ghost;; 675 | selfless;; 676 | echo fox;; 677 | quantum bellator fire;; 678 | bravado;; 679 | planetkey;; 680 | myxmg;; 681 | clan-mystik;; 682 | universalsoldiers;; 683 | recursive;; 684 | lgb;; 685 | xapso;; 686 | reason;; 687 | astana dragons;; 688 | 3dmax;; 689 | absolute legends;; 690 | dynamic;; 691 | vexed;; 692 | valiance;; 693 | csgl;; 694 | complexity;col; 695 | irage;; 696 | nostalgie;; 697 | bx3;; 698 | myrevenge;; 699 | eyes on u;; 700 | server-forge;; 701 | curse;; 702 | killerfish;; 703 | alternate attax;; 704 | wrtt;; 705 | plan-b;; 706 | lemondogs;; 707 | temp.no;; 708 | anexis;; 709 | epsilon;; 710 | quantic;; 711 | virtus.pro;vp; 712 | western wolves;; 713 | vg.flash;; 714 | ago;; 715 | cyberzen;; 716 | ex-titan;; 717 | uya;; 718 | mvp project;; 719 | godsent;; 720 | vg.cyberzen;; 721 | vega squadron;; 722 | splyce;; 723 | vici;; 724 | chiefs;; 725 | avangar;; 726 | order;; 727 | themongolz;; 728 | e-frag.net;; 729 | tempo storm;; 730 | legacy;; 731 | progaming.td;; 732 | lowlandlions;; 733 | esc;; 734 | fmesports;; 735 | n!faculty;; 736 | area 51;; 737 | verygames;; 738 | sharks;; 739 | mvp pk;; 740 | grayhound;; 741 | misfits;; 742 | nrg;; 743 | penta;; 744 | boot;; 745 | ence;; 746 | mibr;; 747 | big;; 748 | tyloo;; 749 | space soldiers;; 750 | heroic;; 751 | immortals;; 752 | optic;; 753 | immunity;; 754 | ebettle;; 755 | renegades;; 756 | mousesports;; 757 | flipsid3;; 758 | kinguin;; 759 | wolves;; 760 | london conspiracy;; 761 | dat;; 762 | vox eminor;; 763 | cph wolves;; 764 | ibuypower;; 765 | ldlc;; 766 | conquest;; 767 | luminosity;; 768 | ?;; 769 | keyd;keyd stars; 770 | clg;; 771 | cloud9;c9; 772 | envy;; 773 | titan;; 774 | tsm;; 775 | hellraisers;; 776 | nip;ninjas in pyjamas; 777 | fnatic;; 778 | natus vincere;na'vi; 779 | dignitas;; 780 | gambit;; 781 | liquid;; 782 | faze;; 783 | north;; 784 | g2;; 785 | astralis;; 786 | sk;; 787 | golden knights;; 788 | --------------------------------------------------------------------------------
Team 1Odd 1Odd 1 predictedTeam 2Odd 2Odd 2 predictedΔEV1ΔEV2
{{pred.match.team1}}{{pred.match.odd1}}{{pred.odd1}}{{pred.match.team2}}{{pred.match.odd2}}{{pred.odd2}}{{pred.delta_ev_1}} {{pred.delta_ev_2}}