PEBL 2.2
Psychology Experiment Building Language - Cross-platform psychological experiment development system
ScaleDefinition Class Reference

#include <ScaleDefinition.h>

Classes

struct  ValidationResult
 

Public Member Functions

 ScaleDefinition ()
 
 ~ScaleDefinition ()
 
bool SaveToFile (const std::string &jsonPath)
 
bool ExportToJSON (const std::string &definitionsPath, const std::string &translationsPath)
 
bool ExportToOSD (const std::string &outputDir)
 
bool LoadFromScalesDir (const std::string &basePath, const std::string &scaleCode)
 
bool IsSourceOSD () const
 
bool Validate (std::string &errorOutput)
 
ScaleInfoGetScaleInfo ()
 
std::map< std::string, ScaleParameter > & GetParameters ()
 
LikertOptionsGetLikertOptions ()
 
std::vector< ScaleQuestion > & GetQuestions ()
 
std::vector< ScaleDimension > & GetDimensions ()
 
std::map< std::string, DimensionScoring > & GetScoring ()
 
std::map< std::string, ComputedVariable > & GetComputed ()
 
ReportConfigGetReportConfig ()
 
DataOutputGetDataOutput ()
 
ScaleTranslationsGetTranslations ()
 
nlohmann::json & GetRawDefinition ()
 
const ScaleInfoGetScaleInfo () const
 
const std::map< std::string, ScaleParameter > & GetParameters () const
 
const LikertOptionsGetLikertOptions () const
 
const std::vector< ScaleQuestion > & GetQuestions () const
 
const std::vector< ScaleDimension > & GetDimensions () const
 
const std::map< std::string, DimensionScoring > & GetScoring () const
 
const std::map< std::string, ComputedVariable > & GetComputed () const
 
const ReportConfigGetReportConfig () const
 
const DataOutputGetDataOutput () const
 
const ScaleTranslationsGetTranslations () const
 
const nlohmann::json & GetRawDefinition () const
 
void AddQuestion (const ScaleQuestion &question)
 
void InsertQuestion (int index, const ScaleQuestion &question)
 
void RemoveQuestion (const std::string &questionID)
 
void MoveQuestion (int fromIndex, int toIndex)
 
ScaleQuestionGetQuestion (const std::string &questionID)
 
void AddDimension (const ScaleDimension &dimension)
 
void RemoveDimension (const std::string &dimensionID)
 
ScaleDimensionGetDimension (const std::string &dimensionID)
 
void AddTranslation (const std::string &language, const std::string &key, const std::string &value)
 
void RemoveTranslation (const std::string &language)
 
std::vector< std::string > GetAvailableLanguages () const
 
std::string GetTranslation (const std::string &language, const std::string &key) const
 
ValidationResult ValidateInternal () const
 
int GetDefaultRequired () const
 
void SetDefaultRequired (int val)
 
bool IsDirty () const
 
void SetDirty (bool dirty)
 

Static Public Member Functions

static std::shared_ptr< ScaleDefinitionCreateNew (const std::string &code)
 
static std::shared_ptr< ScaleDefinitionLoadFromFile (const std::string &jsonPath)
 
static std::shared_ptr< ScaleDefinitionLoadFromOSDFile (const std::string &osdPath)
 

Detailed Description

Definition at line 260 of file ScaleDefinition.h.

Constructor & Destructor Documentation

◆ ScaleDefinition()

ScaleDefinition::ScaleDefinition ( )

Definition at line 152 of file ScaleDefinition.cpp.

153 : mDefaultRequired(-1)
154 , mDirty(false)
155 , mSourceIsOSD(false)
156{
157 mDataOutput.individual_file = "{code}-{subnum}.csv";
158 mDataOutput.pooled_file = "{code}-pooled.csv";
159 mDataOutput.report_file = "{code}-report-{subnum}.html";
160}
std::string report_file
std::string pooled_file
std::string individual_file

References DataOutput::individual_file, DataOutput::pooled_file, and DataOutput::report_file.

◆ ~ScaleDefinition()

ScaleDefinition::~ScaleDefinition ( )

Definition at line 162 of file ScaleDefinition.cpp.

163{
164}

Member Function Documentation

◆ AddDimension()

void ScaleDefinition::AddDimension ( const ScaleDimension dimension)

Definition at line 1338 of file ScaleDefinition.cpp.

1339{
1340 mDimensions.push_back(dimension);
1341 mDirty = true;
1342}

◆ AddQuestion()

