aboutsummaryrefslogtreecommitdiff
path: root/src/utils.h
blob: dea052b6b4363141b20299d5f87080dfac70b280 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#pragma once
#include "json.hpp"
#include "entry.h"
#include <string>
#include <vector>
#include <map>
#include <sstream>
#include <memory>
#include <stdexcept>
#include <filesystem>

namespace utils {
    nlohmann::json loadJson(const std::filesystem::path& path);

    // Recursively loads all .json files under directory
    // If called multiple times with same directory, returns a cached result.
    std::vector<nlohmann::json> loadAllJson(const std::string& directory);

    // looks up directory in settings. Returns element matching name.
    nlohmann::json loadJson(const std::string& type, const std::string& name);

    // goes through the available types and searches for the one matching name.
    nlohmann::json findByName(const std::string& name);

    void saveJson(const nlohmann::json& data, const std::filesystem::path& path);

    // converts in-place
    std::string lower(std::string& in);

    template<typename T> std::shared_ptr<T> instantiate(const std::filesystem::path& path) {
        std::shared_ptr<entry::Entry> ent;
        try {
            ent = entry::Entry::create(loadJson(path));
        } catch(std::exception& e) {
            if(std::filesystem::directory_entry(path).exists()) {
                throw std::runtime_error("Invalid json: " + path.string());
            } else {
                throw std::runtime_error("No such file nor directory: " + path.string());
            }
        }
        std::shared_ptr<T> t = std::dynamic_pointer_cast<T>(ent);
        if(! t) {
            throw std::runtime_error("Wrong instance type: " + ent->getType());
        }
        return t;
    }

    int parseInt(const std::string& s);

    template<typename S, typename D> std::shared_ptr<S> loadDFromJson(const nlohmann::json& data) {
        try {
            return std::shared_ptr<S>(new D(loadJson(data["type"], data["name"]), data));
        } catch(std::exception& e) {
            // Covers errors in building the creature or fs traversal.
            // Fall back on the data passed in.
            return std::shared_ptr<S>(new D(data, data));
        }
    }

    template<typename F, typename T> std::vector<std::shared_ptr<T>> castPtrs(std::vector<std::shared_ptr<F>> from) {
        std::vector<std::shared_ptr<T>> Ts;
        for(std::shared_ptr<F> f : from) {
            std::shared_ptr<T> t = dynamic_pointer_cast<T>(f);
            if(t) {
                Ts.push_back(t);
            }
        }
        return Ts;
    }


    template<typename Container> std::string join(Container parts, std::string joiner) {
        std::stringstream out;
        bool isFirst = true;
        for(auto p : parts) {
            if(! isFirst) {
                out << joiner;
            }
            isFirst = false;
            out << p;
        }
        return out.str();
    }

    const std::map<std::string, int> cpValue {
        {"cp", 1},
            {"sp", 10},
            {"ep", 50},
            {"gp", 100},
            {"pp", 1000}
    };

    // Accepts coins formatted "X Yp" where X is an integer and Y is any of c, s, e, g, p.
    int coins2copper(const std::string& coins);

    // Greedily selects highest coin values to minimize total number of coins
    // Returns a vector of pairs mapping coin type to coint
    std::vector<std::pair<std::string, int>> copper2coins(int coppers);

    std::string getCostString(int coppers);

    std::string toOrdinal(std::size_t number);

    template<typename T> std::vector<T> json2vec(const nlohmann::json& data) {
        using std::begin; using std::end;
        return std::vector<T>(begin(data), end(data));
    }

    template<typename T> std::vector<std::shared_ptr<T>> jsonList2ptrvec(const std::string& type, const std::vector<std::string>& names) {
        std::vector<std::shared_ptr<T>> ret;
        for(auto name : names) {
            auto j = utils::loadJson(type, name);
            ret.push_back(std::shared_ptr<T>(new T(j, j)));
        }
        return ret;
    }

    template<typename T> std::vector<std::shared_ptr<T>> json2ptrvec(const nlohmann::json& data) {
        std::vector<std::shared_ptr<T>> ret;
        for(nlohmann::json d : data) {
            ret.push_back(T::create(d));
        }
        return ret;
    }

    template<typename T> std::vector<nlohmann::json> ptrvec2json(std::vector<T> src) {
        std::vector<nlohmann::json> ret;
        for(T i : src) {
            ret.push_back(i->toJson());
        }
        return ret;
    }
}