Skip to content

Commit

Permalink
Add some animation. Add Mobile adaptation.
Browse files Browse the repository at this point in the history
  • Loading branch information
hwc0919 committed Mar 8, 2020
1 parent 4396458 commit 8c59970
Show file tree
Hide file tree
Showing 15 changed files with 293 additions and 103 deletions.
33 changes: 33 additions & 0 deletions autopackup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import hashlib
import os
import re
import time

html_sha = ''
js_sha = ''

while True:
files = os.listdir('dist')
for filename in files:
filename = os.path.join('dist', filename)
if filename.endswith('.html'):
with open(filename, 'rb') as f:
html_txt = f.read()
if filename.endswith('.js'):
with open(filename, 'rb') as f:
js_txt = f.read()
js_txt = js_txt.replace(b'\\', b'/placeholder/')
new_html_sha = hashlib.sha256(html_txt).hexdigest()
new_js_sha = hashlib.sha256(js_txt).hexdigest()
if (new_html_sha != html_sha or new_js_sha != js_sha):
print('Detect change. Packing...')
new_html_txt = re.sub(rb'<script.*?></script>',
b'<script>\n' + js_txt + b'\n</script>',
html_txt)
new_html_txt = new_html_txt.replace(b'/placeholder/', b'\\')
with open('TreePlaygroundPackup.html', 'wb') as f:
f.write(new_html_txt)
print('Packed...')
html_sha = new_html_sha
js_sha = new_js_sha
time.sleep(1)
29 changes: 16 additions & 13 deletions dist/TreePlayground.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta name="author" content="NitroMelon">
<meta name="school" content="Tsinghua University">
<meta name="institution" content="Tsinghua University">
<meta name="git" content="https://github.com/hwc0919/TreePlayground">
<meta name="website" content="https://192.144.210.149/">
<link rel="Shortcut Icon" href="/favicon.ico">
<title>TreePlayground - NitroMelon</title>
</head>

<body>
<div id="header" style="position: fixed; left: 5px; top: 5px;">
<p style="color: gray">Recommend Chrome on PC</p>
</div>
<div id="TreePlayground" @mousemove='onTPMouseMove($event)' @touchmove='onTPMouseMove($event)'>
<div id="TreePlayground" @mousemove='onTPMouseMove($event)' @touchmove='onTPMouseMove($event)'
@mouseup="onTreeMouseLeave" @touchend="onTreeMouseLeave">
<!-- Top Toolbar -->
<div class="top-toolbar">
<button class="btn btn-primary top-toolbar-item" type="button"
Expand All @@ -23,27 +26,27 @@
<button class="btn btn-primary top-toolbar-item" type="button" @click="traversal(1)">中序遍历</button>
<button class="btn btn-primary top-toolbar-item" type="button" @click="traversal(2)">后序遍历</button>
<button class="btn btn-primary top-toolbar-item" type="button" @click="traversal(3)">层次遍历</button>
<div id="trav-intrvl-ranger" class="top-toolbar-item">
<h4 style="margin: 5px">遍历间隔: <label v-text="commonParams.interval + 'ms'">500ms</label></h4>
<span id="interval-ranger" class="top-toolbar-item">
<span style="margin: 5px">间隔: <label v-text="commonParams.interval + 'ms'">500ms</label></span>
<input type="range" min="100" max="1500" value="500" step="100" v-model.number="commonParams.interval">
</div>
</span>
</div>
<!-- Left Toolbar -->
<div class="left-toolbar">
<button class="btn btn-default" type="button" @click="reset">Reset</button>
<select id="tree-type-selector" v-model="curTreeType">
<button class="btn btn-default left-toolbar-item" type="button" @click="reset">Reset</button>
<select id="tree-type-selector" class="left-toolbar-item" v-model="curTreeType">
<option v-for="status, ttype in availTreeTypes" v-text="ttype" :value="ttype" :disabled="!status">
</option>
</select>
<div id="tree-scale-ranger">
<input type="range" min="50" max="150" value="100" v-model.number="treeScale">
<div id="tree-scale-ranger" class="left-toolbar-item">
<h4>Scale: <label v-text="commonParams.treeScale + '%'"></h4>
<input type="range" min="20" max="180" value="100" v-model.number="treeScale">
</div>
</div>
<!-- Tree Visualization Part -->
<div class="tree" ref="tree" :style="adjustScale" style="transform-origin: top;"
@mousedown.self="onTreeMouseDown" @mouseup.self="onTreeMouseLeave" @touchstart.self="onTreeMouseDown"
@touchend.self="onTreeMouseLeave">
<div class="tree" ref="tree" :style="adjustScale" style="transform-origin: top;">
<div class="tree-dragging-btn" @mousedown.self="onTreeMouseDown" @touchstart.self.prevent="onTreeMouseDown">
</div>
<!-- Top Functional Node -->
<top-binnode id="trvl-sequence" :data="topSequence" @top-build="onTopBuild" @top-insert="onTopInsert"
@top-search="onTopSearch" @top-help="onTopHelp" @top-proper="onTopProper"></top-binnode>
Expand Down
2 changes: 1 addition & 1 deletion dist/bundle.js

