namespace Game.Data { public class Database { public List questions = new List(); public static Database ReadFromFile(string filename) { var db = new Database(); using (StreamReader rd = new StreamReader(filename)) { string? line; int lineNumber = 1; while ((line = rd.ReadLine()) != null) { int i = 0; int len = line.Length; int state = 0; int correctAnswer = -1; List answers = new List(); // read question while (i < len + 1) { if (i == len) { throw new DatabaseReadException(I18n.Message.ERROR_NO_ANSWER_OPTIONS, lineNumber, i); } else if (line[i] == '|') if (state == 1) { ++i; break; } else { state = 1; } else state = 0; ++i; } string question = line.Substring(0, i - 2); int currentAnswer = 0; while (i < len) { // read answer text state = 0; int answerStart = i; while (i < len + 1) { if (i == len) { throw new DatabaseReadException(I18n.Message.ERROR_EXPECTED_ARROW_TOKEN, lineNumber, i); } else if (state == 0) { if (line[i] == '=') state = 1; } else if (state == 1) { if (line[i] == '>') { ++i; break; } else { state = 0; } } ++i; } string answer = line.Substring(answerStart, i - answerStart - 2); // read True or False if (line[i] == 'T') { if (i + 3 < len && line[i + 1] == 'r' && line[i + 2] == 'u' && line[i + 3] == 'e') { correctAnswer = currentAnswer; i += 4; } else { throw new DatabaseReadException(I18n.Message.ERROR_EXPECTED_TRUE_OR_FALSE, lineNumber, i); } } else if (line[i] == 'F') { if (i + 4 < len && line[i + 1] == 'a' && line[i + 2] == 'l' && line[i + 3] == 's' && line[i + 4] == 'e') { i += 5; } else { throw new DatabaseReadException(I18n.Message.ERROR_EXPECTED_TRUE_OR_FALSE, lineNumber, i); } } // consume separator if (i + 1 < len && (line[i] != '|' || line[i + 1] != '|')) throw new DatabaseReadException(I18n.Message.ERROR_EXPECTED_ANSWER_SEPARATOR, lineNumber, i); i += 2; answers.Add(answer); ++currentAnswer; } lineNumber++; db.questions.Add(new Question(question, answers, correctAnswer)); } } return db; } } public class DatabaseReadException : Exception { public readonly int line, column; public readonly I18n.Message messageId; public DatabaseReadException(I18n.Message messageId) { this.messageId = messageId; line = -1; column = -1; } public DatabaseReadException(I18n.Message messageId, int line, int column) { this.messageId = messageId; this.line = line; this.column = column; } } public record Question (string question, List answers, int correctAnswer); }