synchronized developers and entries

This commit is contained in:
Trilarion 2020-09-07 16:39:47 +02:00
parent 8a08425e09
commit 625871062f
5 changed files with 103 additions and 16 deletions

View File

@ -186,7 +186,7 @@ class DevelopersMaintainer:
if not self.developers: if not self.developers:
print('developers not yet loaded') print('developers not yet loaded')
return return
developer_names = [x['Name'] for x in self.developers] developer_names = list(self.developers.keys())
for index, name in enumerate(developer_names): for index, name in enumerate(developer_names):
for other_name in developer_names[index + 1:]: for other_name in developer_names[index + 1:]:
if osg.name_similarity(name, other_name) > 0.8: if osg.name_similarity(name, other_name) > 0.8:
@ -197,9 +197,9 @@ class DevelopersMaintainer:
if not self.developers: if not self.developers:
print('developers not yet loaded') print('developers not yet loaded')
return return
for dev in self.developers: for dev in self.developers.values():
if not dev['Games']: if not dev['Games']:
print(' {} has no "Games" field'.format(dev['Name'])) print(' {} has no games'.format(dev['Name']))
print('orphanes checked') print('orphanes checked')
def check_for_missing_developers_in_entries(self): def check_for_missing_developers_in_entries(self):
@ -209,7 +209,7 @@ class DevelopersMaintainer:
if not self.entries: if not self.entries:
print('entries not yet loaded') print('entries not yet loaded')
return return
for dev in self.developers: for dev in self.developers.values():
dev_name = dev['Name'] dev_name = dev['Name']
for entry_name in dev['Games']: for entry_name in dev['Games']:
x = [x for x in self.entries if x['Title'] == entry_name] 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('Entry "{}" listed in developer "{}" but not listed in that entry'.format(entry_name, dev_name))
print('missed developer checked') 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): def read_entries(self):
self.entries = osg.read_entries() self.entries = osg.read_entries()
print('{} entries read'.format(len(self.entries))) print('{} entries read'.format(len(self.entries)))
@ -237,6 +260,7 @@ if __name__ == "__main__":
'Check for duplicates': m.check_for_duplicates, 'Check for duplicates': m.check_for_duplicates,
'Check for orphans': m.check_for_orphans, 'Check for orphans': m.check_for_orphans,
'Check for games in developers not listed': m.check_for_missing_developers_in_entries, '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 'Read entries': m.read_entries
} }

View File

@ -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) # 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') essential_fields = ('File', 'Title', 'Home', 'State', 'Keywords', 'Code repository', 'Code language', 'Code license')
# only these fields can be used currently (in this order) valid_properties = ('Home', 'Media', 'Inspirations', 'State', 'Play', 'Download', 'Platform', 'Keywords', 'Code repository', 'Code language',
valid_fields = ( 'Code license', 'Code dependencies', 'Assets license', 'Developer')
'File', 'Title', 'Home', 'Media', 'Inspirations', 'State', 'Play', 'Download', 'Platform', 'Keywords', 'Code repository', 'Code language',
'Code license', 'Code dependencies', 'Assets license', 'Developer', 'Note', 'Building')
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) # these are the only valid platforms currently (and must be given in this order)
valid_platforms = ('Windows', 'Linux', 'macOS', 'Android', 'iOS', 'Web') valid_platforms = ('Windows', 'Linux', 'macOS', 'Android', 'iOS', 'Web')

View File