Large diffs are not rendered by default.

42 changes: 25 additions & 17 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import { BST } from "./js/BST"
import { AVL } from "./js/AVL"
import { Splay } from "./js/Splay"

var vm = new Vue({
var tp = new Vue({
el: "#TreePlayground",
data: {
availTreeTypes: { "BinTree": true, "BST": true, "AVL": true, "Splay": true, "RedBlack": false },
commonParams: {
curTreeType: "BinTree", // Important : Always use as `this.curTreeType`.
curTreeType: "BST", // Important : Always use as `this.curTreeType`.
treeScale: 100, // in %
interval: 500 // in ms
},
Expand Down Expand Up @@ -223,25 +223,27 @@ var vm = new Vue({
this.alertAsync(`Step 1: Splay ${node.data}`, -1);
node.active = true;
setTimeout(() => {
// Splay RM Step 1
this.locks.rotateLock = true;
this.splayAsync(node, (rootOrNull) => {
if (rootOrNull === undefined) return false;
if (rootOrNull === null) throw "Error in RemoveOne";
let v = rootOrNull;
let tree = this.tree;
tree._size--;
if (!v.rc || !v.rc) { // Splay Simple Situation
if (!v.rc || !v.rc) { // Splay RM Step 2a
if (!v.rc) { if (tree._root = v.lc) tree._root.parent = null; }
else { if (tree._root = v.rc) tree._root.parent = null; }
this.alertAsync(`Final: remove ${node.data}`, 2500);
this.update();
} else { // Splay Complex Situation
} else { // Splay RM Step 2b
node.active = false; node.deprecated = true;
this.locks.trvlLock = true;
this.alertAsync(`Step 2: Elevate Succ of ${node.data}`, -1);
this.searchAsync(v.rc, v.data, (_, hot) => {
this.locks.rotateLock = true;
this.splayAsync(hot, (newRoot) => {
// Splay RM Step 3
this.alertAsync(`Step 3: Finally remove ${node.data}`, 2500);
tree.reAttachAsLC(newRoot, v.lc);
this.update();
Expand Down Expand Up @@ -272,11 +274,11 @@ var vm = new Vue({
node.deprecated = true;
this.locks.trvlLock = true; // TODO : change to srchLock
this.searchAsync(node, succ.data, () => { // assert res === true
// RM Step 2: Swap with Succ
this.alertAsync(`Step 2: Swap with Succ`, -1);
this.update();
node.deprecated = true; succ.active = true;
setTimeout(() => {
// RM Step 2: Swap
let t = node.data; node.data = succ.data; succ.data = t;
node.deprecated = false; succ.active = false;
node.active = true; succ.deprecated = true;
Expand All @@ -285,8 +287,10 @@ var vm = new Vue({
setTimeout(() => {
this.tree.removeAt(succ);
this.update();
// RM Step 4 : AVL reBalance
if ("AVL" === this.curTreeType) {
this.alertAsync(`Step 4: Solve AVL Unbalance`, -1);
this.alertAsync(`Step 4: AVL reBalance`, -1);
if (this.tree._hot) this.tree._hot.active = true;
setTimeout(() => {
this.locks.rotateLock = true;
this.avlRmRotateAsync(this.tree._hot, () => {
Expand Down Expand Up @@ -494,10 +498,13 @@ var vm = new Vue({
/* Dragger */
/****************************************/
onTreeMouseDown(event) {
if (event.button !== 0 && event.type !== "touchstart") {
this.isDragging = false; return false;
}
console.log("Start dragging")
this.treeXY = [event.target.offsetLeft, event.target.offsetTop];
this.treeXY = [this.$refs.tree.offsetLeft, this.$refs.tree.offsetTop];
switch (event.type) {
case "mousedown": this.mouseXY = [event.x, event.y]; break;
case "mousedown": this.mouseXY = [event.clientX, event.clientY]; break;
case "touchstart":
this.mouseXY = [event.touches[0].clientX, event.touches[0].clientY];
break;
Expand All @@ -509,7 +516,7 @@ var vm = new Vue({
if (this.isDragging) {
let newXY;
switch (event.type) {
case "mousemove": newXY = [event.x, event.y]; break;
case "mousemove": newXY = [event.clientX, event.clientY]; break;
case "touchmove":
newXY = [event.touches[0].clientX, event.touches[0].clientY];
break;
Expand All @@ -520,8 +527,10 @@ var vm = new Vue({
}
},
onTreeMouseLeave(e) {
console.log("End dragging")
this.isDragging = false;
if (this.isDragging) {
console.log("End dragging")
this.isDragging = false;
}
},
/****************************************/
/* Validators */
Expand Down Expand Up @@ -580,13 +589,12 @@ var vm = new Vue({
},
curTreeType: {
get() { return this.commonParams.curTreeType; },
set(newV) { this.commonParams.curTreeType = newV; this.init(); } // Important!!!
set(newV) { this.commonParams.curTreeType = newV; this.init(); } // Important
},
treeScale: {
get() { return this.commonParams.treeScale; },
set(newV) { this.commonParams.treeScale = newV; }
},

curTreeClass() {
return this.treeClassMap[this.curTreeType];
},
Expand All @@ -596,7 +604,7 @@ var vm = new Vue({
},
showExtr() {
return true;
}
},
},
watch: {
tree: {
Expand All @@ -609,14 +617,14 @@ var vm = new Vue({
handler() {
localStorage.commonParams = JSON.stringify(this.commonParams);
}, deep: true
}
},
},
mounted() {
try { this.commonParams = JSON.parse(localStorage.commonParams); }
catch (err) { }
if (this.availTreeTypes[this.curTreeType] == undefined) this.curTreeType = "BinTree";
if (this.availTreeTypes[this.curTreeType] == undefined) this.curTreeType = "BST";
this.init();
},
});

window.vm = vm;
window.tp = tp;
8 changes: 5 additions & 3 deletions src/components/components.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ Vue.component('binnode', {
return { showInput: false, updation: this.node.data }
},
template:
`<div class="binnode intr-binnode" :style="{'left': node.x + 'px', 'top': node.y + 'px'}" :title="'height: ' + node.height"
@click="divOnClick">
<span v-show="!showInput" style="display: inline-block; width: 100%; height: 100%;">{{ node.data }}</span>
`<div class="binnode intr-binnode" :style="{'left': node.x + 'px', 'top': node.y + 'px'}" @click="divOnClick">
<span v-show="!showInput" :title="title" style="display: inline-block; width: 100%; height: 100%;">{{ node.data }}</span>
<label v-show="showRemoveOne" class="node-delete-btn node-upper-btn" title="remove one"
@click.stop="$emit('remove-one', node)">&times;</label>
<label v-show="showRemoveBelow" class="subtree-delete-btn node-upper-btn" title="remove below"
Expand Down Expand Up @@ -72,6 +71,9 @@ Vue.component('binnode', {
}
},
computed: {
title() {
return `height: ${this.node.height}\nsize: ${this.node.size()}\nnpl:${this.node.npl}`
},
/* **************************************** */
/* ************ Remove Buttons ************ */
/* **************************************** */
Expand Down
5 changes: 5 additions & 0 deletions src/css/binnodes.css
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@
z-index: 3;
}

.binnode:hover {
text-shadow: 0px 0px 1px;
box-shadow: 0 0 5px;
}

.binnode:hover .node-upper-btn, .binnode:hover .node-left-btn {
opacity: 0.5;
}
Expand Down
3 changes: 2 additions & 1 deletion src/css/button.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@

.btn:active {
transform: scale(0.99);
}
transform-origin: left;
}

.btn-default:hover {
box-shadow: 0 0 1px 1px gray;
Expand Down
Loading

0 comments on commit 8c59970

Please sign in to comment.