void ScaleDefinition::AddQuestion ( const ScaleQuestion question)

Definition at line 1286 of file ScaleDefinition.cpp.

1287{
1288 mQuestions.push_back(question);
1289 mDirty = true;
1290}

◆ AddTranslation()

void ScaleDefinition::AddTranslation ( const std::string &  language,
const std::string &  key,
const std::string &  value 
)

Definition at line 1365 of file ScaleDefinition.cpp.

1366{
1367 mTranslations[language][key] = value;
1368 mDirty = true;
1369}

◆ CreateNew()

std::shared_ptr< ScaleDefinition > ScaleDefinition::CreateNew ( const std::string &  code)
static

Definition at line 166 of file ScaleDefinition.cpp.

167{
168 auto scale = std::make_shared<ScaleDefinition>();
169 scale->mScaleInfo.code = code;
170 scale->mScaleInfo.name = code; // Default to code, user will change
171
172 // Add default English translations for required keys
173 scale->mTranslations["en"]["question_head"] = "Please answer the following questions:";
174 scale->mTranslations["en"]["debrief"] = "Thank you for completing this questionnaire.";
175
176 scale->mDirty = true;
177 return scale;
178}

Referenced by ScaleManager::CreateScale().

◆ ExportToJSON()

bool ScaleDefinition::ExportToJSON ( const std::string &  definitionsPath,
const std::string &  translationsPath 
)

Definition at line 311 of file ScaleDefinition.cpp.

312{
313 // Save definition
314 std::string defFile = definitionsPath + "/" + mScaleInfo.code + ".json";
315 if (!SaveDefinitionJSON(defFile)) {
316 return false;
317 }
318
319 // Save translations in new format only (.{lang}.json)
320 for (const auto& [lang, translations] : mTranslations) {
321 std::string transFile = translationsPath + "/" + mScaleInfo.code + "." + lang + ".json";
322 if (!SaveTranslationJSON(transFile, lang)) {
323 return false;
324 }
325 }
326
327 mDirty = false;
328 return true;
329}
std::string code

References ScaleInfo::code.

◆ ExportToOSD()

bool ScaleDefinition::ExportToOSD ( const std::string &  outputDir)

Definition at line 331 of file ScaleDefinition.cpp.

332{
333 // Build an OSD bundle: {"osd_version":"1.0","definition":{...},"translations":{...}}
334 // Builds definition JSON from in-memory model (no dependency on .json file on disk).
335 try {
336 json definition;
337 if (!BuildDefinitionJSONObject(definition)) {
338 printf("ExportToOSD: failed to build definition JSON\n");
339 return false;
340 }
341
342 json translations;
343 for (const auto& [lang, transMap] : mTranslations) {
344 json transJson;
345 for (const auto& [key, value] : transMap) {
346 transJson[key] = value;
347 }
348 translations[lang] = transJson;
349 }
350
351 json bundle;
352 bundle["osd_version"] = "1.0";
353 bundle["definition"] = definition;
354 bundle["translations"] = translations;
355
356 std::string osdFile = outputDir + "/" + mScaleInfo.code + ".osd";
357 std::ofstream f(osdFile);
358 if (!f.is_open()) return false;
359 f << bundle.dump(2);
360 return true;
361 } catch (const std::exception& e) {
362 printf("ExportToOSD error: %s\n", e.what());
363 return false;
364 }
365}
nlohmann::json json
Definition Chain.cpp:14

References ScaleInfo::code.

◆ GetAvailableLanguages()

std::vector< std::string > ScaleDefinition::GetAvailableLanguages ( ) const

Definition at line 1377 of file ScaleDefinition.cpp.

1378{
1379 std::vector<std::string> languages;
1380 for (const auto& [lang, _] : mTranslations) {
1381 languages.push_back(lang);
1382 }
1383 return languages;
1384}

◆ GetComputed() [1/2]

std::map< std::string, ComputedVariable > & ScaleDefinition::GetComputed ( )
inline

Definition at line 293 of file ScaleDefinition.h.

293{ return mComputed; }

◆ GetComputed() [2/2]

const std::map< std::string, ComputedVariable > & ScaleDefinition::GetComputed ( ) const
inline

Definition at line 306 of file ScaleDefinition.h.

306{ return mComputed; }

◆ GetDataOutput() [1/2]

DataOutput & ScaleDefinition::GetDataOutput ( )
inline

Definition at line 295 of file ScaleDefinition.h.

295{ return mDataOutput; }

