Skip to content

Instantly share code, notes, and snippets.

@ichi
Last active October 14, 2015 19:05
Show Gist options
  • Select an option

  • Save ichi/38739cd006e316a2b177 to your computer and use it in GitHub Desktop.

Select an option

Save ichi/38739cd006e316a2b177 to your computer and use it in GitHub Desktop.
<!doctype html>
<html>
<head>
<title>pathfinder dice</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
<style type="text/css">
.cols{
display: table;
width: 100%;
}
.cols .col{
display: table-cell;
padding: 0 7px;
vertical-align: top;
}
.cols .col:first-child{
padding-left: 0;
}
.cols .col:last-child{
padding-right: 0;
}
.form-horizontal .control-label{
padding-top: 7px;
}
section.container-fluid{
margin-bottom: 15px;
padding-bottom: 15px;
border-bottom: 1px solid #ccc;
}
section.container-fluid > h4:first-child{
margin-top: 0;
}
header.global{
margin-bottom: 0;
}
section.dice_list{
}
.dice_list .dice{
padding: 15px 15px 0;
border-bottom: 1px solid #ccc;
}
.dice_list .dice .cols{
margin: 0 0 15px;
}
.dice_list .dice .controls .col_customize{
width: 100%;
}
.dice_list .dice .controls .col_del{
text-align: right;
white-space: nowrap;
}
.dice_list .btn_add{
margin: 15px 0 0;
}
section.modified{
padding-bottom: 0;
}
.modified .form-horizontal .control-label{
text-align: left;
}
section.roll_dice{
}
footer.global{
margin-top: -15px;
padding-top: 15px;
margin-bottom: 0;
}
</style>
</head>
<body>
<header class="global navbar navbar-default navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<div class="navbar-brand"><i class="fa fa-square-o fa-spin"></i> Dice</div>
</div>
</div>
</header>
<div id="dice-calculator"></div>
<script type="text/template" id="dice-calculator-template">
<div class="contents">
<section class="dice_list container-fluid">
<dice v-repeat="diceList" v-ref="diceList" remove-dice="{{ removeDice }}" modified-each="{{ modifiedEach }}"></dice>
<button class="btn_add btn btn-info btn-block" v-on="click: addDice"><i class="fa fa-plus"></i> Add dice</button>
</section>
<section class="modified container-fluid">
<h4><i class="fa fa-arrows-v"></i> Modified</h4>
<div class="form-horizontal">
<div class="form-group">
<label class="control-label col-xs-3">Each</label>
<div class="col-xs-9">
<input-num model="{{@ modifiedEach }}"></input-num>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-3">Total</label>
<div class="col-xs-9">
<input-num model="{{@ modified }}"></input-num>
</div>
</div>
</div>
</section>
<section class="expected container-fluid">
<h4><i class="fa fa-calculator"></i> Expected</h4>
<div v-show="expected">
<ul>
<li v-repeat="expected">
{{ dice.number }}D{{ dice.pipsCount }} => {{ expected }}
</li>
</ul>
<div>
<label>Total:</label>
<span>{{ expectedTotal }} {{ modified >= 0 ? '+' : '-' }} {{ Math.abs(modified) }} = {{ expectedTotal + modified }}</span>
</div>
</div>
</section>
</div>
<footer class="global navbar navbar-default">
<section class="roll_dice container-fluid">
<button class="btn btn-primary btn-block" v-on="click: roll"><i class="fa fa-thumbs-up"></i>⌒<i class="fa fa-square-o fa-spin"></i> Roll dice</button>
</section>
<section class="result container-fluid">
<h4><i class="fa fa-check-square-o"></i> Result</h4>
<div>
<ul>
<li v-repeat="results">
{{ dice.number }}D{{ dice.pipsCount }} => {{ results }}
</li>
</ul>
<div>
<label>Total:</label>
<span>{{ resultTotal }} {{ modified >= 0 ? '+' : '-' }} {{ Math.abs(modified) }} = {{ resultTotal + modified }}</span>
</div>
</div>
</section>
<section class="container-fluid">
<p class="text-right"><i class="fa fa-github"></i> gist: <a href="https://gist.github.com/ichi/38739cd006e316a2b177">ichi/38739cd006e316a2b17</a></p>
</section>
</footer>
</script>
<script type="text/template" id="dice-template">
<div class="dice row">
<div class="number_and_pips cols">
<div class="form-group col">
<input-num model="{{@ number }}" min="0"></input-num>
</div>
<div class="form-group col abbr"><div class="form-control-static">D</div></div>
<div class="form-group col">
<input-num model="{{@ pipsCount }}" min="0" disabled="{{ customizing }}"></input-num>
</div>
</div>
<div class="controls cols">
<div class="col col_customize">
<button class="btn btn-default pull-right" v-on="click: startCustomize" v-show="!customizing"><i class="fa fa-cog"></i></button>
<div class="form-control-static expected" v-show="!customizing">
<label>Expected:</label>
<span>{{ number }}D{{ pipsCount }} => {{ expected }}</span>
</div>
<div class="input-group" v-show="customizing">
<input class="form-control" type="text" v-model="pipsString" />
<div class="input-group-btn">
<button class="btn btn-success" v-on="click: finishCustomize"><i class="fa fa-check" aria-hidden="true"></i></button>
</div>
</div>
</div>
<div class="col col_del">
<button class="btn btn-danger" v-on="click: removeDice($index)"><i class="fa fa-trash"></i></button>
</div>
</div>
</div>
</script>
<script type="text/template" id="input-num-template">
<div class="input-group input-num">
<div class="input-group-btn">
<button class="btn btn-default" v-attr="disabled:disabled" v-on="click: minus"><i class="fa fa-minus"></i></button>
</div>
<input class="form-control" type="number" min="0" v-model="model" v-attr="min:min, max:max, disabled:disabled" number />
<div class="input-group-btn">
<button class="btn btn-default" v-attr="disabled:disabled" v-on="click: plus"><i class="fa fa-plus"></i></button>
</div>
</div>
</script>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/vue/0.12.16/vue.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script type="text/javascript" src="http://coffeescript.org/extras/coffee-script.js"></script>
<script type="text/coffeescript">
class Die
constructor: (@pips...)->
roll: ->
return 0 unless @pips.length > 0
_.sample @pips
expected: ->
total = @pips.reduce ((memo, num)-> memo + num ), 0
return 0 unless total > 0
total / @pips.length
modify: (val)->
return @ if val == 0
new_pips = @pips.map (n)->
Math.max 0, n + val
new Die(new_pips...)
root = new Vue(
el: "#dice-calculator"
template: '#dice-calculator-template'
data:
diceList: []
results: null
expected: null
modified: 0
modifiedEach: 0
watch:
diceList: (val, oldVal)->
@$emit 'changeExpected'
modified: (val, oldVal)->
@$emit 'changeExpected'
created: ->
@addDice()
@$on 'changeExpected', ->
@expected = @$.diceList.map (dice)->
{dice: dice, expected: dice.expected}
computed:
resultTotal: ->
return 0 unless @results
@results.reduce (memo, ret)->
sum = ret.results.reduce ((m, n)-> m + n), 0
memo + sum
, 0
expectedTotal: ->
@expected.reduce (memo, exp)->
memo + exp.expected
, 0
methods:
addDice: ->
@diceList.push {}
removeDice: (index)->
@diceList.splice(index, 1);
roll: ->
@results = @$.diceList.map (dice)->
val = _(dice.number).times (i)->
dice.modifiedDie.roll()
{dice: dice, results: val}
components:
'dice':
template: '#dice-template'
data: -> {
number: 0
pips: []
hoge: null
customizing: false
}
watch:
expected: (val, oldVal)->
@$dispatch 'changeExpected' unless val == oldVal
props: ['removeDice', 'modifiedEach']
computed:
pipsCount:
get: ->
@pips.length
set: (val)->
if @pips.length != val
@pips = _.range(1, val + 1)
pipsString:
get: ->
@pips.join ' '
set: (val)->
pips = _.compact(val.split /\s/).map (n)-> n - 0 # toInt
@pipsCount = pips.length
@pips = pips
die: ->
@die = new Die(@pips...)
modifiedDie: ->
@die.modify(@modifiedEach)
expected: ->
@modifiedDie.expected() * @number
methods:
startCustomize: ->
@customizing = true
finishCustomize: ->
@customizing = false
'input-num':
template: '#input-num-template'
props:
model:
type: Number
required: true
disabled: Boolean
max:
type: Number
default: Number.POSITIVE_INFINITY
min:
type: Number
default: Number.NEGATIVE_INFINITY
methods:
plus: ->
@model = Math.min(@model + 1, @max) unless @disabled
minus: ->
@model = Math.max(@model - 1, @min) unless @disabled
)
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment