diff --git a/code/backlog.txt b/code/backlog.txt index 1cef926c..8d55287e 100644 --- a/code/backlog.txt +++ b/code/backlog.txt @@ -98,4 +98,5 @@ https://www.seul.org/~grumbel/tmp/clanlib/games.html https://www.tapatalk.com/groups/imperilist/ https://www.wurfelengine.net/ https://zdoom.org/downloads (gzdoom, lzdoom) -https://zope.readthedocs.io/en/latest/ \ No newline at end of file +https://zope.readthedocs.io/en/latest/ +https://github.com/loudsmilestudios/TetraForce \ No newline at end of file diff --git a/code/html/base.jinja b/code/html/base.jinja index 214d0bf9..cab7b545 100644 --- a/code/html/base.jinja +++ b/code/html/base.jinja @@ -38,7 +38,7 @@ {{ macros.render_icon({'class':'wrench'}) }}Frameworks/Tools {{ macros.render_icon({'class':'users'}) }}Developers {{ macros.render_icon({'class':'bulb'}) }}Inspirations - {{ macros.render_icon({'class':'stats-dots'}) }}Statistics + {{ macros.render_icon({'class':'stats-dots'}) }}Statistics {{ macros.render_icon({'class':'pencil'}) }}Contribute {{ macros.render_icon({'class':'github'}) }}On GitHub diff --git a/code/html/generate_static_website.py b/code/html/generate_static_website.py index a86eb8fd..1f6b49fd 100644 --- a/code/html/generate_static_website.py +++ b/code/html/generate_static_website.py @@ -10,6 +10,12 @@ Sitemaps is not needed, only for large projects with lots of JavaScript und many # TODO most people only come to the main page, put more information there (direct links to genres, ...) # TODO put more explanations on the category pages and the categories (number and short sentences) +# TODO text description automaticall generated from keywords, state, and technical informations for example: First-person action shooter written in C++, inspired by ... but inactive for 7 years. + +# TODO statistics should have disclaimer (warning or info box) about accuracy with link to contribute guidelines + +# TODO game move developer to technical information and maybe rename technical information to details + # TODO game engines should be sorted with frameworks/tools, not with games (they aren't games or are they?) # TODO if the only change is a change in last updated, do not change it (we can probably check with git diff for it) or checksums @@ -23,6 +29,8 @@ Sitemaps is not needed, only for large projects with lots of JavaScript und many # TODO everywhere: singular, plural (game, entries, items) +# TODO games: platform icons and mature, state larger (but maybe not on mobile) + # TODO statistics: better and more statistics with links where possible # TODO statistics: with nice graphics (pie charts in SVG) with matplotlib # TODO statistics: get it from common statistics generator @@ -74,6 +82,8 @@ Sitemaps is not needed, only for large projects with lots of JavaScript und many # TODO add dynamic table (what to include) +# TODO meta titles for all pages, make them nice because they appear in search results! (https://www.contentpowered.com/blog/good-ctr-search-console/) + import os import shutil import math @@ -100,12 +110,14 @@ games_path = ['games'] non_games_path = ['frameworks'] inspirations_path = ['inspirations'] developers_path = ['developers'] +statistics_path = ['statistics'] # derived paths games_index_path = games_path + ['index.html'] non_games_index_path = non_games_path + ['index.html'] inspirations_index_path = inspirations_path + ['index.html'] developers_index_path = developers_path + ['index.html'] +statistics_index_path = statistics_path + ['index.html'] games_by_language_path = games_path + ['languages.html'] games_by_genres_path = games_path + ['genres.html'] @@ -548,6 +560,20 @@ def make_tags(entries): } +def make_detail(summary, detail): + """ + + :param summary: + :param detail: + :return: + """ + return { + 'type': 'detail', + 'summary': summary, + 'detail': detail + } + + def developer_profile_link(link): """ Creates links to developer profiles. @@ -637,10 +663,12 @@ def create_keyword_tag(keyword): else: url = games_by_genres_path.copy() url[-1] += '#{}'.format(keyword) - if keyword.capitalize() in genre_icon_map: - return make_url(url, [make_icon(genre_icon_map[keyword.capitalize()]), make_text(keyword)], '{} games'.format(keyword), 'tag is-info') - else: - return make_url(url, make_text(keyword), '{} games'.format(keyword), 'tag is-info') + # TODO are icons looking good in the keyword tags (I somehow doubt it), maybe put them separately somewhere? + #if keyword.capitalize() in genre_icon_map: + # return make_url(url, [make_icon(genre_icon_map[keyword.capitalize()]), make_text(keyword)], '{} games'.format(keyword), 'tag is-info') + #else: + # return make_url(url, make_text(keyword), '{} games'.format(keyword), 'tag is-info') + return make_url(url, make_text(keyword), '{} games'.format(keyword), 'tag is-info') else: return make_text(keyword, 'tag is-light') @@ -698,10 +726,7 @@ def convert_entries(entries, inspirations, developers): if field == 'Inspiration': e = [make_url(inspirations_references[x], make_text(x)) for x in e] elif field == 'Developer': - if len(e) > 10: # many devs, print smaller - e = [make_url(developer_references[x], make_text(x, 'is-size-7')) for x in e] - else: - e = [make_url(developer_references[x], make_text(x)) for x in e] + e = [make_url(developer_references[x], make_text(x)) for x in e] elif field in c.url_fields: e = [make_url(x, shortcut_url(x, name)) for x in e] else: @@ -777,7 +802,7 @@ def get_top50_games(games): for game in games: # get stars of repositories stars = 0 - for repo in game.get('Code repository', []): + for repo in game.get('Code repository', [])[:1]: # take at most one if isinstance(repo, osg_parse.Value): for c in repo.comment.split(','): c = c.strip() @@ -798,6 +823,25 @@ def get_top50_games(games): return top50_games +def add_screenshot_information(entries): + """ + + :param entries: + :return: + """ + # read screenshot information + overview = osg.read_screenshots_overview() + + # iterate over entries + for entry in entries: + # get screenshots entry + name = osg.canonical_name(entry['Title']) # TODO should be stored upon loading I guess + screenshots = overview.get(name, {}) + screenshots = [{'width': s[0], 'height': s[1], 'url': s[2], 'file': ['screenshots', '{}_{:02d}.jpg'.format(name, id)]} for id, s in screenshots.items()] + if screenshots: # TODO url None should be treated here or in the jinja template + entry['screenshots'] = screenshots + + def generate(entries, inspirations, developers): """ Regenerates the whole static website given an already imported set of entries, inspirations and developers. @@ -856,6 +900,12 @@ def generate(entries, inspirations, developers): utils.copy_tree(os.path.join(c.web_template_path, 'css'), c.web_css_path) utils.copy_tree(os.path.join(c.web_template_path, 'js'), c.web_js_path) + # copy screenshots path + files = [file for file in os.listdir(c.screenshots_path) if file.endswith('.jpg')] + os.makedirs(c.web_screenshots_path, exist_ok=True) + for file in files: + shutil.copyfile(os.path.join(c.screenshots_path, file), os.path.join(c.web_screenshots_path, file)) + # collage_image and google search console token and favicon.svg for file in ('collage_games.jpg', 'google1f8a3863114cbcb3.html', 'favicon.svg'): shutil.copyfile(os.path.join(c.web_template_path, file), os.path.join(c.web_path, file)) @@ -884,7 +934,8 @@ def generate(entries, inspirations, developers): template = environment.get_template('contribute.jinja') write(template.render(), ['contribute.html']) - # statistics page + # statistics page in statistics folder + base['url_to'] = partial(url_to, statistics_path) base['active_nav'] = 'statistics' # statistics preparation @@ -896,16 +947,17 @@ def generate(entries, inspirations, developers): # build-systems build_systems_stat = stat.get_build_systems(entries) - # TODO replace all entries < 10 with "others" - # TODO make Pie chart out of it + build_systems_stat = stat.truncate_stats(build_systems_stat, 10) + stat.export_pie_chart([stat for stat in build_systems_stat if stat[0] != 'N/A'], os.path.join(c.web_path, 'statistics', 'build_systems.svg')) section = { 'title': 'Build system', - 'items': ['{} ({})'.format(*item) for item in build_systems_stat] + 'items': ['{} ({})'.format(*item) for item in build_systems_stat], + 'chart': statistics_path + ['build_systems.svg'] } data['sections'].append(section) # render and write statistics page - write(template.render(data=data), ['statistics.html']) + write(template.render(data=data), statistics_index_path) # non-games folder base['url_to'] = partial(url_to, non_games_path) @@ -998,6 +1050,9 @@ def generate(entries, inspirations, developers): # top 50 games base['active_nav'] = ['filter', 'top50'] + # there are no other games coming afterwards, can actually number them + for index, game in enumerate(top50_games): + game['name'] = '{}. '.format(index+1) + game['name'] listing = { 'title': 'GitHub Stars Top 50', 'subtitle': '50 highest rated (by stars on Github) open source games in the database', @@ -1066,11 +1121,14 @@ if __name__ == "__main__": print('clean current static website') utils.recreate_directory(c.web_path) - # load entries, inspirations and developers and sort them + # load entries, inspirations and developers and sort them alphabetically print('load entries, inspirations and developers') entries = osg.read_entries() entries.sort(key=lambda x: str.casefold(x['Title'])) + # add screenshot information + add_screenshot_information(entries) + inspirations = osg.read_inspirations() inspirations = list(inspirations.values()) inspirations.sort(key=lambda x: str.casefold(x['Name'])) diff --git a/code/html/listing_entries.jinja b/code/html/listing_entries.jinja index 8f86d447..1a696ec1 100644 --- a/code/html/listing_entries.jinja +++ b/code/html/listing_entries.jinja @@ -23,15 +23,27 @@ {#- important fields in a certain order -#}
{{ section['title'] }}
+ {% if 'chart' in section %}The content (games descriptions) is licensed CC-0. Used icons are licensed under CC BY-SA 3.0 (Iconic or Linecons), CC0 1.0 (Simple Icons), CC BY 4.0 (Font Awesome or IcoMoon Free), CC BY-SA 4.0 (Entypo+) or Apache License 2.0 (Material Icons). - This website is built using Python, Lark, Jinja2 and Bulma. Last updated: 2021-10-05 11:16
+ This website is built using Python, Lark, Jinja2 and Bulma. Last updated: 2021-10-13 14:06