Skip to content

Commit

Permalink
Refactored storage of credits data
Browse files Browse the repository at this point in the history
* 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 (476027f).
  • Loading branch information
Vultraz committed Mar 3, 2018
1 parent 1a3a28c commit ec34ed9
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 75 deletions.
130 changes: 89 additions & 41 deletions src/about.cpp
Expand Up @@ -15,6 +15,7 @@
#include "about.hpp"

#include "config.hpp"
#include "gettext.hpp"
#include "serialization/string_utils.hpp"

#include <map>
Expand All @@ -25,77 +26,124 @@
*/
namespace about
{
namespace
{
credits_data parsed_credits_data;
std::map<std::string, std::vector<std::string>> images_campaigns;
std::vector<std::string> images_general;

static config about_list;
static std::map<std::string, std::vector<std::string>> images;
static std::vector<std::string> images_default;
void gather_images(const config& from, std::vector<std::string>& to)
{
const auto& im = utils::parenthetical_split(from["images"], ',');
if(!im.empty()) {
to.insert(to.end(), im.begin(), im.end());
}
}

} // end anon namespace

const config& get_about_config()
credits_group::credits_group(const config& cfg, bool is_campaign_credits)
: sections()
, id()
, header()
{
return about_list;
if(is_campaign_credits) {
id = cfg["id"].str();
header = cfg["name"].t_str();
}

sections.reserve(cfg.child_count("about"));

for(const config& about : cfg.child_range("about")) {
if(!about.has_child("entry")) {
continue;
}

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());
}
}

std::vector<std::string> get_background_images(const std::string& campaign)
credits_group::about_group::about_group(const config& cfg)
: names()
, title(cfg["title"].t_str())
{
if(!campaign.empty() && !images[campaign].empty()){
return images[campaign];
names.reserve(cfg.child_count("entry"));

for(const config& entry : cfg.child_range("entry")) {
names.push_back(entry["name"].str());
}
}

return images_default;
bool credits_group::about_group::operator<(const about_group& o)
{
return translation::compare(title.str(), o.title.str()) < 0;
}

static void gather_images(const config& from, std::vector<std::string>& to)
const credits_data& get_credits_data()
{
const auto& im = utils::parenthetical_split(from["images"], ',');
if(!im.empty()) {
to.insert(to.end(), im.begin(), im.end());
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)
void set_about(const config& cfg)
{
about_list.clear();
parsed_credits_data.clear();

// TODO: should we reserve space in parsed_credits_data here?

images.clear();
images_default.clear();
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")) {
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);
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));
}
}

Expand Down
34 changes: 32 additions & 2 deletions src/about.hpp
Expand Up @@ -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);

Expand Down
42 changes: 10 additions & 32 deletions src/gui/dialogs/end_credits.cpp
Expand Up @@ -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]()
Expand All @@ -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";
}
}
}
Expand Down

0 comments on commit ec34ed9

Please sign in to comment.