◆ GetDataOutput() [2/2]

const DataOutput & ScaleDefinition::GetDataOutput ( ) const
inline

Definition at line 308 of file ScaleDefinition.h.

308{ return mDataOutput; }

◆ GetDefaultRequired()

int ScaleDefinition::GetDefaultRequired ( ) const
inline

Definition at line 339 of file ScaleDefinition.h.

339{ return mDefaultRequired; }

◆ GetDimension()

ScaleDimension * ScaleDefinition::GetDimension ( const std::string &  dimensionID)

Definition at line 1355 of file ScaleDefinition.cpp.

1356{
1357 for (auto& d : mDimensions) {
1358 if (d.id == dimensionID) {
1359 return &d;
1360 }
1361 }
1362 return nullptr;
1363}

References ScaleDimension::id.

◆ GetDimensions() [1/2]

std::vector< ScaleDimension > & ScaleDefinition::GetDimensions ( )
inline

Definition at line 291 of file ScaleDefinition.h.

291{ return mDimensions; }

◆ GetDimensions() [2/2]

const std::vector< ScaleDimension > & ScaleDefinition::GetDimensions ( ) const
inline

Definition at line 304 of file ScaleDefinition.h.

304{ return mDimensions; }

◆ GetLikertOptions() [1/2]

LikertOptions & ScaleDefinition::GetLikertOptions ( )
inline

Definition at line 289 of file ScaleDefinition.h.

289{ return mLikertOptions; }

◆ GetLikertOptions() [2/2]

const LikertOptions & ScaleDefinition::GetLikertOptions ( ) const
inline

Definition at line 302 of file ScaleDefinition.h.

302{ return mLikertOptions; }

◆ GetParameters() [1/2]

std::map< std::string, ScaleParameter > & ScaleDefinition::GetParameters ( )
inline

Definition at line 288 of file ScaleDefinition.h.

288{ return mParameters; }

◆ GetParameters() [2/2]

const std::map< std::string, ScaleParameter > & ScaleDefinition::GetParameters ( ) const
inline

Definition at line 301 of file ScaleDefinition.h.

301{ return mParameters; }

◆ GetQuestion()

ScaleQuestion * ScaleDefinition::GetQuestion ( const std::string &  questionID)

Definition at line 1328 of file ScaleDefinition.cpp.

1329{
1330 for (auto& q : mQuestions) {
1331 if (q.id == questionID) {
1332 return &q;
1333 }
1334 }
1335 return nullptr;
1336}

References ScaleQuestion::id.

◆ GetQuestions() [1/2]

std::vector< ScaleQuestion > & ScaleDefinition::GetQuestions ( )
inline

Definition at line 290 of file ScaleDefinition.h.

290{ return mQuestions; }

◆ GetQuestions() [2/2]

const std::vector< ScaleQuestion > & ScaleDefinition::GetQuestions ( ) const
inline

Definition at line 303 of file ScaleDefinition.h.

303{ return mQuestions; }

◆ GetRawDefinition() [1/2]

nlohmann::json & ScaleDefinition::GetRawDefinition ( )
inline

Definition at line 297 of file ScaleDefinition.h.

297{ return mRawDefinition; }

◆ GetRawDefinition() [2/2]

const nlohmann::json & ScaleDefinition::GetRawDefinition ( ) const
inline

Definition at line 310 of file ScaleDefinition.h.

310{ return mRawDefinition; }

◆ GetReportConfig() [1/2]

ReportConfig & ScaleDefinition::GetReportConfig ( )
inline

Definition at line 294 of file ScaleDefinition.h.

294{ return mReportConfig; }

◆ GetReportConfig() [2/2]

const ReportConfig & ScaleDefinition::GetReportConfig ( ) const
inline

Definition at line 307 of file ScaleDefinition.h.

307{ return mReportConfig; }

◆ GetScaleInfo() [1/2]

ScaleInfo & ScaleDefinition::GetScaleInfo ( )
inline

Definition at line 287 of file ScaleDefinition.h.

287{ return mScaleInfo; }

◆ GetScaleInfo() [2/2]

const ScaleInfo & ScaleDefinition::GetScaleInfo ( ) const
inline

Definition at line 300 of file ScaleDefinition.h.

300{ return mScaleInfo; }

◆ GetScoring() [1/2]

std::map< std::string, DimensionScoring > & ScaleDefinition::GetScoring ( )
inline

Definition at line 292 of file ScaleDefinition.h.

292{ return mScoring; }

◆ GetScoring() [2/2]

