Refactored storage of credits data

* Replaced use of a config with data structs.
* Moved [about] sorting to the parsing stage instead of handling it in the End Credits dialog.

This improves on my refactoring work here from 2016 (476027f239).
This commit is contained in:
Charles Dang 2018-03-04 02:06:37 +11:00
parent 1a3a28c59c
commit ec34ed950d
3 changed files with 135 additions and 79 deletions

View file

@ -15,6 +15,7 @@
#include "about.hpp"
#include "config.hpp"
#include "gettext.hpp"
#include "serialization/string_utils.hpp"
#include <map>
@ -25,26 +26,13 @@
*/
namespace about
{
static config about_list;
static std::map<std::string, std::vector<std::string>> images;
static std::vector<std::string> images_default;
const config& get_about_config()
namespace
{
return about_list;
}
credits_data parsed_credits_data;
std::map<std::string, std::vector<std::string>> images_campaigns;
std::vector<std::string> images_general;
std::vector<std::string> get_background_images(const std::string& campaign)
{
if(!campaign.empty() && !images[campaign].empty()){
return images[campaign];
}
return images_default;
}
static void gather_images(const config& from, std::vector<std::string>& to)
void gather_images(const config& from, std::vector<std::string>& to)
{
const auto& im = utils::parenthetical_split(from["images"], ',');
if(!im.empty()) {
@ -52,50 +40,110 @@ static void gather_images(const config& from, std::vector<std::string>& to)
}
}
void set_about(const config &cfg)
} // end anon namespace
credits_group::credits_group(const config& cfg, bool is_campaign_credits)
: sections()
, id()
, header()
{
about_list.clear();
if(is_campaign_credits) {
id = cfg["id"].str();
header = cfg["name"].t_str();
}
images.clear();
images_default.clear();
sections.reserve(cfg.child_count("about"));
for(const config& group : cfg.child_range("credits_group")) {
if(!group.has_child("about")) {
for(const config& about : cfg.child_range("about")) {
if(!about.has_child("entry")) {
continue;
}
about_list.add_child("credits_group", group);
gather_images(group, images_default);
for(const config& about : group.child_range("about")) {
gather_images(about, images_default);
sections.emplace_back(about);
if(is_campaign_credits) {
gather_images(about, images_campaigns[id]);
} else {
gather_images(about, images_general);
}
}
if(cfg["sort"].to_bool(false)) {
std::sort(sections.begin(), sections.end());
}
}
credits_group::about_group::about_group(const config& cfg)
: names()
, title(cfg["title"].t_str())
{
names.reserve(cfg.child_count("entry"));
for(const config& entry : cfg.child_range("entry")) {
names.push_back(entry["name"].str());
}
}
bool credits_group::about_group::operator<(const about_group& o)
{
return translation::compare(title.str(), o.title.str()) < 0;
}
const credits_data& get_credits_data()
{
return parsed_credits_data;
}
std::vector<std::string> get_background_images(const std::string& campaign)
{
if(!campaign.empty() && !images_campaigns[campaign].empty()){
return images_campaigns[campaign];
}
return images_general;
}
void set_about(const config& cfg)
{
parsed_credits_data.clear();
// TODO: should we reserve space in parsed_credits_data here?
images_campaigns.clear();
images_general.clear();
//
// Parse all [credits_group] tags
//
for(const config& group : cfg.child_range("credits_group")) {
if(group.has_child("about")) {
parsed_credits_data.emplace_back(group, false);
// Not in the credits_group since we don't want to inadvertently
// pick up images from campaigns.
gather_images(group, images_general);
}
}
//
// Parse all toplevel [about] tags.
//
config misc;
for(const config& about : cfg.child_range("about")) {
misc.add_child("about", about);
gather_images(about, images_default);
}
if(!misc.empty()) {
about_list.add_child("credits_group", std::move(misc));
parsed_credits_data.emplace_back(misc, false);
}
//
// Parse all campaign [about] tags.
//
for(const config& campaign : cfg.child_range("campaign")) {
if(!campaign.has_child("about")) {
continue;
if(campaign.has_child("about")) {
parsed_credits_data.emplace_back(campaign, true);
}
const std::string& id = campaign["id"];
config temp;
temp["title"] = campaign["name"];
temp["id"] = id;
for(const config& about : campaign.child_range("about")) {
temp.add_child("about", about);
gather_images(about, images[id]);
}
about_list.add_child("credits_group", std::move(temp));
}
}

View file

@ -14,18 +14,48 @@
#pragma once
class config;
#include "tstring.hpp"
#include <vector>
#include <string>
class config;
namespace about
{
struct credits_group
{
struct about_group
{
explicit about_group(const config& cfg);
/** Contributor names. */
std::vector<std::string> names;
/** The section title. */
t_string title;
bool operator<(const about_group& o);
};
credits_group(const config& cfg, bool is_campaign_credits);
/** The group's sub-groups. Corresponds to each [about] tag .*/
std::vector<about_group> sections;
/** Optional group ID. Currently only used for identifying campaigns. */
std::string id;
/** Optional group tite. Currently only used for identifying campaigns. */
t_string header;
};
using credits_data = std::vector<credits_group>;
/**
* General getter methods for the credits config and image lists by campaign id
*/
const config& get_about_config();
const credits_data& get_credits_data();
std::vector<std::string> get_background_images(const std::string& campaign);

View file

@ -47,19 +47,6 @@ end_credits::end_credits(const std::string& campaign)
{
}
static void parse_about_tag(const config& cfg, std::stringstream& ss)
{
if(!cfg.has_child("entry")) {
return;
}
ss << "\n" << "<span size='x-large'>" << cfg["title"] << "</span>" << "\n";
for(const auto& entry : cfg.child_range("entry")) {
ss << entry["name"] << "\n";
}
}
void end_credits::pre_show(window& window)
{
window.set_callback_next_draw([this]()
@ -75,28 +62,19 @@ void end_credits::pre_show(window& window)
std::stringstream ss;
std::stringstream focus_ss;
const config& credits_config = about::get_about_config();
for(const auto& group : credits_config.child_range("credits_group")) {
std::stringstream& group_stream = (group["id"] == focus_on_) ? focus_ss : ss;
for(const about::credits_group& group : about::get_credits_data()) {
std::stringstream& group_stream = (group.id == focus_on_) ? focus_ss : ss;
group_stream << "\n";
if(group.has_attribute("title")) {
group_stream << "<span size='xx-large'>" << group["title"] << "</span>" << "\n";
if(!group.header.empty()) {
group_stream << "<span size='xx-large'>" << group.header << "</span>" << "\n";
}
if(group["sort"].to_bool(false)) {
auto sections = group.child_range("about");
std::vector<config> sorted(sections.begin(), sections.end());
std::sort(sorted.begin(), sorted.end(), [](const config& entry1, const config& entry2) {
return translation::compare(entry1["title"].str(), entry2["title"].str()) < 0;
});
for(const auto& about : sorted) {
parse_about_tag(about, group_stream);
}
} else {
for(const auto& about : group.child_range("about")) {
parse_about_tag(about, group_stream);
for(const about::credits_group::about_group& about : group.sections) {
group_stream << "\n" << "<span size='x-large'>" << about.title << "</span>" << "\n";
for(const std::string& entry : about.names) {
group_stream << entry << "\n";
}
}
}