maintenance of inspirations

This commit is contained in:
Trilarion 2020-09-01 10:57:33 +02:00
parent 881f0c77c5
commit a1ce1809f3
24 changed files with 1079 additions and 974 deletions

View File

@ -1,5 +1,5 @@
start: entry* start: entry*
entry: "##" name "(" _NUMBER ")\n" property+ entry: "##" name "[" _NUMBER "]\n" property+
property: "-" _key ":" _values "\n" property: "-" _key ":" _values "\n"
_key: /(?! ).+?(?=:)(?<! )/ // key: everything until next ":", not beginning or ending with a space _key: /(?! ).+?(?=:)(?<! )/ // key: everything until next ":", not beginning or ending with a space
_values: [_value ("," _value)*] _values: [_value ("," _value)*]
@ -7,7 +7,7 @@ _value: quoted_value | unquoted_value
quoted_value: /\".+?\"/ // with quotation marks, can contain commas quoted_value: /\".+?\"/ // with quotation marks, can contain commas
unquoted_value: /(?![ \"])[^,\n]+(?<![ \"])/ // cannot contain commas, cannot start or end with quotation mark unquoted_value: /(?![ \"])[^,\n]+(?<![ \"])/ // cannot contain commas, cannot start or end with quotation mark
name: /(?! ).+?(?= \()/ // developer name: everything until " (" name: /(?! ).+?(?= \[)/ // developer name: everything until " ["
_NUMBER: /[0-9]+/ _NUMBER: /[0-9]+/

View File

@ -4,6 +4,7 @@ stored Git repositories.
""" """
import os import os
import sys
import requests import requests
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from utils import constants as c, utils, osg, osg_github from utils import constants as c, utils, osg, osg_github
@ -24,7 +25,11 @@ if __name__ == "__main__":
# read developer info # read developer info
developer_info = osg.read_developer_info() developer_info = osg.read_developer_info()
osg.write_developer_info(developer_info) # write again just to make nice osg.write_developer_info(developer_info) # write again just to make it nice and as sanity check
sys.exit(0)
# assemble info # assemble info
entries = osg.assemble_infos() entries = osg.assemble_infos()

View File

@ -1,9 +1,70 @@
from utils import constants as c, utils, osg """
Maintenance of inspirations.md and synchronization with the inspirations in the entries.
"""
from utils import constants as c, utils, osg, osg_ui
def duplicate_check():
"""
:param inspirations:
:return:
"""
print('\nduplicate check')
inspiration_names = [x['name'] for x in inspirations]
for index, name in enumerate(inspiration_names):
for other_name in inspiration_names[index+1:]:
if osg.name_similarity(name, other_name) > similarity_threshold:
print(' {} - {} is similar'.format(name, other_name))
if __name__ == "__main__": if __name__ == "__main__":
similarity_threshold = 0.8
# load inspirations
inspirations = osg.read_inspirations_info() inspirations = osg.read_inspirations_info()
print('{} inspirations in the inspirations database'.format(len(inspirations)))
osg.write_inspirations_info(inspirations) # write again just to check integrity osg.write_inspirations_info(inspirations) # write again just to check integrity
osg_ui.run_simple_button_app('Maintenance inspirations', (('Duplicate check', duplicate_check),))
# assemble info # assemble info
# entries = osg.assemble_infos() entries = osg.assemble_infos()
# assemble inspirations info from entries
entries_inspirations = {}
for entry in entries:
entry_name = entry['name']
keywords = entry['keywords']
entry_inspirations = [x for x in keywords if x.startswith('inspired by')]
if entry_inspirations:
entry_inspirations = entry_inspirations[0][len('inspired by'):]
entry_inspirations = entry_inspirations.split('+')
entry_inspirations = [x.strip() for x in entry_inspirations]
for entry_inspiration in entry_inspirations:
if entry_inspiration in entries_inspirations:
entries_inspirations[entry_inspiration].append(entry_name)
else:
entries_inspirations[entry_inspiration] = [ entry_name ]
print('{} inspirations in the entries'.format(len(entries_inspirations)))
# first check if all inspiration in entries are also in inspirations
inspiration_names = [x['name'] for x in inspirations]
for inspiration, entries in entries_inspirations.items():
if inspiration not in inspiration_names:
print('new inspiration {} for games {}'.format(inspiration, ', '.join(entries)))
similar_names = [x for x in inspiration_names if osg.name_similarity(inspiration, x) > 0.8]
if similar_names:
print(' similar names {}'.format(', '.join(similar_names)))
# now the other way around
for index, name in enumerate(inspiration_names):
if name not in entries_inspirations:
print('potential removed inspiration {} from games {}'.format(name, inspirations[index]['inspired entries']))
similar_names = [x for x in entries_inspirations.keys() if osg.name_similarity(name, x) > 0.8]
if similar_names:
print(' similar names {}'.format(', '.join(similar_names)))

View File

@ -92,4 +92,4 @@ general_code_dependencies_without_entry = {'OpenGL': 'https://www.opengl.org/',
valid_developer_fields = ('name', 'games', 'contact', 'organization', 'home') valid_developer_fields = ('name', 'games', 'contact', 'organization', 'home')
# inspiration/original game information (in the file all fields will be capitalized) # inspiration/original game information (in the file all fields will be capitalized)
valid_inspiration_fields = ('name', 'inspired entries') valid_inspiration_fields = ('name', 'inspired entries', 'media')

View File

@ -399,14 +399,13 @@ def read_developer_info():
if field not in valid_developer_fields: if field not in valid_developer_fields:
raise RuntimeError('Unknown developer field "{}" for developer: {}.'.format(field, dev['name'])) raise RuntimeError('Unknown developer field "{}" for developer: {}.'.format(field, dev['name']))
# strip from name or organization (just in case) # strip from name or organization (just in case)
for field in ('name', 'organization'): for field in ('name', ):
if field in dev: if field in dev:
dev[field] = dev[field].strip() dev[field] = dev[field].strip()
# split games, contact (are lists) # split games, contact (are lists)
for field in ('games', 'contact'): for field in ('games', 'contact'):
if field in dev: if field in dev:
content = dev[field] content = dev[field]
content = content.split(',')
content = [x.strip() for x in content] content = [x.strip() for x in content]
dev[field] = content dev[field] = content
# check for duplicate names entries # check for duplicate names entries
@ -427,28 +426,31 @@ def write_developer_info(developers):
content = '{}\n'.format(generic_comment_string) content = '{}\n'.format(generic_comment_string)
# number of developer # number of developer
content += '# Developer ({})\n\n'.format(len(developers)) content += '# Developer [{}]\n\n'.format(len(developers))
# sort by name # sort by name
developers.sort(key=lambda x: str.casefold(x['name'])) developers.sort(key=lambda x: str.casefold(x['name']))
# iterate over them # iterate over them
for dev in developers: for dev in developers:
keys = list(dev.keys())
# developer name # developer name
content += '## {} ({})\n\n'.format(dev['name'], len(dev['games'])) content += '## {} [{}]\n\n'.format(dev['name'], len(dev['games']))
keys.remove('name')
# games # all the remaining in alphabetical order, but 'games' first
content += '- Games: {}\n'.format(', '.join(sorted(dev['games'], key=str.casefold))) keys.remove('games')
keys.sort()
# all the remaining in alphabetical order keys = ['games'] + keys
for field in sorted(dev.keys()): for field in keys:
if field not in ('name', 'games'): value = dev[field]
value = dev[field] field = field.capitalize()
field = field.capitalize() # lists get special treatment
if isinstance(value, str): if isinstance(value, list):
content += '- {}: {}\n'.format(field, value) value.sort(key=str.casefold)
else: value = [x if not ',' in x else '"{}"'.format(x) for x in value] # surround those with a comma with quotation marks
content += '- {}: {}\n'.format(field, ', '.join(sorted(value, key=str.casefold))) value = ', '.join(value)
content += '- {}: {}\n'.format(field, value)
content += '\n' content += '\n'
# write # write
@ -502,29 +504,31 @@ def write_inspirations_info(inspirations):
content = '{}\n'.format(generic_comment_string) content = '{}\n'.format(generic_comment_string)
# number of developer # number of developer
content += '# Inspirations ({})\n\n'.format(len(inspirations)) content += '# Inspirations [{}]\n\n'.format(len(inspirations))
# sort by name # sort by name
inspirations.sort(key=lambda x: str.casefold(x['name'])) inspirations.sort(key=lambda x: str.casefold(x['name']))
# iterate over them # iterate over them
for inspiration in inspirations: for inspiration in inspirations:
keys = list(inspiration.keys())
# inspiration name # inspiration name
content += '## {} ({})\n\n'.format(inspiration['name'], len(inspiration['inspired entries'])) content += '## {} [{}]\n\n'.format(inspiration['name'], len(inspiration['inspired entries']))
keys.remove('name')
# games # all the remaining in alphabetical order, but "inspired entries" first
content += '- Inspired entries: {}\n'.format( keys.remove('inspired entries')
', '.join(sorted(inspiration['inspired entries'], key=str.casefold))) keys.sort()
keys = ['inspired entries'] + keys
# all the remaining in alphabetical order for field in keys:
for field in sorted(inspiration.keys()): value = inspiration[field]
if field not in ('name', 'inspired entries'): field = field.capitalize()
value = inspiration[field] # lists get special treatment
field = field.capitalize() if isinstance(value, list):
if isinstance(value, str): value.sort(key=str.casefold)
content += '- {}: {}\n'.format(field, value) value = [x if not ',' in x else '"{}"'.format(x) for x in value] # surround those with a comma with quotation marks
else: value = ', '.join(value)
content += '- {}: {}\n'.format(field, ', '.join(sorted(value, key=str.casefold))) content += '- {}: {}\n'.format(field, value)
content += '\n' content += '\n'
# write # write

32
code/utils/osg_ui.py Normal file
View File

@ -0,0 +1,32 @@
"""
Simple UI helpers with PyQt
"""
from PyQt5 import QtCore, QtGui, QtWidgets
def run_simple_button_app(title, actions):
"""
:param title:
:param actions:
:return:
"""
# create app
app = QtWidgets.QApplication([])
# create single widget
widget = QtWidgets.QWidget()
widget.setWindowTitle(title)
widget.setMinimumSize(200, 400)
# add actions
layout = QtWidgets.QVBoxLayout(widget)
for name, action in actions:
button = QtWidgets.QPushButton(name)
button.clicked.connect(action)
layout.addWidget(button)
# execute app
widget.show()
return app.exec_()

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@ _Clone of Achtung, die Kurve!, a simple skill game._
- State: mature - State: mature
- Play: https://kurve.se/ - Play: https://kurve.se/
- Platform: Web - Platform: Web
- Keywords: action, clone, inspired by Achtung die Kurve!, multiplayer local, open content - Keywords: action, clone, inspired by "Achtung, die Kurve!", multiplayer local, open content
- Code repository: https://github.com/SimonAlling/kurve.git - Code repository: https://github.com/SimonAlling/kurve.git
- Code language: JavaScript - Code language: JavaScript
- Code license: AGPL-3.0 - Code license: AGPL-3.0

View File

@ -4,7 +4,7 @@ _Remake of Battlecity._
- Home: https://battlecity.org/ - Home: https://battlecity.org/
- State: mature, inactive since 2013 - State: mature, inactive since 2013
- Keywords: action, inspired by Battlecity, remake, strategy - Keywords: action, inspired by Battle City, remake, strategy
- Code repository: https://github.com/Deceth/Battle-City.git - Code repository: https://github.com/Deceth/Battle-City.git
- Code language: C, C++, Pascal - Code language: C, C++, Pascal
- Code license: GPL-3.0 - Code license: GPL-3.0

View File

@ -5,7 +5,7 @@ _A DOOM clone engine._
- Home: https://github.com/amroibrahim/DIYDoom - Home: https://github.com/amroibrahim/DIYDoom
- State: beta - State: beta
- Platform: Windows - Platform: Windows
- Keywords: game engine, inspired by DOOM, remake - Keywords: game engine, inspired by Doom, remake
- Code repository: https://github.com/amroibrahim/DIYDoom.git - Code repository: https://github.com/amroibrahim/DIYDoom.git
- Code language: C++ - Code language: C++
- Code license: MIT - Code license: MIT

View File

@ -1,12 +1,12 @@
# FreeOrion # FreeOrion
_Turn-based space empire and galactic conquest (4X) computer game._ _Turn-based space empire and galactic conquest game._
- Home: https://www.freeorion.org/index.php/Main_Page, https://sourceforge.net/projects/freeorion/ - Home: https://www.freeorion.org/index.php/Main_Page, https://sourceforge.net/projects/freeorion/
- Media: https://en.wikipedia.org/wiki/Master_of_Orion#External_links - Media: https://en.wikipedia.org/wiki/Master_of_Orion#External_links
- State: beta - State: beta
- Download: https://www.freeorion.org/index.php/Download - Download: https://www.freeorion.org/index.php/Download
- Keywords: strategy, inspired by Master of Orion 1 + Master of Orion 2, open content, remake, turn-based - Keywords: strategy, inspired by Master of Orion + Master of Orion 2, open content, remake, turn-based
- Code repository: https://github.com/freeorion/freeorion.git, https://svn.code.sf.net/p/freeorion/code (svn) - Code repository: https://github.com/freeorion/freeorion.git, https://svn.code.sf.net/p/freeorion/code (svn)
- Code language: C++, Python - Code language: C++, Python
- Code license: GPL-2.0 - Code license: GPL-2.0

View File

@ -6,7 +6,7 @@ _Remake of Cube 2: Sauerbraten._
- Media: <https://en.wikipedia.org/wiki/Ace_of_Spades_(video_game)> - Media: <https://en.wikipedia.org/wiki/Ace_of_Spades_(video_game)>
- State: beta, inactive since 2018 - State: beta, inactive since 2018
- Keywords: remake, inspired by Cube 2: Sauerbraten - Keywords: remake, inspired by Cube 2: Sauerbraten
- Code repository: https://github.com/inexorgame/inexor-core.git (archived) - Code repository: https://github.com/inexorgame/vulkan-renderer.git, https://github.com/inexorgame/inexor-core.git (+) (archived)
- Code language: C++, JavaScript - Code language: C++, JavaScript
- Code license: zlib - Code license: zlib
- Code dependencies: Cube 2 - Code dependencies: Cube 2

View File

@ -5,7 +5,7 @@ _Bungeon builder._
- Home: https://keeperrl.com/, https://miki151.itch.io/keeperrl - Home: https://keeperrl.com/, https://miki151.itch.io/keeperrl
- State: beta - State: beta
- Platform: Windows - Platform: Windows
- Keywords: simulation, game engine, inspired by Dungeon Keeper II, requires original content - Keywords: simulation, game engine, inspired by Dungeon Keeper 2, requires original content
- Code repository: https://github.com/miki151/keeperrl.git - Code repository: https://github.com/miki151/keeperrl.git
- Code language: C, C++ - Code language: C, C++
- Code license: GPL-2.0 - Code license: GPL-2.0

View File

@ -1,6 +1,6 @@
# Moria # Moria
_Roguelike computer game inspired by J. R. R. Tolkien's novel The Lord of the Rings._ _Roguelike inspired by Tolkien's novel The Lord of the Rings._
- Home: https://umoria.org/, http://beej.us/moria/ - Home: https://umoria.org/, http://beej.us/moria/
- Media: <https://en.wikipedia.org/wiki/Moria_(video_game)> - Media: <https://en.wikipedia.org/wiki/Moria_(video_game)>

View File

@ -4,7 +4,7 @@ _Remake of Achtung, die Kurve!._
- Home: https://pwmarcz.pl/netacka/ - Home: https://pwmarcz.pl/netacka/
- State: mature - State: mature
- Keywords: remake, inspired by Achtung die Kurve!, skill - Keywords: remake, inspired by "Achtung, die Kurve!", skill
- Code repository: https://github.com/pwmarcz/netacka.git - Code repository: https://github.com/pwmarcz/netacka.git
- Code language: C - Code language: C
- Code license: MIT - Code license: MIT

View File

@ -1,12 +1,12 @@
# OpenGothic # OpenGothic
_Engine remake of Gothic 2: Night of the raven._ _Engine remake of Gothic II._
- Home: https://github.com/Try/OpenGothic - Home: https://github.com/Try/OpenGothic
- State: beta - State: beta
- Download: https://github.com/Try/OpenGothic/releases - Download: https://github.com/Try/OpenGothic/releases
- Platform: Windows - Platform: Windows
- Keywords: role playing, commercial content, game engine, inspired by Gothic + Gothic 2, remake, requires original content - Keywords: role playing, commercial content, game engine, inspired by Gothic + Gothic II, remake, requires original content
- Code repository: https://github.com/Try/OpenGothic.git - Code repository: https://github.com/Try/OpenGothic.git
- Code language: C++ - Code language: C++
- Code license: MIT - Code license: MIT

View File

@ -3,7 +3,6 @@
_Remake of Hogs of War._ _Remake of Hogs of War._
- Home: https://github.com/TalonBraveInfo/OpenHoW - Home: https://github.com/TalonBraveInfo/OpenHoW
- Media: https://en.wikipedia.org/wiki/Hogs_of_War
- State: beta - State: beta
- Platform: Windows, Linux - Platform: Windows, Linux
- Keywords: strategy, commercial content, inspired by Hogs of War, remake, requires original content, turn-based - Keywords: strategy, commercial content, inspired by Hogs of War, remake, requires original content, turn-based

View File

@ -1,6 +1,6 @@
# OpenKeeper # OpenKeeper
_Remake of the Dungeon Keeper II engine._ _Remake of the Dungeon Keeper 2 engine._
- Home: https://github.com/tonihele/OpenKeeper - Home: https://github.com/tonihele/OpenKeeper
- State: beta - State: beta

View File

@ -1,11 +1,11 @@
# REGoth # REGoth
_Reimplementation of the zEngine, used by the game "Gothic" and "Gothic II"._ _Reimplementation of the zEngine, used by the games Gothic and Gothic II._
- Home: https://regoth-project.github.io/REGoth-bs/index.html, https://github.com/REGoth-project/REGoth/wiki - Home: https://regoth-project.github.io/REGoth-bs/index.html, https://github.com/REGoth-project/REGoth/wiki
- State: mature - State: mature
- Download: https://github.com/REGoth-project/REGoth/releases - Download: https://github.com/REGoth-project/REGoth/releases
- Keywords: role playing, commercial content, inspired by Gothic + Gothic II, remake, requires original content (Gothic 1 and Gothic 2) - Keywords: role playing, commercial content, inspired by Gothic + Gothic II, remake, requires original content
- Code repository: https://github.com/REGoth-project/REGoth-bs.git, https://github.com/REGoth-project/REGoth.git (+) - Code repository: https://github.com/REGoth-project/REGoth-bs.git, https://github.com/REGoth-project/REGoth.git (+)
- Code language: C++ - Code language: C++
- Code license: GPL-3.0, MIT (https://github.com/REGoth-project/REGoth-bs/blob/master/LICENSE) - Code license: GPL-3.0, MIT (https://github.com/REGoth-project/REGoth-bs/blob/master/LICENSE)

View File

@ -1,6 +1,6 @@
# SDL Asylum # SDL Asylum
_C port of the computer game Asylum, which was written by Andy Southgate in 1994 for the Acorn Archimedes and is now public domain._ _C port of Asylum._
- Home: http://sdl-asylum.sourceforge.net/, https://sourceforge.net/projects/sdl-asylum/ - Home: http://sdl-asylum.sourceforge.net/, https://sourceforge.net/projects/sdl-asylum/
- Media: http://asylum.acornarcade.com/ - Media: http://asylum.acornarcade.com/
@ -16,6 +16,7 @@ _C port of the computer game Asylum, which was written by Andy Southgate in 1994
- Developer: Andy Southgate, Hugh Robinson - Developer: Andy Southgate, Hugh Robinson
[Successor of Asylum](http://asylum.acornarcade.com/) from 1994. [Successor of Asylum](http://asylum.acornarcade.com/) from 1994.
Asylum was written by Andy Southgate in 1994 for the Acorn Archimedes and is now public domain.
## Building ## Building

View File

@ -1,6 +1,6 @@
# xu4 # xu4
_A remake of the computer game Ultima IV._ _A remake of Ultima IV._
- Home: http://xu4.sourceforge.net/, https://sourceforge.net/projects/xu4/ - Home: http://xu4.sourceforge.net/, https://sourceforge.net/projects/xu4/
- Media: <https://en.wikipedia.org/wiki/Ultima_IV:_Quest_of_the_Avatar#Ultima_IV_on_modern_operating_systems> - Media: <https://en.wikipedia.org/wiki/Ultima_IV:_Quest_of_the_Avatar#Ultima_IV_on_modern_operating_systems>

View File

@ -6,7 +6,7 @@ _Remake of a 2D multiplayer game similar to the Tron movie-themed light cycle ga
- State: beta, inactive since 2007 - State: beta, inactive since 2007
- Download: http://zatacka.sourceforge.net/index.php?id=download, https://sourceforge.net/projects/zatacka/files/ - Download: http://zatacka.sourceforge.net/index.php?id=download, https://sourceforge.net/projects/zatacka/files/
- Platform: Windows, Linux - Platform: Windows, Linux
- Keywords: arcade, 2D, inspired by Achtung die Kurve, multiplayer - Keywords: arcade, 2D, inspired by "Achtung, die Kurve!", multiplayer
- Code repository: http://zatacka.cvs.sourceforge.net (cvs) - Code repository: http://zatacka.cvs.sourceforge.net (cvs)
- Code language: C, C++ - Code language: C, C++
- Code license: GPL-2.0 - Code license: GPL-2.0

View File

@ -4,7 +4,7 @@ _Remake of Achtung, die Kurve!._
- Home: https://github.com/simenheg/zatackax - Home: https://github.com/simenheg/zatackax
- State: beta - State: beta
- Keywords: action, inspired by Achtung die Kurve!, remake - Keywords: action, inspired by "Achtung, die Kurve!", remake
- Code repository: https://github.com/simenheg/zatackax.git - Code repository: https://github.com/simenheg/zatackax.git
- Code language: C - Code language: C
- Code license: GPL-3.0 - Code license: GPL-3.0

File diff suppressed because it is too large Load Diff