const std::map< std::string, DimensionScoring > & ScaleDefinition::GetScoring ( ) const
inline

Definition at line 305 of file ScaleDefinition.h.

305{ return mScoring; }

◆ GetTranslation()

std::string ScaleDefinition::GetTranslation ( const std::string &  language,
const std::string &  key 
) const

Definition at line 1386 of file ScaleDefinition.cpp.

1387{
1388 auto langIt = mTranslations.find(language);
1389 if (langIt != mTranslations.end()) {
1390 auto keyIt = langIt->second.find(key);
1391 if (keyIt != langIt->second.end()) {
1392 return keyIt->second;
1393 }
1394 }
1395 return "";
1396}

◆ GetTranslations() [1/2]

ScaleTranslations & ScaleDefinition::GetTranslations ( )
inline

Definition at line 296 of file ScaleDefinition.h.

296{ return mTranslations; }

◆ GetTranslations() [2/2]

const ScaleTranslations & ScaleDefinition::GetTranslations ( ) const
inline

Definition at line 309 of file ScaleDefinition.h.

309{ return mTranslations; }

◆ InsertQuestion()

void ScaleDefinition::InsertQuestion ( int  index,
const ScaleQuestion question 
)

Definition at line 1292 of file ScaleDefinition.cpp.

1293{
1294 if (index < 0) index = 0;
1295 if (index > (int)mQuestions.size()) index = (int)mQuestions.size();
1296 mQuestions.insert(mQuestions.begin() + index, question);
1297 mDirty = true;
1298}

◆ IsDirty()

bool ScaleDefinition::IsDirty ( ) const
inline

Definition at line 343 of file ScaleDefinition.h.

343{ return mDirty; }

◆ IsSourceOSD()

bool ScaleDefinition::IsSourceOSD ( ) const
inline

Definition at line 281 of file ScaleDefinition.h.

281{ return mSourceIsOSD; }

◆ LoadFromFile()

std::shared_ptr< ScaleDefinition > ScaleDefinition::LoadFromFile ( const std::string &  jsonPath)
static

Definition at line 180 of file ScaleDefinition.cpp.

181{
182 auto scale = std::make_shared<ScaleDefinition>();
183 if (!scale->LoadDefinitionJSON(jsonPath)) {
184 return nullptr;
185 }
186 scale->mDirty = false;
187 return scale;
188}

Referenced by ScaleManager::ImportFromFile().

◆ LoadFromOSDFile()

std::shared_ptr< ScaleDefinition > ScaleDefinition::LoadFromOSDFile ( const std::string &  osdPath)
static

Definition at line 190 of file ScaleDefinition.cpp.

191{
192 auto scale = std::make_shared<ScaleDefinition>();
193 if (!scale->LoadFromOSDBundlePath(osdPath)) {
194 return nullptr;
195 }
196 scale->mDirty = false;
197 return scale;
198}

Referenced by ScaleManager::InstallLooseOSD().

◆ LoadFromScalesDir()

bool ScaleDefinition::LoadFromScalesDir ( const std::string &  basePath,
const std::string &  scaleCode 
)

Definition at line 200 of file ScaleDefinition.cpp.

