Commit 0eecc43e authored by Martin LOISEAU's avatar Martin LOISEAU 🎄
Browse files

Add read access to scenario xml

parent a0e78310
......@@ -3,7 +3,19 @@ QR Quest (nom de travail) est un projet de jeu éducatif pour android utilisant
Développé en juin 2020 dans le cadre d'un stage de 3ème année (Polytech Nantes).
Le fonctionnement de la partie QR a été adapté du projet QRLudo : https://github.com/univ-angers/QRLudo
Statut actuel: 4 boutons permettent de tester la synthèse vocale, la reconnaissance vocale, la lecture de fichier MP3 et la lecture de QR code (image de test disponible avec le projet).
A terme, on souhaite que chaque QR code puisse charger un scenario, à l'occasion duquel un fichier mp3 sera lu/la synthèse vocal lira un texte. L'utilisateur pourra alors scanner un autre QR code qui sera accepté ou rejeté afin de faire avancer l'histoire.
Le fonctionnement de l'application est basé sur un système de noeud/atomes.
Chaque noeud représente une série d'action que le jeu effectuera (lire un texte, etc). Chaque noeud possède égalemement une liste d'atomes. Lorsque tout lesa tomes de cette liste sont réunis par le joueur, le noeud se déclenche et effectue toutes ses actions.
Des actions communes sont donc celles d'ajouter ou de retirer un atome par exemple.
Seuls les noeuds ouverts (dans la liste open nodes) sont susceptibles de se déclencher.
Le scenario est donc décrit par la liste de tout les noeuds.
Le point d'entrée du scénario est la première node du scénario, qui ne doit donc contenir aucun atome afin de se déclencher initialement. A partir de ce noeud, on peut initialiser le jeu comme on le souhaite en ajoutant les noeufs ouverts et atomes avec lesquels on souhaite commencer.
Ce projet est un prototype. Les pistes d'améliorations sont :
- Chargement du scenario a partir d'un fichier XML (en cours)
- Optimisation de la vitesse d'éxecution de la lecture par synthèse vocale et de l'ouverture de l'appareil photo pour scanner des QR (peut prendre jusqu'à 3 secondes actuellement)
- Affichage d'une illustration pour chaque node.
- Ajout d'autres actions.
- Parallélisation de l'éxecution des nodes (actuellement séquentiel)
Martin Loiseau
......@@ -40,11 +40,14 @@ import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import org.xmlpull.v1.XmlPullParserException;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.StringWriter;
import java.nio.file.Paths;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
......@@ -89,77 +92,20 @@ public class MainActivity extends AppCompatActivity {
EveryNode = new ArrayList<Node>();
OpenNodes = new ArrayList<Node>();
ArrayList<Action> A1 = new ArrayList<Action>();
A1.add(new TTSReading(this, 1, "Bonjour"));
A1.add(new RemoveAtom(this,1, new ItemAtom(0)));
A1.add(new AddAtom(this,1, new ItemAtom(1)));
A1.add(new ClearNodes(this,1));
A1.add(new AddNode(this,1, 6));
ArrayList<Atom> C1 = new ArrayList<Atom>();
C1.add(new ItemAtom(0));
ArrayList<Action> A2 = new ArrayList<Action>();
A2.add(new ClearNodes(this,2));
A2.add(new TTSReading(this,2, "Mauvais QR code"));
A2.add(new AddNode(this,2, 3));
ArrayList<Atom> C2 = new ArrayList<Atom>();
ArrayList<Action> A3 = new ArrayList<Action>();
A3.add(new ClearNodes(this,3));
A3.add(new TTSReading(this,3, "Cherchons un QR"));
A3.add(new CaptureQR(this,3));
A3.add(new Checker(this,3, "36271", QRAtom.class, 4,2));
ArrayList<Atom> C3 = new ArrayList<Atom>();
C3.add(new ItemAtom(1));
ArrayList<Action> A4 = new ArrayList<Action>();
A4.add(new ClearNodes(this,4));
A4.add(new TTSReading(this,4, "Bon QR code"));
A4.add(new TTSReading(this,4, "Vous avez gagné"));
ArrayList<Atom> C4 = new ArrayList<Atom>();
ArrayList<Action> A5 = new ArrayList<Action>();
A5.add(new ClearNodes(this,5));
A5.add(new TTSReading(this,5, "Mauvaise réponse"));
A5.add(new AddNode(this,5, 6));
ArrayList<Atom> C5 = new ArrayList<Atom>();
ArrayList<Action> A6 = new ArrayList<Action>();
A6.add(new ClearNodes(this,6));
A6.add(new TTSReading(this,6, "Combien font 4 fois 2 ?"));
A6.add(new CaptureSpeech(this,6));
A6.add(new Checker(this,6, "8", SpeechAtom.class, 7,5));
ArrayList<Atom> C6 = new ArrayList<Atom>();
C6.add(new ItemAtom(1));
ArrayList<Action> A7 = new ArrayList<Action>();
A7.add(new ClearNodes(this,7));
A7.add(new TTSReading(this,7, "Bonne réponse"));
A7.add(new TTSReading(this,7, "Vous avez gagné"));
ArrayList<Atom> C7 = new ArrayList<Atom>();
Node n1 = new Node(this,1, A1, C1); // node that launch other nodes
Node n2 = new Node(this,2, A2, C2); // wrong QR code node
Node n3 = new Node(this,3, A3, C3); // Node that check QR codes (launch and check)
Node n4 = new Node(this,4, A4, C4); // Node that declare victory
Node n5 = new Node(this,5, A5, C5); // wrong answer math
Node n6 = new Node(this,6, A6, C6); // Math question
Node n7 = new Node(this,7, A7, C7); // good answer math question
EveryNode.add(n1);
EveryNode.add(n2);
EveryNode.add(n3);
EveryNode.add(n4);
EveryNode.add(n5);
EveryNode.add(n6);
EveryNode.add(n7);
OpenNodes.add(n1);
Log.d("Debug2", "Nodes initialized");
ScenarioLoader scenario = new ScenarioLoader(getApplicationInfo().dataDir + "/scenario.xml");
EveryNode = scenario.GetNodes();
OpenNodes.add(EveryNode.get(0));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Log.d("Debug2", "Current path is: " + Paths.get("").toAbsolutePath().toString());
}
// getApplicationInfo(). +
ScenarioLoader scenario = new ScenarioLoader("/res/scenario/scenario.xml", this);
try {
EveryNode = scenario.GetNodes();
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
// OpenNodes.add(EveryNode.get(0));
}
public void CheckOpenNodes() {
......
package com.example.qrquest;
import android.os.Build;
import android.util.Log;
import android.util.Xml;
import androidx.annotation.RequiresApi;
import com.example.qrquest.actions.Action;
import com.example.qrquest.actions.AddAtom;
import com.example.qrquest.actions.AddNode;
import com.example.qrquest.actions.CaptureQR;
import com.example.qrquest.actions.CaptureSpeech;
import com.example.qrquest.actions.Checker;
import com.example.qrquest.actions.ClearNodes;
import com.example.qrquest.actions.RemoveAtom;
import com.example.qrquest.actions.TTSReading;
import com.example.qrquest.atom.Atom;
import com.example.qrquest.atom.ItemAtom;
import com.example.qrquest.atom.QRAtom;
import com.example.qrquest.atom.SpeechAtom;
import com.example.qrquest.node.Node;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.nio.file.Paths;
import java.util.ArrayList;
public class ScenarioLoader {
......@@ -9,46 +37,201 @@ public class ScenarioLoader {
* The goal of the com.example.qrquest.ScenarioLoader is to get the list of every node from a scenario xml file
*/
ArrayList<Node> ScenarioNodes;
MainActivity mainActivity;
String scenarioPath;
private static final String ns = null;
public ScenarioLoader(String xml_path)
{
ScenarioNodes = new ArrayList<Node>();
public ScenarioLoader(String scenarioPath, MainActivity mainActivity) {
this.mainActivity = mainActivity;
this.scenarioPath = scenarioPath;
}
/*
private static final String ns = null;
public List parse(InputStream in) throws XmlPullParserException, IOException {
private ArrayList<Node> XMLScenario(MainActivity mainActivity) throws XmlPullParserException, IOException {
/*
* based on this guide https://developer.android.com/training/basics/network-ops/xml#java
*/
InputStream in = mainActivity.getResources().openRawResource(
mainActivity.getResources().getIdentifier("scenario",
"raw", mainActivity.getPackageName()));
Log.d("Debug2", "XML FILE :" + in.toString());
// InputStream in = new FileInputStream(new File(scenarioPath));
try {
XmlPullParser parser = Xml.newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
parser.setInput(in, null);
parser.nextTag();
return readFeed(parser);
// return readFeed(parser);
{
ScenarioNodes = new ArrayList<Node>();
parser.require(XmlPullParser.START_TAG, ns, "liste");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
// Starts by looking for the entry tag
if (name.equals("node")) {
Log.d("Debug2", "Node tag detected");
ScenarioNodes.add(readNode(parser));
} else {
skip(parser);
}
}
}
} finally {
in.close();
}
return HardCodedScenario(mainActivity);
}
private List readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {
List entries = new ArrayList();
private Node readNode(XmlPullParser parser) throws XmlPullParserException, IOException {
Log.d("Debug2", "readNode() called in XML");
parser.require(XmlPullParser.START_TAG, ns, "node");
ArrayList<Action> Actions = new ArrayList<Action>();
ArrayList<Atom> Conditions = new ArrayList<Atom>();
int ID = 0;
parser.require(XmlPullParser.START_TAG, ns, "feed");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
// Starts by looking for the entry tag
if (name.equals("entry")) {
entries.add(readEntry(parser));
if (name.equals("id")) {
ID = readID(parser);
Log.d("Debug2", "ID read in XML: " + Integer.toString(ID));
// } else if (name.equals("required_atoms")) {
// Conditions = readAtoms(parser);
// } else if (name.equals("action_list")) {
// Actions = readActions(parser);
} else {
Log.d("Debug2", "skipped a non id balise ");
skip(parser);
}
}
return entries;
return new Node(mainActivity, ID, Actions, Conditions);
}
/*
private ArrayList<Action> readActions(XmlPullParser parser) {
}
private ArrayList<Atom> readAtoms(XmlPullParser parser) {
}*/
private int readID(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, "id");
int ID = readNumber(parser);
parser.require(XmlPullParser.END_TAG, ns, "id");
return ID;
}
private int readNumber(XmlPullParser parser) throws IOException, XmlPullParserException {
int result = 0;
if (parser.next() == XmlPullParser.TEXT) {
result = Integer.parseInt(parser.getText());
parser.nextTag();
}
return result;
}
private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException();
}
int depth = 1;
while (depth != 0) {
switch (parser.next()) {
case XmlPullParser.END_TAG:
depth--;
break;
case XmlPullParser.START_TAG:
depth++;
break;
}
}
}
*/
private ArrayList<Node> HardCodedScenario(MainActivity mainActivity)
{
ArrayList<Action> A1 = new ArrayList<Action>();
A1.add(new TTSReading(mainActivity, 1, "Bonjour"));
A1.add(new RemoveAtom(mainActivity,1, new ItemAtom(0)));
A1.add(new AddAtom(mainActivity,1, new ItemAtom(1)));
A1.add(new ClearNodes(mainActivity,1));
A1.add(new AddNode(mainActivity,1, 6));
ArrayList<Atom> C1 = new ArrayList<Atom>();
ArrayList<Action> A2 = new ArrayList<Action>();
A2.add(new ClearNodes(mainActivity,2));
A2.add(new TTSReading(mainActivity,2, "Mauvais QR code"));
A2.add(new AddNode(mainActivity,2, 3));
ArrayList<Atom> C2 = new ArrayList<Atom>();
ArrayList<Action> A3 = new ArrayList<Action>();
A3.add(new ClearNodes(mainActivity,3));
A3.add(new TTSReading(mainActivity,3, "Cherchons un QR"));
A3.add(new CaptureQR(mainActivity,3));
A3.add(new Checker(mainActivity,3, "36271", QRAtom.class, 4,2));
ArrayList<Atom> C3 = new ArrayList<Atom>();
C3.add(new ItemAtom(1));
ArrayList<Action> A4 = new ArrayList<Action>();
A4.add(new ClearNodes(mainActivity,4));
A4.add(new TTSReading(mainActivity,4, "Bon QR code"));
A4.add(new TTSReading(mainActivity,4, "Vous avez gagné"));
ArrayList<Atom> C4 = new ArrayList<Atom>();
ArrayList<Action> A5 = new ArrayList<Action>();
A5.add(new ClearNodes(mainActivity,5));
A5.add(new TTSReading(mainActivity,5, "Mauvaise réponse"));
A5.add(new AddNode(mainActivity,5, 6));
ArrayList<Atom> C5 = new ArrayList<Atom>();
ArrayList<Action> A6 = new ArrayList<Action>();
A6.add(new ClearNodes(mainActivity,6));
A6.add(new TTSReading(mainActivity,6, "Combien font 4 fois 2 ?"));
A6.add(new CaptureSpeech(mainActivity,6));
A6.add(new Checker(mainActivity,6, "8", SpeechAtom.class, 7,5));
ArrayList<Atom> C6 = new ArrayList<Atom>();
C6.add(new ItemAtom(1));
ArrayList<Action> A7 = new ArrayList<Action>();
A7.add(new ClearNodes(mainActivity,7));
A7.add(new TTSReading(mainActivity,7, "Bonne réponse"));
A7.add(new TTSReading(mainActivity,7, "Vous avez gagné"));
ArrayList<Atom> C7 = new ArrayList<Atom>();
Node n1 = new Node(mainActivity,1, A1, C1); // node that launch other nodes
Node n2 = new Node(mainActivity,2, A2, C2); // wrong QR code node
Node n3 = new Node(mainActivity,3, A3, C3); // Node that check QR codes (launch and check)
Node n4 = new Node(mainActivity,4, A4, C4); // Node that declare victory
Node n5 = new Node(mainActivity,5, A5, C5); // wrong answer math
Node n6 = new Node(mainActivity,6, A6, C6); // Math question
Node n7 = new Node(mainActivity,7, A7, C7); // good answer math question
ArrayList<Node> StaticScenario = new ArrayList<Node>();
StaticScenario.add(n1);StaticScenario.add(n2);StaticScenario.add(n3);StaticScenario.add(n4);StaticScenario.add(n5);StaticScenario.add(n6);StaticScenario.add(n7);
return StaticScenario;
}
public ArrayList<Node> GetNodes() { return ScenarioNodes; }
public ArrayList<Node> GetNodes() throws IOException, XmlPullParserException {
return XMLScenario(mainActivity);
//return HardCodedScenario(mainActivity);
}
}
<?xml version="1.0" encoding="utf-8"?>
<liste>
<node>
<id>1</id>
<id>1555</id>
<required_atoms>
</required_atoms>
<action_list>
......@@ -13,7 +13,8 @@
</action_list>
</node>
<node id="2">
<node>
<id>12</id>
<required_atoms>
</required_atoms>
......@@ -22,7 +23,7 @@
</action_list>
</node>
<node id="3">
<node>
<id>91</id>
</node>
</liste>
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment