implement question bank parsing
This commit is contained in:
parent
e35b8520b4
commit
4ee8a06232
103
App/Data/Database.cs
Normal file
103
App/Data/Database.cs
Normal file
@ -0,0 +1,103 @@
|
||||
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);
|
||||
}
|
@ -30,6 +30,14 @@ namespace Game {
|
||||
}
|
||||
|
||||
string databaseFileName = opts.databaseFilename ?? gameConfig.databasePath;
|
||||
Database questionDatabase;
|
||||
try {
|
||||
questionDatabase = Database.ReadFromFile(databaseFileName);
|
||||
} catch (DatabaseReadException e) {
|
||||
display.ShowFatalError(string.Format(I18n.GetMessage(I18n.Message.SYNTAX_ERROR), I18n.GetMessage(e.messageId), e.line.ToString(), e.column.ToString()));
|
||||
Console.ReadKey();
|
||||
return 3;
|
||||
}
|
||||
|
||||
display.ResetWindow();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user