synchronized developers and entries
This commit is contained in:
parent
8a08425e09
commit
625871062f
@ -186,7 +186,7 @@ class DevelopersMaintainer:
|
||||
if not self.developers:
|
||||
print('developers not yet loaded')
|
||||
return
|
||||
developer_names = [x['Name'] for x in self.developers]
|
||||
developer_names = list(self.developers.keys())
|
||||
for index, name in enumerate(developer_names):
|
||||
for other_name in developer_names[index + 1:]:
|
||||
if osg.name_similarity(name, other_name) > 0.8:
|
||||
@ -197,9 +197,9 @@ class DevelopersMaintainer:
|
||||
if not self.developers:
|
||||
print('developers not yet loaded')
|
||||
return
|
||||
for dev in self.developers:
|
||||
for dev in self.developers.values():
|
||||
if not dev['Games']:
|
||||
print(' {} has no "Games" field'.format(dev['Name']))
|
||||
print(' {} has no games'.format(dev['Name']))
|
||||
print('orphanes checked')
|
||||
|
||||
def check_for_missing_developers_in_entries(self):
|
||||
@ -209,7 +209,7 @@ class DevelopersMaintainer:
|
||||
if not self.entries:
|
||||
print('entries not yet loaded')
|
||||
return
|
||||
for dev in self.developers:
|
||||
for dev in self.developers.values():
|
||||
dev_name = dev['Name']
|
||||
for entry_name in dev['Games']:
|
||||
x = [x for x in self.entries if x['Title'] == entry_name]
|
||||
@ -222,6 +222,29 @@ class DevelopersMaintainer:
|
||||
print('Entry "{}" listed in developer "{}" but not listed in that entry'.format(entry_name, dev_name))
|
||||
print('missed developer checked')
|
||||
|
||||
def update_developers_from_entries(self):
|
||||
if not self.developers:
|
||||
print('developer not yet loaded')
|
||||
return
|
||||
if not self.entries:
|
||||
print('entries not yet loaded')
|
||||
return
|
||||
# loop over all developers and delete all games
|
||||
for dev in self.developers.values():
|
||||
dev['Games'] = []
|
||||
# loop over all entries and add this game to all developers of this game
|
||||
for entry in self.entries:
|
||||
entry_name = entry['Title']
|
||||
entry_devs = entry.get('Developer', [])
|
||||
for entry_dev in entry_devs:
|
||||
entry_dev = entry_dev.value # ignored the comment
|
||||
if entry_dev in self.developers:
|
||||
self.developers[entry_dev]['Games'].append(entry_name)
|
||||
else:
|
||||
# completely new developer
|
||||
self.developers[entry_dev] = {'Name': entry_dev, 'Games': entry_name}
|
||||
print('developers updated')
|
||||
|
||||
def read_entries(self):
|
||||
self.entries = osg.read_entries()
|
||||
print('{} entries read'.format(len(self.entries)))
|
||||
@ -237,6 +260,7 @@ if __name__ == "__main__":
|
||||
'Check for duplicates': m.check_for_duplicates,
|
||||
'Check for orphans': m.check_for_orphans,
|
||||
'Check for games in developers not listed': m.check_for_missing_developers_in_entries,
|
||||
'Update developers from entries': m.update_developers_from_entries,
|
||||
'Read entries': m.read_entries
|
||||
}
|
||||
|
||||
|
@ -35,12 +35,14 @@ generic_comment_string = '[comment]: # (partly autogenerated content, edit with
|
||||
# these fields have to be present in each entry (in this order)
|
||||
essential_fields = ('File', 'Title', 'Home', 'State', 'Keywords', 'Code repository', 'Code language', 'Code license')
|
||||
|
||||
# only these fields can be used currently (in this order)
|
||||
valid_fields = (
|
||||
'File', 'Title', 'Home', 'Media', 'Inspirations', 'State', 'Play', 'Download', 'Platform', 'Keywords', 'Code repository', 'Code language',
|
||||
'Code license', 'Code dependencies', 'Assets license', 'Developer', 'Note', 'Building')
|
||||
valid_properties = ('Home', 'Media', 'Inspirations', 'State', 'Play', 'Download', 'Platform', 'Keywords', 'Code repository', 'Code language',
|
||||
'Code license', 'Code dependencies', 'Assets license', 'Developer')
|
||||
|
||||
valid_building_fields = ('Build system', 'Build instructions')
|
||||
# only these fields can be used currently (in this order)
|
||||
valid_fields = ('File', 'Title') + valid_properties + ('Note', 'Building')
|
||||
|
||||
valid_building_properties = ('Build system', 'Build instructions')
|
||||
valid_building_fields = valid_building_properties + ('Note',)
|
||||
|
||||
# these are the only valid platforms currently (and must be given in this order)
|
||||
valid_platforms = ('Windows', 'Linux', 'macOS', 'Android', 'iOS', 'Web')
|
||||
|
@ -326,6 +326,9 @@ def read_developers():
|
||||
if any(not (x.startswith('http://') or x.startswith('https://')) for x in content):
|
||||
raise RuntimeError('Invalid URL in field "{}" in developer {}.'.format(field, dev['Name']))
|
||||
|
||||
# convert to dictionary
|
||||
developers = {x['Name']: x for x in developers}
|
||||
|
||||
return developers
|
||||
|
||||
|
||||
@ -334,6 +337,9 @@ def write_developers(developers):
|
||||
|
||||
:return:
|
||||
"""
|
||||
# convert dictionary to list
|
||||
developers = list(developers.values())
|
||||
|
||||
# comment
|
||||
content = '{}\n'.format(generic_comment_string)
|
||||
|
||||
@ -517,7 +523,23 @@ def check_and_process_entry(entry):
|
||||
# check for essential fields
|
||||
for field in essential_fields:
|
||||
if field not in entry:
|
||||
message += 'essential property "{}" missing\n'.format(field)
|
||||
message += 'Essential property "{}" missing\n'.format(field)
|
||||
|
||||
# now the same treatment for building
|
||||
building = entry['Building']
|
||||
d = {}
|
||||
for field, value in building:
|
||||
if field in d:
|
||||
message += 'Field "{}" appears twice\n'.format(field)
|
||||
d[field] = value
|
||||
building = d
|
||||
|
||||
# check valid fields TODO should also check order
|
||||
for field in building.keys():
|
||||
if field not in valid_building_fields:
|
||||
message += 'Building field "{}" invalid\n'.format(field)
|
||||
entry['Building'] = building
|
||||
|
||||
|
||||
# check canonical file name
|
||||
file = entry['File']
|
||||
@ -551,7 +573,7 @@ def write_entry(entry):
|
||||
# TODO check entry
|
||||
|
||||
# get path
|
||||
entry_path = os.path.join(entries_path, entry['file'])
|
||||
entry_path = os.path.join(entries_path, entry['File'])
|
||||
|
||||
# create output content
|
||||
content = create_entry_content(entry)
|
||||
@ -571,10 +593,11 @@ def create_entry_content(entry):
|
||||
content = '# {}\n\n'.format(entry['Title'])
|
||||
|
||||
# now properties in the recommended order
|
||||
for field in valid_fields:
|
||||
for field in valid_properties:
|
||||
if field in entry:
|
||||
c = entry[field]
|
||||
c = ['"{}"'.format(x) if ',' in x else x for x in c]
|
||||
c = [str(x) for x in c]
|
||||
content += '- {}: {}\n'.format(field, ', '.join(c))
|
||||
content += '\n'
|
||||
|
||||
@ -587,12 +610,15 @@ def create_entry_content(entry):
|
||||
|
||||
# building properties if present
|
||||
has_properties = False
|
||||
for field in valid_building_fields:
|
||||
for field in valid_building_properties:
|
||||
if field in entry['Building']:
|
||||
if not has_properties:
|
||||
has_properties = True
|
||||
content += '\n'
|
||||
content += '- {}: {}\n'.format(field, ', '.join(entry['Building'][field]))
|
||||
c = entry['Building'][field]
|
||||
c = ['"{}"'.format(x) if ',' in x else x for x in c]
|
||||
c = [str(x) for x in c]
|
||||
content += '- {}: {}\n'.format(field, ', '.join(c))
|
||||
|
||||
# if there is a note, insert it
|
||||
if 'Note' in entry['Building']:
|
||||
|
@ -121,7 +121,6 @@ class ValueWithComment:
|
||||
else:
|
||||
return '{}'.format(self.value)
|
||||
|
||||
|
||||
def parse(parser, transformer, content):
|
||||
tree = parser.parse(content)
|
||||
value = transformer.transform(tree)
|
||||
|
@ -1,5 +1,5 @@
|
||||
[comment]: # (partly autogenerated content, edit with care, read the manual before)
|
||||
# Developer [369]
|
||||
# Developer [378]
|
||||
|
||||
## Akira Higuchi [1]
|
||||
|
||||
@ -46,6 +46,10 @@
|
||||
|
||||
- Games: Maxit
|
||||
|
||||
## Amer Koleci [7]
|
||||
|
||||
- Games: Vortice
|
||||
|
||||
## Anders Svensson [1]
|
||||
|
||||
- Games: Alex the Allegator 4
|
||||
@ -87,6 +91,10 @@
|
||||
- Games: Advanced Strategic Command
|
||||
- Contact: armin906@SF
|
||||
|
||||
## Armin Rigo [18]
|
||||
|
||||
- Games: The Bub's Brothers
|
||||
|
||||
## Arne Reiners [1]
|
||||
|
||||
- Games: GL-117
|
||||
@ -184,6 +192,10 @@
|
||||
- Games: Advanced Strategic Command
|
||||
- Contact: Ed-von-Schleck@GH
|
||||
|
||||
## Chua Kong Sian [9]
|
||||
|
||||
- Games: GNU Chess
|
||||
|
||||
## Chuck Simmons [1]
|
||||
|
||||
- Games: VMS Empire
|
||||
@ -779,6 +791,10 @@
|
||||
|
||||
- Games: Trip on the Funny Boat
|
||||
|
||||
## Kriss [8]
|
||||
|
||||
- Games: GameCake
|
||||
|
||||
## krys [1]
|
||||
|
||||
- Games: Krystal Drop
|
||||
@ -848,6 +864,10 @@
|
||||
|
||||
- Games: Tactics Squad
|
||||
|
||||
## Lukas Geyer [9]
|
||||
|
||||
- Games: GNU Chess
|
||||
|
||||
## Lukas Löhrer [1]
|
||||
|
||||
- Games: Amphetamine
|
||||
@ -997,6 +1017,10 @@
|
||||
|
||||
- Games: GJID
|
||||
|
||||
## Mike Strobel [9]
|
||||
|
||||
- Games: Supremacy
|
||||
|
||||
## Mikey Lubker [1]
|
||||
|
||||
- Games: Snowballz
|
||||
@ -1353,6 +1377,10 @@
|
||||
|
||||
- Games: Simon Tatham's Portable Puzzle Collection
|
||||
|
||||
## Simon Waters [9]
|
||||
|
||||
- Games: GNU Chess
|
||||
|
||||
## Sixth Floor Labs [1]
|
||||
|
||||
- Games: Project Alexandria
|
||||
@ -1415,6 +1443,10 @@
|
||||
|
||||
- Games: Blinken
|
||||
|
||||
## Stuart Cracraft [9]
|
||||
|
||||
- Games: GNU Chess
|
||||
|
||||
## Sylvain Beucler [1]
|
||||
|
||||
- Games: GNU FreeDink
|
||||
@ -1578,3 +1610,7 @@
|
||||
|
||||
- Games: Necklace of the Eye
|
||||
|
||||
## Андрей Питько [13]
|
||||
|
||||
- Games: Wizards Magic
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user