Initial commit

This commit is contained in:
Joey Kimsey
2024-08-04 21:15:59 -04:00
parent c9d1fb983f
commit 0d469501ee
695 changed files with 70184 additions and 71 deletions

View File

@ -0,0 +1,43 @@
<?php
/**
* app/plugins/dice/controllers/dice.php
*
* This is the home controller for the dice plugin.
*
* @package TP Dice
* @version 3.0
* @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
*/
namespace TheTempusProject\Controllers;
use TheTempusProject\Houdini\Classes\Views;
use TheTempusProject\Classes\Controller;
use TheTempusProject\Models\Dicehistory;
use TheTempusProject\Houdini\Classes\Issues;
use TheTempusProject\Houdini\Classes\Components;
use TheTempusProject\TheTempusProject as App;
class Dice extends Controller {
protected static $diceHistory;
public function __construct() {
self::$title = 'Dice Rollers - {SITENAME}';
self::$pageDescription = 'These dice should be able to help you roll just about any combination you would encounter in normal play.';
self::$diceHistory = new Dicehistory;
if ( ! App::$isLoggedIn ) {
Issues::add( 'info', 'If you register an account and log in, you can save your dice roll history.' );
Components::set( 'diceHistory', '' );
} else {
$history = self::$diceHistory->userHistory();
$historyView = Views::simpleView( 'dice.historyElement', $history );
Components::set( 'diceHistory', $historyView );
}
parent::__construct();
}
public function index() {
Views::view( 'dice.index' );
}
}

View File

@ -0,0 +1,27 @@
.die-btn {
margin-top: 10px;
margin-bottom: 30px;
width: 145px;
}
.input-number {
width: 185px;
margin-bottom: 10px;
}
.center-inputs {
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
}
.roll-result-well {
margin-top: 20px;
}
.round-footer {
padding-right: 15px;
padding-bottom: 40px;
padding-left: 15px;
}

416
app/plugins/dice/js/dice.js Normal file
View File