201{
202 // Load from <basePath>/<code>/<code>.json (fall back to <code>.osd bundle)
203 std::string scaleDir = basePath + "/" + scaleCode;
204 std::string defPath = scaleDir + "/" + scaleCode + ".json";
205 std::string osdPath = scaleDir + "/" + scaleCode + ".osd";
206
207 if (fs::exists(defPath)) {
208 if (!LoadDefinitionJSON(defPath)) {
209 return false;
210 }
211 // If a .osd bundle also exists, supplement mParameters from it.
212 // This handles the case where the user edited the .osd directly to add
213 // parameters but the .json was saved before those parameters were added.
214 // The .osd parameters block is the authoritative source for parameter metadata.
215 if (fs::exists(osdPath)) {
216 try {
217 std::ifstream osdFile(osdPath);
218 if (osdFile.is_open()) {
219 json bundle;
220 osdFile >> bundle;
221 if (bundle.contains("definition") && bundle["definition"].contains("parameters")) {
222 for (auto& [key, value] : bundle["definition"]["parameters"].items()) {
223 ScaleParameter param;
224 if (value.contains("type")) param.type = value["type"];
225 if (value.contains("default")) param.defaultValue = value["default"].is_string()
226 ? value["default"].get<std::string>()
227 : value["default"].dump();
228 if (value.contains("description")) param.description = value["description"];
229 if (value.contains("options")) {
230 for (const auto& opt : value["options"]) {
231 param.options.push_back(opt.is_string() ? opt.get<std::string>() : opt.dump());
232 }
233 }
234 // Only add — do not overwrite params already set from .json
235 if (mParameters.find(key) == mParameters.end()) {
236 mParameters[key] = param;
237 }
238 }
239 }
240 }
241 } catch (...) {
242 // OSD supplement is best-effort; don't fail the load
243 }
244 }
245 } else if (fs::exists(osdPath)) {
246 // .osd bundle includes both definition and translations — load all at once
247 if (!LoadFromOSDBundlePath(osdPath)) {
248 return false;
249 }
250 mDirty = false;
251 return true;
252 } else {
253 return false;
254 }
255
256 // Load translations from the same directory
257 // Support both PEBL naming (.pbl-<lang>.json) and OSD format (.<lang>.json)
258 std::string pblPrefix = scaleCode + ".pbl-";
259 std::string defFilename = scaleCode + ".json"; // Skip the definition file itself
260
261 try {
262 if (fs::exists(scaleDir)) {
263 for (const auto& entry : fs::directory_iterator(scaleDir)) {
264 if (entry.is_regular_file()) {
265 std::string filename = entry.path().filename().string();
266
267 // Skip the definition file itself
268 if (filename == defFilename) continue;
269
270 // Try PEBL format: {code}.pbl-{lang}.json
271 if (filename.find(pblPrefix) == 0 &&
272 filename.size() >= 5 &&
273 filename.substr(filename.size() - 5) == ".json") {
274 std::string lang = filename.substr(pblPrefix.length());
275 lang = lang.substr(0, lang.length() - 5);
276 LoadTranslationJSON(entry.path().string(), lang);
277 continue;
278 }
279
280 // Try OSD format: {code}.{lang}.json
281 std::string openPrefix = scaleCode + ".";
282 if (filename.find(openPrefix) == 0 &&
283 filename.size() >= 5 &&
284 filename.substr(filename.size() - 5) == ".json") {
285 std::string lang = filename.substr(openPrefix.length());
286 lang = lang.substr(0, lang.length() - 5);
287 if (!lang.empty() && lang.find('.') == std::string::npos) {
288 LoadTranslationJSON(entry.path().string(), lang);
289 }
290 }
291 }
292 }
293 }
294 } catch (const std::exception& e) {
295 // Continue even if translation loading fails
296 }
297
298 mDirty = false;
299 return true;
300}
std::string description
std::string defaultValue
std::string type
std::vector< std::string > options

References ScaleParameter::defaultValue, ScaleParameter::description, ScaleParameter::options, and ScaleParameter::type.

◆ MoveQuestion()

void ScaleDefinition::MoveQuestion ( int  fromIndex,
int  toIndex 
)

Definition at line 1311 of file ScaleDefinition.cpp.

1312{
1313 if (fromIndex < 0 || fromIndex >= (int)mQuestions.size() ||
1314 toIndex < 0 || toIndex >= (int)mQuestions.size()) {
1315 return;
1316 }
1317
1318 if (fromIndex == toIndex) {
1319 return;
1320 }
1321
1322 ScaleQuestion q = mQuestions[fromIndex];
1323 mQuestions.erase(mQuestions.begin() + fromIndex);
1324 mQuestions.insert(mQuestions.begin() + toIndex, q);
1325 mDirty = true;
1326}

◆ RemoveDimension()

void ScaleDefinition::RemoveDimension ( const std::string &  dimensionID)

Definition at line 1344 of file ScaleDefinition.cpp.

1345{
1346 auto it = std::remove_if(mDimensions.begin(), mDimensions.end(),
1347 [&dimensionID](const ScaleDimension& d) { return d.id == dimensionID; });
1348
1349 if (it != mDimensions.end()) {
1350 mDimensions.erase(it, mDimensions.end());
1351 mDirty = true;
1352 }
1353}

◆ RemoveQuestion()

void ScaleDefinition::RemoveQuestion ( const std::string &  questionID)

Definition at line 1300 of file ScaleDefinition.cpp.

1301{
1302 auto it = std::remove_if(mQuestions.begin(), mQuestions.end(),
1303 [&questionID](const ScaleQuestion& q) { return q.id == questionID; });
1304
1305 if (it != mQuestions.end()) {
1306 mQuestions.erase(it, mQuestions.end());
1307 mDirty = true;
1308 }
1309}

