some fixes of entries, datatable html and git archive python code

This commit is contained in:
Trilarion 2018-06-11 09:44:45 +02:00
parent 8220365691
commit 81228e509b
19 changed files with 149 additions and 120 deletions

2
.gitignore vendored
View File

@ -1,2 +1,2 @@
/.idea
/tools/git archive/*
/tools/git_archive/*

View File

@ -1,9 +1,9 @@
# Open Source Games
[comment]: # (start of autogenerated content, do not edit)
406 entries
405 entries
- **[Action/Arcade games](games/action/_toc.md)** (17)
- **[Adventure games & Visual novels](games/adventure/_toc.md)** (16)
- **[Adventure games & Visual novels](games/adventure/_toc.md)** (15)
- **[Game frameworks](games/framework/_toc.md)** (52)
- **[Popular required libraries](games/library/_toc.md)** (22)
- **[Role Playing Games](games/rpg/_toc.md)** (106)

File diff suppressed because one or more lines are too long

View File

@ -11,13 +11,13 @@
<table class="table"></table>
</div>
<script>
var dataTable = new DataTable("table", {
perPage: 50,
perPageSelect: [20, 50, 100],
fixedHeigt: true,
ajax: "data.json",
footer: true
});
var dataTable = new DataTable("table", {
perPage: 50,
perPageSelect: [20, 50, 100],
fixedHeigt: true,
ajax: "data.json",
footer: true
});
</script>
</body>
</html>

View File

@ -2266,21 +2266,7 @@
// Valid JSON string
if (json) {
obj = {
headings: [],
data: []
};
each(json, function (data, i) {
obj.data[i] = [];
each(data, function (value, column) {
if (obj.headings.indexOf(column) < 0) {
obj.headings.push(column);
}
obj.data[i].push(value);
});
});
obj = json;
} else {
console.warn("That's not valid JSON!");
}

View File

@ -2,11 +2,10 @@
[comment]: # (start of autogenerated content, do not edit)
- **[AdaVenture](adaventure.md)** (Ada, GPL-3.0, mature)
- **[Camelia Girls](camelia_girls.md)** (Ren'py, mature)
- **[Clou!](clou.md)** (C, beta)
- **[Colossal Cave Adventure](colossal_cave.md)** (Python, Apache-2.0, mature)
- **[Digital: A Love Story](digital_a_love_story.md)** (Ren'py, mature)
- **[Dragon History](dragon_history.md)** (GPL, mature)
- **[Digital: A Love Story](digital_a_love_story.md)** (Ren'py, CC-BY-NC-SA, mature)
- **[Dragon History](dragon_history.md)** (GPL-2.0, mature, inactive since 2010)
- **[Fanwor](fanwor.md)** (C, GPL-2.0, mature)
- **[Free in the Dark (engine)](fitd.md)** (C, C++, GPL-2.0, beta)
- **[GameLV](gamelv.md)** (C++, GPL, beta)
@ -14,7 +13,7 @@
- **[Sentient Storage](sentient_storage.md)** (Python, Public Domain, mature)
- **[Sintel The Game](sintel.md)** (Python, MIT, beta, inactive since 2014)
- **[Solaris the Game](solaris.md)** (beta)
- **[Star Maiden Rio](star_maiden_rio.md)** (mature)
- **[Star Maiden Rio](star_maiden_rio.md)** (Ren'py, CC-BY-NC, mature)
- **[TwinEngine](twin_engine.md)** (C, GPL-2.0, mature, inactive since 2015)
- **[Visions from the Other Side](visions_from_the_other_side.md)** (Ren'py, Freeware, mature, inactive since 2006)

View File

@ -1,14 +0,0 @@
# Camelia Girls
_A simple slice-of-life Visual Novel from the point of a view of a computer-savvy transfer student at the Camelia All-Girls Academy._
- Home: https://web.archive.org/web/20140523011334/http://pigux.com:80/cameliagirls/
- Download: https://web.archive.org/web/20140107152141/http://pigux.com:80/cameliagirls/download.html
- State: mature
- Keywords: visual novel
- Code language: Ren'py
- Artwork license: CC-BY-SA
## Building

View File

@ -2,11 +2,12 @@
_A computer mystery/romance set five minutes into the future of 1988._
- Home: https://lgdb.org/game/digital_love_story
- Home: http://scoutshonour.com/digital/, https://lgdb.org/game/digital_love_story
- Download: (see home)
- State: mature
- Keywords: visual novel
- Code repository: (see download)
- Code language: Ren'py
- Artwork license: CC-BY-SA
- Code license: CC-BY-NC-SA
## Building

View File

@ -3,8 +3,10 @@
_Czech adventure game._
- Home: http://www.ucw.cz/draci-historie/index-en.html
- State: mature
- Code license: GPL
- Download: http://www.ucw.cz/draci-historie/index-en.html#download
- State: mature, inactive since 2010
- Code repository: (see download)
- Code license: GPL-2.0
Runs in ScummVM or Dosbox

View File

@ -4,8 +4,11 @@
- Download: http://www.mediafire.com/file/jog3fcfxgsyd03f/Astraea_Rio-1.05-all.zip
- State: mature
- Keywords: visual novel, rating 18
- Language: Ren'py
- Artwork license: CC-BY-NC
- Code repository: (see download)
- Code language: Ren'py
- Code license: CC-BY-NC
- Code dependencies: Ren'py
- Assets license: CC-BY-NC
## Building

View File

@ -3,9 +3,10 @@
_Short Visual Novel_
- Home: http://www.insani.org/mukou.html
- Download: (see home)
- Download: (see home, torrents)
- State: mature, inactive since 2006
- Keywords: visual novel
- Code repository: (see download)
- Code language: Ren'py
- Code license: Freeware

View File

@ -1,23 +1,23 @@
[comment]: # (autogenerated content, do not edit)
# Statistics
analyzed 406 entries on 2018-06-08 14:40:18
analyzed 405 entries on 2018-06-10 18:20:46
## State
- mature: 237 (58.4%)
- beta: 169 (41.6%)
- inactive: 166 (40.9%)
- mature: 236 (58.3%)
- beta: 169 (41.7%)
- inactive: 169 (41.7%)
##### Inactive State
Zone of Control (2017), 3d.city (2016), Atrinik (2016), Birth of the Empires (2016), DNT (2016), Dark Destiny (2016), Dungeon Monkey Eternal (2016), FreeRCT (2016), Mechanized Assault & eXploration Reloaded (2016), Polis (2016), WarGame (2016), Dash Engine (2015), Delta Engine (2015), Egoboo (2015), Free heroes2 engine (2015), M.E.W.L. (2015), Project Helena (2015), Roguish (2015), The Epic of Heroes (2015), TwinEngine (2015), Witch Blast (2015), pyORPG (2015), Argentum Online (2014), Battles of Antargis (2014), Deity (2014), Drop Shock (2014), Dune Dynasty (2014), EternalWinterWars (2014), FAR Colony (2014), Hale (2014), Heroes of Wing Commander (2014), Kingdoms (2014), Lips of Suna (2014), Open RPG Maker (2014), Open Tibia (2014), Sintel The Game (2014), Summoning Wars (2014), Turious (2014), Xenowar (2014), rpge (2014), sandbox Game Maker (2014), Bos Wars (2013), C-evo (2013), Decker (2013), DemiGod (2013), Dungeon Mapper (2013), Holyspirit (2013), MechCommander 2 Omnitech (2013), Mpango (2013), OpenRPG (2013), Phantasy Star Rebirth (2013), Room for Change (2013), Source of Tales (2013), Trinity Reign (2013), VegaTrek (2013), BlackNova Traders (2012), Cataclysm (2012), CommandoJS (2012), Conquests (2012), Dark City (2012), Goblin Camp (2012), Hexwar (2012), Outer Space (2012), PARPG (2012), Solar Empire (2012), Thousand Parsec (2012), UFO2000 (2012), Wizards Magic (2012), Age of Magic (2011), Atlantis (2011), Battlefield Java (2011), Danger from the Deep (2011), Dawn (2011), GalaxyMage Redux (2011), JaNaG - Java Name Generator (2011), KQ Lives (2011), Kobold's Quest 2 (2011), OpenMOO2 (2011), Project Diaspora (2011), RuneSword II (2011), Song of Albion (2011), Star Control II: The Ur-Quan Masters (2011), UlDunAd (2011), World of Phaos (2011), X-Force: Fight For Destiny (2011), AI Wars (2010), Crimson Fields (2010), Endgame: Singularity (2010), Labyrinth of Worlds (2010), Linwarrior 3D (2010), Mercenary Commander (2010), OpenHoMM (2010), Radakan (2010), Skrupel - Tribute Compilation (2010), Slay (2010), SpaceTrader for Java (2010), XSera (2010), 8 Kingdoms (2009), Annchienta (2009), Ardentryst (2009), Begin2 (2009), Blitzkrieg (2009), Dark Oberon (2009), Duel Commander (2009), Fall of Imyrin (2009), Fallen Spire (2009), FreeTrain (2009), Glest (2009), Goblin Hack (2009), ORIENT (2009), OpenPop (2009), Secret Mario Chronicles (2009), World of Heroes (2009), A Planet's Revenge (2008), Attal (2008), Freestars (2008), Mars, Land of No Mercy (2008), Meritous (2008), Moopy (2008), Moria (2008), S.C.O.U.R.G.E. (2008), Scoreos (2008), Sengoku: Warring States of Japan (2008), Space Opera (2008), Space Trader for Windows (2008), Armies (2007), Eos, Dawn of Light: A Space Opera (2007), Silvertree (2007), Slash'EM (2007), Arthur's Knights (2006), Avanor (2006), Betrayer's Moon Tactics (2006), Boson (2006), Crown and Cutless (2006), Eleconics (2006), JQuest (2006), Linley's Dungeon Crawl (2006), Metal Mech (2006), RPDungeon - computer aided role playing (2006), Rogue Clone IV (2006), Underworld Adventures (2006), GalaxyNG (2005), H-World (2005), Spice Trade (2005), WAtomic (2005), ZAngband (2005), Colonization too (2004), GM Tools (2004), Gee Whiz (2004), Iter Vehemens ad Necem (2004), Openglad (2004), Promisance (2004), T-Bots (2004), AntiChess (2003), Cat Mother Dead Justice (2003), Civil (2003), Machinations (2003), Pizza Business (2003), Planetary Hoppers (2003), The Clans (2003), Wargamer (2003), XArchon (2003), Umbra (2002), Greenius' Civil War (2001), Tux Racer (2001), Operation Citadel (2000)
Zone of Control (2017), 3d.city (2016), Atrinik (2016), Birth of the Empires (2016), DNT (2016), Dark Destiny (2016), Dungeon Monkey Eternal (2016), FreeRCT (2016), Mechanized Assault & eXploration Reloaded (2016), Polis (2016), WarGame (2016), Dash Engine (2015), Delta Engine (2015), Egoboo (2015), Free heroes2 engine (2015), M.E.W.L. (2015), Project Helena (2015), Roguish (2015), The Epic of Heroes (2015), TwinEngine (2015), Witch Blast (2015), pyORPG (2015), Argentum Online (2014), Battles of Antargis (2014), Deity (2014), Drop Shock (2014), Dune Dynasty (2014), EternalWinterWars (2014), FAR Colony (2014), Hale (2014), Heroes of Wing Commander (2014), Kingdoms (2014), Lips of Suna (2014), Open RPG Maker (2014), Open Tibia (2014), Sintel The Game (2014), Summoning Wars (2014), Turious (2014), Xenowar (2014), rpge (2014), sandbox Game Maker (2014), Bos Wars (2013), C-evo (2013), Decker (2013), DemiGod (2013), Dungeon Mapper (2013), Holyspirit (2013), MechCommander 2 Omnitech (2013), Mpango (2013), OpenRPG (2013), Phantasy Star Rebirth (2013), Room for Change (2013), Source of Tales (2013), Trinity Reign (2013), VegaTrek (2013), BlackNova Traders (2012), Cataclysm (2012), CommandoJS (2012), Conquests (2012), Dark City (2012), Goblin Camp (2012), Hexwar (2012), Outer Space (2012), PARPG (2012), Solar Empire (2012), Thousand Parsec (2012), UFO2000 (2012), Wizards Magic (2012), Age of Magic (2011), Atlantis (2011), Battlefield Java (2011), Danger from the Deep (2011), Dawn (2011), GalaxyMage Redux (2011), JaNaG - Java Name Generator (2011), KQ Lives (2011), Kobold's Quest 2 (2011), OpenMOO2 (2011), Project Diaspora (2011), RuneSword II (2011), Song of Albion (2011), Star Control II: The Ur-Quan Masters (2011), UlDunAd (2011), World of Phaos (2011), X-Force: Fight For Destiny (2011), AI Wars (2010), Crimson Fields (2010), Dragon History (2010), Endgame: Singularity (2010), Labyrinth of Worlds (2010), Linwarrior 3D (2010), Mercenary Commander (2010), OpenHoMM (2010), Radakan (2010), Skrupel - Tribute Compilation (2010), Slay (2010), SpaceTrader for Java (2010), XSera (2010), 8 Kingdoms (2009), Alien Assault Traders (2009), Annchienta (2009), Ardentryst (2009), Begin2 (2009), Blitzkrieg (2009), Dark Oberon (2009), Duel Commander (2009), Fall of Imyrin (2009), Fallen Spire (2009), FreeTrain (2009), Glest (2009), Goblin Hack (2009), ORIENT (2009), OpenPop (2009), Secret Mario Chronicles (2009), World of Heroes (2009), A Planet's Revenge (2008), Attal (2008), Freestars (2008), Mars, Land of No Mercy (2008), Meritous (2008), Moopy (2008), Moria (2008), S.C.O.U.R.G.E. (2008), Scoreos (2008), Sengoku: Warring States of Japan (2008), Space Opera (2008), Space Trader for Windows (2008), Armies (2007), Eos, Dawn of Light: A Space Opera (2007), Silvertree (2007), Slash'EM (2007), Arthur's Knights (2006), Avanor (2006), Betrayer's Moon Tactics (2006), Boson (2006), Crown and Cutless (2006), Eleconics (2006), JQuest (2006), Linley's Dungeon Crawl (2006), Metal Mech (2006), RPDungeon - computer aided role playing (2006), Rogue Clone IV (2006), Underworld Adventures (2006), Visions from the Other Side (2006), GalaxyNG (2005), H-World (2005), Spice Trade (2005), WAtomic (2005), ZAngband (2005), Colonization too (2004), GM Tools (2004), Gee Whiz (2004), Iter Vehemens ad Necem (2004), Openglad (2004), Promisance (2004), T-Bots (2004), AntiChess (2003), Cat Mother Dead Justice (2003), Civil (2003), Machinations (2003), Pizza Business (2003), Planetary Hoppers (2003), The Clans (2003), Wargamer (2003), XArchon (2003), Umbra (2002), Greenius' Civil War (2001), Tux Racer (2001), Operation Citadel (2000)
## Code Languages
Without language tag: 18 (4.4%)
Without language tag: 17 (4.2%)
Crimson Fields, Dragon History, Evol Online, Greenius' Civil War, Imperium, Land of Fire, Machinations, Murder In The Public Domain, Open AL, Open General, Open RPG Maker, OpenMOO2, PARPG, Solaris the Game, Space Station 13, Star Maiden Rio, VegaTrek, Xconq
Crimson Fields, Dragon History, Evol Online, Greenius' Civil War, Imperium, Land of Fire, Machinations, Murder In The Public Domain, Open AL, Open General, Open RPG Maker, OpenMOO2, PARPG, Solaris the Game, Space Station 13, VegaTrek, Xconq
##### Language frequency
@ -55,29 +55,31 @@ Crimson Fields, Dragon History, Evol Online, Greenius' Civil War, Imperium, Land
## Code licenses
Without license tag: 48 (11.8%)
Without license tag: 44 (10.9%)
8 Kingdoms, A Planet's Revenge, Alien Assault Traders, AntiChess, Armies, Atrinik, Battlefield Java, BlackNova Traders, C-evo, Camelia Girls, Clou!, Crimson Fields, Dark Destiny, Digital: A Love Story, Drop Shock, Eleconics, Evol Online, First Strike, FreeRails, Freestars, Greenius' Civil War, H-World, Heroes of Wesnoth, Hexwar, Imperium, JQuest, Labyrinth of Worlds, Land of Fire, Machinations, Mpango, Open General, Open RPG Maker, OpenMOO2, OpenRPG, Other-Life, PARPG, PCGen, Project Helena, RuneSword II, Solar Empire, Solaris the Game, Space Station 13, SpaceTrader for Java, Star Maiden Rio, War Of Kingdom, Warzone 2100, ZAngband, sCoreForge Pathfinder Character Creator
8 Kingdoms, A Planet's Revenge, AntiChess, Armies, Atrinik, Battlefield Java, BlackNova Traders, C-evo, Clou!, Crimson Fields, Dark Destiny, Drop Shock, Eleconics, Evol Online, First Strike, FreeRails, Freestars, Greenius' Civil War, H-World, Heroes of Wesnoth, Hexwar, Imperium, JQuest, Labyrinth of Worlds, Land of Fire, Machinations, Mpango, Open General, Open RPG Maker, OpenMOO2, OpenRPG, Other-Life, PARPG, PCGen, Project Helena, RuneSword II, Solar Empire, Solaris the Game, Space Station 13, SpaceTrader for Java, War Of Kingdom, Warzone 2100, ZAngband, sCoreForge Pathfinder Character Creator
##### Licenses frequency
- GPL-2.0 (38.5%)
- GPL-3.0 (24.9%)
- MIT (11.4%)
- Custom (5.3%)
- GPL-2.0 (38.7%)
- GPL-3.0 (24.7%)
- MIT (11.3%)
- Custom (5.2%)
- Apache-2.0 (3.3%)
- zlib (2.8%)
- zlib (2.7%)
- BSD (2.2%)
- GPL (2.2%)
- GPL (1.9%)
- LGPL-3.0 (1.1%)
- AGPL-3.0 (0.8%)
- BSD-3 (0.8%)
- LGPL-2.0 (0.8%)
- LGPL-2.1 (0.8%)
- MPL (0.6%)
- MPL (0.5%)
- Artistic License (0.3%)
- Boost license 1.0 (0.3%)
- Boost-1.0 (0.3%)
- CC-BY-NC (0.3%)
- CC-BY-NC-SA (0.3%)
- CC-BY-SA-3 (0.3%)
- CC0 (0.3%)
- CDDL (0.3%)
@ -96,21 +98,21 @@ Without license tag: 48 (11.8%)
##### Keywords frequency
- TBS (10.5%)
- TBS (10.6%)
- RTS (8.9%)
- roguelike (8.0%)
- roguelike (8.1%)
- remake (7.6%)
- requires original content (7.6%)
- MMO (7.2%)
- online (6.8%)
- tool (5.5%)
- SP (4.6%)
- SP (4.7%)
- MP (3.4%)
- 3D (3.0%)
- visual novel (2.5%)
- browser (2.1%)
- shooter (2.1%)
- sports (2.1%)
- visual novel (2.1%)
- engine (1.7%)
- popular (1.7%)
- board game (1.3%)

View File

@ -7,7 +7,7 @@
- **[AI Wars](ai_wars.md)** (Python, MIT, beta, inactive since 2010)
- **[Advanced Strategic Command](asc.md)** (C++, GPL-2.0, mature)
- **[Age of Magic](age_of_magic.md)** (C++, GPL-2.0, beta, inactive since 2011)
- **[Alien Assault Traders](alien_assault_traders.md)** (PHP, beta, inactive since 2009)
- **[Alien Assault Traders](alien_assault_traders.md)** (PHP, GPL-2.0, beta, inactive since 2009)
- **[Ancient Beast](ancient_beast.md)** (Javascript, AGPL-3.0, mature)
- **[Antares](antares.md)** (C++, LGPL-3.0, beta)
- **[AntiChess](antichess.md)** (Java, mature, inactive since 2003)

View File

@ -6,7 +6,9 @@ _Alien Assault Traders is an online, web-based, turn-based strategy space tradin
- Download: https://sourceforge.net/projects/aatrade/files/AATraders%200.4x/
- State: beta, inactive since 2009
- Keywords: online
- Code repository: (see download)
- Code language: PHP
- Code license: GPL-2.0
## Building

View File

@ -1,13 +0,0 @@
https://github.com/FreezingMoon/AncientBeast
https://github.com/godrin/antargis
https://github.com/bote-team/bote
https://github.com/Trilarion/civil
https://github.com/SWY1985/CivOne
https://github.com/colobot/colobot
https://github.com/tautvilas/epoh
https://github.com/hinogi/eternalwinterwars
https://github.com/infidel-/cult
https://github.com/Vakarias/farcolony
https://github.com/freeciv/freeciv
https://github.com/freeciv/freeciv-web
https://github.com/freeorion/freeorion
1 https://github.com/FreezingMoon/AncientBeast
2 https://github.com/godrin/antargis
3 https://github.com/bote-team/bote
4 https://github.com/Trilarion/civil
5 https://github.com/SWY1985/CivOne
6 https://github.com/colobot/colobot
7 https://github.com/tautvilas/epoh
8 https://github.com/hinogi/eternalwinterwars
9 https://github.com/infidel-/cult
10 https://github.com/Vakarias/farcolony
11 https://github.com/freeciv/freeciv
12 https://github.com/freeciv/freeciv-web
13 https://github.com/freeorion/freeorion

View File

@ -0,0 +1,5 @@
Clones and/or pulls many git repositories from the open source games entries, so that one has an archive of them.
Currently requires at least 35 GB space!
Run update.py to update the archive. Git URLs are stored in archives.json.

File diff suppressed because one or more lines are too long

View File

@ -7,15 +7,25 @@
"""
import os
import csv
import json
import subprocess
def read_text(file):
"""
Reads a whole text file (UTF-8 encoded).
"""
with open(file, mode='r', encoding='utf-8') as f:
text = f.read()
return text
def derive_folder_name(url):
github = 'https://github.com/'
if url.startswith(github):
url = url[len(github):].split('/')
folder = 'github.' + url[0] + '.' + url[1] + '.git'
parts = url[len(github):].split('/')
parts.insert(0, 'github')
folder = '.'.join(parts)
return folder
@ -36,22 +46,18 @@ if __name__ == '__main__':
# get this folder
root_folder = os.path.realpath(os.path.dirname(__file__))
# read archives.csv
archives = []
with open('archives.csv', newline='') as f:
reader = csv.reader(f)
for row in reader:
archives.append(row)
# read archives.json
text = read_text(os.path.join(root_folder, 'archives.json'))
archives = json.loads(text)
# loop over archives
for archive in archives:
url = archive[0]
folder = os.path.join(root_folder, derive_folder_name(url))
folder = os.path.join(root_folder, derive_folder_name(archive))
# if not existing do the initial checkout
if not os.path.isdir(folder):
os.chdir(root_folder)
clone(url, folder)
clone(archive, folder)
# pull all
os.chdir(folder)

View File

@ -64,10 +64,7 @@ def extract_overview_for_toc(file):
To be displayed after the game name in the category TOCs.
"""
with open(file, mode='r', encoding='utf-8') as f:
text = f.read()
info = parse_entry(text)
info = infos[file]
output = []
@ -301,9 +298,12 @@ def parse_entry(content):
# split on ','
v = v.split(',')
# finally strip
# strip
v = [x.strip() for x in v]
# remove all being false (empty)
v = [x for x in v if x]
# store in info
info[field.lower()] = v
@ -319,9 +319,15 @@ def parse_entry(content):
# state must contain either beta or mature but not both
v = info['state']
if 'beta' in v != 'mature' in v:
printf('State must be one of <"beta", "mature"> in entry "{}"'.format(info['title']))
print('State must be one of <"beta", "mature"> in entry "{}"'.format(info['title']))
return info # so that the rest can run through
# github repositories should not end on .git
repos = info['code repository']
for repo in repos:
if repo.startswith('https://github.com/') and repo.endswith('.git'):
print('Github repo {} in entry "{}" should not end on .git.'.format(repo, info['title']))
# extract inactive
phrase = 'inactive since '
inactive_year = [x[len(phrase):] for x in info['state'] if x.startswith(phrase)]
@ -340,7 +346,7 @@ def assemble_infos():
category_paths = get_category_paths()
# a database of all important infos about the entries
infos = []
infos = {}
# for each category
for category_path in category_paths:
@ -364,7 +370,7 @@ def assemble_infos():
info['file'] = os.path.basename(entry_path)[:-3] # [:-3] to cut off the .md
# add to list
infos.append(info)
infos[entry_path] = info
return infos
@ -376,25 +382,28 @@ def generate_statistics():
Should be done every time the entries change.
"""
# for this function replace infos with infos.values
infois = infos.values()
# start the page
statistics_path = os.path.join(games_path, 'statistics.md')
statistics = '[comment]: # (autogenerated content, do not edit)\n# Statistics\n\n'
# total number
number_entries = len(infos)
number_entries = len(infois)
rel = lambda x: x / number_entries * 100 # conversion to percent
statistics += 'analyzed {} entries on {}\n\n'.format(number_entries, datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
# State (beta, mature, inactive)
statistics += '## State\n\n'
number_state_beta = sum(1 for x in infos if 'beta' in x['state'])
number_state_mature = sum(1 for x in infos if 'mature' in x['state'])
number_inactive = sum(1 for x in infos if 'inactive' in x)
number_state_beta = sum(1 for x in infois if 'beta' in x['state'])
number_state_mature = sum(1 for x in infois if 'mature' in x['state'])
number_inactive = sum(1 for x in infois if 'inactive' in x)
statistics += '- mature: {} ({:.1f}%)\n- beta: {} ({:.1f}%)\n- inactive: {} ({:.1f}%)\n\n'.format(number_state_mature, rel(number_state_mature), number_state_beta, rel(number_state_beta), number_inactive, rel(number_inactive))
if number_inactive > 0:
entries_inactive = [(x['title'], x['inactive']) for x in infos if 'inactive' in x]
entries_inactive = [(x['title'], x['inactive']) for x in infois if 'inactive' in x]
entries_inactive.sort(key=lambda x: x[0]) # first sort by name
entries_inactive.sort(key=lambda x: x[1], reverse=True) # then sort by inactive year (more recently first)
entries_inactive = ['{} ({})'.format(*x) for x in entries_inactive]
@ -405,16 +414,16 @@ def generate_statistics():
field = 'code language'
# those without language tag
number_no_language = sum(1 for x in infos if field not in x)
number_no_language = sum(1 for x in infois if field not in x)
if number_no_language > 0:
statistics += 'Without language tag: {} ({:.1f}%)\n\n'.format(number_no_language, rel(number_no_language))
entries_no_language = [x['title'] for x in infos if field not in x]
entries_no_language = [x['title'] for x in infois if field not in x]
entries_no_language.sort()
statistics += ', '.join(entries_no_language) + '\n\n'
# get all languages together
languages = []
for info in infos:
for info in infois:
if field in info:
languages.extend(info[field])
@ -430,16 +439,16 @@ def generate_statistics():
field = 'code license'
# those without license
number_no_license = sum(1 for x in infos if field not in x)
number_no_license = sum(1 for x in infois if field not in x)
if number_no_license > 0:
statistics += 'Without license tag: {} ({:.1f}%)\n\n'.format(number_no_license, rel(number_no_license))
entries_no_license = [x['title'] for x in infos if field not in x]
entries_no_license = [x['title'] for x in infois if field not in x]
entries_no_license.sort()
statistics += ', '.join(entries_no_license) + '\n\n'
# get all licenses together
licenses = []
for info in infos:
for info in infois:
if field in info:
licenses.extend(info[field])
@ -456,7 +465,7 @@ def generate_statistics():
# get all keywords together
keywords = []
for info in infos:
for info in infois:
if field in info:
keywords.extend(info[field])
@ -482,10 +491,11 @@ def export_json():
db['headings'] = ['Name', 'Download']
entries = []
for info in infos:
for info in infos.values():
entry = [info['title']]
if 'download' in info:
entry.append(info['download'][0])
field = 'download'
if field in info and info[field]:
entry.append(info[field][0])
else:
entry.append('')
entries.append(entry)
@ -497,6 +507,41 @@ def export_json():
write_text(json_path, text)
def git_repo(repo):
if repo.startswith('https://github.com/'):
if len(repo.split('/')) == 5:
return repo + '.git'
return None
def update_primary_code_repositories():
primary_repos = []
# for every entry
for info in infos.values():
field = 'code repository'
# if field 'Code repository' is available
if field in info:
repos = info[field]
# if there are code repositories given
if repos:
repo = repos[0]
repo = git_repo(repo)
if repo:
primary_repos.append(repo)
# filter those out, that we can process
# sort them alphabetically
primary_repos.sort()
# write them to tools/git
json_path = os.path.join(games_path, os.path.pardir, 'tools', 'git_archive', 'archives.json')
text = json.dumps(primary_repos)
write_text(json_path, text)
if __name__ == "__main__":
# paths
@ -523,3 +568,6 @@ if __name__ == "__main__":
# check external links (only rarely)
# check_validity_external_links()
# collect list of primary code repositories
update_primary_code_repositories()