Skip to content

Commit

Permalink
Added new source book
Browse files Browse the repository at this point in the history
- Added option to reset database to initial defaults
- Added spells from Elemental Evil Player's Companion
- Added details and images to README
- Converted sources array to a Map (for short and full name)
  • Loading branch information
dseguin committed Sep 4, 2020
1 parent dbea3fe commit f0e3705
Show file tree
Hide file tree
Showing 14 changed files with 142 additions and 14 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@
/captures
.externalNativeBuild
.cxx
*.swp
56 changes: 54 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,67 @@
D&DB
====

Android app and database for searching and displaying data for Dungeons and Dragons (5e).
![Opening Screen](images/screen1.png) ![Spell List](images/screen2.png) ![Spell Details](images/screen3.png)

Android app and database for searching and displaying data for Dungeons & Dragons (5e).

Pre-built binaries available in the [releases tab](https://github.com/dseguin/dndb/releases/tag/v0.1.0), or download the [latest release directly](https://github.com/dseguin/dndb/releases/download/v0.1.0/dndb-androidapi19-0.1.0.apk).

Spells
------

![Spell Filtering](images/screen4.png) ![Spell Sorting](images/screen5.png)

Spells can be sorted and filtered, and selecting one shows further details. The spells included are only the ones available under the Open Game License.

More spells can be imported from `Settings->Import Source`. These source packages follow a specific format.

Source Package Format
---------------------

[An example source package can be found here](app/src/main/res/raw/srd.zip).

In order to be imported, a source package must be a zip archive with the following structure:
```
Source.zip
↳ Manifest.xml
↳ [other files]
```

The "other files" are specified in `Manifest.xml`. The manifest file sits at the top of the folder structure and contains a list of all other files to be processed by the app.
Here's an example `Manifest.xml`:
```xml
<?xml version="1.0" encoding="utf-8"?>
<Source>
<ShortName>SRD</ShortName>
<Name>Basic Rules</Name>
<Spells>
<AssetFile>spells_SRD_A-G.sql</AssetFile>
<AssetFile>spells_SRD_H-P.sql</AssetFile>
<AssetFile>spells_SRD_R-Z.sql</AssetFile>
<AssetFile>spells_SRD_extra.sql</AssetFile>
</Spells>
</Source>
```

At the moment, all specified asset files are processed as SQLite statements.

D&DB's Database Design
----------------------

D&DB expects SQLite DML statements for adding or updating the internal database. The current database definition [can be found here](app/src/main/res/raw/spells_ddl.sql). There are no enforced foreign keys to maintain compatibility with older versions of SQLite. Just assume that any table named `<table1>_<table2>` is a join table. An example SELECT query can be seen in the comments at the top of the [previously mentioned data definition file](app/src/main/res/raw/spells_ddl.sql).

(entity relationship diagram to be added in the future for reference)

License
-------

Source code specific to D&DB is released under the MIT License.

Data for the "Basic Rules" and other included material is provided by [Wizards of the Coast](https://dnd.wizards.com) under the [Open Game License](https://media.wizards.com/2016/downloads/DND/SRD-OGL_V5.1.pdf).

The "dragon ampersand" is part of the Dungeons & Dragons logo and [is available as a press asset from Wizards of the Coast](https://dnd.wizards.com/pressassets).

This software was developed using Google's Android Studio, which is based on IntelliJ IDEA Community Edition, and released under the Apache v2 License. The software makes use of the Android SDK, which is subject to [the Android SDK terms and conditions](https://developer.android.com/studio/terms).

Other than the base libraries provided by the Android SDK and JDK, all code is original.
Other than the base libraries provided by the Android SDK and JDK, all D&DB code is original and provided under the MIT License.
9 changes: 6 additions & 3 deletions app/src/main/java/ca/printf/dndb/entity/Spell.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import ca.printf.dndb.data.DndbSQLManager;

public class Spell implements Serializable {
Expand Down Expand Up @@ -97,7 +99,8 @@ public class Spell implements Serializable {
private ArrayList<String> atk_types = new ArrayList<>();
private ArrayList<String> dmg_types = new ArrayList<>();
private ArrayList<String> conditions = new ArrayList<>();
private ArrayList<String> sources = new ArrayList<>();
// <SHORTNAME, FULLNAME> (shortname for list/selection, fullname for details)
private Map<String, String> sources = new HashMap<>();
private ArrayList<String> classes = new ArrayList<>();

public Spell(long id) {this.id = id;}
Expand Down Expand Up @@ -125,7 +128,7 @@ public class Spell implements Serializable {
public ArrayList<String> getAtkTypes() {return atk_types;}
public ArrayList<String> getDmgTypes() {return dmg_types;}
public ArrayList<String> getConditions() {return conditions;}
public ArrayList<String> getSources() {return sources;}
public Map<String, String> getSources() {return sources;}
public ArrayList<String> getClasses() {return classes;}

public void setId(long id) {this.id = id;}
Expand All @@ -150,7 +153,7 @@ public class Spell implements Serializable {
public void setAtkTypes(ArrayList<String> atk_types) {this.atk_types = atk_types;}
public void setDmgTypes(ArrayList<String> dmg_types) {this.dmg_types = dmg_types;}
public void setConditions(ArrayList<String> conditions) {this.conditions = conditions;}
public void setSources(ArrayList<String> sources) {this.sources = sources;}
public void setSources(Map<String, String> sources) {this.sources = sources;}
public void setClasses(ArrayList<String> classes) {this.classes = classes;}

private static final String JOIN_SPELL_TABLE(final String TABLE) {
Expand Down
39 changes: 39 additions & 0 deletions app/src/main/java/ca/printf/dndb/view/SettingsFragment.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ca.printf.dndb.view;

import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
Expand All @@ -9,6 +10,8 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import androidx.appcompat.app.AlertDialog;
import androidx.core.util.Supplier;
import androidx.fragment.app.Fragment;
import java.io.FileNotFoundException;
import java.io.IOException;
Expand All @@ -26,13 +29,27 @@ public View onCreateView(LayoutInflater li, ViewGroup vg, Bundle b) {
View v = li.inflate(R.layout.fragment_settings, vg, false);
Button importBtn = v.findViewById(R.id.settings_import_source);
importBtn.setOnClickListener(importBtnListener);
Button resetBtn = v.findViewById(R.id.settings_reset_db);
resetBtn.setOnClickListener(resetBtnListener);
return v;
}

private View.OnClickListener importBtnListener = new View.OnClickListener() {
public void onClick(View v) {showFilePicker();}
};

private View.OnClickListener resetBtnListener = new View.OnClickListener() {
public void onClick(View v) {
Supplier<Void> resetAction = new Supplier<Void>() {
public Void get() {
resetDB();
return null;
}
};
confirmationDialog(getString(R.string.label_settings_reset_db_confim_msg), resetAction);
}
};

// https://riptutorial.com/android/example/14425/showing-a-file-chooser-and-reading-the-result
private void showFilePicker() {
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
Expand All @@ -56,4 +73,26 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.e("onActivityResult", "Error processing SQL in " + data.getData().toString(), e);
}
}

private void resetDB() {
DndbSQLManager dbman = new DndbSQLManager(getContext());
SQLiteDatabase db = dbman.getWritableDatabase();
Log.d("resetDB", "Clearing database with onCreate()");
dbman.onCreate(db);
db.close();
dbman.close();
}

private void confirmationDialog(String msg, final Supplier<Void> confirmAction) {
AlertDialog.Builder confirm = new AlertDialog.Builder(getContext());
confirm.setTitle(R.string.general_confirm_dialog_title);
confirm.setMessage(msg);
confirm.setNegativeButton(R.string.general_button_cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {dialog.dismiss();}
});
confirm.setPositiveButton(R.string.general_button_confirm, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {confirmAction.get();}
});
confirm.create().show();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Collection;
import ca.printf.dndb.R;
import ca.printf.dndb.entity.Spell;

Expand Down Expand Up @@ -65,7 +66,7 @@ public View onCreateView(LayoutInflater li, ViewGroup vg, Bundle b) {
displayStringList(spell.getAtkTypes(), v, R.id.spelldetail_attacks, R.id.spelldetail_attacks_container);
displayStringList(spell.getDmgTypes(), v, R.id.spelldetail_damages, R.id.spelldetail_damages_container);
displayStringList(spell.getConditions(), v, R.id.spelldetail_conditions, R.id.spelldetail_conditions_container);
((TextView)v.findViewById(R.id.spelldetail_sources)).setText(colateStringList(spell.getSources()));
((TextView)v.findViewById(R.id.spelldetail_sources)).setText(colateStringList(spell.getSources().values()));
((TextView)v.findViewById(R.id.spelldetail_classes)).setText(colateStringList(spell.getClasses()));
return v;
}
Expand All @@ -82,7 +83,7 @@ private void displayStringList(ArrayList<String> list, View parent, int textId,
parent.findViewById(containerId).setVisibility(View.VISIBLE);
}

private String colateStringList(ArrayList<String> list) {
private String colateStringList(Collection<String> list) {
String ret = "";
String delim = "";
for(String s : list) {
Expand Down
20 changes: 13 additions & 7 deletions app/src/main/java/ca/printf/dndb/view/SpellsListFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ public void onClick(DialogInterface dialog, int which) {
}
if(!source.contains(getString(R.string.label_spell_filter_source))) {
boolean found = false;
for(String t : s.getSources()) {
for(String t : s.getSources().keySet()) {
if(found = source.equals(t))
break;
}
Expand Down Expand Up @@ -329,7 +329,6 @@ public void onClick(DialogInterface dialog, int which) {
continue;
spellsFiltered.add(s);
}
Log.d("DEBUG", "FILTERED SEARCH");
spells = spellsFiltered;
adapter.setSpells(spells);
adapter.notifyDataSetChanged();
Expand All @@ -347,15 +346,20 @@ private void initSpells() {
}

private void insertDefaultSpells() {
insertSpellsFromResource(R.raw.srd);
insertSpellsFromResource(R.raw.ee);
}

private void insertSpellsFromResource(int rawResourceId) {
SQLiteDatabase db = dbman.getWritableDatabase();
InputStream zip = getResources().openRawResource(R.raw.srd);
InputStream zip = getResources().openRawResource(rawResourceId);
try {
dbman.execZipPackage(db, zip);
} catch (IOException e) {
db.close();
Log.e("initSpells", "Error processing stream R.raw.srd", e);
Log.e("initSpells", "Error processing stream " + getResources().getResourceName(rawResourceId), e);
ErrorFragment.errorScreen(getActivity().getSupportFragmentManager(),
"initSpells: Error processing stream R.raw.srd", e);
"initSpells: Error processing stream " + getResources().getResourceName(rawResourceId), e);
}
db.close();
}
Expand Down Expand Up @@ -423,8 +427,10 @@ private void setSpellMultivalues(Spell s, SQLiteDatabase db) {
s.getConditions().add(row.getString(row.getColumnIndex(stripTableFromCol(Spell.COL_CONDITION))));
row.close();
row = db.rawQuery(Spell.querySource(s.getName()), null);
while(row.moveToNext())
s.getSources().add(row.getString(row.getColumnIndex(stripTableFromCol(Spell.COL_SOURCE_SHORTNAME))));
while(row.moveToNext()) {
s.getSources().put(row.getString(row.getColumnIndex(stripTableFromCol(Spell.COL_SOURCE_SHORTNAME))),
row.getString(row.getColumnIndex(stripTableFromCol(Spell.COL_SOURCE_FULLNAME))));
}
row.close();
row = db.rawQuery(Spell.queryClass(s.getName()), null);
while(row.moveToNext())
Expand Down
21 changes: 21 additions & 0 deletions app/src/main/res/layout/fragment_settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,25 @@
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/colorPrimary"/>
<View
android:layout_width="match_parent"
android:layout_height="10dp"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:backgroundTint="@color/colorAccent"
android:text="@string/label_settings_reset_db"
android:id="@+id/settings_reset_db"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="20dp"
android:text="@string/label_settings_reset_db_desc"/>
<View
android:layout_width="match_parent"
android:layout_height="10dp"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/colorPrimary"/>
</LinearLayout>
Binary file added app/src/main/res/raw/ee.zip
Binary file not shown.
5 changes: 5 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,9 @@
<string name="label_settings_header">Settings</string>
<string name="label_settings_import_source">Import Source</string>
<string name="label_settings_import_source_desc">Loads a sourcebook package and adds it to the current database.</string>
<string name="label_settings_reset_db">Reset Database</string>
<string name="label_settings_reset_db_desc">Deletes all data from the database and refills it with default data.</string>
<string name="general_confirm_dialog_title">Are you sure?</string>
<string name="general_button_confirm">Confirm</string>
<string name="label_settings_reset_db_confim_msg">Are you sure you want to reset your database to initial defaults?</string>
</resources>
Binary file added images/screen1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/screen2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/screen3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/screen4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/screen5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit f0e3705

Please sign in to comment.