Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
288 changes: 264 additions & 24 deletions app/src/main/java/org/teiath/ellak/ellakandroideducation/DBHandler.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,46 @@
package org.teiath.ellak.ellakandroideducation;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;


/**
* Η κλάση DBHandler επιστρέφει πληροφορίες από τη βάση δεδομένων και δημιουργεί ερωτηματολόγια. Περιγράφονται κάποιες
* από τις απαιτούμενες μεθόδους οι οποίες είναι απαραίτητες για την λειτουργία άλλων κλάσεων της εφαρμογής.
* Η κλάση DBHandler είναι singleton.
*/
public class DBHandler
{
private static DBHandler ourInstance = new DBHandler ();
public class DBHandler {
private static Context mcontext;
private static DBHandler ourInstance;
private Cursor cursor;
private Cursor catCursor;
private Cursor sumCursor;
private Cursor ansCursor;
private Cursor subCursor;
private SQLiteDatabase sqldb;

/**
* Επιστρέφει αναφορά στο μοναδικό αντικείμενο που δημιουργείται από την κλάση.
* Πρεπει να καλειται πρωτη για να λαμβανεται η αναφορα στο αντικειμενο.
* ΔΕΝ ΠΡΕΠΕΙ ΝΑ ΔΗΜΙΟΥΡΓΗΘΕΙ ΚΑΙΝΟΥΡΙΟ ΑΝΤΙΚΕΙΜΕΝΟ DBHandler!!!
*
* @param context ενα αντικειμενο context ειτε σαν μεταβλητη context ειτε σαν μεθοδο(getApplicationContext()).
* @return Η αναφορά στο αντικείμενο.
*/
public static DBHandler getInstance ()
{
public static DBHandler getInstance(Context context) {
if (ourInstance == null) {
ourInstance = new DBHandler(context.getApplicationContext());
}
return ourInstance;
}

Expand All @@ -25,47 +49,265 @@ public static DBHandler getInstance ()
* πρέπει να είναι ο έλεγχος ύπαρξης του sqlite αρχείου στον αποθεκευτικό χώρο της εφαρμογής και η μεταφορά του από
* τα assets αν χρειάζεται.
*/
private DBHandler ()
{

private DBHandler(Context context) {
mcontext = context;
if (!CheckDB())
CopyDB();
}

/**
* Επιστρέφει την λίστα με τα γνωστικά αντικείμενα τα οποίες βρίσκονται στη Βάση Δεδομένων. Τα γνωστικά αντικείμενα
* επιστρέφονται ως LinkedList με αντικείμενα {@link SubjectRec}.
*
* @return Η λίστα με τις κατηγορίες εξέτασης.
*/
public LinkedList <SubjectRec> GetKategories ()
{
return null;
public LinkedList<SubjectRec> GetKategories() {
LinkedList<SubjectRec> list = new LinkedList<>();
String MyDB = mcontext.getApplicationContext().getFilesDir().getAbsolutePath() + "/databases/EllakDB.sqlite";
SQLiteDatabase sqldb = SQLiteDatabase.openDatabase(MyDB, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS);
Cursor cursor = sqldb.rawQuery("SELECT COUNT(*) FROM Subjects", null);
cursor.moveToFirst();
int x = cursor.getInt(0);
SubjectRec[] sr = new SubjectRec[x];
for (int j = 0; j < sr.length; j++) {
sr[j] = new SubjectRec();
}
cursor = sqldb.rawQuery("SELECT * FROM Subjects", null);
cursor.moveToFirst();
for (int i = 0; i < sr.length; i++) {
sr[i].SubjectID = cursor.getInt(0);
sr[i].SubjectName = cursor.getString(1);
list.add(sr[i]);
cursor.moveToNext();
}
cursor.close();
sqldb.close();
return list;
}

/**
* Δημιουργεί και επιστρέφει ένα ολόκληρο ερωτηματολόγιο. Οι ερωτήσεις επιλέγονται τυχαία από τις διαθέσιμες
* υποκατηγορίες και οι διαθέσιμες απαντήσεις των ερωτήσεων τοποθετούνται με, επίσης, τυχαία σειρά.
*
* @param Subject Ο κωδικός του γνωστικού αντικειμένου της εξέτασης.
* @return Το ερωτηματολόγιο ως στιγμιότυπο της κλάσης {@link TestSheet}.
*/
public TestSheet CreateTestSheet (int Subject)
{
return null;
public TestSheet CreateTestSheet(int Subject) {
List<Integer> list;
List<Integer> ansList = new LinkedList<>();
/** Χρησιμοποιούμε λίστες για να αποτρέψουμε την random από το να παράξει το ίδιο αποτέλεσμα **/
TestSheet ts = new TestSheet();
ts.SubjectID = Subject;
int count = 0;
cursorInit(Subject);
int[] categories = categInit();
ts.Quests = makeQuest();
ts.ReqCorAnswers = reqAnswers(ts.Quests);
for (int i = 0; i < categories.length; i++) {
int q = categories[i];
list = getSubCateg(i);
for (int j = 0; j < q; j++) {
ts.Quests[count] = insertQuestions(list, ansList);
ansList.clear();
count++;
}
list.clear();
}
cursor = sqldb.rawQuery("SELECT STime FROM Subjects WHERE SubjectCode = " + Subject, null);
cursor.moveToFirst();
ts.ExamTime = cursor.getInt(0);
cursor.close();
catCursor.close();
ansCursor.close();
subCursor.close();
sumCursor.close();
sqldb.close();
return ts;
}

/**
* Επιστρέφει την έκδοση της τρέχουσας έκδοσης της βάσης δεδομένων.
*
* @return Η τρέχουσα έκδοση της βάσης δεδομένων.
*/
public float GetVersion ()
{
return 0.0f;
public float GetVersion() {
String MyDB = mcontext.getApplicationContext().getFilesDir().getAbsolutePath() + "/databases/EllakDB.sqlite";
SQLiteDatabase sqldb = SQLiteDatabase.openDatabase(MyDB, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS);
Cursor cursor = sqldb.rawQuery("SELECT * FROM Misc", null);
cursor.moveToFirst();
float ver = cursor.getFloat(0);
cursor.close();
sqldb.close();
return ver;
}

private boolean CheckDB() {
String DB_PATH = mcontext.getApplicationContext().getFilesDir().getAbsolutePath() + "/databases/";
File dbf = new File(DB_PATH + "EllakDB.sqlite");
return dbf.exists();
}

private void CopyDB() {
InputStream myInput = null;
try {
myInput = mcontext.getApplicationContext().getAssets().open("EllakDB.sqlite");
CreateDirectory();
String DB_PATH = mcontext.getApplicationContext().getFilesDir().getAbsolutePath() + "/databases/";
String outFileName = DB_PATH + "EllakDB.sqlite";
OutputStream myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myOutput.close();
myInput.close();
} catch (IOException e) {
System.err.println("Error in copying: " + e.getMessage());
}
}

private void CreateDirectory() {
String DB_DIR = mcontext.getApplicationContext().getFilesDir().getAbsolutePath() + "/databases/";
File Dir = new File(DB_DIR);
if (!Dir.exists())
Dir.mkdir();
}

/**
* Τοποθετεί τα δεδομένα απο τη βάση σε cursors για να χρησιμοποιηθούν στην createTestSheet.
*
* @param Subject ο αριθμός του γνωστικού αντικειμένου στη βάση.
*/
private void cursorInit(int Subject) {
String MyDB = mcontext.getApplicationContext().getFilesDir().getAbsolutePath() + "/databases/EllakDB.sqlite";
sqldb = SQLiteDatabase.openDatabase(MyDB, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS);
cursor = sqldb.rawQuery("SELECT QCODE,QSUBJECT,QKATEG,QLECT,QPHOTO from questions where qsubject=" + Subject + " order by qkateg;", null);
catCursor = sqldb.rawQuery("SELECT Kategory,Numb FROM Numbers WHERE SCode=" + Subject, null);
sumCursor = sqldb.rawQuery("SELECT SUM(Numb) FROM Numbers WHERE SCode=" + Subject, null);
subCursor = sqldb.rawQuery("SELECT SLect FROM Subjects WHERE SubjectCode=" + Subject, null);
}

/**
* @return ο πίνακας των υποκατηγοριών και ο απαιτούμενος αριθμός ερωτήσεων για κάθε υποκατηγορία.
*/
private int[] categInit() {
int[] categories = new int[catCursor.getCount()];
catCursor.moveToFirst();
for (int i = 0; i < categories.length; i++) {
categories[i] = catCursor.getInt(1);
catCursor.moveToNext();
}
return categories;
}

/**
* Αρχικοποιεί έναν πίνακα με αντικείμενα Question
*
* @return ο πίνακας με τα αντικείμενα τύπου Question
*/
private Question[] makeQuest() {
sumCursor.moveToFirst();
Question[] Quests = new Question[sumCursor.getInt(0)];
for (int i = 0; i < Quests.length; i++) {
Quests[i] = new Question();
}
return Quests;
}

/**
* Λαμβάνοντας το μήκος του πίνακα των ερωτήσεων υπολογίζει τις απαιτούμενες σωστές απαντήσεις.
*
* @param Quests Ο πίνακας με τις ερωτήσεις
* @return Τον αριθμό των απαιτούμενων σωστών απαντήσεων
*/
private int reqAnswers(Question[] Quests) {
int ReqCorAnswers;
subCursor.moveToFirst();
if (subCursor.getString(0).equals("ΚΩΔΙΚΑΣ")) {
ReqCorAnswers = Quests.length - 2;
} else {
ReqCorAnswers = Quests.length - 1;
}
return ReqCorAnswers;
}

/**
* Γεμίζει μία λίστα με ερωτήσεις που ανήκουν σε μια συγκεκριμένη υποκατηγορία.
*
* @param i Ο αριθμός υποκατηγορίας
* @return Την λίστα με τις ερωτήσεις μιας συγκεκριμένης υποκατηγορίας
*/
private List<Integer> getSubCateg(int i) {
List<Integer> list = new LinkedList<>();
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
if (cursor.getInt(2) == i + 1) {
list.add(cursor.getPosition());
}
cursor.moveToNext();
}
return list;
}

/**
* Χρησιμοποιείται για να γεμίσει τον πίνακα των ερωτήσεων με τυχαίες ερωτήσεις
* και τοποθετεί τις απαντήσεις επίσης με τυχαια σειρά.
*
* @param list η λίστα των ερωτήσεων
* @param ansList η λίστα των απαντήσεων
* @return Το αντικέιμενο τύπου Question που περιέχει όλα τα δεδομένα.
*/
private Question insertQuestions(List<Integer> list, List<Integer> ansList) {
Question quest = new Question();
int numb = new Random().nextInt(list.size());
System.out.println(list.size());
cursor.moveToPosition(list.remove(numb));
ansCursor = sqldb.rawQuery("SELECT ALect,ACorr FROM Answers WHERE AQcod=" + cursor.getInt(0), null);
quest.AText = new String[ansCursor.getCount()];
quest.QNum = cursor.getInt(0);
quest.QText = cursor.getString(3);
if (cursor.getString(4).equals("0")) {
quest.PicName = "-";
} else {
quest.PicName = cursor.getString(4) + ".jpg";
}
for (int k = 0; k < ansCursor.getCount(); k++) {
ansList.add(k);
}
for (int k = 0; k < ansCursor.getCount(); k++) {
int ansNumb = new Random().nextInt(ansList.size());
ansCursor.moveToPosition(ansList.remove(ansNumb));
quest.AText[k] = ansCursor.getString(0);
if (ansCursor.getInt(1) == 1) {
quest.CorAnswer = k;
}
}
return quest;
}

public LinkedHashSet<String> GetPhotos(){
LinkedHashSet<String> lhs = new LinkedHashSet<>();
String MyDB = mcontext.getApplicationContext().getFilesDir().getAbsolutePath() + "/databases/EllakDB.sqlite";
sqldb = SQLiteDatabase.openDatabase(MyDB, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS);
Cursor photoCursor = sqldb.rawQuery("SELECT QPhoto FROM Questions",null);
photoCursor.moveToFirst();
while(!photoCursor.isAfterLast()){
if(!photoCursor.getString(4).equals("0")){
lhs.add(photoCursor.getString(4));
}
photoCursor.moveToNext();
}
photoCursor.close();
return lhs;
}
}


/**
* Παριστά,ως record, ένα γνωστικό αντικείμενο εξέτασης.
*/
class SubjectRec
{
class SubjectRec {
/**
* Ο κωδικός του γνωστικού αντικειμένου εξέτασης.
*/
Expand All @@ -79,8 +321,7 @@ class SubjectRec
/**
* Παριστά, ως Record, μία ερώτηση του ερωτηματολογίου.
*/
class Question
{
class Question {
/**
* Ο Αύξωντας Αριθμός της Ερώτησης στο ερωτηματολόγιο
*/
Expand All @@ -106,8 +347,7 @@ class Question
/**
* Παριστά, ως Record, ένα ολόκληρο ερωτηματολόγιο.
*/
class TestSheet
{
class TestSheet {
/**
* Ο κωδικός του γνωστικού αντικειμένου του ερωτηματολογίου
*/
Expand All @@ -124,4 +364,4 @@ class TestSheet
* Το πλήθος των ερωτήσεων που πρέπει να απαντηθούν σωστά προκειμένου η εξέταση να θεωρηθεί επιτυχής.
*/
int ReqCorAnswers;
}
}