bonuska1/App/Data/Database.cs

103 lines
4.4 KiB
C#

namespace Game.Data {
public class Database {
public List<Question> questions = new List<Question>();
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<string> answers = new List<string>();
// 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<string> answers, int correctAnswer);
}