@ -0,0 +1,416 @@
const d2Btn = document.getElementById('d2-roll');
const d4Btn = document.getElementById('d4-roll');
const d6Btn = document.getElementById('d6-roll');
const d8Btn = document.getElementById('d8-roll');
const d10Btn = document.getElementById('d10-roll');
const d12Btn = document.getElementById('d12-roll');
const d20Btn = document.getElementById('d20-roll');
const d100Btn = document.getElementById('d100-roll');
const dxBtn = document.getElementById('dx-roll');
const dice = document.getElementById('last-roll-dice');
const mods = document.getElementById('last-roll-dice-with-mods');
const bonuses = document.getElementById('dice-total-with-bonuses');
const total = document.getElementById('dice-total');
const results = document.getElementById('roll-results');
const history = document.getElementById('roll-history');
const rollType = document.getElementById('roll-type');
window.addEventListener('DOMContentLoaded', (event) => {
d2Btn.addEventListener('click', rollD2);
d4Btn.addEventListener('click', rollD4);
d6Btn.addEventListener('click', rollD6);
d8Btn.addEventListener('click', rollD8);
d10Btn.addEventListener('click', rollD10);
d12Btn.addEventListener('click', rollD12);
d20Btn.addEventListener('click', rollD20);
d100Btn.addEventListener('click', rollD100);
dxBtn.addEventListener('click', rollDx);
});
$(document).ready(function() {
$(document).on('click', '.mod-minus', function() {
var inputValue = $(this).closest('.input-group').find('input').val();
var newValue;
if ( inputValue ) {
newValue = parseInt(inputValue, 10) - 1;
} else {
newValue = -1;
}
$(this).closest('.input-group').find('input').val( newValue );
});
$(document).on('click', '.mod-plus', function() {
var inputValue = $(this).closest('.input-group').find('input').val();
var newValue;
if ( inputValue ) {
newValue = parseInt(inputValue, 10) + 1;
} else {
newValue = 1;
}
$(this).closest('.input-group').find('input').val( newValue );
});
$(document).on('click', '.bonus-minus', function() {
var inputValue = $(this).closest('.input-group').find('input').val();
var newValue;
if ( inputValue ) {
newValue = parseInt(inputValue, 10) - 1;
} else {
newValue = -1;
}
$(this).closest('.input-group').find('input').val( newValue );
});
$(document).on('click', '.bonus-plus', function() {
var inputValue = $(this).closest('.input-group').find('input').val();
var newValue;
if ( inputValue ) {
newValue = parseInt(inputValue, 10) + 1;
} else {
newValue = 1;
}
$(this).closest('.input-group').find('input').val( newValue );
});
$(document).on('click', '.die-minus', function() {
var inputValue = $(this).closest('.input-group').find('input').val();
var newValue;
if ( '1' == inputValue ) {
return;
}
if ( !inputValue ) {
newValue = '1';
} else {
newValue = parseInt(inputValue, 10) - 1;
}
$(this).closest('.input-group').find('input').val( newValue );
});
$(document).on('click', '.die-plus', function() {
var inputValue = $(this).closest('.input-group').find('input').val();
var newValue;
if ( inputValue ) {
newValue = parseInt(inputValue, 10) + 1;
} else {
newValue = 2;
}
$(this).closest('.input-group').find('input').val( newValue );
});
$(document).on('click', '.face-minus', function() {
var inputValue = $(this).closest('.input-group').find('input').val();
var newValue;
if ( '2' == inputValue ) {
return;
}
if ( !inputValue ) {
newValue = '2';
} else {
newValue = parseInt(inputValue, 10) - 1;
}
$(this).closest('.input-group').find('input').val( newValue );
});
$(document).on('click', '.face-plus', function() {
var inputValue = $(this).closest('.input-group').find('input').val();
var newValue;
if ( inputValue ) {
newValue = parseInt(inputValue, 10) + 1;
} else {
newValue = 3;
}
$(this).closest('.input-group').find('input').val( newValue );
});
$(document).on('click', '.history-remove', function() {
$(this).closest('tr').remove();
});
$(document).on('click', '#history-clear', function() {
$('#roll-history-table').empty();
});
});
const rollD2 = async function (event) {
event.preventDefault();
var resultDiv = document.getElementById('d2-last-roll');
var dieCount = document.getElementById('d2-die-count').value;
let rolls = [];
if ( !dieCount ) {
dieCount = 1;
}
for (let index = 0; index < dieCount; index++) {
var roll = getRandomInt( 1, 3 );
if ( roll > 1 ) {
roll = 'Heads';
} else {
roll = 'Tails';
}
rolls.push( roll );
}
resetResults();
updateLastRollDice( rolls );
rollType.innerText = 'Coin';
resultDiv.innerText = rolls.filter(result => result === 'Heads').length + ' ("Heads")';
addRollHistory();
}
const rollD4 = async function (event) {
event.preventDefault();
var resultDiv = document.getElementById('d4-last-roll');
var mod = document.getElementById('d4-mod').value;
var bonus = document.getElementById('d4-bonus').value;
var dieCount = document.getElementById('d4-die-count').value;
let rolls = [];
if ( !dieCount ) {
dieCount = 1;
}
for (let index = 0; index < dieCount; index++) {
rolls.push( getRandomInt( 1, 5 ) );
}
updateLastRoll( rolls, mod, bonus );
rollType.innerText = 'D4';
resultDiv.innerText = calculateTotalWithModAndBonus( rolls, mod, bonus );
addRollHistory();
}
const rollD6 = async function (event) {
event.preventDefault();
var resultDiv = document.getElementById('d6-last-roll');
var mod = document.getElementById('d6-mod').value;
var bonus = document.getElementById('d6-bonus').value;
var dieCount = document.getElementById('d6-die-count').value;
let rolls = [];
if ( !dieCount ) {
dieCount = 1;
}
for (let index = 0; index < dieCount; index++) {
rolls.push( getRandomInt( 1, 7 ) );
}
updateLastRoll( rolls, mod, bonus );
rollType.innerText = 'D6';
resultDiv.innerText = calculateTotalWithModAndBonus( rolls, mod, bonus );
addRollHistory();
}
const rollD8 = async function (event) {
event.preventDefault();
var resultDiv = document.getElementById('d8-last-roll');
var mod = document.getElementById('d8-mod').value;
var bonus = document.getElementById('d8-bonus').value;
var dieCount = document.getElementById('d8-die-count').value;
let rolls = [];
if ( !dieCount ) {
dieCount = 1;
}
for (let index = 0; index < dieCount; index++) {
rolls.push( getRandomInt( 1, 9 ) );
}
updateLastRoll( rolls, mod, bonus );
rollType.innerText = 'D8';
resultDiv.innerText = calculateTotalWithModAndBonus( rolls, mod, bonus );
addRollHistory();
}
const rollD10 = async function (event) {
event.preventDefault();
var resultDiv = document.getElementById('d10-last-roll');
var mod = document.getElementById('d10-mod').value;
var bonus = document.getElementById('d10-bonus').value;
var dieCount = document.getElementById('d10-die-count').value;
let rolls = [];
if ( !dieCount ) {
dieCount = 1;
}
for (let index = 0; index < dieCount; index++) {
rolls.push( getRandomInt( 1, 11 ) );
}
updateLastRoll( rolls, mod, bonus );
rollType.innerText = 'D10';
resultDiv.innerText = calculateTotalWithModAndBonus( rolls, mod, bonus );
addRollHistory();
}
const rollD12 = async function (event) {
event.preventDefault();
var resultDiv = document.getElementById('d12-last-roll');
var mod = document.getElementById('d12-mod').value;
var bonus = document.getElementById('d12-bonus').value;
var dieCount = document.getElementById('d12-die-count').value;
let rolls = [];
if ( !dieCount ) {
dieCount = 1;
}
for (let index = 0; index < dieCount; index++) {
rolls.push( getRandomInt( 1, 13 ) );
}
updateLastRoll( rolls, mod, bonus );
rollType.innerText = 'D12';
resultDiv.innerText = calculateTotalWithModAndBonus( rolls, mod, bonus );
addRollHistory();
}
const rollD20 = async function (event) {
event.preventDefault();
var resultDiv = document.getElementById('d20-last-roll');
var mod = document.getElementById('d20-mod').value;
var bonus = document.getElementById('d20-bonus').value;
var dieCount = document.getElementById('d20-die-count').value;
let rolls = [];
if ( !dieCount ) {
dieCount = 1;
}
for (let index = 0; index < dieCount; index++) {
rolls.push( getRandomInt( 1, 21 ) );
}
updateLastRoll( rolls, mod, bonus );
rollType.innerText = 'D20';
resultDiv.innerText = calculateTotalWithModAndBonus( rolls, mod, bonus );
addRollHistory();
}
const rollD100 = async function (event) {
event.preventDefault();
var resultDiv = document.getElementById('d100-last-roll');
var mod = document.getElementById('d100-mod').value;
var bonus = document.getElementById('d100-bonus').value;
var dieCount = document.getElementById('d100-die-count').value;
let rolls = [];
if ( !dieCount ) {
dieCount = 1;
}
for (let index = 0; index < dieCount; index++) {
rolls.push( getRandomInt( 1, 101 ) );
}
updateLastRoll( rolls, mod, bonus );
rollType.innerText = 'Percentile';
resultDiv.innerText = calculateTotalWithModAndBonus( rolls, mod, bonus );
addRollHistory();
}
const rollDx = async function (event) {
event.preventDefault();
var resultDiv = document.getElementById('dx-last-roll');
var mod = document.getElementById('dx-mod').value;
var bonus = document.getElementById('dx-bonus').value;
var faceCount = document.getElementById('dx-face-count').value;
var dieCount = document.getElementById('dx-die-count').value;
let rolls = [];
if ( !dieCount ) {
dieCount = 1;
}
if ( !faceCount ) {
faceCount = 2;
}
faceCount++;
for (let index = 0; index < dieCount; index++) {
rolls.push( getRandomInt( 1, faceCount ) );
}
updateLastRoll( rolls, mod, bonus );
rollType.innerText = 'D' + faceCount;
resultDiv.innerText = calculateTotalWithModAndBonus( rolls, mod, bonus );
addRollHistory();
}
function getRandomInt(min, max) {
const minCeiled = Math.ceil(min);
const maxFloored = Math.floor(max);
return Math.floor(Math.random() * (maxFloored - minCeiled) + minCeiled);
}
function resetResults() {
dice.innerHTML = '';
mods.innerHTML = '';
bonuses.innerHTML = '';
total.innerHTML = '';
}
function updateLastRollDiceMod( rolls, mod ) {
if (!rolls) {
rolls = [];
}
if (!mod) {
mod = 0;
}
var rollsStringWithMods = '';
for (let i = 0; i < rolls.length; i++) {
rollsStringWithMods = rollsStringWithMods + '<b>' + ( parseInt( rolls[i] ) + parseInt( mod )) + '</b> (' + rolls[i] + '+' + mod + '), ';
}
mods.innerHTML = rollsStringWithMods;
}
function updateLastRollDice( rolls ) {
results.style.display = '';
if (!rolls) {
rolls = [];
}
var rollsString = rolls.join(', ');
dice.innerHTML = rollsString + ' <b>('+rolls.length+')</b>';
}
function addRollHistory() {
history.style.display = '';
var tpeValue = rollType.innerText
var diceValue = dice.innerHTML
var modsValue = mods.innerHTML
var totalValue = total.innerHTML
var bonusesValue = bonuses.innerHTML
var rollList = document.getElementById('roll-history-table');
var row = document.createElement('tr');
row.innerHTML = `
<td class="text-center">${tpeValue}</td>
<td class="text-center">${diceValue}</td>
<td class="text-center">${modsValue}</td>
<td class="text-center">${totalValue}</td>
<td class="text-center">${bonusesValue}</td>
<td class="text-right"><button class="btn btn-danger btn-sm history-remove" aria-label="Remove "><span class="glyphicon glyphicon-trash"></span></button></td>
`;
var firstRow = rollList.rows[0];
if (firstRow) {
rollList.insertBefore(row, firstRow);
} else {
rollList.appendChild(row);
}
}
function updateLastRollTotal( rolls ) {
if (!rolls) {
rolls = [];
}
var sum = rolls.reduce((total, currentValue) => total + currentValue, 0);
total.innerHTML = '<b>' + sum + '</b>';
}
function calculateTotalWithModAndBonus( rolls, mod, bonus ) {
if (!rolls) {
rolls = [];
}
if (!bonus) {
bonus = 0;
}
if (!mod) {
mod = 0;
}
var sum = rolls.reduce((total, currentValue) => total + currentValue, 0);
var sumWithMods;
if ( 0 == mod ) {
sumWithMods = sum;
} else {
sumWithMods = parseInt(sum) + ( rolls.length * parseInt(mod) );
}
var total = parseInt(sumWithMods) + parseInt(bonus);
return total;
}
function updateLastRoll( rolls, mod, bonus ) {
resetResults();
updateLastRollDice( rolls );
updateLastRollDiceMod( rolls, mod );
updateLastRollTotal( rolls );
var sum = rolls.reduce((total, currentValue) => total + currentValue, 0);
if (!bonus) {
bonus = '0';
}
if (!mod) {
mod = '0';
}
bonuses.innerHTML = '<b>' + calculateTotalWithModAndBonus( rolls, mod, bonus ) + '</b> ( '+sum+' + ( '+rolls.length+' * '+mod+' ) + '+bonus+' )';
}

