diff --git a/.install/copylaradio.sh b/.install/copylaradio.sh new file mode 100755 index 0000000..c5595d2 --- /dev/null +++ b/.install/copylaradio.sh @@ -0,0 +1,75 @@ +#!/bin/bash +copylaradio() { +########################################### +echo "NO READY TO USE. REWRITING..." && exit 1 +########################################### + +MY_PATH="`dirname \"$0\"`" # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized + +isARM=$(cat $MY_PATH/.OS | grep YES) + +################################## +## INSTALL TOOLS +######## YOUTUBE-DL ########## +sudo wget https://yt-dl.org/downloads/latest/youtube-dl -O /usr/local/bin/youtube-dl || err=1 +sudo chmod a+rx /usr/local/bin/youtube-dl +sudo apt install libid3-tools mpd mpc lame omxplayer -y || err=1 + +## CONFIG MPD +sudo cp -f $MY_PATH/mpd.conf /etc/mpd.conf +sudo sed -i "s/_USER/$USER/g" /etc/mpd.conf || err=1 + +sudo chown -R $USER /var/lib/mpd/ /var/run/mpd /run/mpd /var/log/mpd +sudo service mpd restart || err=1 + + +sudo apt-get install nginx php-curl php-sqlite3 php-gd php-json php-xml php-mbstring php-fpm sqlite -y || err=1 +sudo apt-get install lame sox libsox-fmt-mp3 eyed3 python-chardet imagemagick curl -y #libav-tools || err=1 +sudo apt-get install ca-certificates git-core binutils rsync alsa-utils bc libid3-tools espeak mpg321 fuse atomicparsley -y || err=1 + +wget http://launchpadlibrarian.net/339874908/libav-tools_3.3.4-2_all.deb -O $MY_PATH/libav-tools.deb +wget http://ftp.fr.debian.org/debian/pool/non-free/s/svox/libttspico-data_1.0+git20130326-3_all.deb -O $MY_PATH/libttspico-data.deb +if [[ $isARM ]]; then + wget http://ftp.fr.debian.org/debian/pool/non-free/s/svox/libttspico0_1.0+git20130326-3_armhf.deb -O $MY_PATH/libttspico0.deb + wget http://ftp.fr.debian.org/debian/pool/non-free/s/svox/libttspico-utils_1.0+git20130326-3_armhf.deb -O $MY_PATH/libttspico-utils.deb +else + wget http://ftp.fr.debian.org/debian/pool/non-free/s/svox/libttspico0_1.0+git20130326-5_amd64.deb -O $MY_PATH/libttspico0.deb + wget http://ftp.fr.debian.org/debian/pool/non-free/s/svox/libttspico-utils_1.0+git20130326-9_amd64.deb -O $MY_PATH/libttspico-utils.deb +fi +sudo dpkg -i $MY_PATH/libttspico-data.deb || err=1 +sudo dpkg -i $MY_PATH/libttspico0.deb || err=1 +sudo dpkg -i $MY_PATH/libttspico-utils.deb || err=1 +sudo dpkg -i $MY_PATH/libav-tools.deb || sudo apt --fix-broken install -y || err=1 +rm $MY_PATH/libttspico-data.deb $MY_PATH/libttspico0.deb $MY_PATH/libttspico-utils.deb $MY_PATH/libav-tools.deb + + +# CONFIG NGINX +sudo cp -f $MY_PATH/default /etc/nginx/sites-available/ +sudo sed -i "s/_USER/$USER/g" /etc/nginx/sites-available/default + +sudo systemctl restart nginx || err=1 + +################################# +## Get _CopyLaRadio distrib +# ipfs get Qm.... > /tmp/copylaradio.zip + +# Add CopyLaRadio to system PATH +#export PATH=$PATH:/home/$USER/_CopyLaRadio +# etc.... + +# INSTALL ROMPR WebSite LINKs +sudo ln -s $MY_PATH/../www/rompr /var/www/rompr +sudo chmod 777 $MY_PATH/../www/rompr/albumart +sudo chmod 777 $MY_PATH/../www/rompr/prefs + +if [[ $err ]]; then + echo -e "${c_red}Installation de copylaradio incomplète$c_" + exit 1 +else + echo -e "${c_green}CopyLaRadio a été installé avec succès$c_" + exit 0 +fi +} + +$@ diff --git a/.install/ipfs/install b/.install/ipfs/install deleted file mode 100755 index c170fc1..0000000 --- a/.install/ipfs/install +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env bash -# shellcheck disable=SC1091 - -set -e - -GO_IPFS_VERSION="v0.4.22" - -ARCH="$(uname -m)" -case "$ARCH" in - x86_64) - ARCH="amd64" - ;; - i386 | i586 | i686 ) - ARCH="386" - ;; armv7l) - ARCH="arm"; - ;; - armv6l) - ARCH="arm"; - ;; - aarch64) - ARCH="arm64"; - ;; - *) - echo "Unknown Arch" - exit 1 - ;; -esac - -# Hyperborea connected peer used to bootstrap Hyperborea only ipfs nodes -# DarkDrgn2k's peer -IPFS_PEER_1="/ip6/fc6e:691e:dfaa:b992:a10a:7b49:5a1a:5e09/tcp/4001/ipfs/QmU6NeD2Uu34WKest1NZGvGmScLhN1zVo66K35GeE6Jft2" -# HeavyMetal's peer -IPFS_PEER_2="/ip6/fc6d:3961:6744:7d94:31ba:2bf3:30bf:ebab/tcp/4001/ipfs/QmRGk8DdMWy5P5xgUisnv7u4hV4WfgEhbxa6iGpviYGC7q" -# Yggdrasil connected peer used to bootstrap hyperborea only ipfs nodes -IPFS_PEER_3="/ip6/301:4541:2f84:1188:216:3eff:fed5:a2df/tcp/4001/ipfs/QmWZpTdfETtpjJphVE1YbxMkUcL84idkg44Cq1XWSBNm7P" -# DarkDrgn2k's peer -IPFS_PEER_4="/ip6/200:98bf:d6df:e49a:f525:40bf:18d:ac45/tcp/4001/ipfs/QmU6NeD2Uu34WKest1NZGvGmScLhN1zVo66K35GeE6Jft2" -# HeavyMetal's peer -IPFS_PEER_5="/ip6/201:3d73:dbf:da97:e008:2d29:3919:cdb1/tcp/4001/ipfs/QmRGk8DdMWy5P5xgUisnv7u4hV4WfgEhbxa6iGpviYGC7q" -# Yk3Music's Irvine-CA peer -IPFS_PEER_6="/ip6/fcbb:1db3:54fb:e519:d915:d7db:4893:4f30/tcp/4001/ipfs/QmZEiPvrfZHapq4uiyTDEcR2szCUhDnjdS4q3Uv2b1Uh88" - -BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -# Download and install IPFS -mkdir "$BASE_DIR/tmp" -wget "https://dist.ipfs.io/go-ipfs/${GO_IPFS_VERSION}/go-ipfs_${GO_IPFS_VERSION}_linux-${ARCH}.tar.gz" -O "$BASE_DIR/tmp/go-ipfs.tar.gz" -tar xvfz "$BASE_DIR/tmp/go-ipfs.tar.gz" -C "$BASE_DIR/tmp" -sudo cp "$BASE_DIR/tmp/go-ipfs/ipfs" /usr/local/bin/ipfs -sudo chown root:staff /usr/local/bin/ipfs -rm -rf "$BASE_DIR/tmp" - -# Initialize IPFS if not already -if [ ! -d "$HOME/.ipfs" ]; then - ipfs init || true -fi - -# Enable gossipsub routing -ipfs config Pubsub.Router gossipsub - -# Enable Filestore for --nocopy capability -ipfs config --bool Experimental.FilestoreEnabled true - -# Setup connection management - Reduce connections to stress the Pi less -# XXX: These values need to be tweaked and tested -ipfs config Swarm.ConnMgr.Type basic -ipfs config --json Swarm.ConnMgr.LowWater 100 -ipfs config --json Swarm.ConnMgr.HighWater 200 -ipfs config Swarm.ConnMgr.GracePeriod 60s - -# Enable QUIC for better connections when possible -ipfs config --bool Experimental.QUIC true - -# Configure HTTP reverse proxy to IPFS gateway -sudo cp "$BASE_DIR/ipfs-http-gateway.conf" /etc/nginx/site-path-enabled/ipfs-http-gateway.conf -sudo systemctl restart nginx.service - -# shellcheck source=../shared/nodeinfo/install -source "$BASE_DIR/../shared/nodeinfo/install" -sudo cp "$BASE_DIR/nodeinfo-ipfs" /opt/tomesh/nodeinfo.d/ipfs - -# Add bootstrap addresses -ipfs bootstrap add "$IPFS_PEER_1" -ipfs bootstrap add "$IPFS_PEER_2" -ipfs bootstrap add "$IPFS_PEER_3" -ipfs bootstrap add "$IPFS_PEER_4" -ipfs bootstrap add "$IPFS_PEER_5" -ipfs bootstrap add "$IPFS_PEER_6" - -# Download dependencies -sudo apt-get install -y jq - -# Copy file -sudo cp "$BASE_DIR/ipfs-swarm.sh" /usr/local/bin/ -sudo chmod +x /usr/local/bin/ipfs-swarm.sh - -# Configure systemd to start ipfs.service on system boot -sudo cp "$BASE_DIR/ipfs.service" /etc/systemd/system/ipfs.service -sudo sed -i "s|__USER_HOME__|${HOME}|" /etc/systemd/system/ipfs.service -sudo systemctl daemon-reload -sudo systemctl enable ipfs.service -sudo systemctl start ipfs.service - -# Add entry into nginx home screen -APP="
" -sudo sed -i "s#<\!--APPLIST-->#$APP\n<\!--APPLIST-->#" "/var/www/html/index.html" diff --git a/.install/ipfs/ipfs-http-gateway.conf b/.install/ipfs/ipfs-http-gateway.conf deleted file mode 100644 index 2ccb3b3..0000000 --- a/.install/ipfs/ipfs-http-gateway.conf +++ /dev/null @@ -1,18 +0,0 @@ - location /ipfs { - proxy_pass http://127.0.0.1:8080/ipfs; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - location /ipns { - proxy_pass http://127.0.0.1:8080/ipns; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - # Prevent Caching - expires 0; - add_header Cache-Control private; - } diff --git a/.install/ipfs/ipfs-swarm.sh b/.install/ipfs/ipfs-swarm.sh deleted file mode 100644 index 0b24d77..0000000 --- a/.install/ipfs/ipfs-swarm.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env bash - -# This script connects to local mesh peers, -# and it sets up connection filters based on what networks this node can access. -# It runs continually, to change IPFS settings as the environment around the node changes. - - -# Wait for IPFS to initalize -attempts=10 -until [[ $(curl http://localhost:5001/api/v0/id -s 2>/dev/null) || ${attempts} -eq 0 ]]; do - sleep 3 - attempts=$((attempts-1)) -done - -if [[ ${attempts} -eq 0 ]]; then - echo "Error: Failed to connect to local IPFS daemon. Is it running?" - exit 1 -fi - -function addPeer { - addr=$1 - # See if they have IPFS enabled - res=$(curl http://["${addr}"]/nodeinfo.json -s) - if [ ! -x "${res}" ]; then - id=$(echo "${res}" | jq -r -M '.services.ipfs.ID') - # Value is found - if [[ ! ${id} == "null" ]] && [[ ! "${id}" == "" ]]; then - # Connect to neighbouring IPFS nodes - # Check for QUIC connections first - if [ "$(echo "${res}" | jq -r -M '.services.IPFS.quic_enabled')" == 'true' ]; then - # ID is not needed for QUIC connections - echo "Connecting to ${addr} with QUIC" - ipfs swarm connect "/ip6/${addr}/udp/4001/quic" - else - echo "Connecting to ${addr} over TCP" - ipfs swarm connect "/ip6/${addr}/tcp/4001/ipfs/${id}" - fi - fi - fi -} - -# Add cjdns direct peers -while read -r cjdns_peer; do - cjdns_addr=$(sudo /opt/cjdns/publictoip6 "$cjdns_peer") - addPeer "${cjdns_addr}" - - # Add all that node's peers to the bottom of the list to check further hop peers - # XXX: The below command hasn't been working -- so for now only 1-hop peers are checked - #peers+=$(cjdnstool query getpeers $peer | sed -e '1d;$d' |awk -F. '{ print $6".k" }') - -done <<< "$(sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($3 == "ESTABLISHED") print $2 }' | awk -F. '{ print $6".k" }' | xargs)" - -# Add yggdrasil direct peers -if [ "$(command -v yggdrasil)" ]; then - while read -r ygg_peer; do - addPeer "${ygg_peer}" - done <<< "$(sudo yggdrasilctl getPeers | grep -v "(self)" | awk '{print $1}' | grep -v bytes_recvd | xargs)" -fi - -# Update peers data since ipfs just started -sudo /usr/local/bin/nodeinfo-update.sh diff --git a/.install/ipfs/ipfs.service b/.install/ipfs/ipfs.service deleted file mode 100644 index 26cabf7..0000000 --- a/.install/ipfs/ipfs.service +++ /dev/null @@ -1,16 +0,0 @@ -[Unit] -Description=IPFS daemon -Wants=network.target -After=network.target - -[Service] -Type=simple -Environment=IPFS_PATH=__USER_HOME__/.ipfs -ExecStart=/usr/local/bin/ipfs daemon --enable-namesys-pubsub --migrate=true -ExecStartPost=/usr/local/bin/ipfs-swarm.sh -ExecStop=/bin/kill -s QUIT $MAINPID -Restart=on-failure -RestartSec=10s - -[Install] -WantedBy=multi-user.target diff --git a/.install/ipfs/nodeinfo-ipfs b/.install/ipfs/nodeinfo-ipfs deleted file mode 100755 index 0fad8e2..0000000 --- a/.install/ipfs/nodeinfo-ipfs +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh - -ipfsinfo=$( curl -s http://localhost:5001/api/v0/id) -id=$(echo $ipfsinfo | jq ".ID") -version=$(echo $ipfsinfo | jq ".AgentVersion") - -if [ -z "$id" ]; then - id='""' -fi -if [ -z "$version" ]; then - version='""' -fi - -echo '"ipfs":{' -echo '"version":'${version}',' - -if [ quic_enabled = "$(ipfs config Experimental.QUIC)" ]; then - echo '"quic_enabled":"'${quic_enabled}'",' -else - echo '"quic_enabled":"false",' -fi - -echo '"ID":'${id} - -echo "}," diff --git a/.install/ipfs/uninstall b/.install/ipfs/uninstall deleted file mode 100755 index 1bf8f69..0000000 --- a/.install/ipfs/uninstall +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash - -set -e - -# Remove script and service for ipfs bootstrap -sudo rm -r /usr/local/bin/ipfs-swarm.sh || true - -# Uninstall dependencies -sudo apt-get remove -y jq - -# Uninstall IPFS -sudo systemctl disable ipfs.service 2>/dev/null || true -sudo systemctl stop ipfs.service 2>/dev/null || true -sudo systemctl daemon-reload -sudo rm -f /usr/local/bin/ipfs -sudo rm -f /etc/systemd/system/ipfs.service - -if [ -d "$HOME/.ipfs" ]; then - echo "Found ~/.ipfs" - read -p "Keep your IPFS data (Y/n)? " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Nn]$ ]]; then - echo -e "\e[1;31mRemoving ~/.ipfs\e[0m" - sudo rm -rf ~/.ipfs - else - echo -e "\e[1;32mKeeping ~/.ipfs\e[0m" - fi -fi - -# Remove HTTP to IPFS gateway -sudo rm -f /etc/nginx/sites-enabled/ipfs-http-gateway -sudo rm -f /etc/nginx/sites-available/ipfs-http-gateway -sudo systemctl restart nginx.service diff --git a/.install/mpd.conf b/.install/mpd.conf new file mode 100644 index 0000000..d82f0fc --- /dev/null +++ b/.install/mpd.conf @@ -0,0 +1,27 @@ +music_directory "/home/_USER/music" +playlist_directory "/home/_USER/playlists" +user "$USER" +bind_to_address "any" +auto_update "yes" +zeroconf_enabled "yes" +zeroconf_name "CopyLaRadio Music Recorder" + +filesystem_charset "UTF-8" +id3v1_encoding "UTF-8" +############################### + + audio_output { + type "pulse" + name "My Pulse Output" + server "127.0.0.1" + } + + audio_output { + type "httpd" + name "CopyLaRadio HTTP Stream" + encoder "lame" + port "8000" + quality "5.0" + # bitrate "128" + format "44100:16:1" + } diff --git a/.install/nginx/cgi-bin.conf b/.install/nginx/cgi-bin.conf deleted file mode 100644 index bbc3a3f..0000000 --- a/.install/nginx/cgi-bin.conf +++ /dev/null @@ -1,7 +0,0 @@ -location /cgi-bin/ { - gzip off; - root /var/www/html; - fastcgi_pass unix:/var/run/fcgiwrap.socket; - include /etc/nginx/fastcgi_params; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; -} \ No newline at end of file diff --git a/.install/nginx/common.css b/.install/nginx/common.css deleted file mode 100644 index e8d23ba..0000000 --- a/.install/nginx/common.css +++ /dev/null @@ -1,24 +0,0 @@ -body { - font-family: Arial, Helvetica, sans-serif; -} -h1 { - text-align:center; -} -.app h2 { - margin:0; - padding:0; - background:black; - color:white; - padding:5px; - margin-bottom:5px; -} -.app { - display:inline-block; - float:left; - width:calc( 33% - 20px ); - vertical-align: top; - border:1px solid #cccccc; - margin:5px; - padding:5px; - min-width:400px; -} diff --git a/.install/nginx/common.js b/.install/nginx/common.js deleted file mode 100644 index 77d093f..0000000 --- a/.install/nginx/common.js +++ /dev/null @@ -1,58 +0,0 @@ -// CJDNS pubkey to IPv6 -// BASE32 code form CJDNS library -var numForAscii = [ - 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, - 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, - 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,99,99,99,99,99,99, - 99,99,10,11,12,99,13,14,15,99,16,17,18,19,20,99, - 21,22,23,24,25,26,27,28,29,30,31,99,99,99,99,99, - 99,99,10,11,12,99,13,14,15,99,16,17,18,19,20,99, - 21,22,23,24,25,26,27,28,29,30,31,99,99,99,99,99, - ]; - - // see util/Base32.h - var Base32_decode = function (input) { - var output = []; - - var outputIndex = 0; - var inputIndex = 0; - var nextByte = 0; - var bits = 0; - - while (inputIndex < input.length) { - var o = input.charCodeAt(inputIndex); - if (o & 0x80) { throw new Error(); } - var b = numForAscii[o]; - inputIndex++; - if (b > 31) { throw new Error("bad character " + input[inputIndex] + " in " + input); } - - nextByte |= (b << bits); - bits += 5; - - if (bits >= 8) { - output[outputIndex] = nextByte & 0xff; - outputIndex++; - bits -= 8; - nextByte >>= 8; - } - } - - if (bits >= 5 || nextByte) { - throw new Error("bits is " + bits + " and nextByte is " + nextByte); - } - return output; - }; - -// Convert Public Key to IPv6 -// TODO add : -var publicKeyCache = []; -function public2IPv6(PubKey) { - if (!publicKeyCache[PubKey]) { - var IPv6=Base32_decode(PubKey); - IPv6=sha512(sha512.array(IPv6)); - IPv6=IPv6.substr(0,32); - publicKeyCache[PubKey]=IPv6; - } - return publicKeyCache[PubKey]; -} \ No newline at end of file diff --git a/.install/nginx/index.html b/.install/nginx/index.html deleted file mode 100644 index a4ce099..0000000 --- a/.install/nginx/index.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - -=e[o].start&&e[n].end<=e[o].end?e[n].remove=!0:e[n].start>=e[o].start&&e[n].start<=e[o].end?(e[o].end=e[n].end,e[n].remove=!0):e[n].end>=e[o].start&&e[n].end<=e[o].end&&(e[o].start=e[n].start,e[n].remove=!0));for(o=0;oa&&(a=u))}var c=Math.abs(r-n)-Math.abs(a-s);c>0?(s-=.5*c,a+=.5*c):(n+=.5*c,r-=.5*c);var p=Math.max(1e-5,Math.abs(r-n)),f=.5*p,m=.5*(n+r),v=.5*(s+a),g={root:{centerOfMass:{x:0,y:0},mass:0,range:{minX:m-f,maxX:m+f,minY:v-f,maxY:v+f},size:p,calcSize:1/p,children:{data:null},maxWidth:0,level:0,childrenCount:4}};this._splitBranch(g.root);for(var y=0;ye.x?o.maxY>e.y?"NW":"SW":o.maxY>e.y?"NE":"SE",this._placeInRegion(t,e,n)}},{key:"_placeInRegion",value:function(t,e,i){var o=t.children[i];switch(o.childrenCount){case 0:o.children.data=e,o.childrenCount=1,this._updateBranchMass(o,e);break;case 1:o.children.data.x===e.x&&o.children.data.y===e.y?(e.x+=this.seededRandom(),e.y+=this.seededRandom()):(this._splitBranch(o),this._placeInTree(o,e));break;case 4:this._placeInTree(o,e)}}},{key:"_splitBranch",value:function(t){var e=null;1===t.childrenCount&&(e=t.children.data,t.mass=0,t.centerOfMass.x=0,t.centerOfMass.y=0),t.childrenCount=4,t.children.data=null,this._insertRegion(t,"NW"),this._insertRegion(t,"NE"),this._insertRegion(t,"SW"),this._insertRegion(t,"SE"),null!=e&&this._placeInTree(t,e)}},{key:"_insertRegion",value:function(t,e){var i=void 0,o=void 0,n=void 0,s=void 0,r=.5*t.size;switch(e){case"NW":i=t.range.minX,o=t.range.minX+r,n=t.range.minY,s=t.range.minY+r;break;case"NE":i=t.range.minX+r,o=t.range.maxX,n=t.range.minY,s=t.range.minY+r;break;case"SW":i=t.range.minX,o=t.range.minX+r,n=t.range.minY+r,s=t.range.maxY;break;case"SE":i=t.range.minX+r,o=t.range.maxX,n=t.range.minY+r,s=t.range.maxY}t.children[e]={centerOfMass:{x:0,y:0},mass:0,range:{minX:i,maxX:o,minY:n,maxY:s},size:.5*t.size,calcSize:2*t.calcSize,children:{data:null},maxWidth:0,level:t.level+1,childrenCount:0}}},{key:"_debug",value:function(t,e){void 0!==this.barnesHutTree&&(t.lineWidth=1,this._drawBranch(this.barnesHutTree.root,t,e))}},{key:"_drawBranch",value:function(t,e,i){void 0===i&&(i="#FF0000"),4===t.childrenCount&&(this._drawBranch(t.children.NW,e),this._drawBranch(t.children.NE,e),this._drawBranch(t.children.SE,e),this._drawBranch(t.children.SW,e)),e.strokeStyle=i,e.beginPath(),e.moveTo(t.range.minX,t.range.minY),e.lineTo(t.range.maxX,t.range.minY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.minY),e.lineTo(t.range.maxX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.maxY),e.lineTo(t.range.minX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.minX,t.range.maxY),e.lineTo(t.range.minX,t.range.minY),e.stroke()}}]),t}();e.default=h},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(0),s=o(n),r=i(1),a=o(r),h=function(){function t(e,i,o){(0,s.default)(this,t),this.body=e,this.physicsBody=i,this.setOptions(o)}return(0,a.default)(t,[{key:"setOptions",value:function(t){this.options=t}},{key:"solve",value:function(){for(var t=void 0,e=void 0,i=void 0,o=void 0,n=this.body.nodes,s=this.physicsBody.physicsNodeIndices,r=this.physicsBody.forces,a=0;a"+this.xLabel+": "+t.point.x+" "+this.yLabel+": "+t.point.y+" ",e.style.left="0",e.style.top="0",this.frame.appendChild(e),this.frame.appendChild(i),this.frame.appendChild(o);var n=e.offsetWidth,s=e.offsetHeight,r=i.offsetHeight,h=o.offsetWidth,d=o.offsetHeight,l=t.screen.x-n/2;l=Math.min(Math.max(l,10),this.frame.clientWidth-10-n),i.style.left=t.screen.x+"px",i.style.top=t.screen.y-r+"px",e.style.left=l+"px",e.style.top=t.screen.y-r-s+"px",o.style.left=t.screen.x-h/2+"px",o.style.top=t.screen.y-d/2+"px"},o.prototype._hideTooltip=function(){if(this.tooltip){this.tooltip.dataPoint=null;for(var t in this.tooltip.dom)if(this.tooltip.dom.hasOwnProperty(t)){var e=this.tooltip.dom[t];e&&e.parentNode&&e.parentNode.removeChild(e)}}},o.prototype.setCameraPosition=function(t){f.setCameraPosition(t,this),this.redraw()},o.prototype.setSize=function(t,e){this._setSize(t,e),this.redraw()},t.exports=o},function(t,e,i){i(163),t.exports=i(7).Object.assign},function(t,e,i){var o=i(17);o(o.S+o.F,"Object",{assign:i(164)})},function(t,e,i){var o=i(33),n=i(63),s=i(42),r=i(41),a=i(78),h=Object.assign;t.exports=!h||i(28)(function(){var t={},e={},i=Symbol(),o="abcdefghijklmnopqrst";return t[i]=7,o.split("").forEach(function(t){e[t]=t}),7!=h({},t)[i]||Object.keys(h({},e)).join("")!=o})?function(t,e){for(var i=r(t),h=arguments.length,d=1,l=n.f,u=s.f;h>d;)for(var c,p=a(arguments[d++]),f=l?o(p).concat(l(p)):o(p),m=f.length,v=0;m>v;)u.call(p,c=f[v++])&&(i[c]=p[c]);return i}:h},function(t,e,i){t.exports={default:i(166),__esModule:!0}},function(t,e,i){i(167),t.exports=i(7).Math.sign},function(t,e,i){var o=i(17);o(o.S,"Math",{sign:i(168)})},function(t,e){t.exports=Math.sign||function(t){return 0==(t=+t)||t!=t?t:t<0?-1:1}},function(t,e,i){t.exports={default:i(170),__esModule:!0}},function(t,e,i){i(171);var o=i(7).Object;t.exports=function(t,e,i){return o.defineProperty(t,e,i)}},function(t,e,i){var o=i(17);o(o.S+o.F*!i(21),"Object",{defineProperty:i(20).f})},function(t,e,i){Object.defineProperty(e,"__esModule",{value:!0});var o="string",n="boolean",s="number",r={fill:{string:o},stroke:{string:o},strokeWidth:{number:s},__type__:{string:o,object:"object",undefined:"undefined"}},a={animationAutoStart:{boolean:n,undefined:"undefined"},animationInterval:{number:s},animationPreload:{boolean:n},axisColor:{string:o},backgroundColor:r,xBarWidth:{number:s,undefined:"undefined"},yBarWidth:{number:s,undefined:"undefined"},cameraPosition:{distance:{number:s},horizontal:{number:s},vertical:{number:s},__type__:{object:"object"}},xCenter:{string:o},yCenter:{string:o},dataColor:r,dotSizeMinFraction:{number:s},dotSizeMaxFraction:{number:s},dotSizeRatio:{number:s},filterLabel:{string:o},gridColor:{string:o},onclick:{function:"function"},keepAspectRatio:{boolean:n},xLabel:{string:o},yLabel:{string:o},zLabel:{string:o},legendLabel:{string:o},xMin:{number:s,undefined:"undefined"},yMin:{number:s,undefined:"undefined"},zMin:{number:s,undefined:"undefined"},xMax:{number:s,undefined:"undefined"},yMax:{number:s,undefined:"undefined"},zMax:{number:s,undefined:"undefined"},showAnimationControls:{boolean:n,undefined:"undefined"},showGrid:{boolean:n},showLegend:{boolean:n,undefined:"undefined"},showPerspective:{boolean:n},showShadow:{boolean:n},showXAxis:{boolean:n},showYAxis:{boolean:n},showZAxis:{boolean:n},xStep:{number:s,undefined:"undefined"},yStep:{number:s,undefined:"undefined"},zStep:{number:s,undefined:"undefined"},style:{number:s,string:["bar","bar-color","bar-size","dot","dot-line","dot-color","dot-size","line","grid","surface"]},tooltip:{boolean:n,function:"function"},tooltipStyle:{content:{color:{string:o},background:{string:o},border:{string:o},borderRadius:{string:o},boxShadow:{string:o},padding:{string:o},__type__:{object:"object"}},line:{borderLeft:{string:o},height:{string:o},width:{string:o},__type__:{object:"object"}},dot:{border:{string:o},borderRadius:{string:o},height:{string:o},width:{string:o},__type__:{object:"object"}},__type__:{object:"object"}},xValueLabel:{function:"function"},yValueLabel:{function:"function"},zValueLabel:{function:"function"},valueMax:{number:s,undefined:"undefined"},valueMin:{number:s,undefined:"undefined"},verticalRatio:{number:s},height:{string:o},width:{string:o},__type__:{object:"object"}};e.allOptions=a},function(t,e,i){function o(){this.dataTable=null}var n=i(11),s=i(12),r=i(174),a=i(96),h=i(94),d=i(34);o.prototype.initializeData=function(t,e,i){if(void 0!==e){Array.isArray(e)&&(e=new n(e));var o;if(!(e instanceof n||e instanceof s))throw new Error("Array, DataSet, or DataView expected");if(o=e.get(),0!=o.length){this.style=i,this.dataSet&&this.dataSet.off("*",this._onChange),this.dataSet=e,this.dataTable=o;var r=this;this._onChange=function(){t.setData(r.dataSet)},this.dataSet.on("*",this._onChange),this.colX="x",this.colY="y",this.colZ="z";var h=t.hasBars(i);if(h&&(void 0!==t.defaultXBarWidth?this.xBarWidth=t.defaultXBarWidth:this.xBarWidth=this.getSmallestDifference(o,this.colX)||1,void 0!==t.defaultYBarWidth?this.yBarWidth=t.defaultYBarWidth:this.yBarWidth=this.getSmallestDifference(o,this.colY)||1),this._initializeRange(o,this.colX,t,h),this._initializeRange(o,this.colY,t,h),this._initializeRange(o,this.colZ,t,!1),o[0].hasOwnProperty("style")){this.colValue="style";var d=this.getColumnRange(o,this.colValue);this._setRangeDefaults(d,t.defaultValueMin,t.defaultValueMax),this.valueRange=d}this.getDataTable()[0].hasOwnProperty("filter")&&void 0===this.dataFilter&&(this.dataFilter=new a(this,"filter",t),this.dataFilter.setOnLoadCallback(function(){t.redraw()}));return this.dataFilter?this.dataFilter._getDataPoints():this._getDataPoints(this.getDataTable())}}},o.prototype._collectRangeSettings=function(t,e){if(-1==["x","y","z"].indexOf(t))throw new Error("Column '"+t+"' invalid");var i=t.toUpperCase();return{barWidth:this[t+"BarWidth"],min:e["default"+i+"Min"],max:e["default"+i+"Max"],step:e["default"+i+"Step"],range_label:t+"Range",step_label:t+"Step"}},o.prototype._initializeRange=function(t,e,i,o){var n=this._collectRangeSettings(e,i),s=this.getColumnRange(t,e);o&&"z"!=e&&s.expand(n.barWidth/2),this._setRangeDefaults(s,n.min,n.max),this[n.range_label]=s,this[n.step_label]=void 0!==n.step?n.step:s.range()/5},o.prototype.getDistinctValues=function(t,e){void 0===e&&(e=this.dataTable);for(var i=[],o=0;o"+this.zLabel+": "+t.point.z+" /.test(t.substr(i.position,6))?(i.emitBlock(),i.mono=!0,i.modStack.unshift("mono"),i.position+=5):!i.mono&&"bold"===i.mod()&&/<\/b>/.test(t.substr(i.position,4))?(i.emitBlock(),i.bold=!1,i.modStack.shift(),i.position+=3):!i.mono&&"ital"===i.mod()&&/<\/i>/.test(t.substr(i.position,4))?(i.emitBlock(),i.ital=!1,i.modStack.shift(),i.position+=3):"mono"===i.mod()&&/<\/code>/.test(t.substr(i.position,7))?(i.emitBlock(),i.mono=!1,i.modStack.shift(),i.position+=6):i.add(o):(i.emitBlock(),i.ital=!0,i.modStack.unshift("ital"),i.position+=2):(i.emitBlock(),i.bold=!0,i.modStack.unshift("bold"),i.position+=2):/&/.test(o)?/</.test(t.substr(i.position,4))?(i.add("<"),i.position+=3):/&/.test(t.substr(i.position,5))?(i.add("&"),i.position+=4):i.add("&"):i.add(o),i.position++}return i.emitBlock(),e}},{key:"splitMarkdownBlocks",value:function(t){var e=[],i={bold:!1,ital:!1,mono:!1,beginable:!0,spacing:!1,position:0,buffer:"",modStack:[]};for(i.mod=function(){return 0===this.modStack.length?"normal":this.modStack[0]},i.modName=function(){return 0===this.modStack.length?"normal":"mono"===this.modStack[0]?"mono":i.bold&&i.ital?"boldital":i.bold?"bold":i.ital?"ital":void 0},i.emitBlock=function(){arguments.length>0&&void 0!==arguments[0]&&arguments[0];this.spacing&&(this.add(" "),this.spacing=!1),this.buffer.length>0&&(e.push({text:this.buffer,mod:this.modName()}),this.buffer="")},i.add=function(t){" "===t&&(i.spacing=!0),i.spacing&&(this.buffer+=" ",this.spacing=!1)," "!=t&&(this.buffer+=t)};i.position