Best Python code snippet using autotest_python
model.py
Source:model.py  
1import datetime2import glob3import json4import os5import re6class AppModel(object):7    RUNS = [8        {9            'slug': 'tpp-rand-chatty-crystal',10            'title': 'TwitchPlaysPokemon - Randomized Chatty Crystal',11            'run_start': datetime.datetime(2022, 2, 12, 23, 18, tzinfo=datetime.timezone.utc),12            'url': 'https://www.twitch.tv/twitchplayspokemon'13        },14        {15            'slug': 'tpp-legends-arceus',16            'title': 'TwitchPlaysPokemon - Legends: Arceus',17            'run_start': datetime.datetime(2022, 1, 29, 21, 0, tzinfo=datetime.timezone.utc),18            'url': 'https://www.twitch.tv/twitchplayspokemon'19        },20        {21            'slug': 'tpp-brilliant-diamond',22            'title': 'TwitchPlaysPokemon - Brilliant Diamond',23            'run_start': datetime.datetime(2021, 11, 20, 21, 0, tzinfo=datetime.timezone.utc),24            'url': 'https://www.twitch.tv/twitchplayspokemon'25        },26        {27            'slug': 'tpp-gold-reforged',28            'title': 'TwitchPlaysPokemon - Spaceworld Gold Reforged',29            'run_start': datetime.datetime(2021, 10, 9, 21, 0, tzinfo=datetime.timezone.utc),30            'url': 'https://www.twitch.tv/twitchplayspokemon'31        },32        {33            'slug': 'tpp-blazing-emerald',34            'title': 'TwitchPlaysPokemon - Blazing Emerald',35            'run_start': datetime.datetime(2021, 8, 21, 21, 0, tzinfo=datetime.timezone.utc),36            'url': 'https://www.twitch.tv/twitchplayspokemon'37        },38        {39            'slug': 'tpp-post-rand-black',40            'title': 'TwitchPlaysPokemon - Post Randomized Pokemon Black Intermission',41            'run_start': datetime.datetime(2021, 7, 3, 21, 0, tzinfo=datetime.timezone.utc),42            'url': 'https://www.twitch.tv/twitchplayspokemon'43        },44        {45            'slug': 'tpp-rand-black',46            'title': 'TwitchPlaysPokemon - Randomized Pokemon Black',47            'run_start': datetime.datetime(2021, 7, 3, 21, 0, tzinfo=datetime.timezone.utc),48            'url': 'https://www.twitch.tv/twitchplayspokemon'49        },50        {51            'slug': 'tpp-post-rgb-race',52            'title': 'TwitchPlaysPokemon - Post RGB Race Intermission',53            'run_start': datetime.datetime(2021, 5, 13, 21, 0, tzinfo=datetime.timezone.utc),54            'url': 'https://www.twitch.tv/twitchplayspokemon'55        },56        {57            'slug': 'tps-rgb-race',58            'title': 'TwitchPlaysSpeedruns - The War Of The TwitchPlays',59            'run_start': datetime.datetime(2021, 5, 8, 21, 0, tzinfo=datetime.timezone.utc),60            'url': 'https://www.twitch.tv/twitchplaysspeedruns'61        },62        {63            'slug': 'tpp-rgb-race',64            'title': 'TwitchPlaysPokemon - Red Green Blue Race',65            'run_start': datetime.datetime(2021, 5, 8, 21, 0, tzinfo=datetime.timezone.utc),66            'url': 'https://www.twitch.tv/twitchplayspokemon'67        },68        {69            'slug': 'tppm-rgb-race',70            'title': 'TwitchPlaysPaperMario - Pokemon R/G/B Race',71            'run_start': datetime.datetime(2021, 5, 8, 21, 0, tzinfo=datetime.timezone.utc),72            'url': 'https://www.twitch.tv/twitchplayspapermario'73        },74        {75            'slug': 'tpp-post-renegade-platinum',76            'title': 'TwitchPlaysPokemon Post Pokemon Renegade Platinum Intermission',77            'run_start': datetime.datetime(2021, 4, 21, 21, 0, tzinfo=datetime.timezone.utc),78            'url': 'http://www.twitch.tv/twitchplayspokemon'79        },80        {81            'slug': 'tpp-renegade-platinum',82            'title': 'TwitchPlaysPokemon Pokemon Renegade Platinum',83            'run_start': datetime.datetime(2021, 4, 10, 21, 0, tzinfo=datetime.timezone.utc),84            'url': 'http://www.twitch.tv/twitchplayspokemon'85        },86        {87            'slug': 'tpp-post-chatty-crystal',88            'title': 'TwitchPlaysPokemon Post Chatty Crystal Intermission',89            'run_start': datetime.datetime(2021, 3, 8, 0, 30, tzinfo=datetime.timezone.utc),90            'url': 'http://www.twitch.tv/twitchplayspokemon'91        },92        {93            'slug': 'tpp-chatty-crystal',94            'title': 'TwitchPlaysPokemon Chatty Crystal',95            'run_start': datetime.datetime(2021, 2, 14, 21, 00, tzinfo=datetime.timezone.utc),96            'url': 'http://www.twitch.tv/twitchplayspokemon'97        },98        {99            'slug': 'tpp-post-vega',100            'title': 'TwitchPlaysPokemon Post Vega Intermission',101            'run_start': datetime.datetime(2020, 12, 25, 9, 00, tzinfo=datetime.timezone.utc),102            'url': 'http://www.twitch.tv/twitchplayspokemon'103        },104        {105            'slug': 'tpp-vega',106            'title': 'TwitchPlaysPokemon Vega',107            'run_start': datetime.datetime(2020, 12, 12, 21, 00, tzinfo=datetime.timezone.utc),108            'url': 'http://www.twitch.tv/twitchplayspokemon'109        },110        {111            'slug': 'tpp-post-rising-ruby',112            'title': 'TwitchPlaysPokemon Post Rising Ruby Intermission',113            'run_start': datetime.datetime(2020, 8, 21, 19, 00, tzinfo=datetime.timezone.utc),114            'url': 'http://www.twitch.tv/twitchplayspokemon'115        },116        {117            'slug': 'tpp-rising-ruby',118            'title': 'TwitchPlaysPokemon Rising Ruby',119            'run_start': datetime.datetime(2020, 8, 8, 21, 00, tzinfo=datetime.timezone.utc),120            'url': 'http://www.twitch.tv/twitchplayspokemon'121        },122        {123            'slug': 'tpp-post-sirius',124            'title': 'TwitchPlaysPokemon Post Sirius Intermission',125            'run_start': datetime.datetime(2020, 7, 1, 21, 00, tzinfo=datetime.timezone.utc),126            'url': 'http://www.twitch.tv/twitchplayspokemon'127        },128        {129            'slug': 'tpp-sirius',130            'title': 'TwitchPlaysPokemon Sirius',131            'run_start': datetime.datetime(2020, 6, 13, 21, 00, tzinfo=datetime.timezone.utc),132            'url': 'http://www.twitch.tv/twitchplayspokemon'133        },134        {135            'slug': 'tpp-post-gauntlet',136            'title': 'TwitchPlaysPokemon Post Gauntlet Intermission',137            'run_start': datetime.datetime(2020, 5, 11, 21, 00, tzinfo=datetime.timezone.utc),138            'url': 'http://www.twitch.tv/twitchplayspokemon'139        },140        {141            'slug': 'tpp-the-gauntlet',142            'title': 'TwitchPlaysPokemon The Gauntlet',143            'run_start': datetime.datetime(2020, 2, 13, 13, 22, tzinfo=datetime.timezone.utc),144            'url': 'http://www.twitch.tv/twitchplayspokemon'145        },146        {147            'slug': 'tpp-post-sword',148            'title': 'TwitchPlaysPokemon Post Pokémon Sword Intermission',149            'run_start': datetime.datetime(2019, 12, 1, 21, 00, tzinfo=datetime.timezone.utc),150            'url': 'http://www.twitch.tv/twitchplayspokemon'151        },152        {153            'slug': 'tpp-sword',154            'title': 'TwitchPlaysPokemon Pokémon Sword',155            'run_start': datetime.datetime(2019, 11, 23, 21, 00, tzinfo=datetime.timezone.utc),156            'url': 'http://www.twitch.tv/twitchplayspokemon'157        },158        {159            'slug': 'tpp-post-rum',160            'title': 'TwitchPlaysPokemon Post Randomized Ultra Moon Intermission',161            'run_start': datetime.datetime(2019, 10, 23, 13, 00, tzinfo=datetime.timezone.utc),162            'url': 'http://www.twitch.tv/twitchplayspokemon'163        },164        {165            'slug': 'tpp-rum',166            'title': 'TwitchPlaysPokemon Randomized Ultra Moon',167            'run_start': datetime.datetime(2019, 10, 12, 21, 00, tzinfo=datetime.timezone.utc),168            'url': 'http://www.twitch.tv/twitchplayspokemon'169        },170        {171            'slug': 'tpp-post-trihard',172            'title': 'TwitchPlaysPokemon Post TriHard Emerald Intermission',173            'run_start': datetime.datetime(2019, 8, 20, 21, 00, tzinfo=datetime.timezone.utc),174            'url': 'http://www.twitch.tv/twitchplayspokemon'175        },176        {177            'slug': 'tpp-trihard',178            'title': 'TwitchPlaysPokemon TriHard Emerald',179            'run_start': datetime.datetime(2019, 8, 10, 21, 00, tzinfo=datetime.timezone.utc),180            'url': 'http://www.twitch.tv/twitchplayspokemon'181        },182        {183            'slug': 'tpp-post-xg',184            'title': 'TwitchPlaysPokemon Post Pokemon XG Intermission',185            'run_start': datetime.datetime(2019, 7, 22, 4, 00, tzinfo=datetime.timezone.utc),186            'url': 'http://www.twitch.tv/twitchplayspokemon'187        },188        {189            'slug': 'tpp-xg',190            'title': 'TwitchPlaysPokemon Pokemon XG',191            'run_start': datetime.datetime(2019, 7, 13, 21, 00, tzinfo=datetime.timezone.utc),192            'url': 'http://www.twitch.tv/twitchplayspokemon'193        },194        {195            'slug': 'tpp-post-rand-col',196            'title': 'TwitchPlaysPokemon Post Randomized Colosseum Intermission',197            'run_start': datetime.datetime(2019, 5, 15, 1, 22, tzinfo=datetime.timezone.utc),198            'url': 'http://www.twitch.tv/twitchplayspokemon'199        },200        {201            'slug': 'tpp-rand-col',202            'title': 'TwitchPlaysPokemon Randomized Colosseum',203            'run_start': datetime.datetime(2019, 5, 8, 1, 22, tzinfo=datetime.timezone.utc),204            'url': 'http://www.twitch.tv/twitchplayspokemon'205        },206        {207            'slug': 'tpp-post-volt-white',208            'title': 'TwitchPlaysPokemon Post Volt White Intermission',209            'run_start': datetime.datetime(2019, 4, 25, 1, 22, tzinfo=datetime.timezone.utc),210            'url': 'http://www.twitch.tv/twitchplayspokemon'211        },212        {213            'slug': 'tpp-volt-white',214            'title': 'TwitchPlaysPokemon Volt White',215            'run_start': datetime.datetime(2019, 4, 13, 1, 22, tzinfo=datetime.timezone.utc),216            'url': 'http://www.twitch.tv/twitchplayspokemon'217        },218        {219            'slug': 'tpp-post-burning-red',220            'title': 'TwitchPlaysPokemon Post Burning Red Intermission',221            'run_start': datetime.datetime(2019, 2, 13, 1, 22, tzinfo=datetime.timezone.utc),222            'url': 'http://www.twitch.tv/twitchplayspokemon'223        },224        {225            'slug': 'tpp-burning-red',226            'title': 'TwitchPlaysPokemon Burning Red',227            'run_start': datetime.datetime(2019, 2, 13, 1, 22, tzinfo=datetime.timezone.utc),228            'url': 'http://www.twitch.tv/twitchplayspokemon'229        },230        {231            'slug': 'tpp-post-fused-crystal',232            'title': 'TwitchPlaysPokemon Post Fused Crystal Intermission',233            'run_start': datetime.datetime(2018, 12, 19, 21, 00, tzinfo=datetime.timezone.utc),234            'url': 'http://www.twitch.tv/twitchplayspokemon'235        },236        {237            'slug': 'tpp-fused-crystal',238            'title': 'TwitchPlaysPokemon Fused Crystal',239            'run_start': datetime.datetime(2018, 12, 8, 21, 00, tzinfo=datetime.timezone.utc),240            'url': 'http://www.twitch.tv/twitchplayspokemon'241        },242        {243            'slug': 'tpp-post-flora-sky',244            'title': 'TwitchPlaysPokemon Post Flora Sky Intermission',245            'run_start': datetime.datetime(2018, 10, 13, 21, 00, tzinfo=datetime.timezone.utc),246            'url': 'http://www.twitch.tv/twitchplayspokemon'247        },248        {249            'slug': 'tpp-flora-sky',250            'title': 'TwitchPlaysPokemon Flora Sky',251            'run_start': datetime.datetime(2018, 10, 13, 21, 00, tzinfo=datetime.timezone.utc),252            'url': 'http://www.twitch.tv/twitchplayspokemon'253        },254        {255            'slug': 'tpp-post-rand-y',256            'title': 'TwitchPlaysPokemon Post Randomized Y Intermission',257            'run_start': datetime.datetime(2018, 8, 26, 21, 00, tzinfo=datetime.timezone.utc),258            'url': 'http://www.twitch.tv/twitchplayspokemon'259        },260        {261            'slug': 'tpp-rand-y',262            'title': 'TwitchPlaysPokemon Randomized Y',263            'run_start': datetime.datetime(2018, 8, 11, 21, 00, tzinfo=datetime.timezone.utc),264            'url': 'http://www.twitch.tv/twitchplayspokemon'265        },266        {267            'slug': 'tpp-post-bronze',268            'title': 'TwitchPlaysPokemon Post Bronze Intermission',269            'run_start': datetime.datetime(2018, 6, 18, 5, 22, tzinfo=datetime.timezone.utc),270            'url': 'http://www.twitch.tv/twitchplayspokemon'271        },272        {273            'slug': 'tpp-bronze',274            'title': 'TwitchPlaysPokemon Bronze',275            'run_start': datetime.datetime(2018, 6, 9, 21, 00, tzinfo=datetime.timezone.utc),276            'url': 'http://www.twitch.tv/twitchplayspokemon'277        },278        {279            'slug': 'tpp-post-storm-silver',280            'title': 'TwitchPlaysPokemon Post Storm Silver Intermission',281            'run_start': datetime.datetime(2018, 5, 4, 0, 00, tzinfo=datetime.timezone.utc),282            'url': 'http://www.twitch.tv/twitchplayspokemon'283        },284        {285            'slug': 'tpp-storm-silver',286            'title': 'TwitchPlaysPokemon Storm Silver',287            'run_start': datetime.datetime(2018, 4, 14, 21, 00, tzinfo=datetime.timezone.utc),288            'url': 'http://www.twitch.tv/twitchplayspokemon'289        },290        {291            'slug': 'tpp-post-ani-2018',292            'title': 'TwitchPlaysPokemon Post 2018 Anniversary Intermission',293            'run_start': datetime.datetime(2018, 2, 27, 3, 00, tzinfo=datetime.timezone.utc),294            'url': 'http://www.twitch.tv/twitchplayspokemon'295        },296        {297            'slug': 'tpp-ani-2018',298            'title': 'TwitchPlaysPokemon 2018 Anniversary Run',299            'run_start': datetime.datetime(2018, 2, 13, 1, 22, tzinfo=datetime.timezone.utc),300            'url': 'http://www.twitch.tv/twitchplayspokemon'301        },302        {303            'slug': 'tpp-post-ultra-sun',304            'title': 'TwitchPlaysPokemon Post Ultra Sun Intermission',305            'run_start': datetime.datetime(2017, 12, 9, 21, 0, tzinfo=datetime.timezone.utc),306            'url': 'http://www.twitch.tv/twitchplayspokemon'307        },308        {309            'slug': 'tpp-ultra-sun',310            'title': 'TwitchPlaysPokemon Ultra Sun',311            'run_start': datetime.datetime(2017, 11, 25, 21, 0, tzinfo=datetime.timezone.utc),312            'url': 'http://www.twitch.tv/twitchplayspokemon'313        },314        {315            'slug': 'tpp-post-theta-emerald-ex',316            'title': 'TwitchPlaysPokemon Post Theta Emerald EX Intermission',317            'run_start': datetime.datetime(2017, 10, 15, 21, 0, tzinfo=datetime.timezone.utc),318            'url': 'http://www.twitch.tv/twitchplayspokemon'319        },320        {321            'slug': 'tpp-theta-emerald-ex',322            'title': 'TwitchPlaysPokemon Theta Emerald EX',323            'run_start': datetime.datetime(2017, 9, 30, 21, 0, tzinfo=datetime.timezone.utc),324            'url': 'http://www.twitch.tv/twitchplayspokemon'325        },326        {327            'slug': 'tpp-post-pyrite',328            'title': 'TwitchPlaysPokemon Post Pyrite Intermission',329            'run_start': datetime.datetime(2017, 8, 28, 21, 0, tzinfo=datetime.timezone.utc),330            'url': 'http://www.twitch.tv/twitchplayspokemon'331        },332        {333            'slug': 'tpp-pyrite',334            'title': 'TwitchPlaysPokemon Pyrite',335            'run_start': datetime.datetime(2017, 8, 12, 21, 0, tzinfo=datetime.timezone.utc),336            'url': 'http://www.twitch.tv/twitchplayspokemon'337        },338        {339            'slug': 'tpp-post-rand-white-2',340            'title': 'TwitchPlaysPokemon Post Randomized White 2',341            'run_start': datetime.datetime(2017, 6, 21, 19, 0, tzinfo=datetime.timezone.utc),342            'url': 'http://www.twitch.tv/twitchplayspokemon',343            'download_link': 'https://archive.org/details/tpp-post-rand-white-2-screenshots'344        },345        {346            'slug': 'tpp-rand-white-2',347            'title': 'TwitchPlaysPokemon Randomized White 2',348            'run_start': datetime.datetime(2017, 6, 3, 21, 0, tzinfo=datetime.timezone.utc),349            'url': 'http://www.twitch.tv/twitchplayspokemon',350            'download_link': 'https://archive.org/details/tpp-rand-white-2-screenshots'351        },352        {353            'slug': 'tpp-post-blazed-glazed',354            'title': 'TwitchPlaysPokemon Post Blazed Glazed',355            'run_start': datetime.datetime(2017, 4, 8, 16, 0, tzinfo=datetime.timezone.utc),356            'url': 'http://www.twitch.tv/twitchplayspokemon',357            'download_link': 'https://archive.org/details/tpp-post-blazed-glazed-screenshots'358        },359        {360            'slug': 'tpp-blazed-glazed',361            'title': 'TwitchPlaysPokemon Blazed Glazed',362            'run_start': datetime.datetime(2017, 4, 8, 16, 0, tzinfo=datetime.timezone.utc),363            'url': 'http://www.twitch.tv/twitchplayspokemon',364            'download_link': 'https://archive.org/details/tpp-blazed-glazed-screenshots'365        },366        {367            'slug': 'tpp-post-ani-2017',368            'title': 'TwitchPlaysPokemon Post 2017 Anniversary',369            'run_start': datetime.datetime(2017, 2, 24, 16, 0, tzinfo=datetime.timezone.utc),370            'url': 'http://www.twitch.tv/twitchplayspokemon',371            'download_link': 'https://archive.org/details/tpp-post-ani-2017-screenshots'372        },373        {374            'slug': 'tpp-ani-2017',375            'title': 'TwitchPlaysPokemon 2017 Anniversary',376            'run_start': datetime.datetime(2017, 2, 12, 21, 0, tzinfo=datetime.timezone.utc),377            'url': 'http://www.twitch.tv/twitchplayspokemon',378            'download_link': 'https://archive.org/details/tpp-ani-2017-chatty-yellow-screenshots',379        },380        {381            'slug': 'tpp-post-waning-moon',382            'title': 'TwitchPlaysPokemon Post Waning Moon',383            'run_start': datetime.datetime(2017, 1, 27, 6, 0, tzinfo=datetime.timezone.utc),384            'url': 'http://www.twitch.tv/twitchplayspokemon',385            'download_link': 'https://archive.org/details/tpp-post-waning-moon',386        },387        {388            'slug': 'tpp-waning-moon',389            'title': 'TwitchPlaysPokemon Waning Moon',390            'run_start': datetime.datetime(2017, 1, 13, 18, 0, tzinfo=datetime.timezone.utc),391            'url': 'http://www.twitch.tv/twitchplayspokemon',392            'download_link': 'https://archive.org/details/tpp-waning-moon-screenshots',393        },394        {395            'slug': 'tpp-post-sun',396            'title': 'TwitchPlaysPokemon Post-Sun',397            'run_start': datetime.datetime(2016, 12, 2, 22, 0, tzinfo=datetime.timezone.utc),398            'url': 'http://www.twitch.tv/twitchplayspokemon',399            'download_link': 'https://archive.org/details/tpp-post-sun-screenshots',400        },401        {402            'slug': 'tpp-sun',403            'title': 'TwitchPlaysPokemon Sun',404            'run_start': datetime.datetime(2016, 11, 19, 22, 0, tzinfo=datetime.timezone.utc),405            'url': 'http://www.twitch.tv/twitchplayspokemon',406            'download_link': 'https://archive.org/details/tpp-sun-screenshots'407        },408        {409            'slug': 'tpp-post-prism',410            'title': 'TwitchPlaysPokemon Post Prism',411            'run_start': datetime.datetime(2016, 10, 9, 21, 0, tzinfo=datetime.timezone.utc),412            'url': 'http://www.twitch.tv/twitchplayspokemon',413            'download_link': 'https://archive.org/details/tpp-post-prism-screenshots'414        },415        {416            'slug': 'tpp-prism',417            'title': 'TwitchPlaysPokemon Prism',418            'run_start': datetime.datetime(2016, 10, 9, 21, 0, tzinfo=datetime.timezone.utc),419            'url': 'http://www.twitch.tv/twitchplayspokemon',420            'download_link': 'https://archive.org/download/tpp-prism-screenshots'421        },422        {423            'slug': 'tpp-post-rand-plat',424            'title': 'TwitchPlaysPokemon Post Randomized Platinum',425            'run_start': datetime.datetime(2016, 7, 31, 21, 0, tzinfo=datetime.timezone.utc),426            'url': 'http://www.twitch.tv/twitchplayspokemon',427            'download_link': 'https://archive.org/details/tpp-post-rand-plat-screenshots',428        },429        {430            'slug': 'tpp-rand-plat',431            'title': 'Twitch Plays Randomized Platinum (By TwitchPlaysPokemon)',432            'run_start': datetime.datetime(2016, 7, 31, 21, 0, tzinfo=datetime.timezone.utc),433            'url': 'http://www.twitch.tv/twitchplayspokemon',434            'download_link': 'https://archive.org/details/tpp-rand-plat-screenshots',435        },436        {437            'slug': 'tpp-brown',438            'title': 'Twitch Plays Pokemon Brown (By TwitchPlaysPokemon)',439            'run_start': datetime.datetime(2016, 6, 19, 21, 0, tzinfo=datetime.timezone.utc),440            'url': 'http://www.twitch.tv/twitchplayspokemon',441            'download_link': 'https://archive.org/details/tpp-brown-screenshots'442        },443        {444            'slug': 'aiss-dual-test',445            'title': 'Misc dual game test (Aissurtievos)',446            'run_start': datetime.datetime(2016, 4, 24, 19, 0, tzinfo=datetime.timezone.utc),447            'url': 'http://www.twitch.tv/aissurtievos'448        },449        {450            'slug': 'tpp-telefang',451            'title': 'Twitch Plays "Pokémon Diamond" Telefang (By TwitchPlaysPokemon)',452            'run_start': datetime.datetime(2016, 3, 16, 21, 0, tzinfo=datetime.timezone.utc),453            'url': 'http://www.twitch.tv/twitchplayspokemon',454            'download_link': 'https://archive.org/details/tpp-telefang-screenshots',455        },456        {457            'slug': 'tpp-crystal-251',458            'title': 'Twitch Plays Pokémon Anniversary Crystal 251 (By TwitchPlaysPokemon)',459            'run_start': datetime.datetime(2016, 2, 14, 21, 0, tzinfo=datetime.timezone.utc),460            'url': 'http://www.twitch.tv/twitchplayspokemon',461            'download_link': 'https://archive.org/details/tpp-ac-screenshots',462        },463        {464            'slug': 'aoc-2016-01-30',465            'title': 'AoC #8: Twitch Plays Surgeon Sim, Twitch Does Your Homework, Twitch makes a promo for the next TPP run, other weird things... (By AdventuresOfChat)',466            'run_start': datetime.datetime(2016, 1, 31, 1, 0, tzinfo=datetime.timezone.utc),467            'url': 'http://www.twitch.tv/AdventuresOfChat'468        },469        {470            'slug': 'aoc-2016-01-09',471            'title': 'Twitch Flies A Plane, Twitch Plays Flash Games, <top-secret thing> (By AdventuresOfChat)',472            'run_start': datetime.datetime(2016, 1, 10, 1, 0, tzinfo=datetime.timezone.utc),473            'url': 'http://www.twitch.tv/AdventuresOfChat'474        },475        {476            'slug': 'aiss-psmd-post',477            'title': 'PSMD post game misc (Aissurtievos)',478            'run_start': datetime.datetime(2016, 1, 10, 0, 0, tzinfo=datetime.timezone.utc),479            'url': 'http://www.twitch.tv/aissurtievos'480        },481        {482            'slug': 'aiss-psmd',483            'title': 'Twitch Plays Pokémon Super Mystery Dungeon (By Aissurtievos)',484            'run_start': datetime.datetime(2015, 12, 26, 17, 0, tzinfo=datetime.timezone.utc),485            'url': 'http://www.twitch.tv/aissurtievos'486        },487        {488            'slug': 'aiss-psmd-pre',489            'title': 'Testing (Aissurtievos)',490            'run_start': datetime.datetime(2015, 12, 24, 0, 0, tzinfo=datetime.timezone.utc),491            'url': 'http://www.twitch.tv/aissurtievos'492        },493    ]494    RUN_MAP = {}495    for run_info in RUNS:496        RUN_MAP[run_info['slug']] = run_info497    def __init__(self, app):498        self._app = app499    def get_screenshots_dir(self):500        return os.path.join(501            os.path.abspath(self._app.config['data_dir']), 'screenshots'502        )503    def get_screenshot_date_listing(self, slug):504        screenshots_path = os.path.join(self.get_screenshots_dir(), slug)505        listing = []506        for name in os.listdir(screenshots_path):507            if re.match(r'\d{4}-\d\d-\d\d$', name):508                listing.append(name)509            elif re.match(r'\d{4}-\d\d-\d\d\.txt$', name):510                listing.append(name[:10])511        listing = sorted(frozenset(listing))512        return listing513    def get_screenshot_filename_listing(self, slug, date_str):514        screenshots_path = os.path.join(self.get_screenshots_dir(), slug)515        directory_path = os.path.join(screenshots_path, date_str)516        pattern = directory_path + '/[0-9]*[0-9].jpg'517        paths = list(os.path.basename(path) for path in glob.glob(pattern))518        text_file_path = os.path.join(screenshots_path, '{}.txt'.format(date_str))519        if os.path.exists(text_file_path):520            with open(text_file_path) as file:521                for line in file:522                    line = line.strip()523                    if not line:524                        continue525                    if 'thumb' not in line:526                        paths.append(line)527        placeholder_pattern = directory_path + '/[0-9]*[0-9].placeholder'528        paths.extend(529            os.path.basename(path).replace('.placeholder', '.jpg')530            for path in glob.glob(placeholder_pattern))531        return sorted(frozenset(paths))532    def get_recent_screenshots(self, slug, count=5):533        image_filenames = []534        date_strs = reversed(self.get_screenshot_date_listing(slug))535        for date_str in date_strs:536            filename_listing = reversed(self.get_screenshot_filename_listing(slug, date_str))537            for filename in filename_listing:538                image_filenames.append(filename)539                if len(image_filenames) >= count:540                    return image_filenames541        return image_filenames542    def is_screenshots_unavailable(self, slug):543        if slug not in self.RUN_MAP:544            return False545        recent = self.get_recent_screenshots(slug, count=1)546        return not recent and self.RUN_MAP[slug].get('download_link')547    def get_object_url_prefix(self, slug):548        screenshots_path = os.path.join(self.get_screenshots_dir(), slug)549        json_path = os.path.join(screenshots_path, 'meta.json')550        if os.path.exists(json_path):551            with open(json_path) as file:552                doc = json.load(file)...sort_algorithm.py
Source:sort_algorithm.py  
1import random2from visualizer.data import Tuple, Frame, StateSnapshot3from copy import deepcopy4class Sort:5    """6    Implements the external multipass sort algorithm7    """8    def __init__(self, B: int, F: int):9        self.B = B10        self.F = F11        self.tuples_per_frame = 412        self.steps = []13        self.buffer = []14        self.relation = []15        for _ in range(self.F):16            data = [Tuple(empty = True) for _ in range(self.tuples_per_frame)]17            self.buffer.append(Frame(data))18        values = list(range(self.B * self.tuples_per_frame))19        random.shuffle(values)20        for i in range(self.B):21            data = [Tuple(value = values[i * self.tuples_per_frame + j]) for j in range(self.tuples_per_frame)]22            self.relation.append(Frame(data))23    """24    Sort the relation data, creating a series of StateSnapshot snapshots that the GUI will later visualize25    """26    def sort(self):27        # Step 1. Create runs of F frames28        self.snapshot(f'Step 1: Create runs')29        run_start, run_end = [], []30        for i in range(0, self.B, self.F):31            run_length = min(self.F, self.B - i)32            run_start.append(i)33            run_end.append(i + run_length)34            for j in range(run_length):35                self.buffer[j], self.relation[i+j] = self.relation[i+j], self.buffer[j]36            self.snapshot(f'Load {run_length} frames')37            self.sort_buffer(0, run_length)38            self.snapshot(f'Sort frames')39            for j in range(run_length):40                self.buffer[j], self.relation[i+j] = self.relation[i+j], self.buffer[j]41            self.snapshot(f'Store sorted run {i // self.F}')42        # Step 2...N. Merge runs together43        if self.F - 1 == 1 and len(run_start) > 1:44            self.snapshot('Unable to merge with only 2 frames')45            return46        while len(run_start) > 1:47            new_run_start, new_run_end = [], []48            for first_frame in range(0, len(run_start), self.F - 1):49                num_runs = min(self.F - 1, len(run_start) - first_frame)50                output_frames = []51                output_start = run_start[first_frame]52                new_run_start.append(run_start[first_frame])53                new_run_end.append(run_end[first_frame + num_runs - 1])54                # Load the first frame of each run55                for j in range(num_runs):56                    self.load_frame(run_start[first_frame + j], j)57                # Prepare output frame58                self.buffer[num_runs].clear()59                self.snapshot(f'Load first frames for {run_start[first_frame]} - {run_end[first_frame+num_runs-1]}')60                while True:61                    frame_id, t = self.next_min_tuple(0, num_runs)62                    # Merge completed63                    if t is None:64                        break65                    # Add tuple to output frame66                    self.buffer[self.F - 1].insert_tuple(t)67                    self.snapshot(f'Output min element {t}')68                    # Flush if needed69                    if self.buffer[self.F - 1].num_tuples() == self.tuples_per_frame:70                        output_frames.append(deepcopy(self.buffer[self.F - 1]))71                        self.buffer[self.F - 1].clear()72                        self.snapshot('Flush output frame')73                    # Load new input frame74                    if self.buffer[frame_id].num_tuples() == 0:75                        run_start[first_frame + frame_id] += 176                        if run_start[first_frame + frame_id] < run_end[first_frame + frame_id]:77                            self.load_frame(run_start[first_frame + frame_id], frame_id)78                            self.snapshot('Load new input frame')79                # F-1 runs are sorted into one80                self.relation[output_start:output_start + len(output_frames)] = output_frames81            run_start, run_end = new_run_start, new_run_end82        self.snapshot('Done')83    def sort_buffer(self, start, end):84        items = []85        for i in range(start, end):86            items += self.buffer[i].data87        items.sort()88        for i in range(start, end):89            self.buffer[i].data = items[i * self.tuples_per_frame : (i+1) * self.tuples_per_frame]90    def next_min_tuple(self, start, end):91        idx, cur_best = -1, None92        for i,frame in enumerate(self.buffer[start:end]):93            t = frame.get_first_tuple()94            if t is None:95                continue96            if cur_best is None or t < cur_best:97                cur_best = t98                idx = i99        if idx == -1: return idx, None100        return idx, self.buffer[idx].pop_first_tuple()101    def load_frame(self, pos_in_relation, pos_in_buffer):102        self.buffer[pos_in_buffer], self.relation[pos_in_relation] = \103            self.relation[pos_in_relation], self.buffer[pos_in_buffer]104    def snapshot(self, description = ''):...helper.py
Source:helper.py  
1import numpy as np2def to_rle(mask):3    """4    Convert mask (as 2-D numpy array) to run-length encoding5    """6    rle = ''7    y_pos, x_pos = np.where(mask == 1)8    pixel_nums = []9    for i in range(y_pos.shape[0]):10        pixel_nums.append(x_pos[i] * mask.shape[0] + y_pos[i] + 1)11    pixel_nums_sorted = sorted(pixel_nums)12    run_start = np.where(np.diff(pixel_nums_sorted) != 1)[0] + 113    if len(pixel_nums_sorted) > 0:14        run_start = np.concatenate(([0], run_start))15    run_length = np.diff(run_start)16    if len(pixel_nums_sorted) > 0:17        run_length = np.concatenate((run_length, [len(pixel_nums_sorted) - run_start[-1]]))18    if run_start.shape[0] != run_length.shape[0]:19        raise Exception('run_start and run_length do not have the same length.')20    if run_start.shape[0] > 0:21        rle += '{} {}'.format(pixel_nums_sorted[run_start[0]], run_length[0])22    for i in range(1, run_start.shape[0]):23        rle += ' {} {}'.format(pixel_nums_sorted[run_start[i]], run_length[i])...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