View File

@ -0,0 +1,116 @@
<?php
/**
* app/plugins/feedback/models/feedback.php
*
* This class is used for the manipulation of the feedback database table.
*
* @todo make this send a confirmation email
*
* @package TP Feedback
* @version 3.0
* @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
*/
namespace TheTempusProject\Models;
use TheTempusProject\Bedrock\Classes\Config;
use TheTempusProject\Bedrock\Functions\Check;
use TheTempusProject\Canary\Canary as Debug;
use TheTempusProject\Classes\DatabaseModel;
use TheTempusProject\Plugins\Feedback as Plugin;
use TheTempusProject\TheTempusProject as App;
class Dicehistory extends DatabaseModel {
public $tableName = 'feedback';
public $databaseMatrix = [
[ 'name', 'varchar', '128' ],
[ 'time', 'int', '10' ],
[ 'email', 'varchar', '128' ],
[ 'ip', 'varchar', '64' ],
[ 'feedback', 'text', '' ],
// face_count ( d2, d20, d100, etc.. )
// die_count ( how many dice were rolled )
// dice_values ( json array of the dice values )
// bonus
// modifier
// roll_total ( all dice added together )
// modified_total ( all dice added together with modifiers )
// final_total ( all dice added together, with modifiers, and bonus )
// userID
// createdAt
];
public $plugin;
/**
* The model constructor.
*/
public function __construct() {
parent::__construct();
$this->plugin = new Plugin;
}
/**
* Saves a feedback form to the db.
*
* @param string $name -the name on the form
* @param string $email -the email provided
* @param string $feedback -contents of the feedback form.
* @return bool
*/
public function create( $name, $email, $feedback ) {
if ( !$this->plugin->checkEnabled() ) {
Debug::info( 'Feedback is disabled in the config.' );
return false;
}
$fields = [
'name' => $name,
'email' => $email,
'feedback' => $feedback,
'time' => time(),
'ip' => $_SERVER['REMOTE_ADDR'],
];
if ( !self::$db->insert( $this->tableName, $fields ) ) {
Debug::info( 'Feedback::create - failed to insert to db' );
return false;
}
return self::$db->lastId();
}
/**
* Function to clear feedback from the DB.
*
* @todo is there a way i could check for success here I'm pretty sure this is just a bad idea?
* @return bool
*/
public function clear() {
if ( empty( self::$log ) ) {
self::$log = new Log;
}
self::$db->delete( $this->tableName, ['ID', '>=', '0'] );
self::$log->admin( 'Cleared Feedback' );
Debug::info( 'Feedback Cleared' );
return true;
}
public function userHistory( $limit = 0 ) {
$whereClause = [
'userID', '=', App::$activeUser->ID,
'AND',
'deletedAt', '=', '0',
'AND',
'expiresAt', '<', time(),
];
if ( empty( $limit ) ) {
$notifications = self::$db->get( $this->tableName, $whereClause );
} else {
$notifications = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [0, $limit] );
}
if ( !$notifications->count() ) {
Debug::info( 'No Notifications found.' );
return false;
}
return $this->filter( $notifications->results() );
}
}