@ -326,6 +326,9 @@ def read_developers():
if any(not (x.startswith('http://') or x.startswith('https://')) for x in content): 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'])) 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 return developers
@ -334,6 +337,9 @@ def write_developers(developers):
:return: :return:
""" """
# convert dictionary to list
developers = list(developers.values())
# comment # comment
content = '{}\n'.format(generic_comment_string) content = '{}\n'.format(generic_comment_string)
@ -517,7 +523,23 @@ def check_and_process_entry(entry):
# check for essential fields # check for essential fields
for field in essential_fields: for field in essential_fields:
if field not in entry: 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 # check canonical file name
file = entry['File'] file = entry['File']
@ -551,7 +573,7 @@ def write_entry(entry):
# TODO check entry # TODO check entry
# get path # get path
entry_path = os.path.join(entries_path, entry['file']) entry_path = os.path.join(entries_path, entry['File'])
# create output content # create output content
content = create_entry_content(entry) content = create_entry_content(entry)
@ -571,10 +593,11 @@ def create_entry_content(entry):
content = '# {}\n\n'.format(entry['Title']) content = '# {}\n\n'.format(entry['Title'])
# now properties in the recommended order # now properties in the recommended order
for field in valid_fields: for field in valid_properties:
if field in entry: if field in entry:
c = entry[field] c = entry[field]
c = ['"{}"'.format(x) if ',' in x else x for x in c] 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'.format(field, ', '.join(c))
content += '\n' content += '\n'
@ -587,12 +610,15 @@ def create_entry_content(entry):
# building properties if present # building properties if present
has_properties = False has_properties = False
for field in valid_building_fields: for field in valid_building_properties:
if field in entry['Building']: if field in entry['Building']:
if not has_properties: if not has_properties:
has_properties = True has_properties = True
content += '\n' 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 there is a note, insert it
if 'Note' in entry['Building']: if 'Note' in entry['Building']:

View File

@ -121,7 +121,6 @@ class ValueWithComment:
else: else:
return '{}'.format(self.value) return '{}'.format(self.value)
def parse(parser, transformer, content): def parse(parser, transformer, content):
tree = parser.parse(content) tree = parser.parse(content)
value = transformer.transform(tree) value = transformer.transform(tree)

View File

@ -1,5 +1,5 @@
[comment]: # (partly autogenerated content, edit with care, read the manual before) [comment]: # (partly autogenerated content, edit with care, read the manual before)
# Developer [369] # Developer [378]
## Akira Higuchi [1] ## Akira Higuchi [1]
@ -46,6 +46,10 @@
- Games: Maxit - Games: Maxit
## Amer Koleci [7]
- Games: Vortice
## Anders Svensson [1] ## Anders Svensson [1]
- Games: Alex the Allegator 4 - Games: Alex the Allegator 4
@ -87,6 +91,10 @@
- Games: Advanced Strategic Command - Games: Advanced Strategic Command
- Contact: armin906@SF - Contact: armin906@SF
## Armin Rigo [18]
- Games: The Bub's Brothers
## Arne Reiners [1] ## Arne Reiners [1]
- Games: GL-117 - Games: GL-117
@ -184,6 +192,10 @@
- Games: Advanced Strategic Command - Games: Advanced Strategic Command
- Contact: Ed-von-Schleck@GH - Contact: Ed-von-Schleck@GH
## Chua Kong Sian [9]
- Games: GNU Chess
## Chuck Simmons [1] ## Chuck Simmons [1]
- Games: VMS Empire - Games: VMS Empire
@ -779,6 +791,10 @@
- Games: Trip on the Funny Boat - Games: Trip on the Funny Boat
## Kriss [8]
- Games: GameCake
## krys [1] ## krys [1]
- Games: Krystal Drop - Games: Krystal Drop
@ -848,6 +864,10 @@
- Games: Tactics Squad - Games: Tactics Squad
## Lukas Geyer [9]
- Games: GNU Chess
## Lukas Löhrer [1] ## Lukas Löhrer [1]
- Games: Amphetamine - Games: Amphetamine
@ -997,6 +1017,10 @@
- Games: GJID - Games: GJID
## Mike Strobel [9]
- Games: Supremacy
## Mikey Lubker [1] ## Mikey Lubker [1]
- Games: Snowballz - Games: Snowballz
@ -1353,6 +1377,10 @@
- Games: Simon Tatham's Portable Puzzle Collection - Games: Simon Tatham's Portable Puzzle Collection
## Simon Waters [9]
- Games: GNU Chess
## Sixth Floor Labs [1] ## Sixth Floor Labs [1]
- Games: Project Alexandria - Games: Project Alexandria
@ -1415,6 +1443,10 @@
- Games: Blinken - Games: Blinken
## Stuart Cracraft [9]
- Games: GNU Chess
## Sylvain Beucler [1] ## Sylvain Beucler [1]
- Games: GNU FreeDink - Games: GNU FreeDink
@ -1578,3 +1610,7 @@
- Games: Necklace of the Eye - Games: Necklace of the Eye
## Андрей Питько [13]
- Games: Wizards Magic