sql_importer_character.cpp (10402B)
1 #include "scraps/format/rags_sql/sql_importer_private.hpp" // IWYU pragma: associated 2 3 #include "scraps/format/rags_common/description.hpp" 4 #include "scraps/format/rags_sql/test_helper/sql_helper.hpp" 5 6 #include <libshit/char_utils.hpp> 7 #include <libshit/doctest.hpp> 8 #include <libshit/utils.hpp> 9 10 #define LIBSHIT_LOG_NAME "import" 11 #include <libshit/logger_helper.hpp> 12 13 namespace Scraps::Format::RagsSql 14 { 15 using namespace std::string_literals; 16 using namespace Libshit::NonowningStringLiterals; 17 TEST_SUITE_BEGIN("Scraps::Format::RagsSql"); 18 19 void Importer::ImportPlayer(Proto::Character::Builder player) 20 { 21 SCRAPS_FORMAT_SQL_SIMPLE_SELECT( 22 sql, "Player", SCRAPS_FORMAT_RAGS_PLAYER_MEMBERS 23 SCRAPS_FORMAT_RAGS_PLAYER_TO_GAME_MEMBERS); 24 25 sql.AssertHasRow(); 26 SCRAPS_FORMAT_RAGS_SQL_IMPORT(player, SCRAPS_FORMAT_RAGS_PLAYER_MEMBERS); 27 SCRAPS_FORMAT_RAGS_SQL_IMPORT(game, SCRAPS_FORMAT_RAGS_PLAYER_TO_GAME_MEMBERS); 28 sql.AssertNoRow(); 29 FinishPlayer(player); 30 31 auto act_count = sql.GetCount("PlayerActions"_ns); 32 auto acts = player.InitActions(act_count); 33 34 IdMap act_ids; 35 std::map<std::uint64_t, std::string> parent_ids; 36 37 sql.Query("SELECT [Data] FROM [PlayerActions];"_ns, 1); 38 for (std::uint32_t i = 0; i < act_count; ++i) 39 { 40 sql.AssertHasRow(); 41 42 auto doc = PrepareAction(sql.GetWString()); 43 ImportAction(acts[i], act_ids, parent_ids, *doc); 44 } 45 sql.AssertNoRow(); 46 47 for (std::uint32_t i = 0; i < act_count; ++i) 48 if (auto it = parent_ids.find(acts[i].GetId()); it != parent_ids.end()) 49 acts[i].SetParentId(FindId(act_ids, it->second, "action", "None")); 50 51 std::map<std::string, std::string, AsciiCaseLess> props_map; 52 sql.Query("SELECT [Name], [Value] FROM [PlayerProperties];", 2); 53 while (sql.HasRow()) 54 { 55 auto name = sql.GetWString(); 56 auto val = sql.GetWString(); 57 auto [it, inserted] = 58 props_map.try_emplace(Libshit::Move(name), Libshit::Move(val)); 59 if (!inserted) 60 WARN << "Duplicate property " << Libshit::Quoted(name) 61 << " in player, values " << Libshit::Quoted(it->second) << " vs " 62 << Libshit::Quoted(val) << ", latter ignored" << std::endl; 63 } 64 65 auto props = player.InitProperties(SCRAPS_CAPNP_LIST_LEN(props_map.size())); 66 std::uint32_t i = 0; 67 for (auto&& [k,v] : props_map) 68 { 69 props[i].SetName(sp.InternCopy(k)); 70 props[i].SetValue(sp.InternString(Libshit::Move(v))); 71 ++i; 72 } 73 } 74 75 void Importer::ImportCharacters() 76 { 77 NameSet id_set; 78 auto chars = game.InitCharacters( 79 SCRAPS_CAPNP_LIST_LEN(character_ids.size() + 1)); 80 ImportPlayer(chars[0]); 81 82 auto props = GetProperties("CharacterProperties", "Charname"); 83 84 SCRAPS_FORMAT_SQL_SIMPLE_SELECT( 85 sql, "Characters", SCRAPS_FORMAT_RAGS_CHARACTER_MEMBERS); 86 for (std::uint32_t i = 1, n = character_ids.size(); i < n; ++i) 87 { 88 sql.AssertHasRow(); 89 SCRAPS_FORMAT_RAGS_SQL_IMPORT( 90 chars[i], SCRAPS_FORMAT_RAGS_CHARACTER_MEMBERS); 91 92 chars[i].SetId(character_ids.at(sp.Get(chars[i].GetName()))); 93 ApplyProperties(props, chars[i], sp.Get(chars[i].GetName())); 94 } 95 sql.AssertNoRow(); 96 97 ImportActions( 98 chars, "CharacterActions", "Charname", "character", character_ids); 99 FinishProperties(props, "character"); 100 } 101 102 TEST_CASE("ImportCharacters") 103 { 104 using C = Memory::Cell; 105 TestHelper::TestSqls([](Sql& sql, Memory::DB& db) 106 { 107 db.tables["Player"] = { 108 { 109 { "Name", Memory::Type::NVARCHAR, 250 }, 110 { "Description", Memory::Type::NTEXT }, 111 { "StartingRoom", Memory::Type::NVARCHAR, 250 }, 112 { "PlayerGender", Memory::Type::INT }, 113 { "PromptForName", Memory::Type::BIT }, 114 { "PromptForGender", Memory::Type::BIT }, 115 { "PlayerPortrait", Memory::Type::NVARCHAR, 250 }, 116 { "EnforceWeight", Memory::Type::BIT }, 117 { "WeightLimit", Memory::Type::FLOAT }, 118 }, { 119 { C::Ntext("John"), C::Ntext("Description..."), 120 C::Ntext("00000000000000000000000000000123"), C::Int(1), 121 C::Bit(true), C::Bit(true), C::Ntext("media0"), C::Bit(true), 122 C::Float(3.14) }, 123 } 124 }; 125 db.tables["PlayerActions"] = { 126 { 127 { "Data", Memory::Type::NTEXT }, 128 }, { 129 // <x><Name>Test</Name></x> 130 { C::Ntext("GAAAAB+LCABKkRhgAgOzqbCz8UvMTbULSS0usdEHM230K+wAg3dN9RgAAAA=") }, 131 { C::Ntext("<x><Name>Test2</Name></x>") }, 132 } 133 }; 134 db.tables["PlayerProperties"] = { 135 { 136 { "Name", Memory::Type::NVARCHAR, 250 }, 137 { "Value", Memory::Type::NTEXT }, 138 }, { 139 { C::Ntext("xyz"), C::Ntext("abc") }, 140 { C::Ntext("abc"), C::Ntext("val") }, 141 { C::Ntext("abc"), C::Ntext("ignored") }, 142 } 143 }; 144 145 db.tables["Characters"] = { 146 { 147 { "Charname", Memory::Type::NVARCHAR, 250 }, 148 { "CharnameOverride", Memory::Type::NVARCHAR, 250 }, 149 { "CharGender", Memory::Type::INT }, 150 { "CurrentRoom", Memory::Type::NVARCHAR, 250 }, 151 { "Description", Memory::Type::NTEXT }, 152 { "AllowInventoryInteraction", Memory::Type::BIT }, 153 { "CharPortrait", Memory::Type::NVARCHAR, 250 }, 154 }, { 155 { C::Ntext("player"), C::Ntext("override"), C::Int(0), 156 C::Ntext("r00m"), C::Ntext("desc"), 157 C::Bit(true), C::Ntext("") }, 158 { C::Ntext("char1"), C::Ntext(""), C::Int(2), 159 C::Ntext(Uuid::VOID_ROOM_STR), C::Ntext("foofoofoo"), C::Bit(false), 160 C::Ntext("media1") }, 161 } 162 }; 163 db.tables["CharacterActions"] = { 164 { 165 { "Charname", Memory::Type::NVARCHAR, 250 }, 166 { "Data", Memory::Type::NTEXT }, 167 }, { 168 { C::Ntext("player"), 169 C::Ntext("GAAAAB+LCABKkRhgAgOzqbCz8UvMTbULSS0usdEHM230K+wAg3dN9RgAAAA=") }, 170 } 171 }; 172 db.tables["CharacterProperties"] = { 173 { 174 { "Charname", Memory::Type::NVARCHAR, 250 }, 175 { "Name", Memory::Type::NVARCHAR, 250 }, 176 { "Value", Memory::Type::NTEXT }, 177 }, { 178 { C::Ntext("char1"), C::Ntext("xyz"), C::Ntext("abc") }, 179 { C::Ntext("char1"), C::Ntext("abc"), C::Ntext("val") }, 180 { C::Ntext("char1"), C::Ntext("abc"), C::Ntext("ignored") }, 181 } 182 }; 183 184 Importer imp{sql}; 185 imp.file_ids = {{"media0", imp.GetId()}, {"media1", imp.GetId()}}; // 2-3 186 auto rid = imp.GetId(); // 4 187 imp.room_uuids = {{{0,0x123}, rid}}; 188 imp.room_ids = {{"r00m", rid}}; 189 imp.GenIds(imp.character_ids, "Characters", "Charname"); // 5-6 190 191 imp.ImportCharacters(); // player act: 7-8, chara act: 9 192 CHECK(imp.game.GetPromptName()); 193 CHECK(imp.game.GetPromptGender()); 194 195 auto chars = imp.game.GetCharacters(); 196 REQUIRE(chars.size() == 3); 197 CHECK(chars[0].GetId() == 1); 198 CHECK(imp.sp.Get(chars[0].GetName()) == "player_conflict0"); 199 CHECK(imp.sp.Get(chars[0].GetNameOverride()) == "John"); 200 CHECK(imp.sp.Get(chars[0].GetDescription()) == "Description..."); 201 CHECK(chars[0].GetGender() == Proto::Gender::FEMALE); 202 CHECK(chars[0].GetImageId() == 2); 203 CHECK(chars[0].GetRoomId() == 4); 204 CHECK(!chars[0].GetAllowInventoryInteraction()); 205 CHECK(chars[0].GetEnforceWeightLimit()); 206 CHECK(double(chars[0].GetWeightLimit()) == doctest::Approx(3.14)); 207 208 REQUIRE(chars[0].GetActions().size() == 2); 209 CHECK(chars[0].GetActions()[0].GetId() == 7); 210 CHECK(imp.sp.Get(chars[0].GetActions()[0].GetName()) == "Test"); 211 CHECK(chars[0].GetActions()[1].GetId() == 8); 212 CHECK(imp.sp.Get(chars[0].GetActions()[1].GetName()) == "Test2"); 213 214 REQUIRE(chars[0].GetProperties().size() == 2); 215 CHECK(imp.sp.Get(chars[0].GetProperties()[0].GetName()) == "abc"); 216 CHECK(imp.sp.Get(chars[0].GetProperties()[0].GetValue()) == "val"); 217 CHECK(imp.sp.Get(chars[0].GetProperties()[1].GetName()) == "xyz"); 218 CHECK(imp.sp.Get(chars[0].GetProperties()[1].GetValue()) == "abc"); 219 220 221 CHECK(chars[1].GetId() == 5); 222 CHECK(imp.sp.Get(chars[1].GetName()) == "player"); 223 CHECK(imp.sp.Get(chars[1].GetNameOverride()) == "override"); 224 CHECK(imp.sp.Get(chars[1].GetDescription()) == "desc"); 225 CHECK(chars[1].GetGender() == Proto::Gender::MALE); 226 CHECK(chars[1].GetImageId() == 0); 227 CHECK(chars[1].GetRoomId() == 4); 228 CHECK(chars[1].GetAllowInventoryInteraction()); 229 CHECK(!chars[1].GetEnforceWeightLimit()); 230 CHECK(chars[1].GetWeightLimit() == 0); 231 232 REQUIRE(chars[1].GetActions().size() == 1); 233 CHECK(chars[1].GetActions()[0].GetId() == 9); 234 CHECK(imp.sp.Get(chars[1].GetActions()[0].GetName()) == "Test"); 235 REQUIRE(chars[1].GetProperties().size() == 0); 236 237 238 CHECK(chars[2].GetId() == 6); 239 CHECK(imp.sp.Get(chars[2].GetName()) == "char1"); 240 CHECK(imp.sp.Get(chars[2].GetNameOverride()) == ""); 241 CHECK(imp.sp.Get(chars[2].GetDescription()) == "foofoofoo"); 242 CHECK(chars[2].GetGender() == Proto::Gender::OTHER); 243 CHECK(chars[2].GetImageId() == 3); 244 CHECK(chars[2].GetRoomId() == 0); 245 CHECK(!chars[2].GetAllowInventoryInteraction()); 246 CHECK(!chars[2].GetEnforceWeightLimit()); 247 CHECK(chars[2].GetWeightLimit() == 0); 248 249 REQUIRE(chars[2].GetActions().size() == 0); 250 REQUIRE(chars[2].GetProperties().size() == 2); 251 CHECK(imp.sp.Get(chars[2].GetProperties()[0].GetName()) == "abc"); 252 CHECK(imp.sp.Get(chars[2].GetProperties()[0].GetValue()) == "val"); 253 CHECK(imp.sp.Get(chars[2].GetProperties()[1].GetName()) == "xyz"); 254 CHECK(imp.sp.Get(chars[2].GetProperties()[1].GetValue()) == "abc"); 255 256 // sort chara 257 auto alpha = RagsCommon::SortOrder::ALPHA; 258 imp.FinishGame(alpha, alpha, alpha); 259 260 CHECK(chars[0].GetId() == 1); 261 CHECK(imp.sp.Get(chars[0].GetName()) == "player_conflict0"); 262 CHECK(imp.sp.Get(chars[0].GetNameOverride()) == "John"); 263 CHECK(chars[1].GetId() == 5); 264 CHECK(imp.sp.Get(chars[1].GetName()) == "char1"); 265 CHECK(imp.sp.Get(chars[1].GetNameOverride()) == ""); 266 CHECK(chars[2].GetId() == 6); 267 CHECK(imp.sp.Get(chars[2].GetName()) == "player"); 268 CHECK(imp.sp.Get(chars[2].GetNameOverride()) == "override"); 269 }); 270 } 271 272 TEST_SUITE_END(); 273 }