View File

@ -0,0 +1,44 @@
<?php
/**
* app/plugins/dice/plugin.php
*
* This houses all of the main plugin info and functionality.
*
* @package TP Dice
* @version 3.0
* @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
*/
namespace TheTempusProject\Plugins;
use TheTempusProject\Classes\Plugin;
class Dice extends Plugin {
public $pluginName = 'TP Dice';
public $pluginAuthor = 'JoeyK';
public $pluginWebsite = 'https://TheTempusProject.com';
public $modelVersion = '1.0';
public $pluginVersion = '3.0';
public $pluginDescription = 'A simple plugin which adds various dice for tabletop gaming.';
public $configName = 'dice';
public $configMatrix = [
'enabled' => [
'type' => 'radio',
'pretty' => 'Enable dice usage.',
'default' => true,
],
];
public $permissionMatrix = [
'dice' => [
'pretty' => 'Can use dice',
'default' => true,
],
];
public $main_links = [
[
'text' => 'Dice',
'url' => '{ROOT_URL}dice/index',
],
];
}

View File

@ -0,0 +1,13 @@
{LOOP}
<tr data-id="{ID}">
<th class="text-center">Roll Type</th>
<th class="text-center">Dice Values</th>
<th class="text-center">Modified Dice Values</th>
<th class="text-center">Dice Total</th>
<th class="text-center">Modified Total</th>
<th></th>
</tr>
{/LOOP}
{ALT}
<tr><td colspan="6" class="text-center">No rolls have been saved / made yet.</td></tr>
{/ALT}