◆ RemoveTranslation()

void ScaleDefinition::RemoveTranslation ( const std::string &  language)

Definition at line 1371 of file ScaleDefinition.cpp.

1372{
1373 mTranslations.erase(language);
1374 mDirty = true;
1375}

◆ SaveToFile()

bool ScaleDefinition::SaveToFile ( const std::string &  jsonPath)

Definition at line 302 of file ScaleDefinition.cpp.

303{
304 if (SaveDefinitionJSON(jsonPath)) {
305 mDirty = false;
306 return true;
307 }
308 return false;
309}

◆ SetDefaultRequired()

void ScaleDefinition::SetDefaultRequired ( int  val)
inline

Definition at line 340 of file ScaleDefinition.h.

340{ mDefaultRequired = val; mDirty = true; }

◆ SetDirty()

void ScaleDefinition::SetDirty ( bool  dirty)
inline

Definition at line 344 of file ScaleDefinition.h.

344{ mDirty = dirty; }

◆ Validate()

bool ScaleDefinition::Validate ( std::string &  errorOutput)

Definition at line 1463 of file ScaleDefinition.cpp.

1464{
1465 // Use internal validation
1466 ValidationResult result = ValidateInternal();
1467
1468 std::stringstream ss;
1469 if (!result.errors.empty()) {
1470 ss << "Errors:\n";
1471 for (const auto& err : result.errors) {
1472 ss << " - " << err << "\n";
1473 }
1474 }
1475 if (!result.warnings.empty()) {
1476 ss << "Warnings:\n";
1477 for (const auto& warn : result.warnings) {
1478 ss << " - " << warn << "\n";
1479 }
1480 }
1481
1482 errorOutput = ss.str();
1483 return result.IsValid();
1484}
ValidationResult ValidateInternal() const

References ScaleDefinition::ValidationResult::errors, ScaleDefinition::ValidationResult::IsValid(), ValidateInternal(), and ScaleDefinition::ValidationResult::warnings.

◆ ValidateInternal()

ScaleDefinition::ValidationResult ScaleDefinition::ValidateInternal ( ) const

Definition at line 1398 of file ScaleDefinition.cpp.

1399{
1400 ValidationResult result;
1401
1402 // Check scale info
1403 if (mScaleInfo.code.empty()) {
1404 result.errors.push_back("Scale code is required");
1405 }
1406 if (mScaleInfo.name.empty()) {
1407 result.errors.push_back("Scale name is required");
1408 }
1409
1410 // Check questions
1411 if (mQuestions.empty()) {
1412 result.errors.push_back("Scale must have at least one question");
1413 }
1414
1415 // Check for duplicate question IDs
1416 std::map<std::string, int> idCounts;
1417 for (const auto& q : mQuestions) {
1418 if (q.id.empty()) {
1419 result.errors.push_back("Question missing ID");
1420 } else {
1421 idCounts[q.id]++;
1422 }
1423 if (q.text_key.empty()) {
1424 result.warnings.push_back("Question " + q.id + " missing text_key");
1425 }
1426 if (q.type.empty()) {
1427 result.errors.push_back("Question " + q.id + " missing type");
1428 }
1429 }
1430
1431 for (const auto& [id, count] : idCounts) {
1432 if (count > 1) {
1433 result.errors.push_back("Duplicate question ID: " + id);
1434 }
1435 }
1436
1437 // Check dimensions reference valid questions
1438 for (const auto& dim : mDimensions) {
1439 if (dim.id.empty()) {
1440 result.errors.push_back("Dimension missing ID");
1441 }
1442 }
1443
1444 // Check scoring references valid questions
1445 for (const auto& [dimId, scoring] : mScoring) {
1446 for (const auto& qid : scoring.items) {
1447 bool found = false;
1448 for (const auto& q : mQuestions) {
1449 if (q.id == qid) {
1450 found = true;
1451 break;
1452 }
1453 }
1454 if (!found) {
1455 result.warnings.push_back("Scoring " + dimId + " references non-existent question: " + qid);
1456 }
1457 }
1458 }
1459
1460 return result;
1461}
std::string name
int count
Definition test.cpp:12

References ScaleInfo::code, count, ScaleDefinition::ValidationResult::errors, ScaleQuestion::id, ScaleInfo::name, ScaleQuestion::text_key, ScaleQuestion::type, and ScaleDefinition::ValidationResult::warnings.

Referenced by Validate().


The documentation for this class was generated from the following files: