360 lines
20 KiB
HTML
360 lines
20 KiB
HTML
|
<!doctype html>
|
||
|
<html lang="en">
|
||
|
|
||
|
<head>
|
||
|
<meta charset="utf-8">
|
||
|
|
||
|
<title>CSE 662 - Languages and Runtimes for Big Data - Fall 2015</title>
|
||
|
|
||
|
<meta name="description" content="CSE662 - Fall 2015">
|
||
|
<meta name="author" content="Oliver Kennedy & Lukasz Ziarek">
|
||
|
|
||
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||
|
|
||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">
|
||
|
|
||
|
<link rel="stylesheet" href="../reveal.js-3.1.0/css/reveal.css">
|
||
|
<link rel="stylesheet" href="ubodin.css" id="theme">
|
||
|
|
||
|
<!-- Code syntax highlighting -->
|
||
|
<link rel="stylesheet" href="../reveal.js-3.1.0/lib/css/zenburn.css">
|
||
|
|
||
|
<!-- Printing and PDF exports -->
|
||
|
<script>
|
||
|
var link = document.createElement( 'link' );
|
||
|
link.rel = 'stylesheet';
|
||
|
link.type = 'text/css';
|
||
|
link.href = window.location.search.match( /print-pdf/gi ) ? '../reveal.js-3.1.0/css/print/pdf.css' : '../reveal.js-3.1.0/css/print/paper.css';
|
||
|
document.getElementsByTagName( 'head' )[0].appendChild( link );
|
||
|
</script>
|
||
|
|
||
|
<!--[if lt IE 9]>
|
||
|
<script src="../reveal.js-3.1.0/lib/js/html5shiv.js"></script>
|
||
|
<![endif]-->
|
||
|
</head>
|
||
|
|
||
|
<body>
|
||
|
|
||
|
<div class="reveal">
|
||
|
<div class="header">
|
||
|
<!-- Any Talk-Specific Header Content Goes Here -->
|
||
|
University at Buffalo
|
||
|
</div>
|
||
|
<div class="footer">
|
||
|
<!-- Any Talk-Specific Footer Content Goes Here -->
|
||
|
<div style="float: left;">
|
||
|
CSE 662
|
||
|
</div>
|
||
|
<div style="float: right;">
|
||
|
Languages and Runtimes for Big Data
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
|
||
|
<!-- Any section element inside of this container is displayed as a slide -->
|
||
|
<div class="slides">
|
||
|
|
||
|
<section>
|
||
|
<section>
|
||
|
<h2>The Scalable Games Language</h2>
|
||
|
<h4>September 28, 2015</h4>
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Declarative Languages</h3>
|
||
|
<ul>
|
||
|
<li>SQL</li>
|
||
|
<li>SparQL</li>
|
||
|
<li>XPath/XQuery</li>
|
||
|
<li>Pig Latin</li>
|
||
|
<li>Graal+Truffle</li>
|
||
|
<li>Scala LMS</li>
|
||
|
</ul>
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Declarative Languages</h3>
|
||
|
<ul>
|
||
|
<li>(Often) less expressive</li>
|
||
|
<li>Common design patterns abstracted out</li>
|
||
|
<li>Easier to identify and fix inefficiencies</li>
|
||
|
</ul>
|
||
|
</section>
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<section>
|
||
|
<h3>Declarative Languages for Games</h3>
|
||
|
<img src="graphics/ScalableGames-ExpressivenessVsScale.png" height="400"/>
|
||
|
<p class="fragment"><b>Now:</b> You get complexity or scale, but not both.</p>
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Challenges</h3>
|
||
|
<ul>
|
||
|
<li>Computing resources are limited</li>
|
||
|
<li>AI Devs work at the unit-scale</li>
|
||
|
<li>Gameplay designers work at the effect scale</li>
|
||
|
<li>More units/effects = more compute</li>
|
||
|
</ul>
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>The Setting</h3>
|
||
|
<svg height="400" width="700">
|
||
|
<defs>
|
||
|
<marker id="arrow" markerWidth="10" markerHeight="10" refx="0" refy="3" orient="auto" markerUnits="strokeWidth">
|
||
|
<path d="M0,0 L0,6 L9,3 z" fill="#000" />
|
||
|
</marker>
|
||
|
</defs>
|
||
|
<text x="120" y="50">Compute What Happens Next</text>
|
||
|
<text x="480" y="350" class="fragment" data-fragment-index="1">Update State</text>
|
||
|
<text x="0" y="350" class="fragment" data-fragment-index="2">Render the Scene</text>
|
||
|
<text x="280" y="240" class="fragment" data-fragment-index="3" style="font-weight: bold; ">One Tick</text>
|
||
|
<line x1="390" y1="70" x2="570" y2="290" stroke="#000" stroke-width="3" marker-end="url(#arrow)" class="fragment" data-fragment-index="1" />
|
||
|
<line x1="470" y1="340" x2="320" y2="340" stroke="#000" stroke-width="3" marker-end="url(#arrow)" class="fragment" data-fragment-index="2" />
|
||
|
<line x1="130" y1="300" x2="300" y2="90" stroke="#000" stroke-width="3" marker-end="url(#arrow)" class="fragment" data-fragment-index="3" />
|
||
|
</svg>
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>The Setting</h3>
|
||
|
<svg height="400" width="700">
|
||
|
<defs>
|
||
|
<marker id="arrow" markerWidth="10" markerHeight="10" refx="0" refy="3" orient="auto" markerUnits="strokeWidth">
|
||
|
<path d="M0,0 L0,6 L9,3 z" fill="#000" />
|
||
|
</marker>
|
||
|
</defs>
|
||
|
<text x="120" y="50" fill="blue">Compute What Happens Next</text>
|
||
|
<text x="480" y="350" fill="blue">Update State</text>
|
||
|
<text x="0" y="350" fill="grey">Render the Scene</text>
|
||
|
<text x="280" y="240" style="font-weight: bold; ">One Tick</text>
|
||
|
<line x1="390" y1="70" x2="570" y2="290" stroke="#000" stroke-width="3" marker-end="url(#arrow)" />
|
||
|
<line x1="470" y1="340" x2="320" y2="340" stroke="#000" stroke-width="3" marker-end="url(#arrow)" />
|
||
|
<line x1="130" y1="300" x2="300" y2="90" stroke="#000" stroke-width="3" marker-end="url(#arrow)" />
|
||
|
</svg>
|
||
|
</section>
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<section>
|
||
|
<h3>The State/Effect Pattern</h3>
|
||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="172 139 284 154" width="284pt" height="154pt" xmlns:dc="http://purl.org/dc/elements/1.1/"><metadata> Produced by OmniGraffle 6.3.2 <dc:date>2015-09-28 03:46:30 +0000</dc:date></metadata><defs><font-face font-family="Helvetica Neue" font-size="16" panose-1="2 0 8 3 0 0 0 9 0 4" units-per-em="1000" underline-position="-100" underline-thickness="50" slope="0" x-height="517" cap-height="714" ascent="975.0061" descent="-216.99524" font-weight="bold"><font-face-src><font-face-name name="HelveticaNeue-Bold"/></font-face-src></font-face><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="black"><g><path d="M 8 0 L 0 -3 L 0 3 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/></g></marker><font-face font-family="Helvetica Neue" font-size="14" panose-1="2 0 5 3 0 0 0 2 0 4" units-per-em="1000" underline-position="-100" underline-thickness="50" slope="0" x-height="517" cap-height="714" ascent="951.99585" descent="-212.99744" font-weight="500"><font-face-src><font-face-name name="HelveticaNeue"/></font-face-src></font-face><font-face font-family="Helvetica Neue" font-size="14" panose-1="2 0 8 3 0 0 0 9 0 4" units-per-em="1000" underline-position="-100" underline-thickness="50" slope="0" x-height="517" cap-height="714" ascent="975.0061" descent="-216.99524" font-weight="bold"><font-face-src><font-face-name name="HelveticaNeue-Bold"/></font-face-src></font-face></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title>Canvas 1</title><rect fill="white" width="1037" height="842"/><g><title>Layer 1</title><text transform="translate(177.5625 206.5)" fill="black"><tspan font-family="Helvetica Neue" font-size="16" font-weight="bold" x=".492" y="16" textLength="40.016">State</tspan></text><text transform="translate(396.0625 206.5)" fill="black"><tspan font-family="Helvetica Neue" font-size="16" font-weight="bold" x=".432" y="16" textLength="20.544">Eff</tspan><tspan font-family="Helvetica Neue" font-size="16" font-weight="bold" x="20.976" y="16" textLength="32.592">ects</tspan></text><path d="M 210.62041 201 C 228.07219 182.3664 262.4797 153 306 153 C 344.67102 153 379.5053 176.18666 400.92548 194.42692" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="223.32496" y="139.01716" width="169" height="28" fill="white"/><text transform="translate(228.32496 144.51716)" fill="black"><tspan font-family="Helvetica Neue" font-size="14" font-weight="500" fill="black" x=".414" y="14" textLength="31.892">… is </tspan><tspan font-family="Helvetica Neue" font-size="14" font-weight="bold" fill="black" x="32.306" y="14" textLength="50.54">queried</tspan><tspan font-family="Helvetica Neue" font-size="14" font-weight="500" fill="black" x="82.846" y="14" textLength="75.74"> to compute</tspan></text><path d="M 406.1891 231 C 383.37648 249.6336 340.5203 279 297 279 C 259.02173 279 231.17789 256.63663 214.87366 238.55795" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="216.8873" y="264.40796" width="182" height="28" fill="white"/><text transform="translate(221.8873 269.90796)" fill="black"><tspan font-family="Helvetica Neue" font-size="14" font-weight="500" x=".187" y="14" textLength="30.072">… ar</tspan><tspan font-family="Helvetica Neue" font-size="14" font-weight="500" x="30.007" y="14" textLength="11.41">e </tspan><tspan font-family="Helvetica Neue" font-size="14" font-weight="bold" x="41.417" y="14" textLength="66.332">combined</tspan><tspan font-family="Helvetica Neue" font-size="14" font-weight="500" x="107.749" y="14" textLength="64.064"> to update</tspan></text></g></g></svg>
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<table>
|
||
|
<tr><th>State</th><th>Effects</th></tr>
|
||
|
<tr><td>Persistent across ticks</td><td>Computed once per tick</td></tr>
|
||
|
<tr><td>Queried for potential effects</td><td>Merged into state</td></tr>
|
||
|
<tr><td>Have an initial value</td><td>Have a combiner function</td></tr>
|
||
|
<tr><td>Read+Update only</td><td>Merge only</td></tr>
|
||
|
</table>
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Benefits of Limiting Expressiveness</h3>
|
||
|
<ul>
|
||
|
<li>Update phase guaranteed to be $O(1)$.</li>
|
||
|
<li>Query phase can be reduced to one or more aggregate queries. Opportunities for...<ul>
|
||
|
<li>... work-sharing: Merge scans over same data</li>
|
||
|
<li>... parallelism: Safe to parallelize scans over same data</li>
|
||
|
<li>... pre-computation: Index data for multiple scans</li>
|
||
|
</li></ul>
|
||
|
</ul>
|
||
|
<p class="fragment"><b>State/effect similar to barrier-based programming</b></p>
|
||
|
</section>
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<section>
|
||
|
<h3>Example</h3>
|
||
|
<pre><code>
|
||
|
class Unit {
|
||
|
|
||
|
state:
|
||
|
number player = 0; number type = 0;
|
||
|
number x = 0; number y = 0;
|
||
|
number health = 0; Unit target = null;
|
||
|
effects:
|
||
|
number vx : avg; number vy : avg;
|
||
|
number damage : sum; number healing : max;
|
||
|
Unit acquired : priority;
|
||
|
update:
|
||
|
x = x + vx; y = y + vy;
|
||
|
health = health - damage;
|
||
|
target = (acquired != null ? acquired : target);
|
||
|
}
|
||
|
</code></pre>
|
||
|
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Example AI</h3>
|
||
|
<pre><code>
|
||
|
let (number dist = (x-target.x)*(x-target.x)+
|
||
|
(y-target.y)*(y-target.y)) in {
|
||
|
if (dist < ATTACK_RANGE) {
|
||
|
// If in range, attack.
|
||
|
target.damage <- DMG_AMOUNT;
|
||
|
} else {
|
||
|
// Else move closer (use unit velocity)
|
||
|
vx <- (target.x-x)/dist;
|
||
|
vx <- (target.y-y)/dist;
|
||
|
} }
|
||
|
</code></pre>
|
||
|
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Merging = Aggregation</h3>
|
||
|
<code>target.damage <- DMG_AMOUNT;</code>
|
||
|
|
||
|
<p>Damage is an <b>effect.</b> How is damage merged?</p>
|
||
|
<p class="fragment">The total damage can be expressed as: <code>SUM(DMG_AMOUNT)</code>. <span class="fragment">... over what data?</span></p>
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Example Relational Plan</h3>
|
||
|
<img src="graphics/DeclarativeGames-Example1.svg" height="400" />
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Example Relational Plan</h3>
|
||
|
<img src="graphics/DeclarativeGames-Example2.svg" height="400" />
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Example Relational Plan</h3>
|
||
|
<img src="graphics/DeclarativeGames-Example3.svg" height="400" />
|
||
|
</section>
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<section>
|
||
|
<h3>Group Exercise</h3>
|
||
|
<p>There are two types of units: <b>Soldiers</b> and <b>Skeletons</b></p>
|
||
|
<p>Design an AI for a soldier who attacks the nearest skeleton <b>if there are at more soldiers than skeletons within 50 ft.</b></p>
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Making Repeated Aggregation Fast</h3>
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<p>Given 8 numbers...</p>
|
||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="134 150 277 104" width="277pt" height="104pt" xmlns:dc="http://purl.org/dc/elements/1.1/"><metadata> Produced by OmniGraffle 6.3.2 <dc:date>2015-09-28 04:45:59 +0000</dc:date></metadata><defs><font-face font-family="Helvetica Neue" font-size="16" panose-1="2 0 5 3 0 0 0 2 0 4" units-per-em="1000" underline-position="-100" underline-thickness="50" slope="0" x-height="517" cap-height="714" ascent="951.99585" descent="-212.99744" font-weight="500"><font-face-src><font-face-name name="HelveticaNeue"/></font-face-src></font-face><font-face font-family="Helvetica Neue" font-size="16" panose-1="2 0 8 3 0 0 0 9 0 4" units-per-em="1000" underline-position="-100" underline-thickness="50" slope="0" x-height="517" cap-height="714" ascent="975.0061" descent="-216.99524" font-weight="bold"><font-face-src><font-face-name name="HelveticaNeue-Bold"/></font-face-src></font-face></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title>Canvas 1</title><rect fill="white" width="1037" height="842"/><g class="fragment" data-fragment-index="3"><title>Layer 3</title><rect x="234" y="216" width="144" height="36" fill="white"/><rect x="234" y="216" width="144" height="36" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/></g><g class="fragment" data-fragment-index="5"><title>Layer 4</title><text transform="translate(250 155.5)" fill="black"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x=".004" y="16" textLength="69.2">36 - 12 = </tspan><tspan font-family="Helvetica Neue" font-size="16" font-weight="bold" x="69.204" y="16" textLength="17.792">24</tspan></text><rect x="198" y="180" width="36" height="36" fill="white"/><rect x="198" y="180" width="36" height="36" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><rect x="342" y="180" width="36" height="36" fill="white"/><rect x="342" y="180" width="36" height="36" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/></g><g><title>Layer 1</title><text transform="translate(139.5625 225)" fill="black"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x=".052" y="15" textLength="8.896">2</tspan></text><text transform="translate(175.5625 225)" fill="black"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x=".052" y="15" textLength="8.896">4</tspan></text><text transform="translate(247.5625 225)" fill="black"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x=".052" y="15" textLength="8.896">7</tspan></text><text transform="translate(211.5625 225)" fill="black"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x=".052" y="15" textLength="8.896">6</tspan></text><text transform="translate(279.0625 225)" fill="black"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x=".104" y="15" textLength="17.792">10</tspan></text><text transform="translate(319.5625 225)" fill="black"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x=".052" y="15" textLength="8.896">6</tspan></text><text transform="translate(355.5625 225)" fill="black"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x=".052" y="15" textLength="8.896">1</tspan></text><text transform="translate(391.5625 225)" fill="black"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x=".052" y="15" textLength="8.896">1</tspan></text></g><g class="fragment" data-fragment-index="1"><title>Layer 2</title><text transform="translate(139.5625 189)" fill="black"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x=".052" y="15" textLength="8.896">2</tspan></text><text transform="translate(175.5625 189)" fill="black"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x=".052" y="15" textLength="8.896">6</tspan></text><text transform="translate(243.0625 189)" fill="black"><tspan font-family="Helvetica Neue" font-size="16" font
|
||
|
<small>
|
||
|
<p class="fragment" data-fragment-index="1">Precompute $index_j = \sum_{i \leq j} data_i$ for each j <span class="fragment" data-fragment-index="2">(... is $O(N)$).</span></p>
|
||
|
<p class="fragment" data-fragment-index="3">For a summation query on (3,7]... <span class="fragment" data-fragment-index="4">(... is normally $O(|Q|)$)</span></p>
|
||
|
<p class="fragment" data-fragment-index="5">...use $index_7 - index_{3}$ <span class="fragment" data-fragment-index="6">(... is now $O(1)$).</span></p>
|
||
|
</small>
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Does this work for Min/Max?</h3>
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Max Tree</h3>
|
||
|
<img src="graphics/DeclarativeGames-MinMax.svg" height="400" />
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Max Tree</h3>
|
||
|
<img src="graphics/DeclarativeGames-MinMax2.svg" height="400" />
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Max Tree</h3>
|
||
|
<img src="graphics/DeclarativeGames-MinMax3.svg" height="400" />
|
||
|
<p class="fragment">At most $O(\log N)$ lookups.</p>
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Linear Sweep</h3>
|
||
|
<img src="graphics/DeclarativeGames-LinearSweep1.svg" height="400" />
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Linear Sweep</h3>
|
||
|
<img src="graphics/DeclarativeGames-LinearSweep2.svg" height="400" />
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Linear Sweep</h3>
|
||
|
<img src="graphics/DeclarativeGames-LinearSweep3.svg" height="400" />
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Linear Sweep</h3>
|
||
|
<img src="graphics/DeclarativeGames-LinearSweep4.svg" height="400" />
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Linear Sweep</h3>
|
||
|
<img src="graphics/DeclarativeGames-LinearSweep5.svg" height="400" />
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Linear Sweep</h3>
|
||
|
<img src="graphics/DeclarativeGames-LinearSweep6.svg" height="400" />
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<h3>Linear Sweep</h3>
|
||
|
<img src="graphics/DeclarativeGames-LinearSweep7.svg" height="400" />
|
||
|
</section>
|
||
|
</section>
|
||
|
|
||
|
<section>
|
||
|
<section>
|
||
|
<ul>
|
||
|
<li>Language restrictions can help optimizers.</li>
|
||
|
<li>Computer Games are Data-Intensive.</li>
|
||
|
<li>Relational-Algebra can be used to find opportunities for...
|
||
|
<ul>
|
||
|
<li>work-sharing</li>
|
||
|
<li>pre-computation</li>
|
||
|
<li>parallelization</li>
|
||
|
</ul>
|
||
|
</li>
|
||
|
</ul>
|
||
|
</section>
|
||
|
</section>
|
||
|
|
||
|
</div></div>
|
||
|
|
||
|
<script src="../reveal.js-3.1.0/lib/js/head.min.js"></script>
|
||
|
<script src="../reveal.js-3.1.0/js/reveal.js"></script>
|
||
|
|
||
|
<script>
|
||
|
|
||
|
// Full list of configuration options available at:
|
||
|
// https://github.com/hakimel/../reveal.js#configuration
|
||
|
Reveal.initialize({
|
||
|
controls: false,
|
||
|
progress: true,
|
||
|
history: true,
|
||
|
center: true,
|
||
|
|
||
|
transition: 'fade', // none/fade/slide/convex/concave/zoom
|
||
|
|
||
|
// Optional ../reveal.js plugins
|
||
|
dependencies: [
|
||
|
{ src: '../reveal.js-3.1.0/lib/js/classList.js', condition: function() { return !document.body.classList; } },
|
||
|
{ src: '../reveal.js-3.1.0/plugin/math/math.js', condition: function() { return true; } },
|
||
|
{ src: '../reveal.js-3.1.0/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
|
||
|
{ src: '../reveal.js-3.1.0/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
|
||
|
{ src: '../reveal.js-3.1.0/plugin/highlight/highlight.js', async: true, condition: function() { return !!document.querySelector( 'pre code' ); }, callback: function() { hljs.initHighlightingOnLoad(); } },
|
||
|
{ src: '../reveal.js-3.1.0/plugin/zoom-js/zoom.js', async: true },
|
||
|
{ src: '../reveal.js-3.1.0/plugin/notes/notes.js', async: true }
|
||
|
]
|
||
|
});
|
||
|
|
||
|
</script>
|
||
|
|
||
|
</body>
|
||
|
</html>
|