View File

@ -0,0 +1,429 @@
<link rel="stylesheet" href="{ROOT_URL}app/plugins/dice/css/dice.css" crossorigin="anonymous">
<script src="{ROOT_URL}app/plugins/dice/js/dice.js" type="module" defer></script>
<h1 class="text-center">Dice</h1>
<div id="roll-results" class="row well well-sm" style="display: none;">
<dl class="dl-horizontal roll-result-well">
<dt>Dice</dt>
<dd id="last-roll-dice"></dd>
<dt>Dice (with Modifiers)</dt>
<dd id="last-roll-dice-with-mods"></dd>
<dt>Dice Total</dt>
<dd id="dice-total"></dd>
<dt>Total Value</dt>
<dd id="dice-total-with-bonuses"></dd>
</dl>
<div id="roll-type" style="display: none;"></div>
</div>
<div class="row">
<!-- Coin Flip -->
<div class="col-lg-4 center-inputs">
<div class="col-lg-12 text-center">
<label class="sr-only" for="d2-last-roll">Last Flip</label>
<h3 id="d2-last-roll">-</h3>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d2-die-count">Coin Count</label>
<div class="input-group-btn">
<button id="d2-minus" class="die-minus btn btn-danger" aria-label="Remove Die">-</button>
</div>
<input type="number" id="d2-die-count" name="d2-die-count" class="form-control" autocomplete="on" aria-label="Coin Count" placeholder="Coin Count">
<div class="input-group-btn">
<button id="d2-plus" class="die-plus btn btn-success" aria-label="Add Die">+</button>
</div>
</div>
<div class="col-lg-12 text-center">
<button id="d2-roll" class="d2-die die-btn btn btn-primary">
Flip Coin(s)
</button>
</div>
</div>
<!-- D4 -->
<div class="col-lg-4 center-inputs">
<div class="col-lg-12 text-center">
<label class="sr-only" for="d4-last-roll">Last Roll</label>
<h3 id="d4-last-roll">0</h3>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d4-die-count">Die Count</label>
<div class="input-group-btn">
<button id="d4-minus" class="die-minus btn btn-danger" aria-label="Remove Die">-</button>
</div>
<input type="number" id="d4-die-count" name="d4-die-count" class="form-control" autocomplete="on" aria-label="Die Count" placeholder="Die Count">
<div class="input-group-btn">
<button id="d4-plus" class="die-plus btn btn-success" aria-label="Add Die">+</button>
</div>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d4-mod">Modifier</label>
<div class="input-group-btn">
<button id="d4-mod-minus" class="mod-minus btn btn-danger" aria-label="Decrease Modifier">-</button>
</div>
<input type="number" id="d4-mod" name="d4-mod" class="form-control" autocomplete="on" aria-label="Modifier" placeholder="Modifier">
<div class="input-group-btn">
<button id="d4-mod-plus" class="mod-plus btn btn-success" aria-label="Increase Modifier">+</button>
</div>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d4-bonus">Bonus</label>
<div class="input-group-btn">
<button id="d4-bonus-minus" class="bonus-minus btn btn-danger" aria-label="Decrease Bonus">-</button>
</div>
<input type="number" id="d4-bonus" name="d4-bonus" class="form-control" autocomplete="on" aria-label="Bonus" placeholder="Bonus">
<div class="input-group-btn">
<button id="d4-bonus-plus" class="bonus-plus btn btn-success" aria-label="Increase Bonus">+</button>
</div>
</div>
<div class="col-lg-12 text-center">
<button id="d4-roll" class="d4-die die-btn btn btn-primary">
D4
</button>
</div>
</div>
<!-- D6 -->
<div class="col-lg-4 center-inputs">
<div class="col-lg-12 text-center">
<label class="sr-only" for="d6-last-roll">Last Roll</label>
<h3 id="d6-last-roll">0</h3>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d6-die-count">Die Count</label>
<div class="input-group-btn">
<button id="d6-minus" class="die-minus btn btn-danger" aria-label="Remove Die">-</button>
</div>
<input type="number" id="d6-die-count" name="d6-die-count" class="form-control" autocomplete="on" aria-label="Die Count" placeholder="Die Count">
<div class="input-group-btn">
<button id="d6-plus" class="die-plus btn btn-success" aria-label="Add Die">+</button>
</div>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d6-mod">Modifier</label>
<div class="input-group-btn">
<button id="d6-mod-minus" class="mod-minus btn btn-danger" aria-label="Decrease Modifier">-</button>
</div>
<input type="number" id="d6-mod" name="d6-mod" class="form-control" autocomplete="on" aria-label="Modifier" placeholder="Modifier">
<div class="input-group-btn">
<button id="d6-mod-plus" class="mod-plus btn btn-success" aria-label="Increase Modifier">+</button>
</div>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d6-bonus">Bonus</label>
<div class="input-group-btn">
<button id="d6-bonus-minus" class="bonus-minus btn btn-danger" aria-label="Decrease Bonus">-</button>
</div>
<input type="number" id="d6-bonus" name="d6-bonus" class="form-control" autocomplete="on" aria-label="Bonus" placeholder="Bonus">
<div class="input-group-btn">
<button id="d6-bonus-plus" class="bonus-plus btn btn-success" aria-label="Increase Bonus">+</button>
</div>
</div>
<div class="col-lg-12 text-center">
<button id="d6-roll" class="d6-die die-btn btn btn-primary">
D6
</button>
</div>
</div>
<!-- D8 -->
<div class="col-lg-4 center-inputs">
<div class="col-lg-12 text-center">
<label class="sr-only" for="d8-last-roll">Last Roll</label>
<h3 id="d8-last-roll">0</h3>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d8-die-count">Die Count</label>
<div class="input-group-btn">
<button id="d8-minus" class="die-minus btn btn-danger" aria-label="Remove Die">-</button>
</div>
<input type="number" id="d8-die-count" name="d8-die-count" class="form-control" autocomplete="on" aria-label="Die Count" placeholder="Die Count">
<div class="input-group-btn">
<button id="d8-plus" class="die-plus btn btn-success" aria-label="Add Die">+</button>
</div>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d8-mod">Modifier</label>
<div class="input-group-btn">
<button id="d8-mod-minus" class="mod-minus btn btn-danger" aria-label="Decrease Modifier">-</button>
</div>
<input type="number" id="d8-mod" name="d8-mod" class="form-control" autocomplete="on" aria-label="Modifier" placeholder="Modifier">
<div class="input-group-btn">
<button id="d8-mod-plus" class="mod-plus btn btn-success" aria-label="Increase Modifier">+</button>
</div>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d8-bonus">Bonus</label>
<div class="input-group-btn">
<button id="d8-bonus-minus" class="bonus-minus btn btn-danger" aria-label="Decrease Bonus">-</button>
</div>
<input type="number" id="d8-bonus" name="d8-bonus" class="form-control" autocomplete="on" aria-label="Bonus" placeholder="Bonus">
<div class="input-group-btn">
<button id="d8-bonus-plus" class="bonus-plus btn btn-success" aria-label="Increase Bonus">+</button>
</div>
</div>
<div class="col-lg-12 text-center">
<button id="d8-roll" class="d8-die die-btn btn btn-primary">
D8
</button>
</div>
</div>
<!-- D10 -->
<div class="col-lg-4 center-inputs">
<div class="col-lg-12 text-center">
<label class="sr-only" for="d10-last-roll">Last Roll</label>
<h3 id="d10-last-roll">0</h3>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d10-die-count">Die Count</label>
<div class="input-group-btn">
<button id="d10-minus" class="die-minus btn btn-danger" aria-label="Remove Die">-</button>
</div>
<input type="number" id="d10-die-count" name="d10-die-count" class="form-control" autocomplete="on" aria-label="Die Count" placeholder="Die Count">
<div class="input-group-btn">
<button id="d10-plus" class="die-plus btn btn-success" aria-label="Add Die">+</button>
</div>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d10-mod">Modifier</label>
<div class="input-group-btn">
<button id="d10-mod-minus" class="mod-minus btn btn-danger" aria-label="Decrease Modifier">-</button>
</div>
<input type="number" id="d10-mod" name="d10-mod" class="form-control" autocomplete="on" aria-label="Modifier" placeholder="Modifier">
<div class="input-group-btn">
<button id="d10-mod-plus" class="mod-plus btn btn-success" aria-label="Increase Modifier">+</button>
</div>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d10-bonus">Bonus</label>
<div class="input-group-btn">
<button id="d10-bonus-minus" class="bonus-minus btn btn-danger" aria-label="Decrease Bonus">-</button>
</div>
<input type="number" id="d10-bonus" name="d10-bonus" class="form-control" autocomplete="on" aria-label="Bonus" placeholder="Bonus">
<div class="input-group-btn">
<button id="d10-bonus-plus" class="bonus-plus btn btn-success" aria-label="Increase Bonus">+</button>
</div>
</div>
<div class="col-lg-12 text-center">
<button id="d10-roll" class="d10-die die-btn btn btn-primary">
D10
</button>
</div>
</div>
<!-- D12 -->
<div class="col-lg-4 center-inputs">
<div class="col-lg-12 text-center">
<label class="sr-only" for="d12-last-roll">Last Roll</label>
<h3 id="d12-last-roll">0</h3>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d12-die-count">Die Count</label>
<div class="input-group-btn">
<button id="d12-minus" class="die-minus btn btn-danger" aria-label="Remove Die">-</button>
</div>
<input type="number" id="d12-die-count" name="d12-die-count" class="form-control" autocomplete="on" aria-label="Die Count" placeholder="Die Count">
<div class="input-group-btn">
<button id="d12-plus" class="die-plus btn btn-success" aria-label="Add Die">+</button>
</div>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d12-mod">Modifier</label>
<div class="input-group-btn">
<button id="d12-mod-minus" class="mod-minus btn btn-danger" aria-label="Decrease Modifier">-</button>
</div>
<input type="number" id="d12-mod" name="d12-mod" class="form-control" autocomplete="on" aria-label="Modifier" placeholder="Modifier">
<div class="input-group-btn">
<button id="d12-mod-plus" class="mod-plus btn btn-success" aria-label="Increase Modifier">+</button>
</div>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d12-bonus">Bonus</label>
<div class="input-group-btn">
<button id="d12-bonus-minus" class="bonus-minus btn btn-danger" aria-label="Decrease Bonus">-</button>
</div>
<input type="number" id="d12-bonus" name="d12-bonus" class="form-control" autocomplete="on" aria-label="Bonus" placeholder="Bonus">
<div class="input-group-btn">
<button id="d12-bonus-plus" class="bonus-plus btn btn-success" aria-label="Increase Bonus">+</button>
</div>
</div>
<div class="col-lg-12 text-center">
<button id="d12-roll" class="d12-die die-btn btn btn-primary">
D12
</button>
</div>
</div>
<!-- D20 -->
<div class="col-lg-4 center-inputs">
<div class="col-lg-12 text-center">
<label class="sr-only" for="d20-last-roll">Last Roll</label>
<h3 id="d20-last-roll">0</h3>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d20-die-count">Die Count</label>
<div class="input-group-btn">
<button id="d20-minus" class="die-minus btn btn-danger" aria-label="Remove Die">-</button>
</div>
<input type="number" id="d20-die-count" name="d20-die-count" class="form-control" autocomplete="on" aria-label="Die Count" placeholder="Die Count">
<div class="input-group-btn">
<button id="d20-plus" class="die-plus btn btn-success" aria-label="Add Die">+</button>
</div>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d20-mod">Modifier</label>
<div class="input-group-btn">
<button id="d20-mod-minus" class="mod-minus btn btn-danger" aria-label="Decrease Modifier">-</button>
</div>
<input type="number" id="d20-mod" name="d20-mod" class="form-control" autocomplete="on" aria-label="Modifier" placeholder="Modifier">
<div class="input-group-btn">
<button id="d20-mod-plus" class="mod-plus btn btn-success" aria-label="Increase Modifier">+</button>
</div>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d20-bonus">Bonus</label>
<div class="input-group-btn">
<button id="d20-bonus-minus" class="bonus-minus btn btn-danger" aria-label="Decrease Bonus">-</button>
</div>
<input type="number" id="d20-bonus" name="d20-bonus" class="form-control" autocomplete="on" aria-label="Bonus" placeholder="Bonus">
<div class="input-group-btn">
<button id="d20-bonus-plus" class="bonus-plus btn btn-success" aria-label="Increase Bonus">+</button>
</div>
</div>
<div class="col-lg-12 text-center">
<button id="d20-roll" class="d20-die die-btn btn btn-primary">
D20
</button>
</div>
</div>
<!-- Percentile -->
<div class="col-lg-4 center-inputs">
<div class="col-lg-12 text-center">
<label class="sr-only" for="d100-last-roll">Last Roll</label>
<h3 id="d100-last-roll">0</h3>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d100-die-count">Die Count</label>
<div class="input-group-btn">
<button id="d100-minus" class="die-minus btn btn-danger" aria-label="Remove Die">-</button>
</div>
<input type="number" id="d100-die-count" name="d100-die-count" class="form-control" autocomplete="on" aria-label="Die Count" placeholder="Die Count">
<div class="input-group-btn">
<button id="d100-plus" class="die-plus btn btn-success" aria-label="Add Die">+</button>
</div>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d100-mod">Modifier</label>
<div class="input-group-btn">
<button id="d100-mod-minus" class="mod-minus btn btn-danger" aria-label="Decrease Modifier">-</button>
</div>
<input type="number" id="d100-mod" name="d100-mod" class="form-control" autocomplete="on" aria-label="Modifier" placeholder="Modifier">
<div class="input-group-btn">
<button id="d100-mod-plus" class="mod-plus btn btn-success" aria-label="Increase Modifier">+</button>
</div>
</div>
<div class="input-group input-number">
<label class="sr-only" for="d100-bonus">Bonus</label>
<div class="input-group-btn">
<button id="d100-bonus-minus" class="bonus-minus btn btn-danger" aria-label="Decrease Bonus">-</button>
</div>
<input type="number" id="d100-bonus" name="d100-bonus" class="form-control" autocomplete="on" aria-label="Bonus" placeholder="Bonus">
<div class="input-group-btn">
<button id="d100-bonus-plus" class="bonus-plus btn btn-success" aria-label="Increase Bonus">+</button>
</div>
</div>
<div class="col-lg-12 text-center">
<button id="d100-roll" class="d100-die die-btn btn btn-primary">
Percentile (D-100)
</button>
</div>
</div>
<!-- Custom Die -->
<div class="col-lg-4 center-inputs">
<div class="col-lg-12 text-center">
<label class="sr-only" for="dx-last-roll">Last Roll</label>
<h3 id="dx-last-roll">0</h3>
</div>
<div class="input-group input-number">
<label class="sr-only" for="dx-face-count">Face Count</label>
<div class="input-group-btn">
<button id="dx-minus" class="face-minus btn btn-danger" aria-label="Remove Face">-</button>
</div>
<input type="number" id="dx-face-count" name="dx-face-count" class="form-control" autocomplete="on" aria-label="Face Count" placeholder="Face Count">
<div class="input-group-btn">
<button id="dx-plus" class="face-plus btn btn-success" aria-label="Add Face">+</button>
</div>
</div>
<div class="input-group input-number">
<label class="sr-only" for="dx-die-count">Die Count</label>
<div class="input-group-btn">
<button id="dx-minus" class="die-minus btn btn-danger" aria-label="Remove Die">-</button>
</div>
<input type="number" id="dx-die-count" name="dx-die-count" class="form-control" autocomplete="on" aria-label="Die Count" placeholder="Die Count">
<div class="input-group-btn">
<button id="dx-plus" class="die-plus btn btn-success" aria-label="Add Die">+</button>
</div>
</div>
<div class="input-group input-number">
<label class="sr-only" for="dx-mod">Modifier</label>
<div class="input-group-btn">
<button id="dx-mod-minus" class="mod-minus btn btn-danger" aria-label="Decrease Modifier">-</button>
</div>
<input type="number" id="dx-mod" name="dx-mod" class="form-control" autocomplete="on" aria-label="Modifier" placeholder="Modifier">
<div class="input-group-btn">
<button id="dx-mod-plus" class="mod-plus btn btn-success" aria-label="Increase Modifier">+</button>
</div>
</div>
<div class="input-group input-number">
<label class="sr-only" for="dx-bonus">Bonus</label>
<div class="input-group-btn">
<button id="dx-bonus-minus" class="bonus-minus btn btn-danger" aria-label="Decrease Bonus">-</button>
</div>
<input type="number" id="dx-bonus" name="dx-bonus" class="form-control" autocomplete="on" aria-label="Bonus" placeholder="Bonus">
<div class="input-group-btn">
<button id="dx-bonus-plus" class="bonus-plus btn btn-success" aria-label="Increase Bonus">+</button>
</div>
</div>
<div class="col-lg-12 text-center">
<button id="dx-roll" class="dx-die die-btn btn btn-primary">
Custom (D-X)
</button>
</div>
</div>
</div>
<!-- Roll History -->
<div id="roll-history" class="row" style="display: none;">
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">Roll History</h3>
</div>
<div class="panel-body">
<table class="table table-striped">
<thead>
<tr>
<th class="text-center">Roll Type</th>
<th class="text-center">Dice Values</th>
<th class="text-center">Modified Dice Values</th>
<th class="text-center">Dice Total</th>
<th class="text-center">Modified Total</th>
<th></th>
</tr>
</thead>
<tbody id="roll-history-table">
{diceHistory}
</tbody>
</table>
</div>
<div class="panel-footer round-footer">
<span class="pull-right">
<button id="history-clear" class="btn btn-danger">
Clear History
</button>
</span>
</div>
</div>
</div>