diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..a40b6ba --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: vangj +patreon: vangj +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: https://oneoffcoder.com/ diff --git a/.gitignore b/.gitignore index 860f418..96d1a7d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .DS_Store -.vscode/ \ No newline at end of file +.vscode/ +.ipynb_checkpoints/ \ No newline at end of file diff --git a/README.md b/README.md index 0cd2029..a80641e 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ info@oneoffcoder.com. * [HTML, CSS, JavaScript](html): Games based on HTML, CSS and JavaScript * [Java, Greenfoot](java/greenfoot): Games based on Java and Greenfoot +* [Python, Pygame](python/pygame): Games based on Python and Pygame # Citation diff --git a/html/README.md b/html/README.md index 25c693a..2c7f949 100644 --- a/html/README.md +++ b/html/README.md @@ -1,7 +1,15 @@ +![One-Off Coder Logo](../logo.png "One-Off Coder") + # Project Description * [guessing-game](guessing-game): Have fun coding a game that asks users to guess which number the computer will generate. * [slot-machine-game](slot-machine-game): Learn about random number generators through coding a slot machine simulator. * [rps-game](rps-game): A challenging project to code the classic Rock, Paper, Scissor game. * [tic-tac-toe](tic-tack-toe): Classic tic tac toe. -* [checkers](checkers): Classic checkers. \ No newline at end of file +* [colors](colors): Colors! +* [checkers](checkers): Classic checkers. +* [solar-system](solar-system): A simulation of the planetary orbits in our solar system. +* [game-of-life](game-of-life): Conway's Game of Life. +* [morse-code](morse-code): Morse code. +* [sign-language](sign-language): Learn sign language alphabets. +* [rps++](rps++): Rock, Paper, Scissor re-invented with a double dose of artificial intelligence; hand pose recognition with deep learning and hand pose prediction with logistic regression. \ No newline at end of file diff --git a/html/checkers/index.html b/html/checkers/index.html index bc22a53..0a2262e 100644 --- a/html/checkers/index.html +++ b/html/checkers/index.html @@ -1,742 +1,764 @@ - - - Checkers - - - - - -
-

Checkers

-
- - -
- - - - - - - - -
- Red Score -
- 0 -
- - One-Off Coder - -
- Red's Turn -
- Black Score -
- 0 -
- - - + return undefined; + } + + + \ No newline at end of file diff --git a/html/colors/index.html b/html/colors/index.html index 2094171..af45613 100644 --- a/html/colors/index.html +++ b/html/colors/index.html @@ -1,109 +1,144 @@ - - Colors - - - -
-

Colors!

-
-
- -
-
-   + + + + + + + + Colors + + + + + +
+
+

Colors!

+

+ Color generator +

+
+

+ Hit scramble to generate new colors +

+

+ + Source Code + +

+
- - - - - - - - - - - - - - - - - - -
   
   
   
- - - - + + + + - + + isPlayingSound = true; + playSound(); + updateColors(); + } + + + \ No newline at end of file diff --git a/html/game-of-life/index.html b/html/game-of-life/index.html new file mode 100644 index 0000000..b0923c8 --- /dev/null +++ b/html/game-of-life/index.html @@ -0,0 +1,400 @@ + + + + + + + + + Game of Life + + + + + +
+
+

Game of Life

+

+ Wikipedia +

+
+

+ Select a pattern. Hit Initialize to create the pattern. Hit Start Simulation to begin. +

+

+ + Source Code + +

+
+
+ +
+
+
+
+
+ +
+ +
+
+
+ + + 0 +
+
+
+ + + +
+ + + + + + + + \ No newline at end of file diff --git a/html/guessing-game/index.html b/html/guessing-game/index.html index a0962f7..4b55aa7 100644 --- a/html/guessing-game/index.html +++ b/html/guessing-game/index.html @@ -1,81 +1,135 @@ - - Guessing Game - - - - -

Guessing Game!

-

- Are you able to guess which numbers the computer will generate? -

-

- Try entering the numbers: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -

- - -
-
- - - + + total += 1; + + const answerDiv = document.getElementById('answer-div'); + answerDiv.innerHTML = message; + answerDiv.style.display = 'block'; + + const scoreDiv = document.getElementById('score-div'); + scoreDiv.innerHTML = `Score = ${score} of ${total}`; + scoreDiv.style.display = 'block'; + + if (number === randomNumber) { + const effect = getRandomEffect(); + playBoing(); + + scoreDiv.className = ''; + scoreDiv.classList.add('alert', 'alert-info', 'animated', effect) + } + } + + function playBoing() { + const boing = document.getElementById('boing'); + boing.play(); + } + + + \ No newline at end of file diff --git a/html/index.html b/html/index.html new file mode 100644 index 0000000..afa4223 --- /dev/null +++ b/html/index.html @@ -0,0 +1,138 @@ + + + + + + + + + Web Programming Demos + + + + + +
+
+

Web Programming Demos

+

+ + One-Off Coder + +

+

+ "The best way to predict the future is to create it," President Abraham Lincoln. +

+
+

+ + Source Code on GitHub + +

+ +
+
+ + + +
+
    +
  • + Checkers: Learn how to code checkers with HTML 5's drag and drop features. +
  • +
  • + Colors: Have fun making colors out of tables. +
  • +
  • + Game of Life: Create artificial life according to Conway's Game of Life. +
  • +
  • + Guessing Game: Test your guessing skills by guessing numbers generated by + the computer. +
  • +
  • + Morse Code: Master sound manipulation with web technologies and learn about + morse code. +
  • +
  • + Rock, Paper, Scissor: Code the classic Rock, Paper, Scissor game. +
  • +
  • + Rock, Paper, Scissor (Re-imagined): Use a double-dose of artificial intelligence to + challenge + the computer in an interactive game of Rock, Paper, Scissor. +
  • +
  • + Sign Language: A fun and neat program to test your knowledge of sign + language + alphabets. +
  • +
  • + Slot Machine: Emulate a slot machine game. +
  • +
  • + Solar System: Bring the solar system to life by coding it! +
  • +
  • + Tic-Tac-Toe: Play tic-tac-toe against the computer. +
  • +
+
+ +
+ + + + + + + + \ No newline at end of file diff --git a/html/logo.png b/html/logo.png new file mode 100644 index 0000000..0b76411 Binary files /dev/null and b/html/logo.png differ diff --git a/html/morse-code/audios/0.wav b/html/morse-code/audios/0.wav new file mode 100644 index 0000000..63f23a1 Binary files /dev/null and b/html/morse-code/audios/0.wav differ diff --git a/html/morse-code/audios/1.wav b/html/morse-code/audios/1.wav new file mode 100644 index 0000000..b9d7eee Binary files /dev/null and b/html/morse-code/audios/1.wav differ diff --git a/html/morse-code/audios/2.wav b/html/morse-code/audios/2.wav new file mode 100644 index 0000000..bc42a81 Binary files /dev/null and b/html/morse-code/audios/2.wav differ diff --git a/html/morse-code/audios/3.wav b/html/morse-code/audios/3.wav new file mode 100644 index 0000000..a804473 Binary files /dev/null and b/html/morse-code/audios/3.wav differ diff --git a/html/morse-code/audios/4.wav b/html/morse-code/audios/4.wav new file mode 100644 index 0000000..07cf508 Binary files /dev/null and b/html/morse-code/audios/4.wav differ diff --git a/html/morse-code/audios/5.wav b/html/morse-code/audios/5.wav new file mode 100644 index 0000000..b3b0f3d Binary files /dev/null and b/html/morse-code/audios/5.wav differ diff --git a/html/morse-code/audios/6.wav b/html/morse-code/audios/6.wav new file mode 100644 index 0000000..add1f54 Binary files /dev/null and b/html/morse-code/audios/6.wav differ diff --git a/html/morse-code/audios/7.wav b/html/morse-code/audios/7.wav new file mode 100644 index 0000000..26da5e4 Binary files /dev/null and b/html/morse-code/audios/7.wav differ diff --git a/html/morse-code/audios/8.wav b/html/morse-code/audios/8.wav new file mode 100644 index 0000000..d5ddc6b Binary files /dev/null and b/html/morse-code/audios/8.wav differ diff --git a/html/morse-code/audios/9.wav b/html/morse-code/audios/9.wav new file mode 100644 index 0000000..a613a7c Binary files /dev/null and b/html/morse-code/audios/9.wav differ diff --git a/html/morse-code/audios/A.wav b/html/morse-code/audios/A.wav new file mode 100644 index 0000000..c7b1a8f Binary files /dev/null and b/html/morse-code/audios/A.wav differ diff --git a/html/morse-code/audios/B.wav b/html/morse-code/audios/B.wav new file mode 100644 index 0000000..0c3db4b Binary files /dev/null and b/html/morse-code/audios/B.wav differ diff --git a/html/morse-code/audios/C.wav b/html/morse-code/audios/C.wav new file mode 100644 index 0000000..b575a9c Binary files /dev/null and b/html/morse-code/audios/C.wav differ diff --git a/html/morse-code/audios/D.wav b/html/morse-code/audios/D.wav new file mode 100644 index 0000000..28d4ff3 Binary files /dev/null and b/html/morse-code/audios/D.wav differ diff --git a/html/morse-code/audios/E.wav b/html/morse-code/audios/E.wav new file mode 100644 index 0000000..6af89a9 Binary files /dev/null and b/html/morse-code/audios/E.wav differ diff --git a/html/morse-code/audios/F.wav b/html/morse-code/audios/F.wav new file mode 100644 index 0000000..7e9749b Binary files /dev/null and b/html/morse-code/audios/F.wav differ diff --git a/html/morse-code/audios/G.wav b/html/morse-code/audios/G.wav new file mode 100644 index 0000000..de21c4b Binary files /dev/null and b/html/morse-code/audios/G.wav differ diff --git a/html/morse-code/audios/H.wav b/html/morse-code/audios/H.wav new file mode 100644 index 0000000..07c7d52 Binary files /dev/null and b/html/morse-code/audios/H.wav differ diff --git a/html/morse-code/audios/I.wav b/html/morse-code/audios/I.wav new file mode 100644 index 0000000..de3bdbe Binary files /dev/null and b/html/morse-code/audios/I.wav differ diff --git a/html/morse-code/audios/J.wav b/html/morse-code/audios/J.wav new file mode 100644 index 0000000..d2084dd Binary files /dev/null and b/html/morse-code/audios/J.wav differ diff --git a/html/morse-code/audios/K.wav b/html/morse-code/audios/K.wav new file mode 100644 index 0000000..db85aec Binary files /dev/null and b/html/morse-code/audios/K.wav differ diff --git a/html/morse-code/audios/L.wav b/html/morse-code/audios/L.wav new file mode 100644 index 0000000..144f199 Binary files /dev/null and b/html/morse-code/audios/L.wav differ diff --git a/html/morse-code/audios/M.wav b/html/morse-code/audios/M.wav new file mode 100644 index 0000000..29ab9a8 Binary files /dev/null and b/html/morse-code/audios/M.wav differ diff --git a/html/morse-code/audios/N.wav b/html/morse-code/audios/N.wav new file mode 100644 index 0000000..4e883e3 Binary files /dev/null and b/html/morse-code/audios/N.wav differ diff --git a/html/morse-code/audios/O.wav b/html/morse-code/audios/O.wav new file mode 100644 index 0000000..dfa4887 Binary files /dev/null and b/html/morse-code/audios/O.wav differ diff --git a/html/morse-code/audios/P.wav b/html/morse-code/audios/P.wav new file mode 100644 index 0000000..b856552 Binary files /dev/null and b/html/morse-code/audios/P.wav differ diff --git a/html/morse-code/audios/Q.wav b/html/morse-code/audios/Q.wav new file mode 100644 index 0000000..bff6a2d Binary files /dev/null and b/html/morse-code/audios/Q.wav differ diff --git a/html/morse-code/audios/R.wav b/html/morse-code/audios/R.wav new file mode 100644 index 0000000..2a1c322 Binary files /dev/null and b/html/morse-code/audios/R.wav differ diff --git a/html/morse-code/audios/S.wav b/html/morse-code/audios/S.wav new file mode 100644 index 0000000..08be62a Binary files /dev/null and b/html/morse-code/audios/S.wav differ diff --git a/html/morse-code/audios/T.wav b/html/morse-code/audios/T.wav new file mode 100644 index 0000000..4f9eaa8 Binary files /dev/null and b/html/morse-code/audios/T.wav differ diff --git a/html/morse-code/audios/U.wav b/html/morse-code/audios/U.wav new file mode 100644 index 0000000..ae7b47f Binary files /dev/null and b/html/morse-code/audios/U.wav differ diff --git a/html/morse-code/audios/V.wav b/html/morse-code/audios/V.wav new file mode 100644 index 0000000..a04a676 Binary files /dev/null and b/html/morse-code/audios/V.wav differ diff --git a/html/morse-code/audios/W.wav b/html/morse-code/audios/W.wav new file mode 100644 index 0000000..8f7b4e6 Binary files /dev/null and b/html/morse-code/audios/W.wav differ diff --git a/html/morse-code/audios/X.wav b/html/morse-code/audios/X.wav new file mode 100644 index 0000000..e1b7f05 Binary files /dev/null and b/html/morse-code/audios/X.wav differ diff --git a/html/morse-code/audios/Y.wav b/html/morse-code/audios/Y.wav new file mode 100644 index 0000000..85a1b93 Binary files /dev/null and b/html/morse-code/audios/Y.wav differ diff --git a/html/morse-code/audios/Z.wav b/html/morse-code/audios/Z.wav new file mode 100644 index 0000000..d7ad843 Binary files /dev/null and b/html/morse-code/audios/Z.wav differ diff --git a/html/morse-code/audios/dah.wav b/html/morse-code/audios/dah.wav new file mode 100644 index 0000000..4f9eaa8 Binary files /dev/null and b/html/morse-code/audios/dah.wav differ diff --git a/html/morse-code/audios/dih.wav b/html/morse-code/audios/dih.wav new file mode 100644 index 0000000..6af89a9 Binary files /dev/null and b/html/morse-code/audios/dih.wav differ diff --git a/html/morse-code/audios/space.wav b/html/morse-code/audios/space.wav new file mode 100644 index 0000000..308c77e Binary files /dev/null and b/html/morse-code/audios/space.wav differ diff --git a/html/morse-code/index.html b/html/morse-code/index.html new file mode 100644 index 0000000..7234d93 --- /dev/null +++ b/html/morse-code/index.html @@ -0,0 +1,339 @@ + + + + + + + + + Morse Code + + + + + +
+
+

Morse Code

+

+ Morse code audio generator +

+
+

+ Dih-dah sounds generated using + + morse-code-wav + +

+

+ Awesome video on Morse code +

+

+ + Source Code + +

+
+
+
+ + +
+ + +
+
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/html/racing/index.html b/html/racing/index.html new file mode 100644 index 0000000..f0b446c --- /dev/null +++ b/html/racing/index.html @@ -0,0 +1,59 @@ + + + + Racing + + + + + + +
+
+ tennis ball progress bar +
+ + + + + + + + \ No newline at end of file diff --git a/html/racing/tennis-ball.png b/html/racing/tennis-ball.png new file mode 100644 index 0000000..d6e6a8a Binary files /dev/null and b/html/racing/tennis-ball.png differ diff --git a/html/rps++/data-capture/README.md b/html/rps++/data-capture/README.md new file mode 100644 index 0000000..62141ee --- /dev/null +++ b/html/rps++/data-capture/README.md @@ -0,0 +1,5 @@ +# Info + +Use this application to acquire training data for learning rock, paper, scissor and shoot hand poses. +The [Python](python) code is a [Jupyter](https://jupyter.org/) notebook that uses the training data to learn a logistic +regression model to make predictions about the meaning of the hand poses. \ No newline at end of file diff --git a/html/rps++/data-capture/index.html b/html/rps++/data-capture/index.html new file mode 100644 index 0000000..9fcef56 --- /dev/null +++ b/html/rps++/data-capture/index.html @@ -0,0 +1,50 @@ + + + + + + + Display Webcam Stream + + + + + + +
+
+ + +
+
+ + + + + + +
+ + + + + + + \ No newline at end of file diff --git a/html/rps++/data-capture/index.js b/html/rps++/data-capture/index.js new file mode 100644 index 0000000..e700581 --- /dev/null +++ b/html/rps++/data-capture/index.js @@ -0,0 +1,210 @@ +let videoWidth, videoHeight, + scatterGLHasInitialized = false, scatterGL, fingerLookupIndices = { + thumb: [0, 1, 2, 3, 4], + indexFinger: [0, 5, 6, 7, 8], + middleFinger: [0, 9, 10, 11, 12], + ringFinger: [0, 13, 14, 15, 16], + pinky: [0, 17, 18, 19, 20] + }; +let model; +const VIDEO_WIDTH = 640; +const VIDEO_HEIGHT = 500; +const mobile = false; +let lastSymbol = undefined; +let symbol = undefined; +const data = { + 'rock': [], + 'paper': [], + 'scissor': [], + 'shoot': [] +} + +function drawKeypoints(ctx, keypoints) { + function drawPoint(ctx, y, x, r) { + ctx.beginPath(); + ctx.arc(x, y, r, 0, 2 * Math.PI); + ctx.fill(); + } + + function drawPath(ctx, points, closePath) { + const region = new Path2D(); + region.moveTo(points[0][0], points[0][1]); + for (let i = 1; i < points.length; i++) { + const point = points[i]; + region.lineTo(point[0], point[1]); + } + + if (closePath) { + region.closePath(); + } + ctx.stroke(region); + } + + const keypointsArray = keypoints; + + for (let i = 0; i < keypointsArray.length; i++) { + const y = keypointsArray[i][0]; + const x = keypointsArray[i][1]; + drawPoint(ctx, x - 2, y - 2, 3); + } + + const fingers = Object.keys(fingerLookupIndices); + for (let i = 0; i < fingers.length; i++) { + const finger = fingers[i]; + const points = fingerLookupIndices[finger].map(idx => keypoints[idx]); + drawPath(ctx, points, false); + } +} + +async function setupCamera() { + if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { + throw new Error( + 'Browser API navigator.mediaDevices.getUserMedia not available'); + } + + const video = document.getElementById('video'); + const stream = await navigator.mediaDevices.getUserMedia({ + 'audio': false, + 'video': { + facingMode: 'user', + width: mobile ? undefined : VIDEO_WIDTH, + height: mobile ? undefined : VIDEO_HEIGHT + }, + }); + video.srcObject = stream; + + return new Promise((resolve) => { + video.onloadedmetadata = () => { + resolve(video); + }; + }); +} + +async function loadVideo() { + const video = await setupCamera(); + video.play(); + return video; +} + +const main = + async () => { + model = await handpose.load(); + let video; + + try { + video = await loadVideo(); + } catch (e) { + let info = document.getElementById('info'); + info.textContent = e.message; + info.style.display = 'block'; + throw e; + } + + landmarksRealTime(video); + } + +const landmarksRealTime = async (video) => { + videoWidth = video.videoWidth; + videoHeight = video.videoHeight; + + const canvas = document.getElementById('output'); + + canvas.width = videoWidth; + canvas.height = videoHeight; + + const ctx = canvas.getContext('2d'); + + ctx.clearRect(0, 0, videoWidth, videoHeight); + ctx.strokeStyle = 'red'; + ctx.fillStyle = 'red'; + + ctx.translate(canvas.width, 0); + ctx.scale(-1, 1); + + // These anchor points allow the hand pointcloud to resize according to its + // position in the input. + const ANCHOR_POINTS = [ + [0, 0, 0], [0, -VIDEO_HEIGHT, 0], [-VIDEO_WIDTH, 0, 0], + [-VIDEO_WIDTH, -VIDEO_HEIGHT, 0] + ]; + + async function frameLandmarks() { + ctx.drawImage( + video, 0, 0, videoWidth, videoHeight, 0, 0, canvas.width, + canvas.height); + const predictions = await model.estimateHands(video); + if (predictions.length > 0) { + const result = predictions[0].landmarks; + const annots = predictions[0].annotations; + + if (symbol) { + const d = captureData(annots); + data[symbol].push(d); + + console.log(d); + uncapture(); + } + + drawKeypoints(ctx, result, annots); + } + requestAnimationFrame(frameLandmarks); + }; + + frameLandmarks(); +}; + +function captureData(annots) { + function getPoints(k, prefix, data) { + for (let i = 0; i < annots[k].length; i++) { + const colPrefix = `${prefix}${i}`; + const suf = ['x', 'y', 'z']; + const arr = annots[k][i]; + for (let j = 0; j < arr.length; j++) { + const col = `${colPrefix}${suf[j]}`; + const val = arr[j]; + data[col] = val; + } + } + } + + const data = {}; + getPoints('indexFinger', 'index', data); + getPoints('middleFinger', 'middle', data); + getPoints('ringFinger', 'ring', data); + getPoints('pinky', 'pinky', data); + getPoints('thumb', 'thumb', data); + getPoints('palmBase', 'palm', data) + return data; +} + +function capture(s) { + symbol = s; +} + +function uncapture() { + lastSymbol = symbol; + symbol = undefined; +} + +function undo() { + data[lastSymbol].pop(); +} + +function download() { + function getMsPastEpoch() { + const now = new Date() + const ms = now.getTime() + return ms; + } + + const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(data)); + const a = document.getElementById('dlAnchor'); + a.setAttribute('href', dataStr); + a.setAttribute('download', `data-${getMsPastEpoch()}.json`); + a.click(); +} + +navigator.getUserMedia = navigator.getUserMedia || + navigator.webkitGetUserMedia || navigator.mozGetUserMedia; + +tf.setBackend('webgl').then(() => main()); diff --git a/html/rps++/data-capture/python/README.md b/html/rps++/data-capture/python/README.md new file mode 100644 index 0000000..8aa4904 --- /dev/null +++ b/html/rps++/data-capture/python/README.md @@ -0,0 +1,6 @@ +# Info + +[model.ipynb](model.ipynb) uses a Logistic regression model to learn the patterns +of rock, paper, scissor and shoot hand poses. The input data are [data-adult.json](data-adult.json) and [data-kid.json](data-kid.json), which are predefined hand poses captured +from an adult and child. The output is [models.json](models.json) which is a JSON +file of the parameters of the predictive models for the hand poses. \ No newline at end of file diff --git a/html/rps++/data-capture/python/data-adult.json b/html/rps++/data-capture/python/data-adult.json new file mode 100644 index 0000000..f869e07 --- /dev/null +++ b/html/rps++/data-capture/python/data-adult.json @@ -0,0 +1 @@ +{"rock":[{"index0x":349.5788393736799,"index0y":208.6439363713304,"index0z":-1.5604321956634521,"index1x":352.439454816465,"index1y":188.40688262034365,"index1z":-26.908557891845703,"index2x":351.6742048706553,"index2y":207.87129084466773,"index2z":-39.9258918762207,"index3x":348.88506263098094,"index3y":217.42191124337344,"index3z":-34.58384704589844,"middle0x":334.97481657740406,"middle0y":206.7200063421924,"middle0z":-0.8374499082565308,"middle1x":337.6616998235406,"middle1y":188.39174200075135,"middle1z":-23.210678100585938,"middle2x":338.16294148384907,"middle2y":211.02416330515743,"middle2z":-33.820533752441406,"middle3x":335.30066995346226,"middle3y":218.46654398508323,"middle3z":-27.149370193481445,"ring0x":320.1109182816754,"ring0y":208.33719038600483,"ring0z":-3.778226852416992,"ring1x":322.57557321136875,"ring1y":191.92654361833297,"ring1z":-24.995407104492188,"ring2x":326.10776285366916,"ring2y":213.99676238211015,"ring2z":-33.54325866699219,"ring3x":323.4330345127075,"ring3y":222.59509589641138,"ring3z":-28.60563087463379,"pinky0x":304.24533930026166,"pinky0y":213.76123981657943,"pinky0z":-7.5594868659973145,"pinky1x":310.5057022970355,"pinky1y":201.22709369353254,"pinky1z":-24.8538818359375,"pinky2x":316.009519277749,"pinky2y":216.03774810137242,"pinky2z":-28.688365936279297,"pinky3x":313.7572854482062,"pinky3y":224.50713774390474,"pinky3z":-24.240015029907227,"thumb0x":347.62848616227075,"thumb0y":256.236218792423,"thumb0z":-14.98921012878418,"thumb1x":364.7725385113902,"thumb1y":234.014542903733,"thumb1z":-18.366636276245117,"thumb2x":359.23105764914527,"thumb2y":214.55318235664183,"thumb2z":-19.95022964477539,"thumb3x":343.5230798086845,"thumb3y":216.15598150715556,"thumb3z":-21.44710922241211,"palm0x":324.5980486950647,"palm0y":263.08743458454074,"palm0z":-0.0013375580310821533},{"index0x":305.1310648773269,"index0y":124.45453635341077,"index0z":-28.991687774658203,"index1x":306.7556773872984,"index1y":102.5809829795734,"index1z":-69.2767562866211,"index2x":303.5959564415183,"index2y":138.82873914812063,"index2z":-83.84068298339844,"index3x":299.2088834801142,"index3y":162.7671807123232,"index3z":-79.84419250488281,"middle0x":271.1626858993949,"middle0y":122.38862579058583,"middle0z":-27.204498291015625,"middle1x":271.4034538948955,"middle1y":108.77899860090189,"middle1z":-71.66704559326172,"middle2x":273.8450855664125,"middle2y":157.81589627683366,"middle2z":-80.3253402709961,"middle3x":277.9419189520846,"middle3y":177.11881534322384,"middle3z":-71.05801391601562,"ring0x":236.68072020980847,"ring0y":126.55376167251711,"ring0z":-29.862804412841797,"ring1x":237.51619057817175,"ring1y":128.10157512004167,"ring1z":-71.00072479248047,"ring2x":247.82195924715376,"ring2y":173.43494284142207,"ring2z":-73.76062774658203,"ring3x":252.9702525895222,"ring3y":184.22806704305202,"ring3z":-63.21534729003906,"pinky0x":206.90542124915868,"pinky0y":139.06396300905936,"pinky0z":-33.59825897216797,"pinky1x":206.04105569647245,"pinky1y":143.60995264164168,"pinky1z":-64.66250610351562,"pinky2x":217.99142193719905,"pinky2y":175.68580637502055,"pinky2z":-63.55521774291992,"pinky3x":226.59116095763773,"pinky3y":185.2293554443727,"pinky3z":-51.37748718261719,"thumb0x":298.5564622275987,"thumb0y":221.63235138266845,"thumb0z":-28.853593826293945,"thumb1x":334.4088158781265,"thumb1y":186.61155916572883,"thumb1z":-47.29142379760742,"thumb2x":339.9161146791208,"thumb2y":153.7768321420491,"thumb2z":-63.60932922363281,"thumb3x":321.33141578549237,"thumb3y":132.0883963964663,"thumb3z":-79.45893859863281,"palm0x":257.2571725229481,"palm0y":229.3274693671841,"palm0z":-0.001331828534603119},{"index0x":158.77367617287302,"index0y":82.64660900093605,"index0z":-5.766336917877197,"index1x":159.76542945840364,"index1y":40.94092079212302,"index1z":-32.083213806152344,"index2x":159.99250735063498,"index2y":85.54577808025292,"index2z":-44.66018295288086,"index3x":155.0718576926175,"index3y":105.74610209895194,"index3z":-39.13585662841797,"middle0x":124.5679614487626,"middle0y":83.29243374202382,"middle0z":-4.501091003417969,"middle1x":124.15343519019133,"middle1y":45.40508410706839,"middle1z":-28.750761032104492,"middle2x":129.2179105182813,"middle2y":95.91687181770521,"middle2z":-38.44501876831055,"middle3x":126.72590524267274,"middle3y":111.7027879067145,"middle3z":-30.97357177734375,"ring0x":90.9313475474996,"ring0y":91.49915257920549,"ring0z":-6.916260719299316,"ring1x":88.50929327380537,"ring1y":54.45466764511905,"ring1z":-29.3592472076416,"ring2x":101.28340139347341,"ring2y":100.8219418362347,"ring2z":-37.375762939453125,"ring3x":101.04329630232348,"ring3y":119.01103343201734,"ring3z":-32.372093200683594,"pinky0x":56.98425175224112,"pinky0y":107.04866317515727,"pinky0z":-10.297653198242188,"pinky1x":59.617284611422946,"pinky1y":75.22586188158274,"pinky1z":-27.958757400512695,"pinky2x":73.84362596519622,"pinky2y":102.94076160635284,"pinky2z":-31.197891235351562,"pinky3x":75.05543591995476,"pinky3y":119.3131103681799,"pinky3z":-26.257450103759766,"thumb0x":170.8039075950193,"thumb0y":186.21215514767192,"thumb0z":-17.13858985900879,"thumb1x":201.74897376672834,"thumb1y":131.73952061386433,"thumb1z":-22.94062042236328,"thumb2x":183.12675085274176,"thumb2y":89.3555261836702,"thumb2z":-26.77819061279297,"thumb3x":142.79882477278827,"thumb3y":96.24229693218716,"thumb3z":-31.449377059936523,"palm0x":122.79060842196068,"palm0y":209.82335230694076,"palm0z":-0.0015365704894065857},{"index0x":186.88737903012063,"index0y":179.05834832242596,"index0z":-0.6407682299613953,"index1x":195.4567006120849,"index1y":141.34001784202627,"index1z":-23.131059646606445,"index2x":192.95485896942867,"index2y":181.78159691677203,"index2z":-36.638946533203125,"index3x":187.10957506439968,"index3y":197.39825252419269,"index3z":-33.66593933105469,"middle0x":159.10879250601113,"middle0y":175.6889091596509,"middle0z":0.07570791244506836,"middle1x":164.97970074083804,"middle1y":140.54544194964848,"middle1z":-19.20734405517578,"middle2x":164.8323722582668,"middle2y":184.52483235920064,"middle2z":-28.026981353759766,"middle3x":159.63510491069434,"middle3y":196.64868679998372,"middle3z":-21.492969512939453,"ring0x":130.23279877036134,"ring0y":178.19882504303376,"ring0z":-2.1623098850250244,"ring1x":133.48399085345358,"ring1y":143.12112025793084,"ring1z":-19.537084579467773,"ring2x":140.25264187395712,"ring2y":184.57150683121523,"ring2z":-26.126070022583008,"ring3x":136.19924317283792,"ring3y":199.67295362180744,"ring3z":-21.63973045349121,"pinky0x":99.42162001552956,"pinky0y":187.4827526181117,"pinky0z":-5.116781234741211,"pinky1x":107.3624627331387,"pinky1y":156.87520616672577,"pinky1z":-18.159732818603516,"pinky2x":118.04676924838301,"pinky2y":182.88050270871594,"pinky2z":-20.066848754882812,"pinky3x":115.60053718640205,"pinky3y":198.59850896777536,"pinky3z":-15.855325698852539,"thumb0x":187.35454343352086,"thumb0y":264.043888877763,"thumb0z":-11.618050575256348,"thumb1x":216.8659795355836,"thumb1y":218.4597947971046,"thumb1z":-13.632129669189453,"thumb2x":201.68248498120937,"thumb2y":179.758463554432,"thumb2z":-13.834517478942871,"thumb3x":169.9613667739204,"thumb3y":189.42830141809173,"thumb3z":-15.042081832885742,"palm0x":144.56022205409354,"palm0y":285.30839624306856,"palm0z":-0.001245640218257904},{"index0x":175.32036356260141,"index0y":319.5479980922219,"index0z":-15.010385513305664,"index1x":181.47989744025344,"index1y":286.3827385314187,"index1z":-38.390289306640625,"index2x":182.58925539371063,"index2y":319.1286507661645,"index2z":-47.27629089355469,"index3x":179.16138329734366,"index3y":337.39390912292674,"index3z":-42.19207763671875,"middle0x":145.23435962718526,"middle0y":318.4372948405033,"middle0z":-14.887651443481445,"middle1x":153.98260752108118,"middle1y":290.47673870340435,"middle1z":-39.25751495361328,"middle2x":157.62477278655257,"middle2y":331.9861015819159,"middle2z":-47.930904388427734,"middle3x":155.11112956927207,"middle3y":346.1825181662931,"middle3z":-42.76239013671875,"ring0x":116.82092880182006,"ring0y":324.59865752508796,"ring0z":-17.725297927856445,"ring1x":124.372417005821,"ring1y":300.6308868053314,"ring1z":-41.12071228027344,"ring2x":133.2731066408972,"ring2y":340.5064511520443,"ring2z":-48.34052658081055,"ring3x":131.8497861882706,"ring3y":355.89454064565183,"ring3z":-44.64386749267578,"pinky0x":89.74575519789317,"pinky0y":338.276390628409,"pinky0z":-21.41387176513672,"pinky1x":97.96400476829535,"pinky1y":319.57121791823175,"pinky1z":-40.83126449584961,"pinky2x":109.6886414001799,"pinky2y":345.96195206482145,"pinky2z":-44.0661506652832,"pinky3x":110.7847462708721,"pinky3y":360.2885814010751,"pinky3z":-39.470699310302734,"thumb0x":177.30854585241232,"thumb0y":408.7391842189641,"thumb0z":-18.077800750732422,"thumb1x":206.24492587964602,"thumb1y":369.49481365855706,"thumb1z":-27.353673934936523,"thumb2x":201.52827413105194,"thumb2y":340.80223397527215,"thumb2z":-35.02554702758789,"thumb3x":179.09292127171545,"thumb3y":341.3281667147951,"thumb3z":-43.13957214355469,"palm0x":138.70962429842763,"palm0y":422.9388067680373,"palm0z":-0.0012373700737953186},{"index0x":339.1092085427405,"index0y":231.271260461782,"index0z":6.8718342781066895,"index1x":354.6117218583622,"index1y":207.79892822424523,"index1z":-8.144258499145508,"index2x":357.25118773146454,"index2y":233.9969080232379,"index2z":-11.055868148803711,"index3x":353.4176747605995,"index3y":246.68811416414673,"index3z":-3.9951014518737793,"middle0x":316.9925488557409,"middle0y":229.70576238970145,"middle0z":2.68247652053833,"middle1x":342.9706496986529,"middle1y":212.64201901498487,"middle1z":-15.951677322387695,"middle2x":345.34994781655615,"middle2y":251.5734608448206,"middle2z":-18.41554832458496,"middle3x":336.425840812352,"middle3y":262.8331665775957,"middle3z":-9.715165138244629,"ring0x":295.62724724548065,"ring0y":234.75879804136798,"ring0z":-4.575410842895508,"ring1x":324.13188471840056,"ring1y":219.6608813010143,"ring1z":-22.39185905456543,"ring2x":328.23250480472416,"ring2y":258.0765791500921,"ring2z":-22.38457679748535,"ring3x":318.33771939475747,"ring3y":269.955812598751,"ring3z":-15.145668983459473,"pinky0x":275.1762672866981,"pinky0y":245.59684323955537,"pinky0z":-12.778690338134766,"pinky1x":302.4739603751609,"pinky1y":231.30757843190784,"pinky1z":-26.116796493530273,"pinky2x":311.21516331824085,"pinky2y":257.0729329906373,"pinky2z":-23.280277252197266,"pinky3x":302.0153975415623,"pinky3y":268.6645019746023,"pinky3z":-15.368335723876953,"thumb0x":343.19623534248046,"thumb0y":318.65613878647235,"thumb0z":-7.492701053619385,"thumb1x":370.5558732937032,"thumb1y":286.21726253778047,"thumb1z":-11.494053840637207,"thumb2x":373.8527562292462,"thumb2y":258.79859025182446,"thumb2z":-16.378742218017578,"thumb3x":361.0166820940245,"thumb3y":253.8570586835746,"thumb3z":-19.270851135253906,"palm0x":306.28100303546074,"palm0y":336.04369613285417,"palm0z":-0.0005298927426338196},{"index0x":451.4792036237983,"index0y":169.29309611407197,"index0z":-7.223790168762207,"index1x":454.37502427996566,"index1y":150.2184348928089,"index1z":-32.598331451416016,"index2x":452.0529341578806,"index2y":168.04268597371632,"index2z":-47.10307693481445,"index3x":449.0648387808229,"index3y":178.61434940243396,"index3z":-44.39500045776367,"middle0x":435.28907120194214,"middle0y":166.73567269052467,"middle0z":-5.167429447174072,"middle1x":437.64654666641457,"middle1y":150.03877669021207,"middle1z":-31.18100357055664,"middle2x":437.3480051055729,"middle2y":172.51554073011783,"middle2z":-42.894588470458984,"middle3x":436.7815475183741,"middle3y":181.75156917259002,"middle3z":-36.671531677246094,"ring0x":419.4334300713575,"ring0y":167.992482698469,"ring0z":-6.762670516967773,"ring1x":420.75140449198784,"ring1y":152.46204117468295,"ring1z":-32.06676483154297,"ring2x":423.9043211859038,"ring2y":174.2920785696481,"ring2z":-41.01239013671875,"ring3x":423.80847120314644,"ring3y":183.85535917388523,"ring3z":-35.66046142578125,"pinky0x":403.55612306704944,"pinky0y":172.19160642975723,"pinky0z":-9.256769180297852,"pinky1x":406.62359669450274,"pinky1y":160.26592652578643,"pinky1z":-29.41709327697754,"pinky2x":411.76005580681874,"pinky2y":174.40645128148427,"pinky2z":-32.72838592529297,"pinky3x":412.5650857483245,"pinky3y":182.87777356514576,"pinky3z":-26.775379180908203,"thumb0x":445.6344283567222,"thumb0y":216.9228244109083,"thumb0z":-18.792600631713867,"thumb1x":463.96484474695615,"thumb1y":196.19555017250272,"thumb1z":-25.45708656311035,"thumb2x":458.16523194622107,"thumb2y":174.5713985858703,"thumb2z":-29.870525360107422,"thumb3x":438.7516487012307,"thumb3y":170.86709752960854,"thumb3z":-34.37517166137695,"palm0x":422.1539211748169,"palm0y":221.67376754539842,"palm0z":-0.0018014684319496155},{"index0x":538.2291055453871,"index0y":318.08778409308275,"index0z":-5.40598201751709,"index1x":551.6963528370346,"index1y":315.3766949664491,"index1z":-31.787750244140625,"index2x":550.2858840252354,"index2y":334.52690746174454,"index2z":-34.86565399169922,"index3x":544.3943993828016,"index3y":341.9597493565214,"index3z":-24.30118751525879,"middle0x":522.8270050376549,"middle0y":318.0292112485041,"middle0z":-8.527071952819824,"middle1x":540.3925370856288,"middle1y":318.8616952724739,"middle1z":-37.084678649902344,"middle2x":540.5727569666251,"middle2y":341.40123765425284,"middle2z":-34.939308166503906,"middle3x":535.0273689721971,"middle3y":345.5813474307884,"middle3z":-21.919864654541016,"ring0x":508.4585398831049,"ring0y":322.40263122288417,"ring0z":-15.951735496520996,"ring1x":525.9844525090625,"ring1y":324.0951841205676,"ring1z":-42.99031448364258,"ring2x":527.8308215326787,"ring2y":344.95570769780846,"ring2z":-37.12422180175781,"ring3x":522.0231064311989,"ring3y":348.5149695434195,"ring3z":-24.833356857299805,"pinky0x":495.4458354521726,"pinky0y":330.1695432594688,"pinky0z":-24.37139320373535,"pinky1x":509.92953677460736,"pinky1y":329.76628760557895,"pinky1z":-42.26925277709961,"pinky2x":515.1679169679027,"pinky2y":342.62052739449376,"pinky2z":-33.97574996948242,"pinky3x":511.9212143505996,"pinky3y":345.2908910052495,"pinky3z":-20.330224990844727,"thumb0x":544.4202315440663,"thumb0y":374.81473837075157,"thumb0z":-15.083842277526855,"thumb1x":560.871925342498,"thumb1y":355.45356586640264,"thumb1z":-27.255130767822266,"thumb2x":563.5758090096351,"thumb2y":340.11202023835534,"thumb2z":-40.57731628417969,"thumb3x":556.3389990922411,"thumb3y":335.23262076859885,"thumb3z":-51.88239669799805,"palm0x":523.22929149602,"palm0y":381.1163737911032,"palm0z":-0.0004124492406845093},{"index0x":541.0073336799032,"index0y":111.4347523777801,"index0z":-5.823825359344482,"index1x":549.1933053607411,"index1y":95.51241130109881,"index1z":-30.240663528442383,"index2x":545.6364232416254,"index2y":114.98122892624275,"index2z":-41.045475006103516,"index3x":540.52474312572,"index3y":122.69438035137418,"index3z":-35.93058395385742,"middle0x":526.1747731238909,"middle0y":107.15592993667823,"middle0z":-4.824545860290527,"middle1x":536.1285294994717,"middle1y":94.01754408370844,"middle1z":-28.347442626953125,"middle2x":532.5239583708372,"middle2y":116.43525727247285,"middle2z":-36.39730453491211,"middle3x":527.4243471492615,"middle3y":121.88068615326902,"middle3z":-29.792421340942383,"ring0x":510.9807925220794,"ring0y":106.11884578818331,"ring0z":-7.199642181396484,"ring1x":519.8329292253134,"ring1y":92.9553915955332,"ring1z":-29.383914947509766,"ring2x":519.4561042797005,"ring2y":115.07341383685858,"ring2z":-34.768558502197266,"ring3x":514.6697170104371,"ring3y":122.1097803270602,"ring3z":-29.41884994506836,"pinky0x":494.73432130518256,"pinky0y":108.31548373025399,"pinky0z":-10.401840209960938,"pinky1x":503.74850966050883,"pinky1y":97.39667202978336,"pinky1z":-28.09165382385254,"pinky2x":507.24617340054243,"pinky2y":111.75687701002326,"pinky2z":-29.139118194580078,"pinky3x":504.09146896068467,"pinky3y":118.65919394804138,"pinky3z":-23.6883602142334,"thumb0x":535.5268335741943,"thumb0y":157.45569312655408,"thumb0z":-15.718673706054688,"thumb1x":554.3957374912696,"thumb1y":137.70180359648,"thumb1z":-20.87903594970703,"thumb2x":550.9409117182587,"thumb2y":116.74557544013892,"thumb2z":-24.008512496948242,"thumb3x":536.0262867633073,"thumb3y":114.40598377648233,"thumb3z":-26.86648178100586,"palm0x":510.9430099430404,"palm0y":162.2626593314966,"palm0z":-0.0013084039092063904},{"index0x":282.435236600798,"index0y":130.94901307496167,"index0z":-6.282792091369629,"index1x":285.76222279190324,"index1y":85.53308754993498,"index1z":-23.51962661743164,"index2x":286.4231720438722,"index2y":121.18334448140084,"index2z":-33.463993072509766,"index3x":286.02458370006985,"index3y":142.88888148523574,"index3z":-32.83297348022461,"middle0x":252.1088160696003,"middle0y":126.89799971124127,"middle0z":-5.16782808303833,"middle1x":254.61959722425152,"middle1y":86.04475281414778,"middle1z":-23.80296516418457,"middle2x":257.9333052677177,"middle2y":132.3373449141619,"middle2z":-31.68488311767578,"middle3x":258.1491802947828,"middle3y":151.48026233551022,"middle3z":-27.77214813232422,"ring0x":221.9213059747183,"ring0y":130.31188407410096,"ring0z":-6.750090599060059,"ring1x":223.09388624979425,"ring1y":92.29747164749153,"ring1z":-23.38188362121582,"ring2x":232.329286501423,"ring2y":137.78068708604135,"ring2z":-28.956111907958984,"ring3x":233.14590912472465,"ring3y":157.47316210670047,"ring3z":-25.7459774017334,"pinky0x":190.77936846082312,"pinky0y":140.93117831302018,"pinky0z":-9.30537223815918,"pinky1x":195.1467365020136,"pinky1y":109.37988907726691,"pinky1z":-21.703453063964844,"pinky2x":207.52834240738525,"pinky2y":137.71855108047396,"pinky2z":-23.644203186035156,"pinky3x":209.9330416708873,"pinky3y":155.05601390354195,"pinky3z":-20.066415786743164,"thumb0x":279.0798520573645,"thumb0y":231.59346977548466,"thumb0z":-14.166396141052246,"thumb1x":310.750002628907,"thumb1y":186.88122441510183,"thumb1z":-19.862092971801758,"thumb2x":305.17542987793917,"thumb2y":145.5193153588887,"thumb2z":-23.69707489013672,"thumb3x":281.49092787356255,"thumb3y":138.47209192776336,"thumb3z":-26.52961540222168,"palm0x":236.0186487201919,"palm0y":251.92579822605893,"palm0z":-0.0011773407459259033},{"index0x":375.82850039265236,"index0y":133.44016211572074,"index0z":-1.7111517190933228,"index1x":381.27326751755425,"index1y":93.44383784381102,"index1z":-20.910736083984375,"index2x":386.48968500289715,"index2y":115.00596757278437,"index2z":-34.608089447021484,"index3x":387.3406972742121,"index3y":136.2524359725344,"index3z":-36.50834655761719,"middle0x":345.724929244764,"middle0y":129.76647357629807,"middle0z":-2.190471649169922,"middle1x":353.37390052793825,"middle1y":94.1576969967742,"middle1z":-25.004064559936523,"middle2x":361.73108939980966,"middle2y":137.79030536855868,"middle2z":-37.5887336730957,"middle3x":360.3699810322948,"middle3y":164.17340057020598,"middle3z":-34.38114929199219,"ring0x":316.2286885086256,"ring0y":135.85179095107696,"ring0z":-6.188285827636719,"ring1x":324.5071271055391,"ring1y":106.74716176040393,"ring1z":-28.62761878967285,"ring2x":336.63517857114834,"ring2y":149.8930600165289,"ring2z":-36.95947265625,"ring3x":335.43124437731205,"ring3y":174.2633098926371,"ring3z":-32.53842544555664,"pinky0x":286.26941787012646,"pinky0y":149.6008008764245,"pinky0z":-11.422555923461914,"pinky1x":299.07090766024515,"pinky1y":126.21551957978224,"pinky1z":-29.98678970336914,"pinky2x":313.75061959867935,"pinky2y":153.09173460262826,"pinky2z":-34.687843322753906,"pinky3x":314.8484776939992,"pinky3y":173.29100280051074,"pinky3z":-30.564136505126953,"thumb0x":367.44408986859605,"thumb0y":243.0851810221954,"thumb0z":-15.522136688232422,"thumb1x":402.2074042205942,"thumb1y":201.60001446044123,"thumb1z":-22.367769241333008,"thumb2x":401.9189003964212,"thumb2y":163.05250231022387,"thumb2z":-28.982635498046875,"thumb3x":376.94273630534605,"thumb3y":148.62796482306285,"thumb3z":-34.27616500854492,"palm0x":323.58166539547324,"palm0y":253.38282192815774,"palm0z":-0.0010488331317901611}],"paper":[{"index0x":328.2896712663623,"index0y":176.74161919161634,"index0z":-9.074779510498047,"index1x":347.42215342627924,"index1y":141.33786940986914,"index1z":-13.012499809265137,"index2x":356.7162775201551,"index2y":117.76040698249504,"index2z":-16.35301399230957,"index3x":362.9122159355707,"index3y":98.00226921602169,"index3z":-19.139184951782227,"middle0x":299.2780678251966,"middle0y":168.31656955887152,"middle0z":-9.548994064331055,"middle1x":305.92427685735083,"middle1y":123.48756766489751,"middle1z":-13.314091682434082,"middle2x":309.6990420165351,"middle2y":92.51620887623233,"middle2z":-17.306421279907227,"middle3x":312.3279367041923,"middle3y":68.48552595700562,"middle3z":-19.978626251220703,"ring0x":272.0897009283424,"ring0y":172.1436594108312,"ring0z":-11.923880577087402,"ring1x":267.8044145242555,"ring1y":129.21568900547305,"ring1z":-16.39287757873535,"ring2x":266.42351582853456,"ring2y":98.86522336035416,"ring2z":-19.441360473632812,"ring3x":266.5368683190862,"ring3y":74.28524229771374,"ring3z":-21.2916202545166,"pinky0x":245.6812280655683,"pinky0y":187.8776337055573,"pinky0z":-15.711530685424805,"pinky1x":229.51725035887014,"pinky1y":157.0851440378662,"pinky1z":-20.612802505493164,"pinky2x":219.30114126912719,"pinky2y":134.93312049508873,"pinky2z":-23.146808624267578,"pinky3x":211.23808303389734,"pinky3y":111.86830452126705,"pinky3z":-24.44133186340332,"thumb0x":316.176168288059,"thumb0y":272.3555774533927,"thumb0z":-11.539417266845703,"thumb1x":353.7847710204291,"thumb1y":246.52081042938693,"thumb1z":-17.33092498779297,"thumb2x":381.08410535111125,"thumb2y":224.11713465583313,"thumb2z":-22.60702896118164,"thumb3x":400.3763971282208,"thumb3y":212.27948801204667,"thumb3z":-27.037450790405273,"palm0x":277.73667242290304,"palm0y":277.97562732803135,"palm0z":-0.0012428611516952515},{"index0x":193.60492844910942,"index0y":153.74771597222326,"index0z":-9.092254638671875,"index1x":206.95336434289285,"index1y":116.34273678116955,"index1z":-14.03842830657959,"index2x":213.82493411385155,"index2y":87.73636864816461,"index2z":-18.250164031982422,"index3x":218.5287473785788,"index3y":63.42280793515148,"index3z":-21.559595108032227,"middle0x":164.60690698002054,"middle0y":148.02053117960517,"middle0z":-10.540170669555664,"middle1x":166.96053033188187,"middle1y":104.09361277918737,"middle1z":-15.897716522216797,"middle2x":167.21307308070536,"middle2y":69.86885218275842,"middle2z":-21.108226776123047,"middle3x":167.0629963380153,"middle3y":45.10782657849819,"middle3z":-24.848270416259766,"ring0x":137.23320897059756,"ring0y":154.28023814362908,"ring0z":-13.531745910644531,"ring1x":127.69610716392657,"ring1y":114.72937558135473,"ring1z":-19.82619285583496,"ring2x":120.99954348544888,"ring2y":83.50043041394792,"ring2z":-24.62535858154297,"ring3x":117.23932511391911,"ring3y":59.69780228210695,"ring3z":-27.911033630371094,"pinky0x":111.29423333374609,"pinky0y":172.15615353607103,"pinky0z":-17.50907325744629,"pinky1x":92.79754827516612,"pinky1y":145.59079640877644,"pinky1z":-24.111417770385742,"pinky2x":80.78659454135507,"pinky2y":124.87075195610541,"pinky2z":-28.511016845703125,"pinky3x":71.41748151303196,"pinky3y":103.6737856120857,"pinky3z":-31.459457397460938,"thumb0x":194.03379136688272,"thumb0y":244.23590645217394,"thumb0z":-8.851739883422852,"thumb1x":226.2554625530453,"thumb1y":213.27808478691145,"thumb1z":-13.986620903015137,"thumb2x":252.3976447610747,"thumb2y":183.54540449498847,"thumb2z":-19.05630111694336,"thumb3x":277.0451994751112,"thumb3y":165.59324631604957,"thumb3z":-23.975791931152344,"palm0x":156.42779099836935,"palm0y":252.88150518655607,"palm0z":-0.001177676022052765},{"index0x":332.34391449593636,"index0y":138.05911135621284,"index0z":-2.512378215789795,"index1x":349.7563999284494,"index1y":102.76857847257344,"index1z":-4.126143932342529,"index2x":358.29037374936297,"index2y":78.4195774670275,"index2z":-5.6743340492248535,"index3x":363.2322338620756,"index3y":57.39298580942781,"index3z":-7.258543968200684,"middle0x":304.733860205102,"middle0y":131.438049123103,"middle0z":-3.5240478515625,"middle1x":308.4480728203244,"middle1y":87.53198916470583,"middle1z":-4.053287506103516,"middle2x":310.1430475875439,"middle2y":56.01965351765169,"middle2z":-5.854452133178711,"middle3x":311.08859929438194,"middle3y":31.020108802881566,"middle3z":-6.975428581237793,"ring0x":279.51641176028716,"ring0y":135.4155056276733,"ring0z":-6.426497459411621,"ring1x":273.3074391815867,"ring1y":94.00564230476517,"ring1z":-7.756374359130859,"ring2x":269.67787149905826,"ring2y":62.64371725275106,"ring2z":-9.035202026367188,"ring3x":267.66068552938617,"ring3y":37.03938103303467,"ring3z":-9.931591033935547,"pinky0x":255.451023149485,"pinky0y":149.5503892424148,"pinky0z":-10.552169799804688,"pinky1x":239.01103386699597,"pinky1y":119.27430594850598,"pinky1z":-13.243697166442871,"pinky2x":228.5459530253657,"pinky2y":97.59406724594861,"pinky2z":-14.675901412963867,"pinky3x":219.55913449457347,"pinky3y":75.14096437183005,"pinky3z":-15.353330612182617,"thumb0x":328.68602737738985,"thumb0y":223.34575668768997,"thumb0z":-7.993535041809082,"thumb1x":364.2393601978216,"thumb1y":196.0224451603485,"thumb1z":-11.491081237792969,"thumb2x":392.2272475694256,"thumb2y":175.49258998171842,"thumb2z":-15.170801162719727,"thumb3x":411.0559191430284,"thumb3y":165.57158548086795,"thumb3z":-18.54182243347168,"palm0x":289.8053398585861,"palm0y":237.81194051191795,"palm0z":-0.0012760236859321594},{"index0x":327.84151124363115,"index0y":329.55876536462483,"index0z":-15.183721542358398,"index1x":339.1590982707896,"index1y":289.5858302907715,"index1z":-22.0672550201416,"index2x":345.23580646665096,"index2y":262.6064892528759,"index2z":-26.907108306884766,"index3x":348.8458951364614,"index3y":239.20748576053845,"index3z":-30.74146270751953,"middle0x":300.07824495316027,"middle0y":327.0485345148228,"middle0z":-18.42438316345215,"middle1x":302.2753676605928,"middle1y":280.8493247233717,"middle1z":-27.336198806762695,"middle2x":302.4201072341914,"middle2y":248.59342542788966,"middle2z":-34.292205810546875,"middle3x":301.906367763926,"middle3y":224.17199729443283,"middle3z":-39.16851806640625,"ring0x":273.7322879935869,"ring0y":337.0181917097859,"ring0z":-22.408573150634766,"ring1x":264.5106223805815,"ring1y":297.0440863555605,"ring1z":-32.05742263793945,"ring2x":258.5890948491585,"ring2y":267.9473942011292,"ring2z":-38.199703216552734,"ring3x":255.0211100412522,"ring3y":244.06761409953177,"ring3z":-42.2685546875,"pinky0x":249.85791723533188,"pinky0y":359.56425655658217,"pinky0z":-26.899078369140625,"pinky1x":229.30353215305354,"pinky1y":335.92893336710455,"pinky1z":-36.042701721191406,"pinky2x":215.6388569344473,"pinky2y":317.28351619375434,"pinky2z":-41.3912353515625,"pinky3x":204.5341463493725,"pinky3y":296.20796464867135,"pinky3z":-45.045936584472656,"thumb0x":325.90646984848496,"thumb0y":417.2194213317789,"thumb0z":-6.976917743682861,"thumb1x":357.7393744366643,"thumb1y":389.66943861431264,"thumb1z":-12.489185333251953,"thumb2x":383.40334461454995,"thumb2y":365.29745304743665,"thumb2z":-17.929697036743164,"thumb3x":407.54816375404454,"thumb3y":352.3184690348376,"thumb3z":-22.935794830322266,"palm0x":290.7870247522383,"palm0y":428.1962689300196,"palm0z":-0.0004877746105194092},{"index0x":464.54551503663436,"index0y":311.2489918289778,"index0z":-10.651058197021484,"index1x":478.2840307431679,"index1y":272.25648811397156,"index1z":-17.37519645690918,"index2x":490.0678036289447,"index2y":248.81744267680457,"index2z":-22.018754959106445,"index3x":499.89095110092114,"index3y":227.95167619210025,"index3z":-25.80290985107422,"middle0x":443.71478665393084,"middle0y":310.2810352758062,"middle0z":-16.596431732177734,"middle1x":450.2196123263732,"middle1y":263.32147219819,"middle1z":-24.88852310180664,"middle2x":458.88491293230305,"middle2y":234.16208679073262,"middle2z":-31.18984603881836,"middle3x":467.09763869114585,"middle3y":209.8380993346026,"middle3z":-35.56595230102539,"ring0x":422.71741840242225,"ring0y":319.4392675361357,"ring0z":-22.885637283325195,"ring1x":420.72219383298074,"ring1y":277.91393602179136,"ring1z":-31.933700561523438,"ring2x":424.60972037591296,"ring2y":250.96499842700564,"ring2z":-38.66653060913086,"ring3x":430.18863226530755,"ring3y":227.28411480620804,"ring3z":-43.349220275878906,"pinky0x":403.14206461985304,"pinky0y":337.82408372361596,"pinky0z":-29.144634246826172,"pinky1x":389.5842886211878,"pinky1y":311.6250526855437,"pinky1z":-37.949405670166016,"pinky2x":382.28209257575156,"pinky2y":292.76271901332996,"pinky2z":-43.935462951660156,"pinky3x":378.18784218682265,"pinky3y":270.52955287803974,"pinky3z":-48.31253433227539,"thumb0x":456.0372365224267,"thumb0y":385.5521322926824,"thumb0z":-1.9135560989379883,"thumb1x":484.78274606999713,"thumb1y":359.47568471589466,"thumb1z":-5.724812030792236,"thumb2x":507.61135683399084,"thumb2y":339.4337917684099,"thumb2z":-10.632275581359863,"thumb3x":527.942017453242,"thumb3y":330.43532125757486,"thumb3z":-15.912263870239258,"palm0x":419.29782675811674,"palm0y":400.9266063897715,"palm0z":-0.0008258670568466187},{"index0x":296.07195104104983,"index0y":263.0190110212227,"index0z":-6.352616786956787,"index1x":333.072156745881,"index1y":255.9730488452187,"index1z":-11.059233665466309,"index2x":360.53137420384815,"index2y":250.95725130896014,"index2z":-15.072443962097168,"index3x":384.8647232881095,"index3y":245.99608089656985,"index3z":-18.487333297729492,"middle0x":289.79144659352914,"middle0y":238.84708203256108,"middle0z":-9.876729011535645,"middle1x":329.9033431567984,"middle1y":220.44205722668713,"middle1z":-16.074506759643555,"middle2x":360.0087603889347,"middle2y":208.25335913296948,"middle2z":-20.69219970703125,"middle3x":383.72478927958457,"middle3y":197.64228868535187,"middle3z":-23.999027252197266,"ring0x":274.20425744038556,"ring0y":219.94758447796323,"ring0z":-14.31523609161377,"ring1x":308.10660895594106,"ring1y":195.2813812768143,"ring1z":-20.563997268676758,"ring2x":334.8231701649942,"ring2y":180.04929541432847,"ring2z":-24.471660614013672,"ring3x":357.104750382304,"ring3y":167.921795129999,"ring3z":-27.28339195251465,"pinky0x":249.981844359335,"pinky0y":205.84048670546784,"pinky0z":-19.209440231323242,"pinky1x":271.0741837965351,"pinky1y":178.87086005988164,"pinky1z":-25.331287384033203,"pinky2x":288.2677494868932,"pinky2y":162.35110713325582,"pinky2z":-28.926189422607422,"pinky3x":306.67920427464577,"pinky3y":146.86172396404396,"pinky3z":-31.63376808166504,"thumb0x":220.31272692756878,"thumb0y":295.5182690626624,"thumb0z":-3.8807058334350586,"thumb1x":257.43203362064327,"thumb1y":309.90619113600064,"thumb1z":-7.4481658935546875,"thumb2x":288.2627216228672,"thumb2y":321.65333465021166,"thumb2z":-11.554354667663574,"thumb3x":312.55304839708265,"thumb3y":337.3943557821174,"thumb3z":-15.751812934875488,"palm0x":189.9207470911307,"palm0y":270.1408498208448,"palm0z":-0.0011007562279701233},{"index0x":207.53037438227895,"index0y":194.51237557056112,"index0z":-13.007633209228516,"index1x":216.2850733521938,"index1y":158.8811048310273,"index1z":-19.392332077026367,"index2x":219.68231721103646,"index2y":130.8822068362961,"index2z":-24.480756759643555,"index3x":221.19413294009112,"index3y":106.44458053915102,"index3z":-28.45255470275879,"middle0x":181.15566410587977,"middle0y":192.03646514220173,"middle0z":-14.149524688720703,"middle1x":180.92151325115412,"middle1y":150.89794842323877,"middle1z":-20.814804077148438,"middle2x":178.64030480438748,"middle2y":118.3600525038419,"middle2z":-26.865699768066406,"middle3x":176.1836588436393,"middle3y":94.36213330132199,"middle3z":-31.298484802246094,"ring0x":157.36645209899922,"ring0y":200.82913892927354,"ring0z":-16.832124710083008,"ring1x":144.90329689811847,"ring1y":165.49268870678722,"ring1z":-24.899160385131836,"ring2x":134.78321375358797,"ring2y":137.0662786172664,"ring2z":-31.068744659423828,"ring3x":127.35064234706044,"ring3y":114.6110341312858,"ring3z":-35.406314849853516,"pinky0x":136.20566843051319,"pinky0y":220.61768384983742,"pinky0z":-20.573049545288086,"pinky1x":117.9625150939896,"pinky1y":196.85794325167024,"pinky1z":-28.668657302856445,"pinky2x":105.93947724628751,"pinky2y":178.11573247045155,"pinky2z":-33.97230911254883,"pinky3x":95.62424927850878,"pinky3y":158.51660359810916,"pinky3z":-37.573482513427734,"thumb0x":216.75816760550595,"thumb0y":278.71600752027587,"thumb0z":-10.75346851348877,"thumb1x":243.2235056190806,"thumb1y":247.26670913961962,"thumb1z":-16.878440856933594,"thumb2x":264.3505704058698,"thumb2y":217.72680898670762,"thumb2z":-22.558380126953125,"thumb3x":287.53948216663235,"thumb3y":199.2949678186053,"thumb3z":-28.082931518554688,"palm0x":184.5253378432218,"palm0y":288.5001162269539,"palm0z":-0.0011481568217277527},{"index0x":279.73037856619067,"index0y":275.06791816454495,"index0z":-12.589860916137695,"index1x":256.3413515215492,"index1y":260.8816121769397,"index1z":-19.292049407958984,"index2x":237.72494257424086,"index2y":249.82678038358904,"index2z":-24.135913848876953,"index3x":220.8139344325801,"index3y":240.940828760327,"index3z":-27.25946617126465,"middle0x":267.8377706387077,"middle0y":292.49532387406833,"middle0z":-14.480027198791504,"middle1x":243.64522769103723,"middle1y":278.43215741653165,"middle1z":-20.258533477783203,"middle2x":224.44374617177039,"middle2y":263.9587933684676,"middle2z":-24.751144409179688,"middle3x":209.26912507164405,"middle3y":251.10364019971487,"middle3z":-27.325716018676758,"ring0x":264.44287746135785,"ring0y":313.1871988599481,"ring0z":-17.590991973876953,"ring1x":236.94629586146928,"ring1y":312.52120219358517,"ring1z":-26.257762908935547,"ring2x":216.02140020750437,"ring2y":305.897837691668,"ring2z":-33.27931213378906,"ring3x":198.01875413511237,"ring3y":296.86133368048286,"ring3z":-37.54485321044922,"pinky0x":269.43818972710807,"pinky0y":334.57471255189284,"pinky0z":-21.579437255859375,"pinky1x":249.82459296414805,"pinky1y":332.83810826658623,"pinky1z":-29.878997802734375,"pinky2x":236.13977907464252,"pinky2y":327.2183149014598,"pinky2z":-35.43904113769531,"pinky3x":220.48466316784263,"pinky3y":316.91144400983194,"pinky3z":-38.45264434814453,"thumb0x":338.7754341997633,"thumb0y":300.5439617007593,"thumb0z":-8.615127563476562,"thumb1x":328.5680971473979,"thumb1y":267.57917321762756,"thumb1z":-14.953995704650879,"thumb2x":320.03179919878664,"thumb2y":241.9265519690474,"thumb2z":-21.378461837768555,"thumb3x":322.73728752516826,"thumb3y":223.58879466489378,"thumb3z":-27.981809616088867,"palm0x":334.1741198798138,"palm0y":326.78772712736134,"palm0z":-0.0005934536457061768},{"index0x":347.07177631879864,"index0y":243.73999878981135,"index0z":-5.153197288513184,"index1x":354.17136957250597,"index1y":216.24094923092366,"index1z":-7.35911750793457,"index2x":357.23903996710646,"index2y":197.40542519385158,"index2z":-9.891413688659668,"index3x":358.0862748967441,"index3y":181.0351087232101,"index3z":-12.280778884887695,"middle0x":325.88407759932767,"middle0y":240.84712532018352,"middle0z":-6.213394641876221,"middle1x":328.4053181307973,"middle1y":209.48330274218137,"middle1z":-8.160454750061035,"middle2x":329.497957061002,"middle2y":187.2818796583209,"middle2z":-11.356246948242188,"middle3x":329.4032879801654,"middle3y":169.18924097503734,"middle3z":-13.224287986755371,"ring0x":306.9835557884455,"ring0y":247.64168804255843,"ring0z":-9.137436866760254,"ring1x":299.7427607226711,"ring1y":220.9111956165783,"ring1z":-13.14632797241211,"ring2x":294.4834268976914,"ring2y":200.85480600824198,"ring2z":-16.390382766723633,"ring3x":290.4533666385292,"ring3y":182.84569941086232,"ring3z":-18.2302188873291,"pinky0x":290.6505543791511,"pinky0y":263.4045702959922,"pinky0z":-13.394838333129883,"pinky1x":279.44417226558994,"pinky1y":245.6312180972146,"pinky1z":-18.260330200195312,"pinky2x":271.1708287717396,"pinky2y":231.8519935668723,"pinky2z":-21.160911560058594,"pinky3x":263.0728464868273,"pinky3y":215.74086516782833,"pinky3z":-22.5474796295166,"thumb0x":350.1094855472169,"thumb0y":321.40149139310296,"thumb0z":-9.411191940307617,"thumb1x":377.22369913720354,"thumb1y":297.09614372362455,"thumb1z":-14.708977699279785,"thumb2x":402.05230199198047,"thumb2y":278.31484095274755,"thumb2z":-20.372846603393555,"thumb3x":424.79162454857385,"thumb3y":268.0036302778431,"thumb3z":-26.194055557250977,"palm0x":323.33434182073023,"palm0y":332.8285474238979,"palm0z":-0.0006944611668586731}],"scissor":[{"index0x":279.2020087675088,"index0y":199.9868361090366,"index0z":-8.339014053344727,"index1x":294.0609779705576,"index1y":168.96122010349387,"index1z":-14.212075233459473,"index2x":303.3861191365179,"index2y":146.56320040762517,"index2z":-18.64291000366211,"index3x":309.7821338724504,"index3y":126.55582973961376,"index3z":-21.52070426940918,"middle0x":250.55864902245136,"middle0y":193.20219558663544,"middle0z":-8.220582962036133,"middle1x":256.3475345245605,"middle1y":159.74033636314783,"middle1z":-12.493255615234375,"middle2x":257.74975738740545,"middle2y":132.804505473004,"middle2z":-16.74551773071289,"middle3x":258.3806947960197,"middle3y":107.18566340569315,"middle3z":-19.460525512695312,"ring0x":225.93636686756636,"ring0y":202.5753007764149,"ring0z":-10.613320350646973,"ring1x":232.5074629636101,"ring1y":191.51437957114348,"ring1z":-26.58766746520996,"ring2x":241.97622113323294,"ring2y":224.69827901465075,"ring2z":-31.46381378173828,"ring3x":244.9740569952863,"ring3y":245.71437699635607,"ring3z":-30.328447341918945,"pinky0x":204.15050654389714,"pinky0y":221.34468921516302,"pinky0z":-13.788534164428711,"pinky1x":215.0095221274937,"pinky1y":215.50798455509678,"pinky1z":-29.543846130371094,"pinky2x":228.01263583839847,"pinky2y":239.06929173717708,"pinky2z":-33.20838165283203,"pinky3x":234.82993066438897,"pinky3y":258.1720170623822,"pinky3z":-33.2287712097168,"thumb0x":256.6884031279906,"thumb0y":293.3985558532622,"thumb0z":-15.500505447387695,"thumb1x":283.3463305306058,"thumb1y":266.4594183541496,"thumb1z":-23.749351501464844,"thumb2x":270.39248896336517,"thumb2y":243.66016375017824,"thumb2z":-30.98538589477539,"thumb3x":246.78397663260156,"thumb3y":234.9027848378214,"thumb3z":-35.530967712402344,"palm0x":222.55355749048957,"palm0y":298.63024159098325,"palm0z":-0.001542709767818451},{"index0x":341.913244538041,"index0y":200.5908042351002,"index0z":-20.593181610107422,"index1x":373.93735389385495,"index1y":169.12075877055287,"index1z":-30.630565643310547,"index2x":396.41879773350104,"index2y":143.0570851840527,"index2z":-37.777259826660156,"index3x":416.3824007271952,"index3y":118.62965473151417,"index3z":-43.010780334472656,"middle0x":317.83479732185833,"middle0y":182.4711067223524,"middle0z":-18.72117805480957,"middle1x":340.33656798063953,"middle1y":142.57499307701644,"middle1z":-24.733306884765625,"middle2x":346.4740666155359,"middle2y":107.27147423270108,"middle2z":-32.83379364013672,"middle3x":349.9295952685922,"middle3y":76.85175978231644,"middle3z":-41.76750946044922,"ring0x":289.3932262211113,"ring0y":177.21774593956283,"ring0z":-17.613359451293945,"ring1x":293.6779329870189,"ring1y":181.8859370941038,"ring1z":-32.72563934326172,"ring2x":293.34915562699035,"ring2y":213.02908604959308,"ring2z":-31.611412048339844,"ring3x":293.279611043506,"ring3y":231.0204130218155,"ring3z":-28.939876556396484,"pinky0x":264.15507463579206,"pinky0y":183.06602613659047,"pinky0z":-17.633581161499023,"pinky1x":270.98914040415605,"pinky1y":196.77137372261848,"pinky1z":-30.94333267211914,"pinky2x":278.18627488433805,"pinky2y":221.81715646725152,"pinky2z":-29.703250885009766,"pinky3x":284.3740147476561,"pinky3y":244.94346733812557,"pinky3z":-27.44462013244629,"thumb0x":301.04461762120025,"thumb0y":265.75786683828267,"thumb0z":-16.077533721923828,"thumb1x":327.76789934818254,"thumb1y":263.5823797904244,"thumb1z":-25.76732635498047,"thumb2x":317.57279807515897,"thumb2y":248.65101296487276,"thumb2z":-31.91267204284668,"thumb3x":300.4255589222422,"thumb3y":229.34008422625567,"thumb3z":-36.38636779785156,"palm0x":260.286954773448,"palm0y":255.8556034754966,"palm0z":-0.0017569437623023987},{"index0x":321.9672247696108,"index0y":297.14693493556723,"index0z":-3.100522518157959,"index1x":358.1106612115377,"index1y":299.64811290345966,"index1z":-7.951975345611572,"index2x":382.97761435729365,"index2y":300.434537269031,"index2z":-11.746868133544922,"index3x":405.1346626047879,"index3y":298.21653301533996,"index3z":-14.232112884521484,"middle0x":316.62222317610616,"middle0y":273.1753165190708,"middle0z":-5.421265125274658,"middle1x":353.5293260386627,"middle1y":263.2700971271293,"middle1z":-9.845588684082031,"middle2x":378.6582968139674,"middle2y":255.65073539361967,"middle2z":-15.258819580078125,"middle3x":399.2105336481259,"middle3y":247.73703828294273,"middle3z":-18.84699058532715,"ring0x":300.6435342451845,"ring0y":258.02575127755665,"ring0z":-9.54845905303955,"ring1x":323.98756246656006,"ring1y":260.4351546072725,"ring1z":-22.613950729370117,"ring2x":305.873082668447,"ring2y":284.9415924399429,"ring2z":-28.415672302246094,"ring3x":290.90706326366967,"ring3y":298.6277308124824,"ring3z":-28.881132125854492,"pinky0x":279.8115451765715,"pinky0y":249.82861004851497,"pinky0z":-13.869037628173828,"pinky1x":297.20758141379605,"pinky1y":256.8738238860253,"pinky1z":-26.550634384155273,"pinky2x":286.62558047080097,"pinky2y":277.2723108493292,"pinky2z":-30.04593276977539,"pinky3x":273.9679791506495,"pinky3y":291.13988101677205,"pinky3z":-30.391340255737305,"thumb0x":241.91545747206726,"thumb0y":316.6572048313901,"thumb0z":-9.20072078704834,"thumb1x":276.458581688463,"thumb1y":325.8692553721446,"thumb1z":-15.700189590454102,"thumb2x":294.99326714738083,"thumb2y":312.9303996318919,"thumb2z":-22.57863998413086,"thumb3x":300.18973047653344,"thumb3y":292.66551599313607,"thumb3z":-26.992691040039062,"palm0x":213.7364174236555,"palm0y":291.4602296593705,"palm0z":-0.0014296174049377441},{"index0x":252.31085985900586,"index0y":209.28525205221655,"index0z":-10.22950553894043,"index1x":262.25085391649463,"index1y":175.62594700037658,"index1z":-16.130624771118164,"index2x":268.5718918100014,"index2y":151.3923078484596,"index2z":-20.23756217956543,"index3x":271.1566104739935,"index3y":129.36298006234495,"index3z":-22.94054412841797,"middle0x":226.97418901864347,"middle0y":206.8062300022375,"middle0z":-9.81229305267334,"middle1x":226.8423343137346,"middle1y":174.3923575502949,"middle1z":-13.73213005065918,"middle2x":225.38829469214406,"middle2y":147.10603284934436,"middle2z":-15.97236156463623,"middle3x":223.3620234322911,"middle3y":121.09607207537296,"middle3z":-17.627639770507812,"ring0x":207.1801241689928,"ring0y":219.90717799589365,"ring0z":-11.372357368469238,"ring1x":206.56776743510983,"ring1y":203.85137480078956,"ring1z":-25.459197998046875,"ring2x":220.13271923475597,"ring2y":228.19499720309636,"ring2z":-30.273717880249023,"ring3x":226.9627169723247,"ring3y":245.0142133280842,"ring3z":-30.23369789123535,"pinky0x":192.02454966634917,"pinky0y":241.52778248947016,"pinky0z":-13.62696647644043,"pinky1x":196.35497600909628,"pinky1y":231.29693423267776,"pinky1z":-28.685604095458984,"pinky2x":211.5404998452074,"pinky2y":248.15240874850906,"pinky2z":-33.5598258972168,"pinky3x":221.2303457802047,"pinky3y":263.8961526276313,"pinky3z":-34.99522018432617,"thumb0x":249.7790760187506,"thumb0y":291.42926458561766,"thumb0z":-13.850011825561523,"thumb1x":265.8022420281468,"thumb1y":261.7753966519828,"thumb1z":-21.478628158569336,"thumb2x":246.37430743454757,"thumb2y":241.0578348995502,"thumb2z":-27.810182571411133,"thumb3x":217.20360612465558,"thumb3y":236.93303313038803,"thumb3z":-31.532367706298828,"palm0x":218.5190091376445,"palm0y":306.3480793379845,"palm0z":-0.00146455317735672},{"index0x":291.59684874940876,"index0y":220.18636534806154,"index0z":-1.1186707019805908,"index1x":300.9186074781684,"index1y":198.26345831326,"index1z":-5.249141216278076,"index2x":304.0801691781231,"index2y":182.34897267402246,"index2z":-7.540800094604492,"index3x":305.1726312757642,"index3y":167.08418680141617,"index3z":-9.665630340576172,"middle0x":276.5673280641615,"middle0y":218.46909921317126,"middle0z":-3.0338997840881348,"middle1x":279.659571016348,"middle1y":196.34864085021215,"middle1z":-5.798713207244873,"middle2x":277.4463956805339,"middle2y":179.0640354200098,"middle2z":-7.818259239196777,"middle3x":274.0176983001141,"middle3y":162.58502042059433,"middle3z":-9.823526382446289,"ring0x":262.4643321679019,"ring0y":224.742892138907,"ring0z":-6.517027854919434,"ring1x":268.45593202109245,"ring1y":222.79736039240345,"ring1z":-19.039657592773438,"ring2x":276.1659090880407,"ring2y":247.29478943050856,"ring2z":-18.32388687133789,"ring3x":278.358777973393,"ring3y":262.2825215205156,"ring3z":-14.619929313659668,"pinky0x":252.83785710048272,"pinky0y":235.59466562320085,"pinky0z":-10.18460464477539,"pinky1x":260.2806866292421,"pinky1y":234.50804326758518,"pinky1z":-21.614376068115234,"pinky2x":268.3007580193353,"pinky2y":249.70612805078815,"pinky2z":-21.409183502197266,"pinky3x":272.5656171281941,"pinky3y":262.29009723245986,"pinky3z":-19.521886825561523,"thumb0x":289.24791789548385,"thumb0y":276.19628788334256,"thumb0z":-7.241090774536133,"thumb1x":300.012146275102,"thumb1y":258.2262299177072,"thumb1z":-12.451042175292969,"thumb2x":293.3049307702314,"thumb2y":242.77450531695075,"thumb2z":-17.708234786987305,"thumb3x":276.35123730655397,"thumb3y":232.4944109862021,"thumb3z":-21.28296661376953,"palm0x":268.00618801019033,"palm0y":291.5281002107454,"palm0z":-0.0015025362372398376},{"index0x":125.8140734718059,"index0y":373.20880478099633,"index0z":-19.021377563476562,"index1x":126.2045139857616,"index1y":349.4586745841881,"index1z":-28.398042678833008,"index2x":126.2733104088465,"index2y":332.7464726432364,"index2z":-35.0723762512207,"index3x":125.7020540294389,"index3y":317.0583677024927,"index3z":-39.49981689453125,"middle0x":105.98177910153673,"middle0y":374.4898920631379,"middle0z":-14.668145179748535,"middle1x":95.47417102354109,"middle1y":347.78901113798656,"middle1z":-24.208690643310547,"middle2x":92.4153518294242,"middle2y":332.6491910971945,"middle2z":-31.99480438232422,"middle3x":90.53955972684139,"middle3y":318.86278967578556,"middle3z":-36.94119644165039,"ring0x":91.02278409670639,"ring0y":383.2674194321443,"ring0z":-13.357967376708984,"ring1x":76.89933641988327,"ring1y":376.2439521793501,"ring1z":-34.234527587890625,"ring2x":85.54435846682446,"ring2y":397.0966685647376,"ring2z":-40.9714469909668,"ring3x":93.822211109088,"ring3y":409.4695726620865,"ring3z":-39.738407135009766,"pinky0x":79.30262785317028,"pinky0y":398.21298867114115,"pinky0z":-13.558624267578125,"pinky1x":67.94989369338465,"pinky1y":393.957900180799,"pinky1z":-31.8763484954834,"pinky2x":74.92539106969916,"pinky2y":407.1262655944614,"pinky2z":-37.008766174316406,"pinky3x":84.10118748513378,"pinky3y":417.457263136004,"pinky3z":-37.10809326171875,"thumb0x":136.5687661121849,"thumb0y":436.02616722854685,"thumb0z":-24.971162796020508,"thumb1x":136.86310377146248,"thumb1y":418.37172379172995,"thumb1z":-37.57377624511719,"thumb2x":111.1009328744625,"thumb2y":413.36644577022514,"thumb2z":-45.5971794128418,"thumb3x":85.68396258099412,"thumb3y":413.7677703160638,"thumb3z":-49.56684494018555,"palm0x":123.13732659377233,"palm0y":440.53370808656956,"palm0z":-0.00010653585195541382},{"index0x":162.89521510961075,"index0y":164.79548907738868,"index0z":-15.98746109008789,"index1x":174.74019962889315,"index1y":124.09036408966911,"index1z":-24.260541915893555,"index2x":181.47705959966805,"index2y":90.50901124368917,"index2z":-30.256303787231445,"index3x":184.0342179163066,"index3y":59.86571407422073,"index3z":-34.10679244995117,"middle0x":126.65723298574447,"middle0y":161.95547873010966,"middle0z":-14.927912712097168,"middle1x":124.97460846626576,"middle1y":118.90888818182114,"middle1z":-20.144542694091797,"middle2x":118.27035112517726,"middle2y":79.79300190643667,"middle2z":-25.88052749633789,"middle3x":110.31945812514522,"middle3y":50.29176361163107,"middle3z":-31.276334762573242,"ring0x":97.07753299607833,"ring0y":175.83876536971232,"ring0z":-15.717072486877441,"ring1x":90.2950265691784,"ring1y":165.2538566020272,"ring1z":-31.390911102294922,"ring2x":107.07570788902845,"ring2y":194.64946574528713,"ring2z":-37.43075180053711,"ring3x":119.31819868553555,"ring3y":218.58870731411903,"ring3z":-38.613014221191406,"pinky0x":75.05917819471912,"pinky0y":200.61365347154998,"pinky0z":-17.618356704711914,"pinky1x":74.1019303103652,"pinky1y":196.86663194393202,"pinky1z":-33.47685241699219,"pinky2x":90.43432565799469,"pinky2y":215.06521977189203,"pinky2z":-39.32973861694336,"pinky3x":105.14888248629754,"pinky3y":235.58164381997855,"pinky3z":-42.09528350830078,"thumb0x":163.11755472567623,"thumb0y":261.6861837305165,"thumb0z":-17.14035415649414,"thumb1x":184.87865956812675,"thumb1y":229.58120630734516,"thumb1z":-27.1372013092041,"thumb2x":159.3119888903175,"thumb2y":212.5692821488158,"thumb2z":-34.73431396484375,"thumb3x":129.13357312257372,"thumb3y":210.00227766864356,"thumb3z":-40.416690826416016,"palm0x":119.10524621923135,"palm0y":270.02453565557005,"palm0z":-0.0013016760349273682},{"index0x":348.5224428805229,"index0y":245.18527197424243,"index0z":-10.838336944580078,"index1x":370.8953980734384,"index1y":186.9131833280926,"index1z":-16.803686141967773,"index2x":383.5633516476702,"index2y":147.24830382192607,"index2z":-20.946353912353516,"index3x":394.4630632741371,"index3y":111.61799111365616,"index3z":-23.404836654663086,"middle0x":310.6535877437257,"middle0y":242.17490388515944,"middle0z":-11.995920181274414,"middle1x":314.7395274156581,"middle1y":180.4161181043104,"middle1z":-18.11058807373047,"middle2x":312.4597923714871,"middle2y":134.4818494500919,"middle2z":-23.00445556640625,"middle3x":310.57856182425064,"middle3y":98.52762288540876,"middle3z":-26.462963104248047,"ring0x":277.7963820274468,"ring0y":257.9218972100177,"ring0z":-14.115825653076172,"ring1x":288.4117238900352,"ring1y":250.21199759426247,"ring1z":-24.19462013244629,"ring2x":306.0346506030253,"ring2y":287.767547712034,"ring2z":-25.169200897216797,"ring3x":318.42845025445007,"ring3y":312.8271240887021,"ring3z":-24.15093231201172,"pinky0x":254.5878381806371,"pinky0y":286.2058468559346,"pinky0z":-17.3419246673584,"pinky1x":270.1123477836109,"pinky1y":288.26894680118437,"pinky1z":-26.31965446472168,"pinky2x":287.903875322566,"pinky2y":313.45118281962596,"pinky2z":-27.619735717773438,"pinky3x":302.96025096950143,"pinky3y":336.3931763566931,"pinky3z":-27.530916213989258,"thumb0x":334.8782733069362,"thumb0y":357.1136408663708,"thumb0z":-9.540361404418945,"thumb1x":365.6449115908352,"thumb1y":316.050374236391,"thumb1z":-15.766923904418945,"thumb2x":347.1478159179101,"thumb2y":285.8127250858022,"thumb2z":-20.953826904296875,"thumb3x":320.44946654862116,"thumb3y":273.97593934057204,"thumb3z":-24.569377899169922,"palm0x":284.44599856697084,"palm0y":375.398325415987,"palm0z":-0.0018930286169052124}],"shoot":[{"index0x":308.54793283720096,"index0y":211.56988970454353,"index0z":-8.058597564697266,"index1x":308.81515440220267,"index1y":182.6414120636658,"index1z":-13.952499389648438,"index2x":309.51302087109207,"index2y":164.08443310692974,"index2z":-17.934158325195312,"index3x":307.2713166202431,"index3y":147.55547716180888,"index3z":-20.75015640258789,"middle0x":290.57574674861183,"middle0y":210.93134236137757,"middle0z":-12.071878433227539,"middle1x":291.9768440713482,"middle1y":180.15556699070137,"middle1z":-21.237581253051758,"middle2x":293.98816219032574,"middle2y":160.5189466995863,"middle2z":-25.900157928466797,"middle3x":294.29095241004507,"middle3y":143.88805621076114,"middle3z":-27.728551864624023,"ring0x":272.64011069107926,"ring0y":218.8065564877064,"ring0z":-16.90406036376953,"ring1x":271.2083983186911,"ring1y":202.38463083522362,"ring1z":-29.503843307495117,"ring2x":276.99090623344586,"ring2y":225.47583939991105,"ring2z":-33.981441497802734,"ring3x":279.6544194704661,"ring3y":242.67838738605911,"ring3z":-33.61666488647461,"pinky0x":255.39631605310512,"pinky0y":232.34877953617604,"pinky0z":-21.892969131469727,"pinky1x":255.70381833222396,"pinky1y":221.602779684382,"pinky1z":-33.16826248168945,"pinky2x":263.7065047471219,"pinky2y":237.00552969128046,"pinky2z":-36.96214294433594,"pinky3x":268.93472566660944,"pinky3y":250.25676517721965,"pinky3z":-37.6300048828125,"thumb0x":307.9927683849147,"thumb0y":276.7657252512271,"thumb0z":-4.798902988433838,"thumb1x":329.99270361503955,"thumb1y":255.39353218389584,"thumb1z":-9.541399955749512,"thumb2x":349.1045088274442,"thumb2y":240.86064131750595,"thumb2z":-15.239678382873535,"thumb3x":366.74864840495883,"thumb3y":234.4632850047408,"thumb3z":-21.300710678100586,"palm0x":280.0875927821442,"palm0y":287.28137622779866,"palm0z":-0.0011576861143112183},{"index0x":151.52693878781963,"index0y":130.82970409813868,"index0z":-12.216693878173828,"index1x":144.7645252708641,"index1y":89.02653308684103,"index1z":-18.620351791381836,"index2x":139.8280450597247,"index2y":61.533562964500526,"index2z":-23.061115264892578,"index3x":131.7406963213768,"index3y":39.415253788064405,"index3z":-25.960044860839844,"middle0x":123.81224951440876,"middle0y":132.66898610102493,"middle0z":-13.216238021850586,"middle1x":118.73552201333479,"middle1y":92.69652223620695,"middle1z":-20.876728057861328,"middle2x":114.06843043191756,"middle2y":58.69653296537287,"middle2z":-24.67089080810547,"middle3x":109.88541345720029,"middle3y":28.08479753900906,"middle3z":-26.51814842224121,"ring0x":98.41048554413355,"ring0y":145.14302635208497,"ring0z":-15.48452377319336,"ring1x":86.6081979719506,"ring1y":129.19601301402318,"ring1z":-30.850725173950195,"ring2x":92.16433273336887,"ring2y":162.91974292797434,"ring2z":-34.035072326660156,"ring3x":95.9485314087792,"ring3y":185.9768403777714,"ring3z":-31.851764678955078,"pinky0x":74.28534339663072,"pinky0y":163.50741487021003,"pinky0z":-18.234661102294922,"pinky1x":66.58813263411896,"pinky1y":152.38091993662755,"pinky1z":-32.022342681884766,"pinky2x":74.46459559352851,"pinky2y":172.8627000961775,"pinky2z":-34.57968521118164,"pinky3x":81.79991013617779,"pinky3y":186.93504064958017,"pinky3z":-33.58417510986328,"thumb0x":154.91935657494173,"thumb0y":219.4754574353297,"thumb0z":-9.529228210449219,"thumb1x":182.47910060494922,"thumb1y":190.3154932157504,"thumb1z":-15.049757957458496,"thumb2x":200.22821660954588,"thumb2y":169.27379539202747,"thumb2z":-20.428817749023438,"thumb3x":221.29810926440473,"thumb3y":158.73619051514066,"thumb3z":-26.560840606689453,"palm0x":114.00702737581653,"palm0y":232.57776443962095,"palm0z":-0.0007116124033927917},{"index0x":454.0769124312801,"index0y":157.12118194532556,"index0z":-2.742478370666504,"index1x":460.7550615504267,"index1y":131.1622188008257,"index1z":-9.152077674865723,"index2x":464.1792785221648,"index2y":113.94161487092887,"index2z":-13.559284210205078,"index3x":465.59256767501165,"index3y":95.96609828156863,"index3z":-16.27959632873535,"middle0x":436.6419762499963,"middle0y":150.96037197296715,"middle0z":-7.396326065063477,"middle1x":446.9189314892285,"middle1y":121.9211158411933,"middle1z":-15.034164428710938,"middle2x":456.18601192498727,"middle2y":102.12247042827944,"middle2z":-21.634963989257812,"middle3x":464.71664736870184,"middle3y":83.81032264059974,"middle3z":-25.602108001708984,"ring0x":416.6573870954565,"ring0y":153.1454746754661,"ring0z":-13.122811317443848,"ring1x":428.8359338330624,"ring1y":145.355685810636,"ring1z":-24.980377197265625,"ring2x":431.25582409497133,"ring2y":174.38980673312076,"ring2z":-28.970155715942383,"ring3x":430.10392045374783,"ring3y":194.00783462399542,"ring3z":-28.795549392700195,"pinky0x":395.7394781586995,"pinky0y":160.47155856099954,"pinky0z":-19.40991973876953,"pinky1x":406.95233313719615,"pinky1y":157.0266032234782,"pinky1z":-27.974273681640625,"pinky2x":411.25420795334924,"pinky2y":176.29208117494125,"pinky2z":-30.3829345703125,"pinky3x":411.4976277256136,"pinky3y":191.16940670657186,"pinky3z":-30.514009475708008,"thumb0x":439.18173207702824,"thumb0y":228.3210598204933,"thumb0z":-5.158973217010498,"thumb1x":471.0285334141578,"thumb1y":212.73766241161238,"thumb1z":-11.58977222442627,"thumb2x":496.2003062123089,"thumb2y":202.57612496195966,"thumb2z":-20.247074127197266,"thumb3x":517.5047663112946,"thumb3y":197.98779712233696,"thumb3z":-29.668169021606445,"palm0x":412.3932620745519,"palm0y":226.47407176437594,"palm0z":-0.0032051876187324524},{"index0x":464.7605123218623,"index0y":292.11974117752686,"index0z":-13.989784240722656,"index1x":461.341783281048,"index1y":266.75597995337824,"index1z":-21.95482635498047,"index2x":459.7361114040567,"index2y":250.40757795226153,"index2z":-27.66367530822754,"index3x":455.94047499462056,"index3y":236.77765935619254,"index3z":-31.63956069946289,"middle0x":448.52479126153514,"middle0y":294.02277144687355,"middle0z":-17.584856033325195,"middle1x":445.11727239754043,"middle1y":268.28606195287125,"middle1z":-28.76188850402832,"middle2x":444.2284744564976,"middle2y":248.56732591689348,"middle2z":-34.77043151855469,"middle3x":443.26624145677226,"middle3y":232.15762866385325,"middle3z":-37.95051956176758,"ring0x":433.6860760000187,"ring0y":303.39106873436333,"ring0z":-21.681535720825195,"ring1x":430.78702499795145,"ring1y":292.92116658049247,"ring1z":-36.03066635131836,"ring2x":439.81316216799274,"ring2y":312.3721286278168,"ring2z":-40.018524169921875,"ring3x":445.97878971707127,"ring3y":326.27834513702845,"ring3z":-39.344478607177734,"pinky0x":420.5307545288727,"pinky0y":317.63226310335546,"pinky0z":-25.96256446838379,"pinky1x":419.4576712423784,"pinky1y":312.3720887277255,"pinky1z":-38.22473907470703,"pinky2x":428.27161911945484,"pinky2y":325.4340847212691,"pinky2z":-41.64570999145508,"pinky3x":435.70431363300554,"pinky3y":334.59333557198266,"pinky3z":-42.05532455444336,"thumb0x":472.4028557522285,"thumb0y":344.7697331128928,"thumb0z":-5.7100934982299805,"thumb1x":488.8099668851167,"thumb1y":324.4885180459446,"thumb1z":-11.324712753295898,"thumb2x":501.8114841077246,"thumb2y":310.17040261268954,"thumb2z":-17.432109832763672,"thumb3x":515.7652059088718,"thumb3y":303.4335348230736,"thumb3z":-23.751277923583984,"palm0x":448.98263340513927,"palm0y":356.71668391334686,"palm0z":-0.0010674819350242615},{"index0x":496.9117157838459,"index0y":343.9780785235906,"index0z":-9.777742385864258,"index1x":496.1359741035842,"index1y":320.9207944418424,"index1z":-18.15583038330078,"index2x":496.19724978909994,"index2y":305.33890847100145,"index2z":-23.427371978759766,"index3x":494.280477341261,"index3y":292.0694721415465,"index3z":-26.443565368652344,"middle0x":481.38074782494243,"middle0y":342.2811161180514,"middle0z":-14.509721755981445,"middle1x":484.7851529798668,"middle1y":327.02116128732877,"middle1z":-26.4909725189209,"middle2x":487.011810579286,"middle2y":318.10026254338663,"middle2z":-31.717994689941406,"middle3x":488.9614797519074,"middle3y":308.70927062118045,"middle3z":-33.18619155883789,"ring0x":465.4221544931917,"ring0y":348.1809794403681,"ring0z":-19.823556900024414,"ring1x":468.117338033253,"ring1y":348.86399903834183,"ring1z":-33.770263671875,"ring2x":470.6393739705585,"ring2y":369.855797736267,"ring2z":-34.890560150146484,"ring3x":472.1440790067522,"ring3y":382.27972310598307,"ring3z":-32.088653564453125,"pinky0x":450.40416580782113,"pinky0y":358.3795120159773,"pinky0z":-25.308490753173828,"pinky1x":453.8398552484327,"pinky1y":361.4951551160808,"pinky1z":-36.790836334228516,"pinky2x":458.1996246627144,"pinky2y":375.8006184592817,"pinky2z":-38.108795166015625,"pinky3x":461.697286948527,"pinky3y":383.698652280403,"pinky3z":-36.5361442565918,"thumb0x":496.4859848261596,"thumb0y":396.598615808609,"thumb0z":-3.6647396087646484,"thumb1x":516.7813717025534,"thumb1y":379.952760370946,"thumb1z":-9.39719009399414,"thumb2x":531.4684829092586,"thumb2y":368.3801194164447,"thumb2z":-16.389055252075195,"thumb3x":545.224487340437,"thumb3y":363.8310313236477,"thumb3z":-24.196760177612305,"palm0x":471.44333880727487,"palm0y":403.3724133759226,"palm0z":-0.0009108409285545349},{"index0x":220.43047556029302,"index0y":244.5175272074127,"index0z":-17.042434692382812,"index1x":217.74672224814356,"index1y":213.7920422697162,"index1z":-24.12031364440918,"index2x":215.77102238922546,"index2y":193.77088947778162,"index2z":-29.092683792114258,"index3x":211.78800423236822,"index3y":177.2497378856576,"index3z":-32.66587448120117,"middle0x":198.3308100538375,"middle0y":245.4749670952126,"middle0z":-17.0839786529541,"middle1x":194.641171604826,"middle1y":216.25419467141208,"middle1z":-26.993967056274414,"middle2x":194.24546543819966,"middle2y":198.29877075861305,"middle2z":-33.52877426147461,"middle3x":194.26583152853362,"middle3y":182.98298275325206,"middle3z":-37.78171920776367,"ring0x":178.90204110861117,"ring0y":254.7073253279202,"ring0z":-18.193904876708984,"ring1x":171.59014951251277,"ring1y":240.71390787695938,"ring1z":-32.22438049316406,"ring2x":176.98048540151558,"ring2y":262.4429905181794,"ring2z":-39.480857849121094,"ring3x":182.23262846777783,"ring3y":278.3581972500694,"ring3z":-41.480220794677734,"pinky0x":161.33552106006846,"pinky0y":269.49529210262216,"pinky0z":-19.952497482299805,"pinky1x":156.00623712705598,"pinky1y":260.95380004116083,"pinky1z":-32.19898986816406,"pinky2x":161.93177203949236,"pinky2y":276.21121575837384,"pinky2z":-37.39437484741211,"pinky3x":167.57944905182077,"pinky3y":288.6830423628423,"pinky3z":-39.29873275756836,"thumb0x":227.59286485569527,"thumb0y":311.2580000187427,"thumb0z":-12.343876838684082,"thumb1x":250.29214975583196,"thumb1y":289.2641823807823,"thumb1z":-20.151752471923828,"thumb2x":267.42053905882835,"thumb2y":270.6612527833017,"thumb2z":-27.245410919189453,"thumb3x":281.278697189837,"thumb3y":260.7464077197839,"thumb3z":-34.528663635253906,"palm0x":197.9544800824092,"palm0y":316.4952404540386,"palm0z":-0.00066356360912323},{"index0x":318.23337153308114,"index0y":209.34356136658454,"index0z":-14.853199005126953,"index1x":319.9980695123378,"index1y":154.64632322474154,"index1z":-24.2705020904541,"index2x":322.99247592687755,"index2y":115.63511097200775,"index2z":-31.005233764648438,"index3x":321.5321593803793,"index3y":81.08971870740788,"index3z":-35.24266052246094,"middle0x":278.9382768798934,"middle0y":202.48114398778574,"middle0z":-16.25607681274414,"middle1x":277.3330525095585,"middle1y":151.82476833571022,"middle1z":-29.38567543029785,"middle2x":279.40457454763276,"middle2y":109.41263652486288,"middle2z":-35.48149871826172,"middle3x":283.4799654425813,"middle3y":70.07109013349172,"middle3z":-36.92053985595703,"ring0x":239.1493281487497,"ring0y":210.65734939932182,"ring0z":-18.73099708557129,"ring1x":229.57140550421286,"ring1y":211.78839922277197,"ring1z":-38.29692077636719,"ring2x":237.00029558742781,"ring2y":262.77298880180706,"ring2z":-37.524410247802734,"ring3x":244.4932805769639,"ring3y":291.76233529770315,"ring3z":-30.94106674194336,"pinky0x":202.55099045814967,"pinky0y":228.73651303658005,"pinky0z":-21.819580078125,"pinky1x":195.59082366478611,"pinky1y":236.66477412024156,"pinky1z":-37.764034271240234,"pinky2x":207.50641962993373,"pinky2y":274.7643024096451,"pinky2z":-36.28265380859375,"pinky3x":222.54006342972167,"pinky3y":294.8316451852341,"pinky3z":-30.595720291137695,"thumb0x":303.0194874264166,"thumb0y":335.64098326242623,"thumb0z":-10.306021690368652,"thumb1x":355.3815681143966,"thumb1y":299.79969040526487,"thumb1z":-16.080768585205078,"thumb2x":388.84037049347154,"thumb2y":272.2137987260988,"thumb2z":-21.783428192138672,"thumb3x":427.51312236573415,"thumb3y":258.3409813572418,"thumb3z":-28.367963790893555,"palm0x":245.0623041169826,"palm0y":339.53965213561673,"palm0z":-0.0003488585352897644}]} \ No newline at end of file diff --git a/html/rps++/data-capture/python/data-kid.json b/html/rps++/data-capture/python/data-kid.json new file mode 100644 index 0000000..b04f974 --- /dev/null +++ b/html/rps++/data-capture/python/data-kid.json @@ -0,0 +1 @@ +{"rock":[{"index0x":247.6623813371358,"index0y":264.2807536968453,"index0z":-19.9260196685791,"index1x":254.45682265933823,"index1y":261.4273928009472,"index1z":-55.10887908935547,"index2x":252.01271297158195,"index2y":275.32894142141834,"index2z":-63.17036437988281,"index3x":249.8144083832354,"index3y":281.38871575872093,"index3z":-59.405494689941406,"middle0x":226.27118732389775,"middle0y":260.3531449807481,"middle0z":-20.367835998535156,"middle1x":240.27041589309394,"middle1y":265.329923732647,"middle1z":-59.936912536621094,"middle2x":239.44916093737322,"middle2y":287.90203476157956,"middle2z":-58.64982986450195,"middle3x":237.61589024320514,"middle3y":290.5860748778249,"middle3z":-47.35655212402344,"ring0x":204.85245290364603,"ring0y":261.7010530642752,"ring0z":-26.32706069946289,"ring1x":219.83623412505347,"ring1y":278.4321726926559,"ring1z":-64.09082794189453,"ring2x":221.98746624951056,"ring2y":300.6791449483461,"ring2z":-48.275115966796875,"ring3x":217.99237142976943,"ring3y":298.302829904702,"ring3z":-28.35495948791504,"pinky0x":185.85827283438095,"pinky0y":270.39996766632385,"pinky0z":-34.1357421875,"pinky1x":197.6570929719095,"pinky1y":284.33340695107677,"pinky1z":-61.531192779541016,"pinky2x":204.57011752977027,"pinky2y":300.204756792533,"pinky2z":-47.38067626953125,"pinky3x":203.51899184144202,"pinky3y":298.88959954231245,"pinky3z":-27.86121940612793,"thumb0x":243.6940062971008,"thumb0y":331.7829734239403,"thumb0z":-27.55266571044922,"thumb1x":264.9941474146504,"thumb1y":309.68804561120834,"thumb1z":-49.07773208618164,"thumb2x":265.3010825991828,"thumb2y":287.7770694431389,"thumb2z":-69.84996032714844,"thumb3x":251.7958196483001,"thumb3y":271.092902902451,"thumb3z":-89.21052551269531,"palm0x":216.9478288294584,"palm0y":337.6541002506633,"palm0z":-0.0017129331827163696},{"index0x":136.94735939345486,"index0y":122.57510712630756,"index0z":4.619382858276367,"index1x":140.22532796958436,"index1y":96.5233887953552,"index1z":-23.78777503967285,"index2x":141.53116531891237,"index2y":128.9813603873174,"index2z":-37.00475311279297,"index3x":138.68944844192575,"index3y":143.00857871859162,"index3z":-30.093542098999023,"middle0x":110.56122268297533,"middle0y":122.17657354781548,"middle0z":7.316549301147461,"middle1x":116.29863906196455,"middle1y":104.63854519417362,"middle1z":-19.786531448364258,"middle2x":122.24609447163971,"middle2y":143.72264699014036,"middle2z":-27.98581314086914,"middle3x":121.02590010340931,"middle3y":152.5708219562937,"middle3z":-15.935745239257812,"ring0x":83.96498455361379,"ring0y":127.5114190615875,"ring0z":5.722416877746582,"ring1x":92.228352716221,"ring1y":113.69695696685852,"ring1z":-20.86638069152832,"ring2x":102.17684465975351,"ring2y":152.76832835330447,"ring2z":-24.615190505981445,"ring3x":98.34567683980791,"ring3y":161.9121931040575,"ring3z":-13.24239730834961,"pinky0x":57.87173068662846,"pinky0y":136.57849573186502,"pinky0z":3.512162208557129,"pinky1x":68.41495203607303,"pinky1y":125.26824251535601,"pinky1z":-16.494007110595703,"pinky2x":79.75953464416324,"pinky2y":152.77613464258894,"pinky2z":-13.761028289794922,"pinky3x":76.69055990983125,"pinky3y":163.5196903748283,"pinky3z":-1.4197888374328613,"thumb0x":141.778627460963,"thumb0y":197.73248674035932,"thumb0z":-17.162391662597656,"thumb1x":165.8196187105668,"thumb1y":159.0051733694983,"thumb1z":-21.47321319580078,"thumb2x":147.51888971724276,"thumb2y":121.39341745115368,"thumb2z":-23.90540313720703,"thumb3x":113.56730736766478,"thumb3y":123.84923074697909,"thumb3z":-26.92599868774414,"palm0x":101.03846324943709,"palm0y":214.95343534104788,"palm0z":-0.0008525103330612183},{"index0x":121.68485235502081,"index0y":303.3334919657752,"index0z":-3.430978298187256,"index1x":140.64271600101284,"index1y":290.2018761257239,"index1z":-29.474056243896484,"index2x":135.17808389969477,"index2y":328.87871897211886,"index2z":-33.9698600769043,"index3x":124.20133685643688,"index3y":339.4611765117854,"index3z":-22.062206268310547,"middle0x":92.13040435884974,"middle0y":302.75096430094203,"middle0z":-4.330502986907959,"middle1x":110.60897850192171,"middle1y":295.3724734926198,"middle1z":-31.700483322143555,"middle2x":109.29649999443096,"middle2y":339.6515411857259,"middle2z":-30.871784210205078,"middle3x":102.77023038958635,"middle3y":340.6847710145388,"middle3z":-14.64416790008545,"ring0x":63.57922008785894,"ring0y":309.8485738308068,"ring0z":-9.49614143371582,"ring1x":82.91705133660213,"ring1y":308.06701407291337,"ring1z":-36.31806182861328,"ring2x":86.88659832227664,"ring2y":350.38646581589137,"ring2z":-32.441917419433594,"ring3x":79.4829375294569,"ring3y":348.9245549432038,"ring3z":-18.566125869750977,"pinky0x":37.027295755067705,"pinky0y":324.44440063008017,"pinky0z":-15.384614944458008,"pinky1x":58.127744748174806,"pinky1y":324.320594370703,"pinky1z":-35.60431671142578,"pinky2x":67.02527755714699,"pinky2y":355.58044692392855,"pinky2z":-30.193584442138672,"pinky3x":58.17480607320589,"pinky3y":356.33682572306236,"pinky3z":-17.847713470458984,"thumb0x":114.91945097630915,"thumb0y":401.7320029985281,"thumb0z":-14.625336647033691,"thumb1x":147.59903057941833,"thumb1y":358.19093110614006,"thumb1z":-21.750686645507812,"thumb2x":134.0290286687024,"thumb2y":321.6397948628069,"thumb2z":-27.528793334960938,"thumb3x":97.05420612408699,"thumb3y":330.3582792692405,"thumb3z":-31.452104568481445,"palm0x":71.8426676237361,"palm0y":424.51429691578346,"palm0z":-0.001354224979877472},{"index0x":319.61570317126046,"index0y":179.29511649931675,"index0z":-0.6037814021110535,"index1x":347.6396404535594,"index1y":164.63197124337336,"index1z":-31.423141479492188,"index2x":348.56247611304644,"index2y":203.38636114930978,"index2z":-38.65268325805664,"index3x":338.70076771260096,"index3y":222.6540199843983,"index3z":-28.0838623046875,"middle0x":282.6220006331435,"middle0y":174.1237875723129,"middle0z":-4.9202775955200195,"middle1x":320.8197545795217,"middle1y":168.68570415357084,"middle1z":-37.688438415527344,"middle2x":320.96259967912886,"middle2y":223.27578344329714,"middle2z":-38.13831329345703,"middle3x":306.0363668608386,"middle3y":231.3475985817052,"middle3z":-21.844820022583008,"ring0x":246.04837046003672,"ring0y":182.23968848007868,"ring0z":-14.357563972473145,"ring1x":287.2086224544881,"ring1y":185.42138905635528,"ring1z":-46.96205520629883,"ring2x":289.4406459425966,"ring2y":239.55909095337117,"ring2z":-42.56021499633789,"ring3x":273.67566264406616,"ring3y":246.87897477835992,"ring3z":-26.55362892150879,"pinky0x":212.16819780804894,"pinky0y":199.90358296286277,"pinky0z":-24.491899490356445,"pinky1x":249.0718167278469,"pinky1y":205.00698276173722,"pinky1z":-50.73185348510742,"pinky2x":258.5806113354988,"pinky2y":244.888166725701,"pinky2z":-45.13248825073242,"pinky3x":244.85946278707513,"pinky3y":254.54654596904416,"pinky3z":-29.52141571044922,"thumb0x":316.6005622720678,"thumb0y":313.7558432996056,"thumb0z":-14.424993515014648,"thumb1x":357.58931268405934,"thumb1y":259.2560614731358,"thumb1z":-24.920326232910156,"thumb2x":364.840707820363,"thumb2y":207.37746924821846,"thumb2z":-37.74260330200195,"thumb3x":341.04544150425744,"thumb3y":176.50517198497317,"thumb3z":-50.55747985839844,"palm0x":259.0569202390452,"palm0y":332.9093535688603,"palm0z":-0.0006336718797683716},{"index0x":272.1768007532619,"index0y":271.78149952093094,"index0z":1.6883509159088135,"index1x":279.7640801316202,"index1y":260.7289345781226,"index1z":-24.298030853271484,"index2x":279.2935148504108,"index2y":282.8180351275733,"index2z":-30.77005958557129,"index3x":274.1806723926923,"index3y":290.0554190466327,"index3z":-18.24826431274414,"middle0x":256.9247507942054,"middle0y":272.32225051106093,"middle0z":0.6419819593429565,"middle1x":264.7306815492434,"middle1y":264.9431181777915,"middle1z":-24.239620208740234,"middle2x":265.7818276559706,"middle2y":289.90499406369617,"middle2z":-25.95465087890625,"middle3x":261.4185573566197,"middle3y":291.9687139260849,"middle3z":-10.855218887329102,"ring0x":241.91333018441995,"ring0y":277.02043323888284,"ring0z":-4.338268280029297,"ring1x":251.09615400593424,"ring1y":271.36751344739054,"ring1z":-27.532556533813477,"ring2x":254.75135026471108,"ring2y":295.3604769981892,"ring2z":-27.25811195373535,"ring3x":250.4898520133336,"ring3y":298.0246814046813,"ring3z":-15.419074058532715,"pinky0x":227.85897798670266,"pinky0y":285.441812448948,"pinky0z":-10.204702377319336,"pinky1x":239.418121891221,"pinky1y":280.97570922287025,"pinky1z":-27.364505767822266,"pinky2x":244.9822574111373,"pinky2y":297.85829039419303,"pinky2z":-24.265090942382812,"pinky3x":239.59424851204582,"pinky3y":301.8900628504739,"pinky3z":-13.331497192382812,"thumb0x":273.25800924209483,"thumb0y":325.55012935551804,"thumb0z":-11.619945526123047,"thumb1x":287.5589846404254,"thumb1y":300.9409538588738,"thumb1z":-15.10429859161377,"thumb2x":280.59431255090396,"thumb2y":278.7721350579593,"thumb2z":-17.546085357666016,"thumb3x":264.2925148951547,"thumb3y":280.06719280818055,"thumb3z":-17.922897338867188,"palm0x":250.67764238209344,"palm0y":339.66671153176054,"palm0z":-0.0009730681777000427},{"index0x":432.76232766391655,"index0y":332.5871668511682,"index0z":2.606642961502075,"index1x":435.87300230003973,"index1y":313.70804249327875,"index1z":-11.566893577575684,"index2x":443.31527581804875,"index2y":331.82794895477383,"index2z":-14.569836616516113,"index3x":446.67800700244516,"index3y":343.0493253766272,"index3z":-10.481513977050781,"middle0x":410.9899214695453,"middle0y":339.1377683635107,"middle0z":0.6945971250534058,"middle1x":423.02242206091455,"middle1y":326.95070967671427,"middle1z":-19.137754440307617,"middle2x":436.4481132082079,"middle2y":354.312067496782,"middle2z":-21.45473861694336,"middle3x":436.91846051937233,"middle3y":361.62350576293295,"middle3z":-14.261551856994629,"ring0x":393.01056217354005,"ring0y":351.01688593059856,"ring0z":-4.242563247680664,"ring1x":407.41884392228576,"ring1y":340.93916090543365,"ring1z":-23.69677734375,"ring2x":422.6551478064217,"ring2y":367.8117891289709,"ring2z":-22.972368240356445,"ring3x":421.66763626132087,"ring3y":375.84607488792864,"ring3z":-15.420945167541504,"pinky0x":377.96932129722705,"pinky0y":365.12100819132206,"pinky0z":-9.910985946655273,"pinky1x":391.4782887229987,"pinky1y":356.35132652983526,"pinky1z":-23.28818702697754,"pinky2x":407.0183038197046,"pinky2y":373.3892275850676,"pinky2z":-20.477161407470703,"pinky3x":407.4679012839562,"pinky3y":381.0210946071275,"pinky3z":-12.450733184814453,"thumb0x":453.2248847639192,"thumb0y":405.202215236677,"thumb0z":-10.21462631225586,"thumb1x":465.76508251709726,"thumb1y":369.52713450854577,"thumb1z":-16.934814453125,"thumb2x":460.3964691944775,"thumb2y":340.48205560984235,"thumb2z":-23.941152572631836,"thumb3x":448.371170971919,"thumb3y":328.0757370883468,"thumb3z":-28.063631057739258,"palm0x":426.28489913987073,"palm0y":427.59654033646797,"palm0z":-0.0010191947221755981},{"index0x":532.4596101467728,"index0y":118.20306607349325,"index0z":19.12835693359375,"index1x":540.6554258371992,"index1y":98.6388624456149,"index1z":3.675968647003174,"index2x":544.1579406639327,"index2y":111.78206773209456,"index2z":-5.955779075622559,"index3x":542.7837187783745,"index3y":120.852880730045,"index3z":-3.1259496212005615,"middle0x":516.8836848878066,"middle0y":116.28060681399346,"middle0z":16.039342880249023,"middle1x":530.8203560153904,"middle1y":99.37836909618737,"middle1z":-1.3639329671859741,"middle2x":534.5241174247391,"middle2y":122.98044452084984,"middle2z":-11.892447471618652,"middle3x":527.6722199405749,"middle3y":131.69252477006123,"middle3z":-6.7018890380859375,"ring0x":500.6045369082099,"ring0y":117.50681176712585,"ring0z":10.076361656188965,"ring1x":514.5116494648904,"ring1y":103.31299892329707,"ring1z":-7.068319320678711,"ring2x":518.9863939769477,"ring2y":126.57591906527358,"ring2z":-14.69459342956543,"ring3x":511.8180317073498,"ring3y":135.9912106389404,"ring3z":-9.904539108276367,"pinky0x":482.6790914816162,"pinky0y":121.08680501587413,"pinky0z":3.979524612426758,"pinky1x":496.9757120696157,"pinky1y":109.20227727837421,"pinky1z":-10.53023910522461,"pinky2x":504.2862370727267,"pinky2y":124.62675221264773,"pinky2z":-14.171525955200195,"pinky3x":499.58357241696893,"pinky3y":134.57851882377187,"pinky3z":-9.236886978149414,"thumb0x":533.1765600033959,"thumb0y":165.930813663945,"thumb0z":-4.133507251739502,"thumb1x":550.0199019949844,"thumb1y":140.95244507513826,"thumb1z":-3.1439907550811768,"thumb2x":550.14545644411,"thumb2y":114.57373270870127,"thumb2z":-4.371058940887451,"thumb3x":539.0960028743972,"thumb3y":99.20695749902612,"thumb3z":-5.8002495765686035,"palm0x":501.74092646576156,"palm0y":182.44437263473986,"palm0z":-0.006285242736339569}],"paper":[{"index0x":362.3747521287449,"index0y":279.1893860933776,"index0z":-12.055824279785156,"index1x":373.6659426834748,"index1y":248.9349935885255,"index1z":-17.94365692138672,"index2x":378.8308924237907,"index2y":227.87263466115718,"index2z":-21.8636531829834,"index3x":382.4053820310931,"index3y":209.3625520174562,"index3z":-24.82712745666504,"middle0x":342.5214089654051,"middle0y":276.22186471988124,"middle0z":-14.381125450134277,"middle1x":342.0407463148244,"middle1y":239.90776710639273,"middle1z":-20.36110496520996,"middle2x":341.20885269983745,"middle2y":214.01175353675958,"middle2z":-24.404640197753906,"middle3x":340.2078209943477,"middle3y":192.47949823671465,"middle3z":-27.33526611328125,"ring0x":324.08918056639055,"ring0y":281.4165604538947,"ring0z":-17.426557540893555,"ring1x":316.28324592269627,"ring1y":250.23116784022153,"ring1z":-24.227779388427734,"ring2x":311.1559068844399,"ring2y":227.45996015153963,"ring2z":-29.36549186706543,"ring3x":307.6197825338026,"ring3y":207.43136055840276,"ring3z":-33.08724594116211,"pinky0x":307.6067237216705,"pinky0y":293.94107139023305,"pinky0z":-20.655563354492188,"pinky1x":291.885245243459,"pinky1y":274.35124992665243,"pinky1z":-27.479440689086914,"pinky2x":281.4930628026431,"pinky2y":261.0099292287235,"pinky2z":-32.1116828918457,"pinky3x":272.3106767490978,"pinky3y":245.40696441629422,"pinky3z":-35.4306526184082,"thumb0x":357.5608928606268,"thumb0y":335.1188341443441,"thumb0z":-5.747415542602539,"thumb1x":378.43816965681737,"thumb1y":313.7895449156229,"thumb1z":-10.058796882629395,"thumb2x":394.94111225786475,"thumb2y":294.46880074697424,"thumb2z":-14.254755020141602,"thumb3x":408.58629943515865,"thumb3y":283.5086963746567,"thumb3z":-18.47174072265625,"palm0x":330.86199865302183,"palm0y":348.4123776877221,"palm0z":-0.001373685896396637},{"index0x":179.0791148131083,"index0y":121.58997239668713,"index0z":13.042884826660156,"index1x":185.96630109371776,"index1y":98.39183639241197,"index1z":17.79799461364746,"index2x":190.55102403931207,"index2y":83.54822803065767,"index2z":19.267431259155273,"index3x":193.803822943602,"index3y":71.0347721555933,"index3z":19.780033111572266,"middle0x":164.11269698642542,"middle0y":122.72723928911054,"middle0z":14.772208213806152,"middle1x":167.70836152322957,"middle1y":98.83148761972046,"middle1z":22.37259292602539,"middle2x":169.0564212392459,"middle2y":82.44039438623969,"middle2z":23.867515563964844,"middle3x":169.70431943792607,"middle3y":69.49742122829569,"middle3z":25.37847328186035,"ring0x":151.16112128402983,"ring0y":128.5123293725726,"ring0z":13.879048347473145,"ring1x":149.59771037550544,"ring1y":109.4073197437714,"ring1z":19.695608139038086,"ring2x":148.55930471694006,"ring2y":95.13846155486146,"ring2z":21.31130599975586,"ring3x":147.97197261278896,"ring3y":83.47147741053332,"ring3z":22.50342559814453,"pinky0x":139.60246468432734,"pinky0y":138.55800414122422,"pinky0z":11.441158294677734,"pinky1x":128.62725813752385,"pinky1y":126.24368615187794,"pinky1z":14.480260848999023,"pinky2x":120.40834776221531,"pinky2y":116.73255706425066,"pinky2z":15.364459037780762,"pinky3x":113.51699075693074,"pinky3y":106.77232109220014,"pinky3z":16.42512321472168,"thumb0x":187.26351660722605,"thumb0y":166.72836820040908,"thumb0z":-7.004197120666504,"thumb1x":199.68821448840248,"thumb1y":142.290375120083,"thumb1z":-6.2645263671875,"thumb2x":208.5742428210021,"thumb2y":120.42911965746305,"thumb2z":-5.924759387969971,"thumb3x":218.57226633056644,"thumb3y":104.83749835426423,"thumb3z":-5.156573295593262,"palm0x":166.13000395255915,"palm0y":186.01145313641928,"palm0z":-0.0017971768975257874},{"index0x":126.24882128032328,"index0y":365.76793997357544,"index0z":-7.445191383361816,"index1x":130.89436328187517,"index1y":327.93390456648956,"index1z":-10.80199146270752,"index2x":132.02194248185137,"index2y":300.56391370705546,"index2z":-14.312105178833008,"index3x":132.53288691789436,"index3y":276.3070394121805,"index3z":-17.302648544311523,"middle0x":100.70773513628916,"middle0y":367.3228191806472,"middle0z":-6.433293342590332,"middle1x":97.8129730357466,"middle1y":325.90548513653897,"middle1z":-9.132612228393555,"middle2x":95.0254056668345,"middle2y":294.7438277482407,"middle2z":-12.894330024719238,"middle3x":92.64103433873882,"middle3y":268.8430551518759,"middle3z":-15.651264190673828,"ring0x":78.6836203403213,"ring0y":377.7433403508659,"ring0z":-7.18978214263916,"ring1x":67.47407465823858,"ring1y":342.66570557540496,"ring1z":-10.46012020111084,"ring2x":60.69483815051107,"ring2y":314.66152223796576,"ring2z":-13.905275344848633,"ring3x":56.16672908175107,"ring3y":290.6848796674127,"ring3z":-16.461042404174805,"pinky0x":59.624419861304894,"pinky0y":396.1805460024911,"pinky0z":-9.360090255737305,"pinky1x":42.51401828369858,"pinky1y":373.0608353845241,"pinky1z":-13.207087516784668,"pinky2x":32.11750944984263,"pinky2y":354.6227058181868,"pinky2z":-16.170757293701172,"pinky3x":23.474302458041578,"pinky3y":334.914473252319,"pinky3z":-18.20586395263672,"thumb0x":141.48526477485154,"thumb0y":447.4015650515977,"thumb0z":-11.48229694366455,"thumb1x":158.488856517646,"thumb1y":411.5321220328211,"thumb1z":-16.666790008544922,"thumb2x":168.57159599039954,"thumb2y":378.240235304858,"thumb2z":-21.257919311523438,"thumb3x":180.37136216034884,"thumb3y":352.4574817009502,"thumb3z":-25.553071975708008,"palm0x":114.92069433957506,"palm0y":468.22253564820534,"palm0z":-0.0010766834020614624},{"index0x":229.32329998878632,"index0y":264.19674352784216,"index0z":-25.80156707763672,"index1x":226.43037848317206,"index1y":198.94145629658837,"index1z":-35.761802673339844,"index2x":223.89188148418523,"index2y":148.93360042061258,"index2z":-42.157325744628906,"index3x":221.2426726634702,"index3y":103.55037780939313,"index3z":-46.80128479003906,"middle0x":182.13028903609467,"middle0y":266.8050197513832,"middle0z":-25.73751449584961,"middle1x":166.18722306204722,"middle1y":200.30226439421023,"middle1z":-39.06501770019531,"middle2x":154.4162348010486,"middle2y":142.20712557965945,"middle2z":-48.83289337158203,"middle3x":146.44491213274324,"middle3y":92.459696306943,"middle3z":-57.11039352416992,"ring0x":147.21442537251374,"ring0y":279.4659497448204,"ring0z":-24.515426635742188,"ring1x":117.1275569981367,"ring1y":220.64564721583304,"ring1z":-36.40359115600586,"ring2x":100.45273432816384,"ring2y":170.57744652353824,"ring2z":-45.63302993774414,"ring3x":89.83907257357885,"ring3y":124.77385702650989,"ring3z":-53.46652603149414,"pinky0x":124.39973570762268,"pinky0y":302.6728372102123,"pinky0z":-22.798194885253906,"pinky1x":85.33648515857121,"pinky1y":263.32295466210246,"pinky1z":-32.108455657958984,"pinky2x":66.07290513999078,"pinky2y":234.03679464531064,"pinky2z":-39.21372604370117,"pinky3x":52.873500787240516,"pinky3y":203.45695279687746,"pinky3z":-45.43977737426758,"thumb0x":258.2450599522382,"thumb0y":358.11778468046066,"thumb0z":-6.932064533233643,"thumb1x":290.4013949306744,"thumb1y":298.9846771549246,"thumb1z":-13.876602172851562,"thumb2x":314.0808034255168,"thumb2y":245.67297823822577,"thumb2z":-19.192655563354492,"thumb3x":345.65313031726055,"thumb3y":209.3163548929782,"thumb3z":-24.75373077392578,"palm0x":201.17410230756371,"palm0y":391.1389351119034,"palm0z":-0.001242712140083313},{"index0x":480.0267239603353,"index0y":418.0908350631622,"index0z":-11.128583908081055,"index1x":481.6818455443542,"index1y":390.9149174642765,"index1z":-15.250287055969238,"index2x":482.0304006026254,"index2y":372.84910096023646,"index2z":-19.232025146484375,"index3x":481.9880636321326,"index3y":357.92656371958714,"index3z":-22.411785125732422,"middle0x":461.58034906451854,"middle0y":419.5582576432194,"middle0z":-10.645953178405762,"middle1x":455.461881458246,"middle1y":390.2855827242148,"middle1z":-15.801634788513184,"middle2x":451.5262981302925,"middle2y":369.3705913548928,"middle2z":-20.52398109436035,"middle3x":448.6138246948883,"middle3y":354.15319023618946,"middle3z":-23.618820190429688,"ring0x":447.6177791264008,"ring0y":427.50519872160135,"ring0z":-11.352093696594238,"ring1x":435.18027220509026,"ring1y":403.30202392334894,"ring1z":-16.839189529418945,"ring2x":428.3057919052908,"ring2y":385.6458889691998,"ring2z":-21.220882415771484,"ring3x":424.22886984968187,"ring3y":371.9932595325545,"ring3z":-24.001615524291992,"pinky0x":437.55627437339473,"pinky0y":441.7007890928476,"pinky0z":-12.852476119995117,"pinky1x":421.03518793598937,"pinky1y":428.93130675688536,"pinky1z":-18.52131462097168,"pinky2x":411.1482153681294,"pinky2y":419.11249420280603,"pinky2z":-22.58905792236328,"pinky3x":402.9520180741383,"pinky3y":408.95611700039757,"pinky3z":-25.22767448425293,"thumb0x":495.8156846027844,"thumb0y":469.7564455131819,"thumb0z":-9.53307819366455,"thumb1x":508.6919253598787,"thumb1y":445.70545526818466,"thumb1z":-14.624249458312988,"thumb2x":514.6668126558325,"thumb2y":423.500173962707,"thumb2z":-18.654327392578125,"thumb3x":519.09471585725,"thumb3y":410.12976386030647,"thumb3z":-21.910907745361328,"palm0x":475.9183392502815,"palm0y":482.58909227747324,"palm0z":-0.001440100371837616},{"index0x":473.4117168448454,"index0y":173.3757246748759,"index0z":-18.261991500854492,"index1x":475.74678953848803,"index1y":151.9058241902957,"index1z":-25.378517150878906,"index2x":475.0786825682156,"index2y":137.00348402468086,"index2z":-30.509288787841797,"index3x":474.3070747316239,"index3y":124.80747158629784,"index3z":-34.05732345581055,"middle0x":458.4500807062178,"middle0y":174.6624551325055,"middle0z":-17.570632934570312,"middle1x":456.29470372634,"middle1y":151.82090307162758,"middle1z":-25.4042911529541,"middle2x":453.68486269598344,"middle2y":135.09070896382224,"middle2z":-30.87053680419922,"middle3x":451.81113387162907,"middle3y":121.89967654397611,"middle3z":-34.646942138671875,"ring0x":445.90462221246526,"ring0y":179.5439157140604,"ring0z":-17.272619247436523,"ring1x":439.55896994261354,"ring1y":160.5529628452721,"ring1z":-24.57564926147461,"ring2x":434.9399454885705,"ring2y":145.92672304219246,"ring2z":-30.26303482055664,"ring3x":431.97636090814217,"ring3y":133.81822911934808,"ring3z":-34.16200256347656,"pinky0x":435.88674216275393,"pinky0y":187.76378375703933,"pinky0z":-17.436243057250977,"pinky1x":423.6062194835553,"pinky1y":176.38573716789028,"pinky1z":-23.836301803588867,"pinky2x":415.99756678476297,"pinky2y":167.6922108703031,"pinky2z":-28.666484832763672,"pinky3x":410.3462237483223,"pinky3y":158.7664172588128,"pinky3z":-32.094661712646484,"thumb0x":477.78726304963084,"thumb0y":207.238064840986,"thumb0z":-8.998682022094727,"thumb1x":491.12223019914734,"thumb1y":191.67053725567848,"thumb1z":-15.1779146194458,"thumb2x":500.07406601392336,"thumb2y":177.51972821326956,"thumb2z":-20.221574783325195,"thumb3x":508.0290027682891,"thumb3y":166.91608859415763,"thumb3z":-25.19208526611328,"palm0x":458.6457198569587,"palm0y":218.49191472638836,"palm0z":-0.0014158636331558228},{"index0x":577.1583407551193,"index0y":131.3061712804657,"index0z":4.846677303314209,"index1x":580.1825687008748,"index1y":114.0794843380201,"index1z":5.396688938140869,"index2x":580.9966719160525,"index2y":102.52510194842928,"index2z":3.939934253692627,"index3x":581.6913142865054,"index3y":92.88376891647007,"index3z":2.3685715198516846,"middle0x":564.258991100383,"middle0y":130.9710020096368,"middle0z":4.5801873207092285,"middle1x":564.1931957502718,"middle1y":111.6841838992943,"middle1z":6.081568717956543,"middle2x":563.8304017273282,"middle2y":97.77298069277782,"middle2z":3.756993293762207,"middle3x":563.7238397677255,"middle3y":86.74321677933114,"middle3z":2.064859628677368,"ring0x":553.0815142590704,"ring0y":133.64467608831697,"ring0z":2.6449100971221924,"ring1x":550.0968569815981,"ring1y":115.49907650422567,"ring1z":3.5564520359039307,"ring2x":548.4808153456555,"ring2y":102.01177317907599,"ring2z":2.338960647583008,"ring3x":547.8297598296618,"ring3y":91.03215715824514,"ring3z":1.4526206254959106,"pinky0x":543.0489235512754,"pinky0y":139.4927969433503,"pinky0z":-0.41652607917785645,"pinky1x":536.5188117498926,"pinky1y":125.91139847251675,"pinky1z":-0.9427957534790039,"pinky2x":532.6803174584511,"pinky2y":116.0814697368101,"pinky2z":-1.769256591796875,"pinky3x":529.9376426106433,"pinky3y":106.32395748444037,"pinky3z":-2.0965254306793213,"thumb0x":583.435248251472,"thumb0y":166.28069395501626,"thumb0z":-5.294418811798096,"thumb1x":594.3410545026638,"thumb1y":149.97692021163735,"thumb1z":-6.204138278961182,"thumb2x":600.9509768581757,"thumb2y":135.2009750858373,"thumb2z":-7.6101508140563965,"thumb3x":606.6802397649119,"thumb3y":123.73505581041057,"thumb3z":-8.966116905212402,"palm0x":565.401629204918,"palm0y":180.51887998170918,"palm0z":-0.0012037083506584167}],"scissor":[{"index0x":338.6239356620103,"index0y":267.7190002887425,"index0z":0.28728461265563965,"index1x":345.1283537181137,"index1y":234.7375578553404,"index1z":-2.3965187072753906,"index2x":348.6195318671085,"index2y":211.1267906460315,"index2z":-5.169862270355225,"index3x":349.4467453927045,"index3y":190.8710970607873,"index3z":-7.365993976593018,"middle0x":316.09504603956026,"middle0y":266.9680161487687,"middle0z":-0.44333040714263916,"middle1x":314.3048332037029,"middle1y":233.63230897679088,"middle1z":-0.7502905130386353,"middle2x":312.06162937115914,"middle2y":205.1565346892516,"middle2z":-3.0830416679382324,"middle3x":311.1583813035142,"middle3y":181.46729667996448,"middle3z":-5.472931861877441,"ring0x":299.31084206881565,"ring0y":278.1588784921496,"ring0z":-3.182701587677002,"ring1x":299.8730347155124,"ring1y":260.3872591138662,"ring1z":-13.062613487243652,"ring2x":313.1674296073103,"ring2y":282.0904219502813,"ring2z":-17.774784088134766,"ring3x":320.91061597329974,"ring3y":299.5811130202826,"ring3z":-18.278057098388672,"pinky0x":285.7695388379047,"pinky0y":295.99381585609194,"pinky0z":-6.383512020111084,"pinky1x":289.99112163319313,"pinky1y":282.90800567975333,"pinky1z":-17.241016387939453,"pinky2x":303.37904365823545,"pinky2y":296.98784085197707,"pinky2z":-21.418231964111328,"pinky3x":312.99730165869784,"pinky3y":311.07927203962487,"pinky3z":-23.185558319091797,"thumb0x":344.16185205833386,"thumb0y":339.3133595991423,"thumb0z":-8.489073753356934,"thumb1x":355.81912988340633,"thumb1y":309.9625030328439,"thumb1z":-12.356433868408203,"thumb2x":339.75683554051966,"thumb2y":289.4266005147555,"thumb2z":-16.178556442260742,"thumb3x":317.3557697312107,"thumb3y":283.7178763669856,"thumb3z":-18.33396339416504,"palm0x":315.7941645014274,"palm0y":359.58690798009064,"palm0z":-0.0015777945518493652},{"index0x":326.5124960763087,"index0y":222.23583633720727,"index0z":-8.2559814453125,"index1x":336.0710228471512,"index1y":171.4174226006749,"index1z":-12.949479103088379,"index2x":340.18814736408694,"index2y":133.03740028470563,"index2z":-16.850553512573242,"index3x":341.17056793653626,"index3y":98.70133639186062,"index3z":-19.755754470825195,"middle0x":288.4582426113677,"middle0y":220.59648710418318,"middle0z":-7.561570644378662,"middle1x":283.9414582972631,"middle1y":169.98879211842572,"middle1z":-9.230828285217285,"middle2x":275.4151243664152,"middle2y":120.33107035253668,"middle2z":-12.412425994873047,"middle3x":266.63021407456074,"middle3y":75.98917640234059,"middle3z":-16.236543655395508,"ring0x":260.8947325802342,"ring0y":238.54844134491492,"ring0z":-9.090582847595215,"ring1x":254.89507395510896,"ring1y":212.74231404992767,"ring1z":-20.67899513244629,"ring2x":274.6700616776282,"ring2y":248.25570799241802,"ring2z":-26.51803207397461,"ring3x":286.16033283177507,"ring3y":275.3585134391773,"ring3z":-28.39763641357422,"pinky0x":236.30479021638467,"pinky0y":267.6122923499325,"pinky0z":-11.302936553955078,"pinky1x":237.57746039715326,"pinky1y":243.5715324380187,"pinky1z":-23.522125244140625,"pinky2x":257.0821695480274,"pinky2y":259.0549860473809,"pinky2z":-28.256187438964844,"pinky3x":272.5335889579641,"pinky3y":276.4035439866414,"pinky3z":-31.122652053833008,"thumb0x":329.73204210572425,"thumb0y":347.3938753404252,"thumb0z":-13.567416191101074,"thumb1x":350.9876632184847,"thumb1y":303.7473905357069,"thumb1z":-20.50937843322754,"thumb2x":329.2234645788083,"thumb2y":273.8101670441396,"thumb2z":-26.18846893310547,"thumb3x":297.66949198493165,"thumb3y":262.1499210881911,"thumb3z":-29.644485473632812,"palm0x":286.24010674842384,"palm0y":369.8527097278927,"palm0z":-0.0013959407806396484},{"index0x":123.20945411708983,"index0y":244.90875921812932,"index0z":4.470365047454834,"index1x":128.6074586708878,"index1y":218.87201068401205,"index1z":2.463459014892578,"index2x":132.64621255577586,"index2y":195.8117191143412,"index2z":-0.7240296006202698,"index3x":134.92640390154102,"index3y":174.70494477797735,"index3z":-3.4194438457489014,"middle0x":101.75249571870074,"middle0y":243.02100557842073,"middle0z":4.766907215118408,"middle1x":100.47188403980229,"middle1y":214.5318471346485,"middle1z":4.312900066375732,"middle2x":101.34729097017161,"middle2y":188.71831547308085,"middle2z":0.1826419234275818,"middle3x":103.28505847517395,"middle3y":169.06680847880756,"middle3z":-2.5687782764434814,"ring0x":85.8121544159981,"ring0y":252.38021651305218,"ring0z":2.0048649311065674,"ring1x":80.22420852200263,"ring1y":230.87402353455278,"ring1z":-8.7545747756958,"ring2x":86.7058977934804,"ring2y":237.86968617259492,"ring2z":-17.120222091674805,"ring3x":90.46497797477758,"ring3y":244.70752111991104,"ring3z":-19.6209659576416,"pinky0x":70.76612649093036,"pinky0y":269.2033572926599,"pinky0z":-1.612747311592102,"pinky1x":71.3686044111086,"pinky1y":254.3137433714815,"pinky1z":-14.490278244018555,"pinky2x":83.47933244582997,"pinky2y":264.0838351007952,"pinky2z":-20.938762664794922,"pinky3x":92.6354666958313,"pinky3y":275.8060939027548,"pinky3z":-23.61418342590332,"thumb0x":126.60890820688657,"thumb0y":316.63213295528254,"thumb0z":-12.58853816986084,"thumb1x":135.76640844111552,"thumb1y":285.3934519886254,"thumb1z":-16.549951553344727,"thumb2x":114.61055713668503,"thumb2y":263.3725291067286,"thumb2z":-20.3428955078125,"thumb3x":92.3088950441275,"thumb3y":258.7125190636748,"thumb3z":-21.9788761138916,"palm0x":101.57722962393483,"palm0y":333.32027812541565,"palm0z":-0.0013218075037002563},{"index0x":121.60804937761799,"index0y":157.59367125479164,"index0z":7.366225719451904,"index1x":131.81715406025384,"index1y":120.89544299902698,"index1z":7.5995073318481445,"index2x":135.07943772984265,"index2y":100.47335629539266,"index2z":7.2817277908325195,"index3x":138.14717315943096,"index3y":86.07717289215732,"index3z":6.679034233093262,"middle0x":117.72102009067272,"middle0y":161.2619237965208,"middle0z":2.3341379165649414,"middle1x":122.5327311886541,"middle1y":117.61637835515978,"middle1z":1.6875876188278198,"middle2x":122.01049365390358,"middle2y":94.15048871885335,"middle2z":1.5960850715637207,"middle3x":123.04016630067693,"middle3y":79.33193995209741,"middle3z":1.7833530902862549,"ring0x":110.33317999610077,"ring0y":167.70805255857442,"ring0z":-2.7876248359680176,"ring1x":105.06245610494805,"ring1y":131.2277786960537,"ring1z":-3.7353219985961914,"ring2x":95.00068012689556,"ring2y":128.95108138657636,"ring2z":-2.7202658653259277,"ring3x":89.53327870495207,"ring3y":131.0897103677564,"ring3z":-1.8013942241668701,"pinky0x":100.65712241730424,"pinky0y":174.74465572660557,"pinky0z":-7.648252964019775,"pinky1x":96.57880920226758,"pinky1y":144.67063144728786,"pinky1z":-9.601683616638184,"pinky2x":91.18064686453691,"pinky2y":133.76023183495258,"pinky2z":-10.402064323425293,"pinky3x":88.60585370717564,"pinky3y":128.77246748573356,"pinky3z":-11.156954765319824,"thumb0x":86.69478734933742,"thumb0y":202.47659433029645,"thumb0z":6.48472261428833,"thumb1x":93.7546707056801,"thumb1y":170.84258934872793,"thumb1z":9.304750442504883,"thumb2x":95.7296960019626,"thumb2y":145.28295911879079,"thumb2z":10.653910636901855,"thumb3x":95.12030543812132,"thumb3y":127.63002189532928,"thumb3z":13.024991035461426,"palm0x":83.10167766269285,"palm0y":249.0641008386255,"palm0z":-0.0007563009858131409},{"index0x":546.8178658457176,"index0y":326.9489665594164,"index0z":13.89556884765625,"index1x":545.8153002720328,"index1y":299.1402691925234,"index1z":14.36088752746582,"index2x":544.3686740953392,"index2y":277.90807714368725,"index2z":14.334565162658691,"index3x":541.8133571237136,"index3y":262.94569588314243,"index3z":14.358661651611328,"middle0x":534.8062922062651,"middle0y":323.94030502566994,"middle0z":3.1560654640197754,"middle1x":537.1770326526648,"middle1y":288.14846783521074,"middle1z":3.5648856163024902,"middle2x":539.8989398895196,"middle2y":264.42657725880235,"middle2z":2.2171454429626465,"middle3x":538.9914319269695,"middle3y":247.14731146359878,"middle3z":1.4838926792144775,"ring0x":523.220580220945,"ring0y":330.14063840448944,"ring0z":-7.9798431396484375,"ring1x":548.457388728119,"ring1y":313.14444979583936,"ring1z":-16.74110984802246,"ring2x":565.5289933853065,"ring2y":326.3675837082788,"ring2z":-18.463451385498047,"ring3x":568.8763495340785,"ring3y":339.2225372240732,"ring3z":-17.962820053100586,"pinky0x":520.0701756627587,"pinky0y":337.718625753465,"pinky0z":-17.693927764892578,"pinky1x":549.3546819852393,"pinky1y":332.0836672053245,"pinky1z":-26.413928985595703,"pinky2x":567.6674349948822,"pinky2y":343.20130915731147,"pinky2z":-26.532466888427734,"pinky3x":575.2450763373009,"pinky3y":355.9030728733996,"pinky3z":-25.44061851501465,"thumb0x":548.4185136209218,"thumb0y":381.55027539528044,"thumb0z":8.351826667785645,"thumb1x":565.164428991972,"thumb1y":366.0994522556126,"thumb1z":6.0977091789245605,"thumb2x":578.0391663625302,"thumb2y":353.21187678821565,"thumb2z":-1.2458637952804565,"thumb3x":578.9820026403739,"thumb3y":337.2876111974283,"thumb3z":-8.090970993041992,"palm0x":519.619002623556,"palm0y":402.0700899597645,"palm0z":-0.002006709575653076},{"index0x":480.1158459423697,"index0y":200.60739789833815,"index0z":9.718179702758789,"index1x":484.70790638329333,"index1y":172.51601500357017,"index1z":8.067031860351562,"index2x":489.26341545276375,"index2y":155.1603775719159,"index2z":6.745933532714844,"index3x":492.5946246489685,"index3y":141.61797777309738,"index3z":6.1388044357299805,"middle0x":465.06351382489686,"middle0y":201.23635304208346,"middle0z":3.8988990783691406,"middle1x":461.6700367239564,"middle1y":170.21343708265434,"middle1z":3.5356273651123047,"middle2x":461.64247840820855,"middle2y":152.60972052360563,"middle2z":2.216435432434082,"middle3x":458.7473690346036,"middle3y":137.296202559467,"middle3z":1.6598761081695557,"ring0x":455.26643966015814,"ring0y":211.5468699246276,"ring0z":-3.3688478469848633,"ring1x":469.3039113586543,"ring1y":193.5913328892755,"ring1z":-9.778765678405762,"ring2x":487.47057828008434,"ring2y":214.26360978264375,"ring2z":-11.330245971679688,"ring3x":492.69580688277546,"ring3y":230.4086443874171,"ring3z":-11.165571212768555,"pinky0x":450.7179221967888,"pinky0y":223.85450117636427,"pinky0z":-10.29655647277832,"pinky1x":465.48875154516736,"pinky1y":211.29016217826393,"pinky1z":-16.3601131439209,"pinky2x":481.04302355415024,"pinky2y":224.67467209382005,"pinky2z":-16.218441009521484,"pinky3x":488.2706912740175,"pinky3y":238.30681113397048,"pinky3z":-15.948726654052734,"thumb0x":495.6285779352717,"thumb0y":260.161018830047,"thumb0z":0.828558087348938,"thumb1x":504.0045882981904,"thumb1y":236.11864073802855,"thumb1z":-1.242215871810913,"thumb2x":502.8662277818495,"thumb2y":220.00925067515806,"thumb2z":-6.112368106842041,"thumb3x":494.3163175589854,"thumb3y":208.38576735872422,"thumb3z":-9.211282730102539,"palm0x":477.88383439451076,"palm0y":287.64420435043155,"palm0z":-0.0017113536596298218}],"shoot":[{"index0x":261.5930759707492,"index0y":303.6905281142228,"index0z":10.817279815673828,"index1x":259.31565454492335,"index1y":272.82241531165414,"index1z":11.930642127990723,"index2x":255.98674937347633,"index2y":252.75868456927114,"index2z":10.477350234985352,"index3x":250.83803567763687,"index3y":236.04835543534531,"index3z":8.611421585083008,"middle0x":244.75410133582926,"middle0y":306.17682318766884,"middle0z":9.620562553405762,"middle1x":240.9002631919296,"middle1y":271.28752717517705,"middle1z":8.92088794708252,"middle2x":238.50807641905465,"middle2y":250.7861853451944,"middle2z":3.718074321746826,"middle3x":237.28081566751086,"middle3y":236.4277489985747,"middle3z":0.21538883447647095,"ring0x":231.3167743175593,"ring0y":315.4423983399197,"ring0z":6.605212211608887,"ring1x":225.57688766235577,"ring1y":287.2703708099601,"ring1z":-0.6611623167991638,"ring2x":236.53463792786124,"ring2y":297.61235115778504,"ring2z":-9.330368995666504,"ring3x":244.59206627049727,"ring3y":309.2413571874534,"ring3z":-12.865049362182617,"pinky0x":218.76177347036034,"pinky0y":329.74009585034497,"pinky0z":3.452014446258545,"pinky1x":213.90037906882344,"pinky1y":308.388023622729,"pinky1z":-4.992694854736328,"pinky2x":223.44113517269352,"pinky2y":314.3606487061323,"pinky2z":-10.341330528259277,"pinky3x":231.98360863476768,"pinky3y":323.5597989438484,"pinky3z":-12.660213470458984,"thumb0x":274.90059577296785,"thumb0y":360.5003437243553,"thumb0z":-4.780367374420166,"thumb1x":286.43444111444785,"thumb1y":328.5672324594441,"thumb1z":-4.471588611602783,"thumb2x":291.9178445621537,"thumb2y":300.60866956370876,"thumb2z":-5.0683088302612305,"thumb3x":300.1538734947477,"thumb3y":282.0727527088558,"thumb3z":-5.498883247375488,"palm0x":249.55993206823277,"palm0y":391.71657615161206,"palm0z":-0.0013313665986061096},{"index0x":269.776604274333,"index0y":256.09052195072434,"index0z":-6.065363883972168,"index1x":270.81710422581995,"index1y":207.81488540487783,"index1z":-11.571595191955566,"index2x":270.58478573689615,"index2y":177.55182776106957,"index2z":-15.679784774780273,"index3x":266.9030789993969,"index3y":151.28469105644646,"index3z":-18.82068634033203,"middle0x":241.7668252117468,"middle0y":262.7160654033492,"middle0z":-9.209470748901367,"middle1x":240.86451930715737,"middle1y":214.46687138605475,"middle1z":-16.241270065307617,"middle2x":238.7325776822793,"middle2y":177.20627378648194,"middle2z":-21.518722534179688,"middle3x":237.63711721292327,"middle3y":144.21994838304113,"middle3z":-25.41357421875,"ring0x":218.61225934654465,"ring0y":281.1610548337653,"ring0z":-13.447436332702637,"ring1x":221.95381353479218,"ring1y":255.85317547032693,"ring1z":-25.778427124023438,"ring2x":242.7261232939347,"ring2y":283.7332839885176,"ring2z":-30.353588104248047,"ring3x":256.63634666233816,"ring3y":302.96768675442155,"ring3z":-30.94209098815918,"pinky0x":198.82641760947803,"pinky0y":307.7765977495901,"pinky0z":-18.051183700561523,"pinky1x":204.5232982420119,"pinky1y":289.83195919260135,"pinky1z":-28.814634323120117,"pinky2x":223.75928231675275,"pinky2y":307.5162476551826,"pinky2z":-32.142486572265625,"pinky3x":237.63536691503998,"pinky3y":321.5963517197521,"pinky3z":-33.142364501953125,"thumb0x":289.9412651050041,"thumb0y":355.4481907933189,"thumb0z":-5.757209300994873,"thumb1x":311.95322034973486,"thumb1y":305.258782424199,"thumb1z":-9.417499542236328,"thumb2x":321.1530864376191,"thumb2y":264.05722382135355,"thumb2z":-13.636445999145508,"thumb3x":329.7852364188162,"thumb3y":235.3464423875306,"thumb3z":-17.055692672729492,"palm0x":250.77098998839284,"palm0y":390.5350610902497,"palm0z":-0.0011240914463996887},{"index0x":139.38325414643444,"index0y":194.0624463585123,"index0z":2.9555182456970215,"index1x":137.86815306178138,"index1y":170.12275706759638,"index1z":3.774634838104248,"index2x":135.90875150033003,"index2y":154.5363835044602,"index2z":3.8154797554016113,"index3x":133.82625526200354,"index3y":141.46019636620497,"index3z":3.0476813316345215,"middle0x":122.2553735866348,"middle0y":195.91370133326384,"middle0z":3.0334224700927734,"middle1x":119.3120106746825,"middle1y":169.5237348205406,"middle1z":2.2965569496154785,"middle2x":117.85033570126349,"middle2y":146.47161854791625,"middle2z":0.5143038630485535,"middle3x":117.02627159362333,"middle3y":129.086686001198,"middle3z":-1.9679410457611084,"ring0x":107.5164322193366,"ring0y":202.57610181079303,"ring0z":2.215259313583374,"ring1x":102.1760865747367,"ring1y":179.84572567940498,"ring1z":-1.119240403175354,"ring2x":104.39764757402077,"ring2y":177.1492689092831,"ring2z":-3.6026651859283447,"ring3x":107.44502522835212,"ring3y":177.2241596454291,"ring3z":-5.5557403564453125,"pinky0x":93.45496965770978,"pinky0y":213.1262194145258,"pinky0z":1.2272202968597412,"pinky1x":89.03710556398951,"pinky1y":196.1228756414238,"pinky1z":-3.0519957542419434,"pinky2x":92.97693009155579,"pinky2y":194.48116508589135,"pinky2z":-5.792196273803711,"pinky3x":97.53079845101995,"pinky3y":194.47161666313622,"pinky3z":-8.355558395385742,"thumb0x":149.57929388210724,"thumb0y":236.42874408836835,"thumb0z":-3.1966097354888916,"thumb1x":158.29505329765453,"thumb1y":209.884698268897,"thumb1z":-3.0585224628448486,"thumb2x":155.8442487133064,"thumb2y":184.9944066719605,"thumb2z":-2.6893231868743896,"thumb3x":152.98594342141195,"thumb3y":168.78064910843358,"thumb3z":-2.100956678390503,"palm0x":128.6127381464154,"palm0y":253.98137273085348,"palm0z":-0.0016389191150665283},{"index0x":130.5120149404009,"index0y":387.48928366264226,"index0z":9.666637420654297,"index1x":127.78338408588299,"index1y":361.47168218188915,"index1z":10.649968147277832,"index2x":123.43338406235752,"index2y":345.5880035074142,"index2z":9.260210037231445,"index3x":118.14595439956227,"index3y":333.1608745545798,"index3z":7.430234432220459,"middle0x":113.29025401792491,"middle0y":389.1326870088841,"middle0z":9.199333190917969,"middle1x":111.21659546137674,"middle1y":360.6357273703754,"middle1z":8.488073348999023,"middle2x":106.99913698353441,"middle2y":343.1997720642329,"middle2z":3.516939163208008,"middle3x":104.1250530461607,"middle3y":330.93808530821,"middle3z":-0.4658583402633667,"ring0x":99.16341623209468,"ring0y":396.36240977244904,"ring0z":6.717891693115234,"ring1x":93.72362085016469,"ring1y":374.38292828772796,"ring1z":-0.8256875872612,"ring2x":97.49097266678451,"ring2y":387.02877530346797,"ring2z":-9.45235824584961,"ring3x":100.91158100210512,"ring3y":399.49045380864345,"ring3z":-13.384174346923828,"pinky0x":85.88140741193658,"pinky0y":407.2709430223659,"pinky0z":4.050888538360596,"pinky1x":82.75647392463728,"pinky1y":390.6959489793553,"pinky1z":-5.210209846496582,"pinky2x":87.76366321243349,"pinky2y":399.24789802016556,"pinky2z":-11.937389373779297,"pinky3x":91.89297824226045,"pinky3y":408.9879493509964,"pinky3z":-15.848479270935059,"thumb0x":138.47850373007242,"thumb0y":434.2526418390314,"thumb0z":-6.0407514572143555,"thumb1x":150.16984425531635,"thumb1y":405.5232381759713,"thumb1z":-6.274860858917236,"thumb2x":150.88233672771702,"thumb2y":378.11506541577194,"thumb2z":-7.136027812957764,"thumb3x":148.98068207786577,"thumb3y":360.7191520487712,"thumb3z":-8.087919235229492,"palm0x":112.83519885652363,"palm0y":453.8609746906138,"palm0z":-0.0011437684297561646},{"index0x":539.9026604209,"index0y":409.0906333338694,"index0z":-7.254699230194092,"index1x":537.8910685880894,"index1y":382.27058562946956,"index1z":-13.808104515075684,"index2x":534.8616580100205,"index2y":364.60671224129743,"index2z":-19.650136947631836,"index3x":529.8200845577873,"index3y":349.1402241678195,"index3z":-24.506099700927734,"middle0x":524.2833302415949,"middle0y":412.0082991830323,"middle0z":-11.215127944946289,"middle1x":524.2101295012706,"middle1y":383.3048944421767,"middle1z":-19.589628219604492,"middle2x":520.1040263047051,"middle2y":359.8707594097269,"middle2z":-26.77899742126465,"middle3x":515.1734745804645,"middle3y":339.6235908022421,"middle3z":-32.6258659362793,"ring0x":510.6044298798437,"ring0y":422.588743564828,"ring0z":-15.637182235717773,"ring1x":516.9206891321937,"ring1y":409.5869305044275,"ring1z":-26.769670486450195,"ring2x":528.975384794239,"ring2y":427.9609156261341,"ring2z":-30.534147262573242,"ring3x":535.9070625847676,"ring3y":441.33926932094886,"ring3z":-31.207075119018555,"pinky0x":500.5146100957876,"pinky0y":437.1448659612277,"pinky0z":-20.340253829956055,"pinky1x":510.0736259558221,"pinky1y":429.9950365675707,"pinky1z":-29.247642517089844,"pinky2x":521.9711168720195,"pinky2y":442.69956913058684,"pinky2z":-31.201236724853516,"pinky3x":529.6016015576727,"pinky3y":453.00060899409226,"pinky3z":-31.453811645507812,"thumb0x":548.7666001638247,"thumb0y":463.30703179532696,"thumb0z":-4.67949914932251,"thumb1x":562.5706247997208,"thumb1y":438.1893451406912,"thumb1z":-9.76569652557373,"thumb2x":568.3796210884348,"thumb2y":416.6206797042312,"thumb2z":-15.747939109802246,"thumb3x":571.2925856703768,"thumb3y":399.44113288301673,"thumb3z":-20.838123321533203,"palm0x":523.852726063621,"palm0y":483.18008450636995,"palm0z":-0.0015702694654464722},{"index0x":536.5305507514995,"index0y":173.25910739407016,"index0z":5.542724132537842,"index1x":534.7851478378109,"index1y":153.8317631776141,"index1z":3.9883337020874023,"index2x":534.0026884033296,"index2y":140.57688311824694,"index2z":1.5190579891204834,"index3x":532.5636270952942,"index3y":128.82707448643725,"index3z":-0.9856170415878296,"middle0x":524.1852527136605,"middle0y":175.9119007512213,"middle0z":2.2054710388183594,"middle1x":524.690639264999,"middle1y":153.95112161765925,"middle1z":-0.5690478682518005,"middle2x":527.2098959976804,"middle2y":139.29834810147696,"middle2z":-5.878398895263672,"middle3x":529.5921341801129,"middle3y":127.4392670853496,"middle3z":-9.99052619934082,"ring0x":513.5970695060723,"ring0y":183.47579491342387,"ring0z":-2.805131435394287,"ring1x":514.2880235250689,"ring1y":167.00566133100352,"ring1z":-11.308528900146484,"ring2x":524.1800176737801,"ring2y":176.1214696913216,"ring2z":-18.08615493774414,"ring3x":531.1614735374579,"ring3y":185.18978518674285,"ring3z":-21.175617218017578,"pinky0x":503.80801073456166,"pinky0y":194.3518526831153,"pinky0z":-8.262710571289062,"pinky1x":505.79791005502204,"pinky1y":181.33609961660372,"pinky1z":-17.4175968170166,"pinky2x":514.7538757916867,"pinky2y":185.65265337885577,"pinky2z":-21.920257568359375,"pinky3x":521.9571987030264,"pinky3y":192.0911296017554,"pinky3z":-24.273696899414062,"thumb0x":551.329163408653,"thumb0y":221.3700651566832,"thumb0z":-4.734251499176025,"thumb1x":561.5459021110569,"thumb1y":198.9054145242902,"thumb1z":-6.68673038482666,"thumb2x":565.9185179255938,"thumb2y":180.01574552231665,"thumb2z":-9.999878883361816,"thumb3x":569.0948603640372,"thumb3y":163.68185044388807,"thumb3z":-13.441399574279785,"palm0x":530.7668123786146,"palm0y":240.6540404087783,"palm0z":-0.0010848194360733032}]} \ No newline at end of file diff --git a/html/rps++/data-capture/python/model.ipynb b/html/rps++/data-capture/python/model.ipynb new file mode 100644 index 0000000..6fc2908 --- /dev/null +++ b/html/rps++/data-capture/python/model.ipynb @@ -0,0 +1,456 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "df.shape=(61, 64)\n", + "i2k={0: 'rock', 1: 'paper', 2: 'scissor', 3: 'shoot'}\n", + "k2i={'rock': 0, 'paper': 1, 'scissor': 2, 'shoot': 3}\n" + ] + } + ], + "source": [ + "import json\n", + "import pandas as pd\n", + "\n", + "def merge(adata, kdata):\n", + " i2k = {i: k for i, k in enumerate(adata.keys())}\n", + " k2i = {k: i for i, k in i2k.items()}\n", + " \n", + " data = []\n", + " \n", + " for k, arr in adata.items():\n", + " y = k2i[k]\n", + " for d in arr:\n", + " d['y'] = y\n", + " data.append(d)\n", + " \n", + " for k, arr in kdata.items():\n", + " y = k2i[k]\n", + " for d in arr:\n", + " d['y'] = y\n", + " data.append(d)\n", + " \n", + " data = sorted(data, key=lambda d: d['y'])\n", + " \n", + " return i2k, k2i, pd.DataFrame(data)\n", + "\n", + "with open('data-adult.json', 'r') as f:\n", + " adata = json.load(f)\n", + " \n", + "with open('data-kid.json', 'r') as f:\n", + " kdata = json.load(f)\n", + " \n", + "i2k, k2i, df = merge(adata, kdata)\n", + "\n", + "print(f'df.shape={df.shape}')\n", + "print(f'i2k={i2k}')\n", + "print(f'k2i={k2i}')" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0 18\n", + "1 16\n", + "2 14\n", + "3 13\n", + "Name: y, dtype: int64" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.y.value_counts()" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Index(['index0x', 'index0y', 'index0z', 'index1x', 'index1y', 'index1z',\n", + " 'index2x', 'index2y', 'index2z', 'index3x', 'index3y', 'index3z',\n", + " 'middle0x', 'middle0y', 'middle0z', 'middle1x', 'middle1y', 'middle1z',\n", + " 'middle2x', 'middle2y', 'middle2z', 'middle3x', 'middle3y', 'middle3z',\n", + " 'ring0x', 'ring0y', 'ring0z', 'ring1x', 'ring1y', 'ring1z', 'ring2x',\n", + " 'ring2y', 'ring2z', 'ring3x', 'ring3y', 'ring3z', 'pinky0x', 'pinky0y',\n", + " 'pinky0z', 'pinky1x', 'pinky1y', 'pinky1z', 'pinky2x', 'pinky2y',\n", + " 'pinky2z', 'pinky3x', 'pinky3y', 'pinky3z', 'thumb0x', 'thumb0y',\n", + " 'thumb0z', 'thumb1x', 'thumb1y', 'thumb1z', 'thumb2x', 'thumb2y',\n", + " 'thumb2z', 'thumb3x', 'thumb3y', 'thumb3z', 'palm0x', 'palm0y',\n", + " 'palm0z', 'y'],\n", + " dtype='object')" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.columns" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plot poses" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def to_points(idx):\n", + " s = df[[c for c in df.columns if c != 'y']].iloc[idx]\n", + " pose = pd.DataFrame(list(zip(*(iter(s),) * 3)), columns=['x', 'y', 'z'])\n", + " return {\n", + " 'thumb': pose.iloc[[0, 1, 2, 3, 4],:],\n", + " 'index': pose.iloc[[0, 5, 6, 7, 8],:],\n", + " 'middle': pose.iloc[[0, 9, 10, 11, 12],:],\n", + " 'ring': pose.iloc[[0, 13, 14, 15, 16],:],\n", + " 'pinky': pose.iloc[[0, 17, 18, 19, 20],:]\n", + " }\n", + "\n", + "poses = {i2k[c]: to_points(df[df.y == c].index[0]) for c in range(4)}" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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1aFDhxZ/jk72+68lX0MNZTLDnHv8cxSp19CqVav08ccfa+zYsfrqq680ZcoUVVRUBK838jVEQT5Db7zxhp5//nlJUkJCgiwWS723s47JyMjQli1b5PV6VV1drV27dqlnz54tHTeoodzvvvuuli1bpqVLl+qcc84xXe6GMt93333au3evpKN/KVqtVlNlbih3SkqK/va3v2np0qV6+umndf7552vatGmmyt3Yc719+3ZJ0saNG3XxxRerX79+Wr9+vfx+vw4ePCi/3x+x1eOGMl966aX68MMPJUmffvqpzj//fFM9zzh9ZWVlysnJ0eTJk4Nvd7/55psnzF179+5Vdna2fD6famtr9fnnn+viiy9ukTx33313RH9WGsp0LMuVV14ZHH/88cfB1WW3262vv/5a5557btjzNPSz2adPH23atEmStG7dOvXv37/FnqNT/f3XUq+h5Kpq1gAAIABJREFUxjJFcs5trNtE6jW0fPny4Pfnwgsv1Ny5c3XllVe2yGvIEggEAuH4ItqaI0eO6OGHH1ZZWZnq6ur029/+Vtdff73+P3v3HhB1mff//zkHQGRGkYMZKdlBy0xay9JW1m47LN6Vma5hkbrFdpCvq2mtWyJqG1pruNauhm50+oZ0E6WbuHXXXf1yK9e00q/uWnabxzQqQBRmHAeY4feHOg2iqDnDzHx4Pf7q+jDzmfcb7OLt5ftzXXC4TycpKanZLhavvvoqTU1N3H///c16xMIh7tzcXM4++2w6deoEwJVXXsnkyZPDJu7jxZyQkMCTTz5JVFQUsbGxzJkzh65du4ZNzCeK++ifkT179vDggw9SVlYGhM+fkePFfPbZZ5Ofn09UVBRJSUnk5+djs9lYuHAhH374IV6vl+nTpzNgwICwiblPnz7k5eXhcrmw2Wz86U9/onPnzmHzfZbTN2fOHP77v//b90vY4/GwdetWUlJSWsxdRUVFvP3220RFRTFixAjfXBzMeACmTJlCQUFByP5fOV5MRUVF/OpXv+K//uu/fN8ngLlz57Jx40bMZjP33HOPb24KpOP9v3nBBRcwc+ZMGhoaOP/885kzZw4Wi6VNvken8/uvLf4MnSimUM65J/q9ddNNN4Xkz5C/cePG8eijj2I2m9vkz5AKZBERERERP2qxEBERERHxowJZRERERMSPCmQRERERET8qkEVERERE/KhAFhERERHxowJZRERERMSPCmQRERERET8qkEWOePnllxk7dixNTU189tln/PKXv2x2dKWIiASf5mIJBzooROSIpqYmxo8fz7BhwyguLmbu3LlcccUVoQ5LRKRd0Vws4UAFsoifb775huHDh3PHHXfw8MMPhzocEZF2SXOxhJpaLET8fPvtt8TFxfHFF1+gvzuKiISG5mIJNRXIIkc4nU5mzpzJ4sWL6dChA6+88kqoQxIRaXc0F0s4UIuFyBGPPvooUVFRzJgxg71795KZmUlpaSk9evQIdWgiIu2G5mIJByqQRURERET8qMVCRERERMSPCmQRERERET8qkEVERERE/KhAFhERERHxowJZRERERMSPCmQRERERET8qkEVERERE/KhAFhERERHxowJZRERERMSPCmQRERERET8qkEVERERE/KhAFhERERHxowJZ2q1//etfTJ48OdRhiIi0O2vXruXmm28O2P3q6uoYP358wO4nogJZ2q1+/frxl7/8JdRhiIjIGTpw4AD/+te/Qh2GGIg11AGIBJLT6WT69Ons2rULs9lM3759eeyxx1i+fDkvvvgiZrOZLl26MG/ePHbv3k1+fj5///vf+eyzz/jjH/+I1+sF4P777ycjI+OE1+vq6vjDH/7Ali1bMJlM/OIXv+DBBx/EarVy6aWXct1117Flyxbmz59Pv379QvktEREJqePNyzfddBMHDx5k6tSpbN++HbfbzZw5cxgwYECr8+tnn33Gk08+icvlIioqiilTpjBkyBCmT5/OoUOHGDFiBMuXL8disYQ6bYlwWkEWQ3n33XdxOp2sWLGC119/HYD//d//Zf78+Tz33HOsXLmSa6+9lsWLFzd738KFC7n77rtZvnw5jz/+OJ988kmr1+fMmUN8fDwrV65k2bJlfPXVV7zwwgsANDQ0MHToUN555x0VxyLS7h1vXt6zZw/fffcdd911FytWrOD2229n4cKFwInn15qaGiZPnsyMGTNYuXIl8+bNY9q0aXzzzTc88cQTdOjQgRUrVqg4loBQgSyGcsUVV/D1118zbtw4nn32WX7961+zZs0a0tPTOfvsswG46667eOyxx5q97z//8z957LHHeOihh9i8eTMPPvhgq9c//PBDxo4di8lkIjo6mttvv50PP/zQd78BAwa0UcYiIuHtePNyamoqPXr04LLLLgPg4osv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5e+wceP/489/nk+nTp0wmy307XspAH/96zOsXbuGs846iwMH9re4/5Ili9i4cT1ebxNjxtzJtddef0bxioiEWlvOxbt372DChElhNxerQBaRsFHtdbQ6/qkOHjzIU089w3vvvcOrr77Cs8++xIYNn/Paa//le83ChQt49NG5pKaey/z5TwCwffvXbNy4geeeexmX6yC33z6q2X3XrFlNRcVeFi9+Abfbzf33382VVw5sdmyziEikacu5ePv2L3juuRd8rwmXuVgFsoiEjUSz7fBqhd84EHr1uggAm81Oz57nYTKZsNvtuN31vtdUVv5Aauq5APTrdxl79nzDjh3bufjiPpjNZuLibJx//oXN7rt9+9d89dUWfvvb+wBobGzku+8qVCCLSERry7m4c+fOYTkXq0AWkbCRGTsIXDTrewsEk8l00tckJiayc+cOevY8jy+//AK73U5q6rm8/nopXq8Xt9vNzp3bm73n3HN70r//AB5+eAZer5eXXnqOc845JyAxi4iEiuZiFcgiEkZs5pgz7nP7qWbOzGfu3Nl07BhHx44dsdvt9Op1EUOHXs8994wnKSmZLl0Smr1n8OAhbNjwOf/n/9yDy3WQIUOG0rFjXEjiFxEJFM3FYGpqamo6ozuEQGVlXYtrycn2416PVEbLB4yXk/IJf+GcU3Jy5LdhtNX3Npx/jqfKCDmAMfIwQg6gPAL5+cejfZBFRERERPwErcWioaGB3Nxc9u7dS319PTk5Ofz973+nqqoKgL1793LZZZfx1FNPMWHCBPbv309UVBQxMTE899xzwQpLRERERKRVQSuQy8vLiY+Pp6CggJqaGkaOHMmqVasAOHDgAOPHj2f69OkA7N69mzfffPOUmrdFRERERIIpaAXysGHDyMjI8I0tlh/PWV+4cCFjx46la9euVFVVUVtby4QJE6itreW+++5j6NChrd67S5eOWK0tz203Qk+fP6PlA8bLSfmEPyPmJCIiwRW0Ajku7vDTgw6Hg8mTJzNlyhQAqqurWbNmjW/1uKGhgezsbMaPH8+BAwe44447SEtLIzEx8YT3rqk52OJaqJu8A81o+YDxclI+4S+cc1LhLiISvoL6kF5FRQXjx49nxIgRDB8+HIC3336bm2++2beinJSUxO23347VaiUxMZE+ffqwY8eOYIYlIiIiInJCQSuQq6qqyM7OZtq0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nj157LHHWLx4MXa7nYEDB/L2229jt//4CyouLg6Hw3HSe9fUHAxKzMdKTrZTWVnXJp8VLG2dg8Xb5ZhxQkA+Xz+L8KE8Avf5x6MCWUSkHZk7dy4lJSX06tWLkpIS/vjHP5Keno7T6fS9xul0NiuYJfJoVx6RM6MCWUSkHencuTM22+GHtbp27cr69etJS0vj6aefxu12U19fz7Zt2+jdu3eII5UzoV15RM6MCmQRkXZkzpw5TJ06FavVSlRUFPn5+SQnJzNu3DiysrJoampi6tSpxMTEhDpUEZGQCWqB7L+10ObNm5kwYQI9e/YE4I477uDGG29k0aJFrFq1CqvVSm5u7kkfChERkdPTvXt3ysrKABgwYAClpaUtXpOZmUlmZmZbhyYiEpaCViAfu7XQF198wd133012drbvNZs3b2bdunW89tprVFRUMGnSJJYtWxaskERERERETsocrBsf3VroqH//+9+sWrWKO++8k9zcXBwOB59//jnp6emYTCZSUlLweDzs27evlbuKiIiIiARX0FaQj91aKC0tjdtuu41LL72UxYsX88wzz2C324mPj/e9Ji4ujrq6OhISElq994n23gzHffTOhNHyAePlpHzCnxFzEhGR4Gqzh/RuuOEGOnXq5Pvv/Px8rrvuup+0tdDx9t4M9T56gWa0fMB4OSmf8BfOOalwFxEJX0FrsTjWb37zGzZt2gTAmjVr6Nu3L5dffjkff/wxXq+Xb7/9Fq/Xe9LVYxERERGRYGqzFeRHH32U/Px8oqKiSEpKIj8/H5vNxoABAxgzZgxer5dZs2a1VTgi0o55nQ5cy0vw7qvCnJBI7KixmONsoQ5LRETCRFALZP+thfr27XvcrYUmTZrEpEmTghmGiEgzruUlNG76DADvnp24MBE3TocqiIjIYW3WYiEiEi68+6paHYuISPumAllE2h1zQuIx46QQRSIiIuFIR02LSLsTO2osLkxHepCTiB11Z6hDEhGRMKICWUTaHXOcTT3HIiJyQmqxEBERERHxowJZRERERMSPCmQRERERET8qkEVERERE/KhAFhERERHxowJZRERERMSPCmQRERERET8qkEVERERE/KhAFhERERHxowJZRERERMSPCmQRERERET/WUAcgIiIi7ZfX6cC1vATvvirMCYnEjhqLOc4W6rCknVOBLCIiIiHjWl5C46bP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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%matplotlib inline\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "import numpy as np\n", + "\n", + "plt.style.use('seaborn')\n", + "\n", + "fig, axes = plt.subplots(2, 2, figsize=(10, 10))\n", + "axes = np.ravel(axes)\n", + "\n", + "colors = sns.color_palette('hls', 5)\n", + "\n", + "for c, ax in zip(poses.keys(), axes):\n", + " pose = poses[c]\n", + " for i, finger in enumerate(['thumb', 'index', 'middle', 'ring', 'pinky']):\n", + " pose[finger].plot.scatter(x='x', y='y', ax=ax, color=colors[i], label=f'{finger}')\n", + " ax.set_title(c)\n", + " \n", + "plt.tight_layout()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# K-fold cross-validation" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
macromicroweighted
01.000001.0000001.000000
11.000001.0000001.000000
20.825000.8055560.800000
30.856250.8333330.841667
41.000001.0000001.000000
51.000001.0000001.000000
61.000000.9907411.000000
71.000001.0000001.000000
80.968750.9629630.958333
91.000001.0000001.000000
\n", + "
" + ], + "text/plain": [ + " macro micro weighted\n", + "0 1.00000 1.000000 1.000000\n", + "1 1.00000 1.000000 1.000000\n", + "2 0.82500 0.805556 0.800000\n", + "3 0.85625 0.833333 0.841667\n", + "4 1.00000 1.000000 1.000000\n", + "5 1.00000 1.000000 1.000000\n", + "6 1.00000 0.990741 1.000000\n", + "7 1.00000 1.000000 1.000000\n", + "8 0.96875 0.962963 0.958333\n", + "9 1.00000 1.000000 1.000000" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from sklearn.model_selection import StratifiedKFold\n", + "from sklearn.metrics import roc_auc_score, average_precision_score, accuracy_score\n", + "from sklearn.preprocessing import label_binarize\n", + "from sklearn.linear_model import LogisticRegression\n", + "\n", + "X = df[[c for c in df.columns if c != 'y']]\n", + "y = df.y\n", + "\n", + "skf = StratifiedKFold(n_splits=10)\n", + "\n", + "results = []\n", + "for train_index, test_index in skf.split(X, y):\n", + " X_train, y_train = X.iloc[train_index], y[train_index]\n", + " X_test, y_test = X.iloc[test_index], y[test_index]\n", + " \n", + " y_test = label_binarize(y_test, classes=[0.0, 1.0, 2.0, 3.0])\n", + " \n", + " clf = LogisticRegression(random_state=37, max_iter=1000).fit(X_train, y_train)\n", + " y_prob = clf.predict_proba(X_test)\n", + " \n", + " roc_macro = roc_auc_score(y_test, y_prob, average='macro')\n", + " roc_micro = roc_auc_score(y_test, y_prob, average='micro')\n", + " roc_weighted = roc_auc_score(y_test, y_prob, average='weighted')\n", + " results.append({\n", + " 'macro': roc_macro,\n", + " 'micro': roc_micro,\n", + " 'weighted': roc_weighted\n", + " })\n", + " \n", + "results = pd.DataFrame(results)\n", + "results" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "macro 0.965000\n", + "micro 0.959259\n", + "weighted 0.960000\n", + "dtype: float64" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "results.mean()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Learn model on full data" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.linear_model import LogisticRegression\n", + "\n", + "X = df[[c for c in df.columns if c != 'y']]\n", + "y = df.y\n", + "\n", + "clf = LogisticRegression(random_state=37, max_iter=1000).fit(X, y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Test the model on a sample." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 : 0.99983\n", + "1 : 0.29206\n", + "2 : 0.00103\n", + "3 : 0.28947\n" + ] + } + ], + "source": [ + "for i in range(4):\n", + " e = np.exp(clf.intercept_[i] + X.iloc[0].dot(clf.coef_[i]))\n", + " p = e / (1 + e)\n", + " print(f'{i} : {p:.5f}')" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "models = {}\n", + "\n", + "for clazz, i, c in zip(['rock', 'paper', 'scissor', 'shoot'], clf.intercept_, clf.coef_):\n", + " models[clazz] = {\n", + " 'intercept': float(i),\n", + " 'coefs': [float(w) for w in c]\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "\n", + "with open('models.json', 'w') as f:\n", + " json.dump(models, f, indent=1)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/html/rps++/data-capture/python/models.json b/html/rps++/data-capture/python/models.json new file mode 100644 index 0000000..1629b50 --- /dev/null +++ b/html/rps++/data-capture/python/models.json @@ -0,0 +1,274 @@ +{ + "rock": { + "intercept": 0.00016663445532947161, + "coefs": [ + 0.004493594066278487, + -0.0181734867175551, + 0.005816454286539876, + 0.007395881203186832, + -0.021052713127063166, + -0.01500798715307004, + 0.004911851710132168, + 0.01592353320779108, + -0.020577159228584666, + -0.0011558048197663723, + 0.0412232920550652, + -0.010656181936082443, + -0.003855122627525821, + -0.014773240760272222, + 0.007374035871422153, + 0.0024225614798120804, + -0.009702062079755555, + -0.014249427590112267, + -0.0003057471332293967, + 0.039026941393299465, + -0.01541200884855696, + -0.012065863356455556, + 0.06281924690685216, + -0.0014091253058344682, + -0.01037020844725474, + -0.013303465539355274, + 0.006422522757763716, + 9.113270214539499e-05, + -0.016522594930717473, + -0.0076775055261058805, + 0.005339043404761528, + 0.00037986560511112685, + -0.004796379758956194, + -0.0013055819655805173, + 0.00036789860342919357, + 0.0060919296953114216, + -0.016697270688938552, + -0.012629480479088316, + 0.005103006990909591, + -0.0057108164913697215, + -0.01781500837990077, + -0.002764011794977438, + 0.000993638686474716, + -0.006822513530989345, + 0.002355145862881284, + -0.004494793169187664, + -0.004395227676391269, + 0.013420881218017792, + 0.01696347056031915, + 0.005574588046618272, + -0.006677588763661525, + 0.019614195257619278, + -0.009642013148219714, + -0.008204249974550038, + 0.006696780136807361, + -0.02058544268438159, + -0.009153931317764789, + -0.016746868102120522, + -0.01361350016233158, + -0.009211409400370168, + 0.008726930655722803, + 0.01289767965992764, + -1.900009082527232e-06 + ] + }, + "paper": { + "intercept": 5.835654613844104e-05, + "coefs": [ + -0.009139454197085665, + 0.008565854879610004, + -0.009220224313312328, + -0.0061087763642032845, + 0.020272390829743737, + -0.003113458455537707, + -0.0010165469320500434, + 0.0153752347350819, + -0.005444796133333202, + 0.004895262228446878, + 0.0150373670809992, + -0.011385191741365612, + 0.002277442850461132, + 0.013999083467625375, + -0.008377951690502696, + 0.0002909320432572904, + 0.021338669154711803, + 0.0075584635430500785, + -0.0028628258163235086, + 0.019912440133490538, + 0.0092146553243537, + -0.004982543788312038, + 0.02047433676724552, + 0.009105113657712478, + 0.01612396792331375, + 0.017502672063936586, + -0.008879149875499452, + 0.0034397324261617, + 0.02993888816065672, + 0.01002364254607002, + -0.0192768672707338, + -0.028357666778241034, + 0.00908904965885131, + -0.03745124838371773, + -0.08011167692339737, + 0.004034240150638302, + 0.0357015518471651, + 0.01882968995998238, + -0.012186470212627228, + 0.007317792487834422, + 0.024292966056803138, + 0.002029382963444806, + -0.029642505831290692, + -0.01992560501590033, + 0.00026012646555537405, + -0.06269194140352884, + -0.0697427236285067, + -0.002148014770746275, + 0.004291594768267101, + -0.019145512232655405, + -0.007843496625722585, + -0.0023416961603515613, + -0.007879927891031702, + -0.012084825739039223, + 0.021840304252015195, + 0.009127455787217301, + -0.016890576048913638, + 0.06518071828045109, + 0.020193290271455274, + -0.02236403004439325, + 0.018623261216544076, + -0.023804949855688966, + 6.967241066564688e-07 + ] + }, + "scissor": { + "intercept": 0.0004732872275962553, + "coefs": [ + -0.0022927351464847407, + -0.008291005042016403, + 0.013063651569532497, + 0.008306041163775686, + -0.0168495062459517, + 0.015355057324314591, + 0.016632688833974545, + -0.02721764285188774, + 0.019764708150699563, + 0.025465050630419154, + -0.03201631053989809, + 0.025126840770415684, + -0.002140330433519718, + -0.015510554983485615, + 0.00592426548203055, + -0.007788995147753785, + -0.03278973394550188, + 0.014790324595070884, + -0.006494150432250139, + -0.0390125559824367, + 0.023216987984591, + -0.009516242488853837, + -0.042355379867691056, + 0.030910460382777526, + -0.0002314933915167194, + -0.013151950865890716, + -0.0019424587176279974, + 0.020818211668454926, + -0.0037853385338370085, + -0.00845190221605843, + 0.016618268048852573, + 0.019939316896806752, + -0.0014599576811318647, + -0.0015251292134849778, + 0.03635174397354812, + 0.0065296516414917365, + 0.014765491710761568, + -0.011932269808963412, + -0.007788393562453929, + 0.041753228684391124, + 0.007682776739393862, + -0.01463858388201525, + 0.044816020016839854, + 0.029092915818816435, + -0.008374711352544906, + 0.03583325046722424, + 0.050148594157042044, + -0.0019546879721942245, + -0.016808812679485002, + 0.010747326111204476, + 0.006990860564231347, + -0.024584566230194588, + 0.017862421854510074, + 0.0024082511288380476, + -0.05018490922331198, + 0.02574793067828618, + -0.004993774913726719, + -0.0947939127729616, + 0.02119667381109406, + -0.007245178629343176, + -0.013542072920946235, + 0.020731893133612605, + -1.8836892663767876e-07 + ] + }, + "shoot": { + "intercept": -0.0006982782290691921, + "coefs": [ + 0.006938595276950665, + 0.01789863687963746, + -0.009659881542736722, + -0.009593146003105917, + 0.01762982854302785, + 0.002766388284322471, + -0.020527993612413968, + -0.00408112509116473, + 0.006257247211252607, + -0.02920450803946343, + -0.02424434859629662, + -0.0030854670929253607, + 0.003718010210293204, + 0.0162847122758126, + -0.004920349662920951, + 0.005075501624398148, + 0.021153126870311477, + -0.008099360547971076, + 0.009662723381514434, + -0.019926825544509613, + -0.017019634460342235, + 0.026564649633328347, + -0.04093820380650239, + -0.03860644873460304, + -0.005522266084787265, + 0.008952744340975578, + 0.004399085835395952, + -0.024349076796996005, + -0.009630954696388897, + 0.006105765196142563, + -0.0026804441831190435, + 0.008038484276033462, + -0.002832712218712842, + 0.040281959562536676, + 0.04339203434612915, + -0.016655821487390313, + -0.03376977286919372, + 0.005732060327706987, + 0.01487185678420943, + -0.04336020468104305, + -0.014160734416633292, + 0.015373212713596218, + -0.01616715287221629, + -0.002344797272268752, + 0.005759439024160596, + 0.03135348410528389, + 0.02398935714751267, + -0.009318178475024568, + -0.004446252649437305, + 0.002823598074363506, + 0.007530224825156777, + 0.007312067132532629, + -0.00034048081567744545, + 0.017880824584760594, + 0.02164782483405883, + -0.0142899437814946, + 0.031038282280424583, + 0.04636006259415263, + -0.02777646392056524, + 0.03882061807413296, + -0.013808118951585874, + -0.009824622938341668, + 1.3916539025098639e-06 + ] + } +} \ No newline at end of file diff --git a/html/rps++/index.html b/html/rps++/index.html new file mode 100644 index 0000000..7b394b6 --- /dev/null +++ b/html/rps++/index.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + Rock, Paper, Scissor++ + + + + +
+
+

Rock Paper Scissor++

+

+ Use your right hand to play Rock Paper Scissor (RPS)! +

+
+

+ Using artificial intelligence (deep learning) to recognize your hand pose to play RPS +

+

+ + Source Code + +

+
+
+
+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+ + + + +
+
+
Your Score
+

+ 0 +
+ +

+
ready ...
+
+
+
+
+
+
+ + + +
+
+
CPU Score
+

+ 0 +
+ +

+
ready ...
+
+
+
+
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/html/rps++/index.js b/html/rps++/index.js new file mode 100644 index 0000000..e8de2a7 --- /dev/null +++ b/html/rps++/index.js @@ -0,0 +1,601 @@ +let videoWidth, videoHeight, + scatterGLHasInitialized = false, scatterGL, fingerLookupIndices = { + thumb: [0, 1, 2, 3, 4], + indexFinger: [0, 5, 6, 7, 8], + middleFinger: [0, 9, 10, 11, 12], + ringFinger: [0, 13, 14, 15, 16], + pinky: [0, 17, 18, 19, 20] + }; +let model; +const models = getModels(); +const VIDEO_WIDTH = document.getElementById('output').clientWidth; +const VIDEO_HEIGHT = document.getElementById('output').clientHeight; +const mobile = false; +const predictionThreshold = 0.999; +const shootThreshold = 5; +let youScore = 0; +let comScore = 0; +let youSymbol = undefined; +let comSymbol = undefined; +let shootCount = 0; +let loaded = false; +let timer = undefined; +let pBarWidth = 0; + +function drawKeypoints(ctx, keypoints) { + function drawPoint(ctx, y, x, r) { + ctx.beginPath(); + ctx.arc(x, y, r, 0, 2 * Math.PI); + ctx.fill(); + } + + function drawPath(ctx, points, closePath) { + const region = new Path2D(); + region.moveTo(points[0][0], points[0][1]); + for (let i = 1; i < points.length; i++) { + const point = points[i]; + region.lineTo(point[0], point[1]); + } + + if (closePath) { + region.closePath(); + } + ctx.stroke(region); + } + + const keypointsArray = keypoints; + + for (let i = 0; i < keypointsArray.length; i++) { + const y = keypointsArray[i][0]; + const x = keypointsArray[i][1]; + drawPoint(ctx, x - 2, y - 2, 3); + } + + const fingers = Object.keys(fingerLookupIndices); + for (let i = 0; i < fingers.length; i++) { + const finger = fingers[i]; + const points = fingerLookupIndices[finger].map(idx => keypoints[idx]); + drawPath(ctx, points, false); + } +} + +async function setupCamera() { + if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { + throw new Error( + 'Browser API navigator.mediaDevices.getUserMedia not available'); + } + + const video = document.getElementById('video'); + video.onloadeddata = (event) => { + loaded = true; + document.getElementById('gameInfo').classList.remove('d-none'); + }; + const stream = await navigator.mediaDevices.getUserMedia({ + 'audio': false, + 'video': { + facingMode: 'user', + width: mobile ? undefined : VIDEO_WIDTH, + height: mobile ? undefined : VIDEO_HEIGHT + }, + }); + video.srcObject = stream; + + return new Promise((resolve) => { + video.onloadedmetadata = () => { + resolve(video); + }; + }); +} + +async function loadVideo() { + const video = await setupCamera(); + video.play(); + return video; +} + +const main = + async () => { + model = await handpose.load(); + let video; + + try { + video = await loadVideo(); + } catch (e) { + loaded = true; + let info = document.getElementById('info'); + info.textContent = e.message; + info.style.display = 'block'; + throw e; + } + + landmarksRealTime(video); + } + +const landmarksRealTime = async (video) => { + videoWidth = video.videoWidth; + videoHeight = video.videoHeight; + + const canvas = document.getElementById('output'); + + canvas.width = videoWidth; + canvas.height = videoHeight; + + const ctx = canvas.getContext('2d'); + + ctx.clearRect(0, 0, videoWidth, videoHeight); + ctx.strokeStyle = '#dc3545'; + ctx.fillStyle = '#dc3545'; + + ctx.translate(canvas.width, 0); + ctx.scale(-1, 1); + + // These anchor points allow the hand pointcloud to resize according to its + // position in the input. + const ANCHOR_POINTS = [ + [0, 0, 0], [0, -VIDEO_HEIGHT, 0], [-VIDEO_WIDTH, 0, 0], + [-VIDEO_WIDTH, -VIDEO_HEIGHT, 0] + ]; + + async function frameLandmarks() { + ctx.drawImage( + video, 0, 0, videoWidth, videoHeight, 0, 0, canvas.width, + canvas.height); + const predictions = await model.estimateHands(video); + if (predictions.length > 0) { + const result = predictions[0].landmarks; + const annots = predictions[0].annotations; + const d = captureData(annots); + const r = predict(d); + if (r.prob >= predictionThreshold) { + if (r.symbol === 'shoot') { + shootCount++; + } + + if (r.symbol === 'shoot' && shootCount >= shootThreshold && youSymbol) { + comSymbol = getComputerSymbol(); + const winner = getWinner(youSymbol, comSymbol); + if (winner === 'user') { + youScore += 1; + } else if (winner === 'computer') { + comScore += 1; + } + + console.log(`${youSymbol} vs ${comSymbol}, winner = ${winner}, u = ${youScore}, c = ${comScore}`); + + updateLastSymbols(); + youSymbol = undefined; + comSymbol = undefined; + shootCount = 0; + } else if (r.symbol === 'rock' || r.symbol === 'paper' || r.symbol === 'scissor') { + youSymbol = r.symbol; + } + + updateScores(); + updateSymbols(); + } + + drawKeypoints(ctx, result, annots); + } + requestAnimationFrame(frameLandmarks); + }; + + frameLandmarks(); +}; + +function predict(x) { + function predictProb(model) { + let e = model.intercept; + for (let i = 0; i < x.length; i++) { + e += x[i] * model.coefs[i]; + } + e = Math.exp(e); + const p = e / (1.0 + e); + return p; + } + + const symbols = ['rock', 'paper', 'scissor', 'shoot']; + let p = undefined; + let c = undefined; + for (let i = 0; i < symbols.length; i++) { + const symbol = symbols[i]; + const prob = predictProb(models[symbol]); + if (!p || prob > p) { + p = prob; + c = symbol; + } + } + + return { prob: p, symbol: c }; +} + +function captureData(annots) { + function getPoints(k, data) { + for (let i = 0; i < annots[k].length; i++) { + const arr = annots[k][i]; + for (let j = 0; j < arr.length; j++) { + const val = arr[j]; + data.push(val); + } + } + } + + const data = []; + ['indexFinger', 'middleFinger', 'ringFinger', 'pinky', 'thumb', 'palmBase'].forEach(k => { + getPoints(k, data); + }); + return data; +} + +function getModels() { + return { + "rock": { + "intercept": 0.00016663445532947161, + "coefs": [ + 0.004493594066278487, + -0.0181734867175551, + 0.005816454286539876, + 0.007395881203186832, + -0.021052713127063166, + -0.01500798715307004, + 0.004911851710132168, + 0.01592353320779108, + -0.020577159228584666, + -0.0011558048197663723, + 0.0412232920550652, + -0.010656181936082443, + -0.003855122627525821, + -0.014773240760272222, + 0.007374035871422153, + 0.0024225614798120804, + -0.009702062079755555, + -0.014249427590112267, + -0.0003057471332293967, + 0.039026941393299465, + -0.01541200884855696, + -0.012065863356455556, + 0.06281924690685216, + -0.0014091253058344682, + -0.01037020844725474, + -0.013303465539355274, + 0.006422522757763716, + 9.113270214539499e-05, + -0.016522594930717473, + -0.0076775055261058805, + 0.005339043404761528, + 0.00037986560511112685, + -0.004796379758956194, + -0.0013055819655805173, + 0.00036789860342919357, + 0.0060919296953114216, + -0.016697270688938552, + -0.012629480479088316, + 0.005103006990909591, + -0.0057108164913697215, + -0.01781500837990077, + -0.002764011794977438, + 0.000993638686474716, + -0.006822513530989345, + 0.002355145862881284, + -0.004494793169187664, + -0.004395227676391269, + 0.013420881218017792, + 0.01696347056031915, + 0.005574588046618272, + -0.006677588763661525, + 0.019614195257619278, + -0.009642013148219714, + -0.008204249974550038, + 0.006696780136807361, + -0.02058544268438159, + -0.009153931317764789, + -0.016746868102120522, + -0.01361350016233158, + -0.009211409400370168, + 0.008726930655722803, + 0.01289767965992764, + -1.900009082527232e-06 + ] + }, + "paper": { + "intercept": 5.835654613844104e-05, + "coefs": [ + -0.009139454197085665, + 0.008565854879610004, + -0.009220224313312328, + -0.0061087763642032845, + 0.020272390829743737, + -0.003113458455537707, + -0.0010165469320500434, + 0.0153752347350819, + -0.005444796133333202, + 0.004895262228446878, + 0.0150373670809992, + -0.011385191741365612, + 0.002277442850461132, + 0.013999083467625375, + -0.008377951690502696, + 0.0002909320432572904, + 0.021338669154711803, + 0.0075584635430500785, + -0.0028628258163235086, + 0.019912440133490538, + 0.0092146553243537, + -0.004982543788312038, + 0.02047433676724552, + 0.009105113657712478, + 0.01612396792331375, + 0.017502672063936586, + -0.008879149875499452, + 0.0034397324261617, + 0.02993888816065672, + 0.01002364254607002, + -0.0192768672707338, + -0.028357666778241034, + 0.00908904965885131, + -0.03745124838371773, + -0.08011167692339737, + 0.004034240150638302, + 0.0357015518471651, + 0.01882968995998238, + -0.012186470212627228, + 0.007317792487834422, + 0.024292966056803138, + 0.002029382963444806, + -0.029642505831290692, + -0.01992560501590033, + 0.00026012646555537405, + -0.06269194140352884, + -0.0697427236285067, + -0.002148014770746275, + 0.004291594768267101, + -0.019145512232655405, + -0.007843496625722585, + -0.0023416961603515613, + -0.007879927891031702, + -0.012084825739039223, + 0.021840304252015195, + 0.009127455787217301, + -0.016890576048913638, + 0.06518071828045109, + 0.020193290271455274, + -0.02236403004439325, + 0.018623261216544076, + -0.023804949855688966, + 6.967241066564688e-07 + ] + }, + "scissor": { + "intercept": 0.0004732872275962553, + "coefs": [ + -0.0022927351464847407, + -0.008291005042016403, + 0.013063651569532497, + 0.008306041163775686, + -0.0168495062459517, + 0.015355057324314591, + 0.016632688833974545, + -0.02721764285188774, + 0.019764708150699563, + 0.025465050630419154, + -0.03201631053989809, + 0.025126840770415684, + -0.002140330433519718, + -0.015510554983485615, + 0.00592426548203055, + -0.007788995147753785, + -0.03278973394550188, + 0.014790324595070884, + -0.006494150432250139, + -0.0390125559824367, + 0.023216987984591, + -0.009516242488853837, + -0.042355379867691056, + 0.030910460382777526, + -0.0002314933915167194, + -0.013151950865890716, + -0.0019424587176279974, + 0.020818211668454926, + -0.0037853385338370085, + -0.00845190221605843, + 0.016618268048852573, + 0.019939316896806752, + -0.0014599576811318647, + -0.0015251292134849778, + 0.03635174397354812, + 0.0065296516414917365, + 0.014765491710761568, + -0.011932269808963412, + -0.007788393562453929, + 0.041753228684391124, + 0.007682776739393862, + -0.01463858388201525, + 0.044816020016839854, + 0.029092915818816435, + -0.008374711352544906, + 0.03583325046722424, + 0.050148594157042044, + -0.0019546879721942245, + -0.016808812679485002, + 0.010747326111204476, + 0.006990860564231347, + -0.024584566230194588, + 0.017862421854510074, + 0.0024082511288380476, + -0.05018490922331198, + 0.02574793067828618, + -0.004993774913726719, + -0.0947939127729616, + 0.02119667381109406, + -0.007245178629343176, + -0.013542072920946235, + 0.020731893133612605, + -1.8836892663767876e-07 + ] + }, + "shoot": { + "intercept": -0.0006982782290691921, + "coefs": [ + 0.006938595276950665, + 0.01789863687963746, + -0.009659881542736722, + -0.009593146003105917, + 0.01762982854302785, + 0.002766388284322471, + -0.020527993612413968, + -0.00408112509116473, + 0.006257247211252607, + -0.02920450803946343, + -0.02424434859629662, + -0.0030854670929253607, + 0.003718010210293204, + 0.0162847122758126, + -0.004920349662920951, + 0.005075501624398148, + 0.021153126870311477, + -0.008099360547971076, + 0.009662723381514434, + -0.019926825544509613, + -0.017019634460342235, + 0.026564649633328347, + -0.04093820380650239, + -0.03860644873460304, + -0.005522266084787265, + 0.008952744340975578, + 0.004399085835395952, + -0.024349076796996005, + -0.009630954696388897, + 0.006105765196142563, + -0.0026804441831190435, + 0.008038484276033462, + -0.002832712218712842, + 0.040281959562536676, + 0.04339203434612915, + -0.016655821487390313, + -0.03376977286919372, + 0.005732060327706987, + 0.01487185678420943, + -0.04336020468104305, + -0.014160734416633292, + 0.015373212713596218, + -0.01616715287221629, + -0.002344797272268752, + 0.005759439024160596, + 0.03135348410528389, + 0.02398935714751267, + -0.009318178475024568, + -0.004446252649437305, + 0.002823598074363506, + 0.007530224825156777, + 0.007312067132532629, + -0.00034048081567744545, + 0.017880824584760594, + 0.02164782483405883, + -0.0142899437814946, + 0.031038282280424583, + 0.04636006259415263, + -0.02777646392056524, + 0.03882061807413296, + -0.013808118951585874, + -0.009824622938341668, + 1.3916539025098639e-06 + ] + } + }; +} + +function getComputerSymbol() { + return _.sample(['rock', 'paper', 'scissor']); +} + +function getWinner(u, c) { + if (u === 'rock' && c === 'paper') { + return 'computer'; + } else if (u === 'rock' && c === 'scissor') { + return 'user'; + } else if (u === 'rock' && c === 'rock') { + return 'tie'; + } else if (u === 'paper' && c === 'paper') { + return 'tie'; + } else if (u === 'paper' && c === 'scissor') { + return 'computer'; + } else if (u === 'paper' && c === 'rock') { + return 'user'; + } else if (u === 'scissor' && c === 'paper') { + return 'user'; + } else if (u === 'scissor' && c === 'scissor') { + return 'tie'; + } else { + return 'computer'; + } +} + +function updateScores() { + const you = document.getElementById('youScore'); + const com = document.getElementById('computerScore'); + + you.innerHTML = `${youScore}`; + com.innerHTML = `${comScore}`; +} + +function updateSymbols() { + const you = document.getElementById('youSymbol'); + const com = document.getElementById('computerSymbol'); + + if (youSymbol) { + you.innerHTML = youSymbol; + } else { + you.innerHTML = 'ready ...'; + } + + if (comSymbol) { + com.innerHTML = comSymbol; + } else { + com.innerHTML = 'waiting ...'; + } +} + +function updateLastSymbols() { + const you = document.getElementById('youLastSymbol'); + const com = document.getElementById('computerLastSymbol'); + + if (youSymbol) { + you.innerHTML = `You choose: ${youSymbol}`; + } else { + you.innerHTML = ''; + } + + if (comSymbol) { + com.innerHTML = `CPU choose: ${comSymbol}`; + } else { + com.innerHTML = ''; + } +} + +function startProgressBar() { + function doCheck() { + const pbar = document.getElementById('pBar'); + const app = document.getElementById('app'); + + if (loaded) { + clearInterval(timer); + pbar.style = `width: 100%`; + pbar.classList.remove('bg-info'); + pbar.classList.add('bg-danger'); + app.classList.remove('position-offscreen'); + } else { + pBarWidth += 10; + if (pBarWidth > 100) { + pBarWidth = 0; + } + pbar.style = `width: ${pBarWidth}%`; + } + } + timer = setInterval(doCheck, 100); +} + +startProgressBar(); + +navigator.getUserMedia = navigator.getUserMedia || + navigator.webkitGetUserMedia || navigator.mozGetUserMedia; + +tf.setBackend('webgl').then(() => main()); \ No newline at end of file diff --git a/html/rps-game/index.html b/html/rps-game/index.html index da8913e..cf265a0 100644 --- a/html/rps-game/index.html +++ b/html/rps-game/index.html @@ -1,243 +1,295 @@ - - - Rock, Paper, Scissor! - - - + + + + - - -

Rock, Paper, Scissor SHOOT!

- - - - - - - - - - - - - - - -
- Player Score: - - Computer Score: -
-
- -
-
-
- -
-
- - - - - -
-
- - - - - + } + + // gets what the computer selected + function getComputerOption() { + const options = ['rock', 'paper', 'scissor']; + const option = options[Math.floor(Math.random() * options.length)]; + return option; + } + + + \ No newline at end of file diff --git a/html/sign-language/images/a.png b/html/sign-language/images/a.png new file mode 100644 index 0000000..019a19f Binary files /dev/null and b/html/sign-language/images/a.png differ diff --git a/html/sign-language/images/b.png b/html/sign-language/images/b.png new file mode 100644 index 0000000..ecc5db5 Binary files /dev/null and b/html/sign-language/images/b.png differ diff --git a/html/sign-language/images/c.png b/html/sign-language/images/c.png new file mode 100644 index 0000000..8e3ed1d Binary files /dev/null and b/html/sign-language/images/c.png differ diff --git a/html/sign-language/images/d.png b/html/sign-language/images/d.png new file mode 100644 index 0000000..f0bb13a Binary files /dev/null and b/html/sign-language/images/d.png differ diff --git a/html/sign-language/images/e.png b/html/sign-language/images/e.png new file mode 100644 index 0000000..e72830a Binary files /dev/null and b/html/sign-language/images/e.png differ diff --git a/html/sign-language/images/f.png b/html/sign-language/images/f.png new file mode 100644 index 0000000..47fc27b Binary files /dev/null and b/html/sign-language/images/f.png differ diff --git a/html/sign-language/images/g.png b/html/sign-language/images/g.png new file mode 100644 index 0000000..fb482a0 Binary files /dev/null and b/html/sign-language/images/g.png differ diff --git a/html/sign-language/images/h.png b/html/sign-language/images/h.png new file mode 100644 index 0000000..c6a9348 Binary files /dev/null and b/html/sign-language/images/h.png differ diff --git a/html/sign-language/images/i.png b/html/sign-language/images/i.png new file mode 100644 index 0000000..0b03f3f Binary files /dev/null and b/html/sign-language/images/i.png differ diff --git a/html/sign-language/images/j.png b/html/sign-language/images/j.png new file mode 100644 index 0000000..fd76864 Binary files /dev/null and b/html/sign-language/images/j.png differ diff --git a/html/sign-language/images/k.png b/html/sign-language/images/k.png new file mode 100644 index 0000000..fc2d5c0 Binary files /dev/null and b/html/sign-language/images/k.png differ diff --git a/html/sign-language/images/l.png b/html/sign-language/images/l.png new file mode 100644 index 0000000..4827582 Binary files /dev/null and b/html/sign-language/images/l.png differ diff --git a/html/sign-language/images/m.png b/html/sign-language/images/m.png new file mode 100644 index 0000000..60a5ffb Binary files /dev/null and b/html/sign-language/images/m.png differ diff --git a/html/sign-language/images/n.png b/html/sign-language/images/n.png new file mode 100644 index 0000000..d04d0d5 Binary files /dev/null and b/html/sign-language/images/n.png differ diff --git a/html/sign-language/images/o.png b/html/sign-language/images/o.png new file mode 100644 index 0000000..15e24c6 Binary files /dev/null and b/html/sign-language/images/o.png differ diff --git a/html/sign-language/images/p.png b/html/sign-language/images/p.png new file mode 100644 index 0000000..2b00f70 Binary files /dev/null and b/html/sign-language/images/p.png differ diff --git a/html/sign-language/images/q.png b/html/sign-language/images/q.png new file mode 100644 index 0000000..9e79126 Binary files /dev/null and b/html/sign-language/images/q.png differ diff --git a/html/sign-language/images/r.png b/html/sign-language/images/r.png new file mode 100644 index 0000000..f92afe3 Binary files /dev/null and b/html/sign-language/images/r.png differ diff --git a/html/sign-language/images/s.png b/html/sign-language/images/s.png new file mode 100644 index 0000000..e3a5767 Binary files /dev/null and b/html/sign-language/images/s.png differ diff --git a/html/sign-language/images/t.png b/html/sign-language/images/t.png new file mode 100644 index 0000000..cb09511 Binary files /dev/null and b/html/sign-language/images/t.png differ diff --git a/html/sign-language/images/u.png b/html/sign-language/images/u.png new file mode 100644 index 0000000..004d7f1 Binary files /dev/null and b/html/sign-language/images/u.png differ diff --git a/html/sign-language/images/v.png b/html/sign-language/images/v.png new file mode 100644 index 0000000..779bb18 Binary files /dev/null and b/html/sign-language/images/v.png differ diff --git a/html/sign-language/images/w.png b/html/sign-language/images/w.png new file mode 100644 index 0000000..0dc5d34 Binary files /dev/null and b/html/sign-language/images/w.png differ diff --git a/html/sign-language/images/x.png b/html/sign-language/images/x.png new file mode 100644 index 0000000..7016788 Binary files /dev/null and b/html/sign-language/images/x.png differ diff --git a/html/sign-language/images/y.png b/html/sign-language/images/y.png new file mode 100644 index 0000000..1619197 Binary files /dev/null and b/html/sign-language/images/y.png differ diff --git a/html/sign-language/images/z.png b/html/sign-language/images/z.png new file mode 100644 index 0000000..da896d6 Binary files /dev/null and b/html/sign-language/images/z.png differ diff --git a/html/sign-language/index.html b/html/sign-language/index.html new file mode 100644 index 0000000..90c7813 --- /dev/null +++ b/html/sign-language/index.html @@ -0,0 +1,418 @@ + + + + + + + + + Sign Language + + + + + +
+
+

American Manual Alphabet

+

+ Wikipedia +

+

+ + Source Code + +

+
+ +
+
+
+
+
+
+ +
+
+
+
+ Which letter is represented by the picture? +
+
+
+ + +
+ +
+ +
+ +
+ +
+
+
+ + + + + + + + + + + + \ No newline at end of file diff --git a/html/slot-machine-game/index.html b/html/slot-machine-game/index.html index a959c48..910047e 100644 --- a/html/slot-machine-game/index.html +++ b/html/slot-machine-game/index.html @@ -1,106 +1,149 @@ - - Slot Machine! - - - - - -

Play Slot!

-
- -
- - - - - - - - -
- - - - - - - - -
-
- You Won! + .message { + text-align: center; + display: none; + font-size: xx-large; + color: red; + } + + .center { + text-align: center; + } + + .lever { + margin-top: 5px; + } + + table.center { + margin-left: auto; + margin-right: auto; + } + + + + +
+
+

Play Slot!

+

+ Slot machine simulator +

+

+ + Source Code + +

+
+

+ Hit lever button to start +

- - +
+
+ +
+ + + + + + + + +
+ - + + - + + - +
+
+ You Won! +
+ + + + + + + + + \ No newline at end of file diff --git a/html/solar-system/index.html b/html/solar-system/index.html new file mode 100644 index 0000000..df056c2 --- /dev/null +++ b/html/solar-system/index.html @@ -0,0 +1,293 @@ + + + + + + + + + Solar System + + + + + +
+

Solar System

+
+
+ + + + Sun + + + + + Mercury + + + + Venus + + + + earth + + + + Mars + + + + Jupiter + + + + Saturn + + + + Uranus + + + + Neptune + + + + Pluto + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/html/tic-tac-toe/index.html b/html/tic-tac-toe/index.html index 447e3c7..8553576 100644 --- a/html/tic-tac-toe/index.html +++ b/html/tic-tac-toe/index.html @@ -1,228 +1,265 @@ - - Tic-Tac-Toe - - - -
-

Tic-Tac-Toe!

-
-
- -
- - - - - - - - - - - - - - - - - - -
   
   
   
-
+ + + + + + + Tic-Tac-Toe + + + + + +
+
+

Tic-Tac-Toe!

+

+ Classic Tic-Tac-Toe game; play against the computer +

+

+ + Source Code + +

+
+

+ Hit restart at any time to start over +

+
+
+ + + + + + + + + + + + + + + + + + +
   
   
   
+
+ + + + + - + return true; + } + + + \ No newline at end of file diff --git a/java/greenfoot/README.md b/java/greenfoot/README.md index 499dde8..562f5ef 100644 --- a/java/greenfoot/README.md +++ b/java/greenfoot/README.md @@ -1,3 +1,5 @@ +![One-Off Coder Logo](../logo.png "One-Off Coder") + # Projects * [bump-babies](bump-babies): fish eating baby snacks diff --git a/python/pygame/.gitignore b/python/pygame/.gitignore index 62c8935..ee40bb3 100644 --- a/python/pygame/.gitignore +++ b/python/pygame/.gitignore @@ -1 +1,2 @@ -.idea/ \ No newline at end of file +.idea/ +*.pyc \ No newline at end of file diff --git a/python/pygame/README.md b/python/pygame/README.md index b984c56..e4de47e 100644 --- a/python/pygame/README.md +++ b/python/pygame/README.md @@ -1,8 +1,17 @@ +![One-Off Coder Logo](../logo.png "One-Off Coder") + # Pygame Tutorials in [Pygame](https://www.pygame.org). The API documentation is [available](https://www.pygame.org/docs/). -All sound effects taken from [zapsplat](https://www.zapsplat.com/). -All images take from [craftpix](https://craftpix.net/). + +Images + +* [Open Game Art](https://opengameart.org/) +* [craftpix](https://craftpix.net/) + +Audio + +* [zapsplat](https://www.zapsplat.com/) # Basic @@ -13,4 +22,12 @@ All images take from [craftpix](https://craftpix.net/). * [Bouncing Images](basic/bouncing-image.py): learn how to animate images * [Image Rotation](basic/image-rotation.py): learn how to rotate an image * [Sound](basic/bouncing-image-with-sound.py): learn how to play sound -* [Key Events](basic/key-movement.py): learn how to listen for key events \ No newline at end of file +* [Key Events](basic/key-movement.py): learn how to listen for key events +* [Mouse Movement](basic/mouse-movement.py): learn how to move a sprite with the mouse +* [Collision](basic/collection-detection.py): learn how to detect collision +* [Sprite Animation](basic/char-animation.py): learn how to animate a sprite + +# Games + +* [Space Battle](space-battle): learn how to create a space battle program +* [Yappy Bird](yappy-bird): a Flappy-Bird clone \ No newline at end of file diff --git a/python/pygame/basic/bouncing-balls.py b/python/pygame/basic/bouncing-balls.py index 94333ff..ddc479e 100644 --- a/python/pygame/basic/bouncing-balls.py +++ b/python/pygame/basic/bouncing-balls.py @@ -1,3 +1,4 @@ +import os import random import sys @@ -70,10 +71,12 @@ def rand(width, height): def start(): pygame.init() + FPS = 30 width = 400 height = 400 DISPLAYSURF = pygame.display.set_mode((width, height)) pygame.display.set_caption('Bouncing Balls') + fps_clock = pygame.time.Clock() balls = [Ball.rand(width, height) for _ in range(10)] @@ -90,7 +93,9 @@ def start(): ball.update(width, height) pygame.display.update() + fps_clock.tick(FPS) if __name__ == '__main__': + os.environ['SDL_VIDEO_CENTERED'] = '1' start() diff --git a/python/pygame/basic/bouncing-image-with-sound.py b/python/pygame/basic/bouncing-image-with-sound.py index 6d593cf..5c1c8da 100644 --- a/python/pygame/basic/bouncing-image-with-sound.py +++ b/python/pygame/basic/bouncing-image-with-sound.py @@ -1,3 +1,4 @@ +import os import random import sys @@ -83,10 +84,12 @@ def rand(fpath, apath, width, height, scale=0.25): def start(): pygame.init() + FPS = 30 width = 400 height = 400 DISPLAYSURF = pygame.display.set_mode((width, height)) pygame.display.set_caption('Bouncing Image with Sound') + fps_clock = pygame.time.Clock() images = [Image.rand('./images/logo.png', './audios/fairy.wav', width, height, scale=0.5) for _ in range(1)] @@ -106,7 +109,9 @@ def start(): image.play() pygame.display.update() + fps_clock.tick(FPS) if __name__ == '__main__': + os.environ['SDL_VIDEO_CENTERED'] = '1' start() diff --git a/python/pygame/basic/bouncing-images.py b/python/pygame/basic/bouncing-images.py index 91fe8e9..50ece58 100644 --- a/python/pygame/basic/bouncing-images.py +++ b/python/pygame/basic/bouncing-images.py @@ -1,3 +1,4 @@ +import os import random import sys @@ -64,10 +65,12 @@ def rand(fpath, width, height, scale=0.25): def start(): pygame.init() + FPS = 30 width = 400 height = 400 DISPLAYSURF = pygame.display.set_mode((width, height)) pygame.display.set_caption('Bouncing Images') + fps_clock = pygame.time.Clock() images = [Image.rand('./images/ball.png', width, height) for _ in range(10)] @@ -84,7 +87,9 @@ def start(): image.update(width, height) pygame.display.update() + fps_clock.tick(FPS) if __name__ == '__main__': + os.environ['SDL_VIDEO_CENTERED'] = '1' start() diff --git a/python/pygame/basic/char-animation.py b/python/pygame/basic/char-animation.py new file mode 100644 index 0000000..cfcf217 --- /dev/null +++ b/python/pygame/basic/char-animation.py @@ -0,0 +1,60 @@ +import os +import sys + +import pygame +from pygame.locals import * + + +class Bird(pygame.sprite.Sprite): + def __init__(self, position, scale=0.5): + pygame.sprite.Sprite.__init__(self) + + paths = [f'./images/frame-{i + 1}.png' for i in range(8)] + imgs = [pygame.image.load(p) for p in paths] + rect = imgs[0].get_rect() + + w, h = rect.size[0], rect.size[1] + w, h = int(w * scale), int(h * scale) + + self.imgs = [pygame.transform.scale(img, (w, h)) for img in imgs] + self.rect = self.imgs[0].get_rect() + self.rect.center = position[0] - w / 2.0, position[1] - h / 2.0 + self.index = 0 + + def draw(self, surface): + surface.blit(self.imgs[self.index], self.rect.center) + self.index += 1 + if self.index >= len(self.imgs): + self.index = 0 + + +def start(): + pygame.init() + + FPS = 30 + width = 400 + height = 400 + DISPLAYSURF = pygame.display.set_mode((width, height)) + DISPLAYSURF.fill((255, 255, 255)) + pygame.display.set_caption('Key Events') + fps_clock = pygame.time.Clock() + + bird = Bird((200, 200), 0.10) + + while True: + for event in pygame.event.get(): + if event.type == QUIT: + pygame.quit() + sys.exit() + + DISPLAYSURF.fill((255, 255, 255, 0)) + + bird.draw(DISPLAYSURF) + + pygame.display.update() + fps_clock.tick(FPS) + + +if __name__ == '__main__': + os.environ['SDL_VIDEO_CENTERED'] = '1' + start() diff --git a/python/pygame/basic/collison-detection.py b/python/pygame/basic/collison-detection.py new file mode 100644 index 0000000..f6a7798 --- /dev/null +++ b/python/pygame/basic/collison-detection.py @@ -0,0 +1,105 @@ +import os +import random +import sys + +import pygame +from pygame.locals import * + + +class Satyr(pygame.sprite.Sprite): + def __init__(self, position, ipath, scale=0.5): + pygame.sprite.Sprite.__init__(self) + + img = pygame.image.load(ipath) + rect = img.get_rect(center=position) + w, h = rect.size[0], rect.size[1] + w, h = int(w * scale), int(h * scale) + img = pygame.transform.scale(img, (w, h)) + + rect = img.get_rect(center=position) + + self.image = img + self.rect = rect + self.rect.center = position + + def draw(self, surface, position): + self.rect.center = position + surface.blit(self.image, position) + + +class Image(pygame.sprite.Sprite): + def __init__(self, position, ipath, scale=1.0): + pygame.sprite.Sprite.__init__(self) + + img = pygame.image.load(ipath) + w, h = img.get_rect().size[0], img.get_rect().size[1] + w, h = int(w * scale), int(h * scale) + img = pygame.transform.scale(img, (w, h)) + + rect = img.get_rect(center=position) + + self.image = img + self.rect = rect + self.rect.center = position + self.dx = 1 if random.random() < 0.5 else -1 + self.dy = 1 if random.random() < 0.5 else 1 + + def draw(self, surface): + surface.blit(self.image, self.rect.center) + + def update(self, width, height): + x, y = self.rect.center + + if x + self.image.get_rect().size[0] >= width: + self.dx = -1 + elif x <= 0: + self.dx = 1 + + if y + self.image.get_rect().size[1] >= height: + self.dy = -1 + elif y <= 0: + self.dy = 1 + + x, y = x + 1 * self.dx, y + 1 * self.dy + self.rect.center = x, y + + +def start(): + pygame.init() + + FPS = 30 + width = 400 + height = 400 + DISPLAYSURF = pygame.display.set_mode((width, height)) + DISPLAYSURF.fill((255, 255, 255)) + pygame.display.set_caption('Key Events') + fps_clock = pygame.time.Clock() + + satyr = Satyr((200, 200), './images/Satyr_01_Idle_000.png', scale=0.25) + + ball = Image((random.randint(0, width), random.randint(0, height)), './images/ball.png', scale=0.25) + ball_group = pygame.sprite.Group() + ball_group.add(ball) + + while True: + for event in pygame.event.get(): + if event.type == QUIT: + pygame.quit() + sys.exit() + + DISPLAYSURF.fill((255, 255, 255, 0)) + + if pygame.sprite.spritecollide(satyr, ball_group, False): + print(f'collided {ball.rect.center}') + + satyr.draw(DISPLAYSURF, pygame.mouse.get_pos()) + ball.draw(DISPLAYSURF) + ball.update(width, height) + + pygame.display.update() + fps_clock.tick(FPS) + + +if __name__ == '__main__': + os.environ['SDL_VIDEO_CENTERED'] = '1' + start() diff --git a/python/pygame/basic/draw-circles.py b/python/pygame/basic/draw-circles.py index d73e84a..5d2dc28 100644 --- a/python/pygame/basic/draw-circles.py +++ b/python/pygame/basic/draw-circles.py @@ -1,3 +1,4 @@ +import os import random import sys @@ -26,11 +27,14 @@ def get_rand_radius(min_value=10, max_value=30): def start(): pygame.init() + + FPS = 30 width = 400 height = 400 DISPLAYSURF = pygame.display.set_mode((width, height)) pygame.display.set_caption('Circles') + fps_clock = pygame.time.Clock() iters = 0 while True: @@ -46,9 +50,11 @@ def start(): pygame.draw.circle(DISPLAYSURF, get_rand_color(), get_rand_position(width, height), get_rand_radius()) pygame.display.update() + fps_clock.tick(FPS) iters += 1 if __name__ == '__main__': + os.environ['SDL_VIDEO_CENTERED'] = '1' start() diff --git a/python/pygame/basic/draw-shapes.py b/python/pygame/basic/draw-shapes.py index c353660..4d9d875 100644 --- a/python/pygame/basic/draw-shapes.py +++ b/python/pygame/basic/draw-shapes.py @@ -1,3 +1,4 @@ +import os import random import sys @@ -97,11 +98,14 @@ def rand(width, height): def start(): pygame.init() + + FPS = 30 width = 400 height = 400 DISPLAYSURF = pygame.display.set_mode((width, height)) pygame.display.set_caption('Shapes') + fps_clock = pygame.time.Clock() iters = 0 while True: @@ -125,9 +129,11 @@ def start(): shape.draw(DISPLAYSURF) pygame.display.update() + fps_clock.tick(FPS) iters += 1 if __name__ == '__main__': + os.environ['SDL_VIDEO_CENTERED'] = '1' start() diff --git a/python/pygame/basic/draw-sprite.py b/python/pygame/basic/draw-sprite.py index abe249c..11b5756 100644 --- a/python/pygame/basic/draw-sprite.py +++ b/python/pygame/basic/draw-sprite.py @@ -1,3 +1,4 @@ +import os import sys import pygame @@ -29,11 +30,13 @@ def draw(self, surface): def start(): pygame.init() + FPS = 30 width = 400 height = 400 DISPLAYSURF = pygame.display.set_mode((width, height)) DISPLAYSURF.fill((255, 255, 255)) pygame.display.set_caption('Key Events') + fps_clock = pygame.time.Clock() satyr = Satyr((200, 200), 0.25) @@ -48,7 +51,9 @@ def start(): satyr.draw(DISPLAYSURF) pygame.display.update() + fps_clock.tick(FPS) if __name__ == '__main__': + os.environ['SDL_VIDEO_CENTERED'] = '1' start() diff --git a/python/pygame/basic/image-rotation.py b/python/pygame/basic/image-rotation.py index 9a67524..0a48b6b 100644 --- a/python/pygame/basic/image-rotation.py +++ b/python/pygame/basic/image-rotation.py @@ -1,3 +1,4 @@ +import os import random import sys @@ -78,10 +79,12 @@ def rand(fpath, width, height, scale=0.25): def start(): pygame.init() + FPS = 30 width = 400 height = 400 DISPLAYSURF = pygame.display.set_mode((width, height)) pygame.display.set_caption('Rotating Image') + fps_clock = pygame.time.Clock() image = Image.rand('./images/ball.png', width, height) @@ -97,7 +100,9 @@ def start(): image.update(width, height) pygame.display.update() + fps_clock.tick(FPS) if __name__ == '__main__': + os.environ['SDL_VIDEO_CENTERED'] = '1' start() diff --git a/python/pygame/basic/images/frame-1.png b/python/pygame/basic/images/frame-1.png new file mode 100644 index 0000000..3364bed Binary files /dev/null and b/python/pygame/basic/images/frame-1.png differ diff --git a/python/pygame/basic/images/frame-2.png b/python/pygame/basic/images/frame-2.png new file mode 100644 index 0000000..a697b82 Binary files /dev/null and b/python/pygame/basic/images/frame-2.png differ diff --git a/python/pygame/basic/images/frame-3.png b/python/pygame/basic/images/frame-3.png new file mode 100644 index 0000000..ce44ba7 Binary files /dev/null and b/python/pygame/basic/images/frame-3.png differ diff --git a/python/pygame/basic/images/frame-4.png b/python/pygame/basic/images/frame-4.png new file mode 100644 index 0000000..d6f1736 Binary files /dev/null and b/python/pygame/basic/images/frame-4.png differ diff --git a/python/pygame/basic/images/frame-5.png b/python/pygame/basic/images/frame-5.png new file mode 100644 index 0000000..6e4e942 Binary files /dev/null and b/python/pygame/basic/images/frame-5.png differ diff --git a/python/pygame/basic/images/frame-6.png b/python/pygame/basic/images/frame-6.png new file mode 100644 index 0000000..80cecf1 Binary files /dev/null and b/python/pygame/basic/images/frame-6.png differ diff --git a/python/pygame/basic/images/frame-7.png b/python/pygame/basic/images/frame-7.png new file mode 100644 index 0000000..ad726be Binary files /dev/null and b/python/pygame/basic/images/frame-7.png differ diff --git a/python/pygame/basic/images/frame-8.png b/python/pygame/basic/images/frame-8.png new file mode 100644 index 0000000..f7b0d28 Binary files /dev/null and b/python/pygame/basic/images/frame-8.png differ diff --git a/python/pygame/basic/key-movement.py b/python/pygame/basic/key-movement.py index 9d88909..0d3ef4b 100644 --- a/python/pygame/basic/key-movement.py +++ b/python/pygame/basic/key-movement.py @@ -1,3 +1,4 @@ +import os import random import sys @@ -71,11 +72,13 @@ def rand(fpath, width, height, scale=0.25): def start(): pygame.init() + FPS = 30 width = 400 height = 400 DISPLAYSURF = pygame.display.set_mode((width, height)) DISPLAYSURF.fill((255, 255, 255)) pygame.display.set_caption('Key Events') + fps_clock = pygame.time.Clock() satyr = Image('./images/Satyr_01_Idle_000.png', (200, 200), 0.25) @@ -92,7 +95,9 @@ def start(): satyr.draw(DISPLAYSURF) pygame.display.update() + fps_clock.tick(FPS) if __name__ == '__main__': + os.environ['SDL_VIDEO_CENTERED'] = '1' start() diff --git a/python/pygame/basic/mouse-movement.py b/python/pygame/basic/mouse-movement.py new file mode 100644 index 0000000..b054bd2 --- /dev/null +++ b/python/pygame/basic/mouse-movement.py @@ -0,0 +1,60 @@ +import os +import sys + +import pygame +from pygame.locals import * + + +class Satyr(pygame.sprite.Sprite): + def __init__(self, position, scale=0.5): + pygame.sprite.Sprite.__init__(self) + + img = pygame.image.load('./images/Satyr_01_Idle_000.png') + rect = img.get_rect(center=position) + w, h = rect.size[0], rect.size[1] + w, h = int(w * scale), int(h * scale) + img = pygame.transform.scale(img, (w, h)) + + rect = img.get_rect(center=position) + x = position[0] - int(rect.size[0] / 2.0) + y = position[1] - int(rect.size[1] / 2.0) + + self.image = img + self.rect = rect + self.position = x, y + + def draw(self, surface, position): + self.position = position[0] - self.rect.width / 2, position[1] - self.rect.height / 2 + surface.blit(self.image, self.position) + + +def start(): + pygame.init() + + FPS = 30 + width = 400 + height = 400 + DISPLAYSURF = pygame.display.set_mode((width, height)) + DISPLAYSURF.fill((255, 255, 255)) + pygame.display.set_caption('Key Events') + fps_clock = pygame.time.Clock() + + satyr = Satyr((200, 200), 0.25) + + while True: + for event in pygame.event.get(): + if event.type == QUIT: + pygame.quit() + sys.exit() + + DISPLAYSURF.fill((255, 255, 255, 0)) + + satyr.draw(DISPLAYSURF, pygame.mouse.get_pos()) + + pygame.display.update() + fps_clock.tick(FPS) + + +if __name__ == '__main__': + os.environ['SDL_VIDEO_CENTERED'] = '1' + start() diff --git a/python/pygame/space-battle/audio/bullet.wav b/python/pygame/space-battle/audio/bullet.wav new file mode 100644 index 0000000..fc6607a Binary files /dev/null and b/python/pygame/space-battle/audio/bullet.wav differ diff --git a/python/pygame/space-battle/audio/explosion.wav b/python/pygame/space-battle/audio/explosion.wav new file mode 100644 index 0000000..2f1ccf6 Binary files /dev/null and b/python/pygame/space-battle/audio/explosion.wav differ diff --git a/python/pygame/space-battle/audio/game.wav b/python/pygame/space-battle/audio/game.wav new file mode 100644 index 0000000..83dfe62 Binary files /dev/null and b/python/pygame/space-battle/audio/game.wav differ diff --git a/python/pygame/space-battle/game.py b/python/pygame/space-battle/game.py new file mode 100644 index 0000000..33cd0d5 --- /dev/null +++ b/python/pygame/space-battle/game.py @@ -0,0 +1,186 @@ +import itertools +import os +import sys + +import pygame +from pygame.constants import KEYUP, QUIT, K_SPACE, K_q, K_c + +from objects import Ship, Bullet, RockGenerator, GameInfo, GameOverMessage, AudioEffects + + +def get_remaining_objects(bullets, rocks, bullet_group, rock_group): + collisions = pygame.sprite.groupcollide(bullet_group, rock_group, True, True) + n_collisions = len(collisions) + if n_collisions > 0: + collided_bullets = set([b.uuid for b in collisions.keys()]) + bullets = [b for b in bullets if b.uuid not in collided_bullets] + + collided_rocks = set([r.uuid for r in itertools.chain(*collisions.values())]) + rocks = [r for r in rocks if r.uuid not in collided_rocks] + return bullets, rocks, n_collisions + + +def get_remaining_rocks(ship, rocks, rock_group): + collisions = pygame.sprite.spritecollide(ship, rock_group, True) + n_collisions = len(collisions) + if n_collisions > 0: + collided_rocks = set([r.uuid for r in collisions]) + rocks = [r for r in rocks if r.uuid not in collided_rocks] + return rocks, -n_collisions + + +def get_params(): + width = 500 + height = 400 + + DISPLAYSURF = pygame.display.set_mode((width, height)) + DISPLAYSURF.fill((255, 255, 255)) + + score = 0 + lives = 1 + + return { + 'FPS': 30, + 'width': width, + 'height': height, + 'DISPLAYSURF': DISPLAYSURF, + 'fps_clock': pygame.time.Clock(), + 'score': score, + 'lives': lives, + 'bullets': [], + 'rocks': [], + 'bullet_group': pygame.sprite.Group(), + 'rock_group': pygame.sprite.Group(), + 'ship': Ship((width / 2, height - 50), 0.5), + 'rock_generator': RockGenerator(width, height), + 'game_info': GameInfo(score, lives), + 'audio': AudioEffects() + } + + +def quit_game(): + pygame.quit() + sys.exit() + + +def start_game(**params): + width, height = params['width'], params['height'] + ship = params['ship'] + score, lives = params['score'], params['lives'] + bullets, rocks = params['bullets'], params['rocks'] + bullet_group, rock_group = params['bullet_group'], params['rock_group'] + rock_generator = params['rock_generator'] + game_info = params['game_info'] + DISPLAYSURF = params['DISPLAYSURF'] + fps_clock, FPS = params['fps_clock'], params['FPS'] + audio = params['audio'] + + while True: + kwargs = { + 'width': width, + 'height': height, + 'keys': pygame.key.get_pressed(), + 'position': ship.get_center(), + 'score': score, + 'lives': lives + } + + for event in pygame.event.get(): + if event.type == QUIT: + quit_game() + elif event.type == KEYUP and event.key == K_SPACE: + bullet = Bullet.instance(**kwargs) + bullet_group.add(bullet) + bullets.append(bullet) + audio.play('bullet') + + if rock_generator.should_generate(): + rock = rock_generator.next() + rocks.append(rock) + rock_group.add(rock) + + DISPLAYSURF.fill((255, 255, 255, 0)) + + game_info.draw(DISPLAYSURF, **kwargs) + ship.draw(DISPLAYSURF, **kwargs) + + for bullet in bullets: + bullet.draw(DISPLAYSURF, **kwargs) + + for rock in rocks: + rock.draw(DISPLAYSURF, **kwargs) + + bullets, rocks, points = get_remaining_objects(bullets, rocks, bullet_group, rock_group) + score += points + for _ in range(points): + audio.play('explosion') + + rocks, hits = get_remaining_rocks(ship, rocks, rock_group) + lives += hits + + pygame.display.update() + fps_clock.tick(FPS) + + if lives <= 0: + break + + return score, lives + + +def show_game_over(**params): + DISPLAYSURF = params['DISPLAYSURF'] + fps_clock, FPS = params['fps_clock'], params['FPS'] + width, height = params['width'], params['height'] + score, lives = params['score'], params['lives'] + + message = GameOverMessage(width, height, score, lives) + do_continue = False + + while True: + for event in pygame.event.get(): + if event.type == QUIT: + quit_game() + elif event.type == KEYUP: + if event.key == K_q: + quit_game() + elif event.key == K_c: + print('continue') + do_continue = True + break + + if do_continue: + break + + DISPLAYSURF.fill((255, 255, 255, 0)) + + message.draw(DISPLAYSURF) + + pygame.display.update() + fps_clock.tick(FPS) + + return do_continue + + +def start(): + pygame.init() + pygame.display.set_caption('Space Battle') + + pygame.mixer.init() + pygame.mixer.music.load('./audio/game.wav') + pygame.mixer.music.play(loops=-1) + + while True: + params = get_params() + params['score'], params['lives'] = start_game(**params) + + do_continue = show_game_over(**params) + if not do_continue: + break + + pygame.mixer.music.stop() + quit_game() + + +if __name__ == '__main__': + os.environ['SDL_VIDEO_CENTERED'] = '1' + start() diff --git a/python/pygame/space-battle/images/bullet.png b/python/pygame/space-battle/images/bullet.png new file mode 100644 index 0000000..c6070ac Binary files /dev/null and b/python/pygame/space-battle/images/bullet.png differ diff --git a/python/pygame/space-battle/images/rock.png b/python/pygame/space-battle/images/rock.png new file mode 100644 index 0000000..335692c Binary files /dev/null and b/python/pygame/space-battle/images/rock.png differ diff --git a/python/pygame/space-battle/images/ship.png b/python/pygame/space-battle/images/ship.png new file mode 100644 index 0000000..fd793a3 Binary files /dev/null and b/python/pygame/space-battle/images/ship.png differ diff --git a/python/pygame/space-battle/images/upgrade.png b/python/pygame/space-battle/images/upgrade.png new file mode 100644 index 0000000..71bc218 Binary files /dev/null and b/python/pygame/space-battle/images/upgrade.png differ diff --git a/python/pygame/space-battle/objects.py b/python/pygame/space-battle/objects.py new file mode 100644 index 0000000..90a02e6 --- /dev/null +++ b/python/pygame/space-battle/objects.py @@ -0,0 +1,196 @@ +import random +import time +import uuid + +import pygame +from pygame.constants import K_LEFT, K_a, K_RIGHT, K_d + + +class BaseObject(pygame.sprite.Sprite): + def __init__(self, ipath, position, scale=0.5): + pygame.sprite.Sprite.__init__(self) + + self.uuid = str(uuid.uuid4()) + self.image = BaseObject.__scale__(ipath, position, scale) + self.rect = self.image.get_rect(center=position) + + def get_center(self): + return self.rect.center + + def draw(self, surface, **kwargs): + raise NotImplementedError('Not yet implemented') + + @staticmethod + def __scale__(ipath, position, scale): + img = pygame.image.load(ipath) + rect = img.get_rect(center=position) + w, h = rect.size[0], rect.size[1] + w, h = int(w * scale), int(h * scale) + return pygame.transform.scale(img, (w, h)) + + +class Bullet(BaseObject): + def __init__(self, position, scale=1.0): + BaseObject.__init__(self, './images/bullet.png', position, scale) + + def draw(self, surface, **kwargs): + x, y = self.rect.center + self.rect.center = x, y - 5 + + surface.blit(self.image, self.rect.center) + + if y <= 0: + self.kill() + + @staticmethod + def instance(**kwargs): + return Bullet(kwargs['position']) + + +class Rock(BaseObject): + def __init__(self, position, scale=1.0): + BaseObject.__init__(self, './images/rock.png', position, scale) + + def draw(self, surface, **kwargs): + x, y = self.rect.center + self.rect.center = x, y + 1 + + surface.blit(self.image, self.rect.center) + + if y >= kwargs['height']: + self.kill() + + +class Ship(BaseObject): + def __init__(self, position, scale=1.0): + BaseObject.__init__(self, './images/ship.png', position, scale) + + def draw(self, surface, **kwargs): + width, height = kwargs['width'], kwargs['height'] + x, y = self.rect.center + w, h = self.rect.size + + if 'keys' in kwargs: + keys = kwargs['keys'] + if keys[K_LEFT] or keys[K_a]: + if x - w / 2.0 >= 0: + x -= 4 + elif keys[K_RIGHT] or keys[K_d]: + if x + w / 2.0 <= width: + x += 4 + + self.rect.center = x, y + + surface.blit(self.image, self.rect.center) + + +class RockGenerator(object): + def __init__(self, width, height): + rock = Rock((width / 2.0, height / 2.0)) + w, h = rock.rect.size + self.x_pos = [x for x in range(0, width, w)] + self.prev_x = None + self.start_time = None + + def should_generate(self): + if self.start_time is None: + self.start_time = time.time() + return True + + stop_time = time.time() + diff = int(stop_time - self.start_time) + if diff >= 2: + self.start_time = stop_time + return True + return False + + def next(self): + while True: + curr_x = random.choice(self.x_pos) + if curr_x != self.prev_x: + self.prev_x = curr_x + return Rock((curr_x, 20)) + + +class GameInfo(object): + def __init__(self, score, lives): + self.font = pygame.font.Font('freesansbold.ttf', 20) + self.color = (0, 0, 0) + self.position = 10, 10 + self.score = score + self.lives = lives + + def __get_drawing_objects__(self): + text_surface = self.font.render(f'Score: {self.score}, Lives: {self.lives}', True, self.color) + rect = text_surface.get_rect() + rect.x, rect.y = 10, 10 + + return text_surface, rect + + def draw(self, surface, **kwargs): + self.score = kwargs['score'] + self.lives = kwargs['lives'] + + text_surface, rect = self.__get_drawing_objects__() + surface.blit(text_surface, rect) + + +class GameOverMessage(object): + def __init__(self, width, height, score, lives): + self.game_over_font = pygame.font.Font('freesansbold.ttf', 30) + self.game_info_font = pygame.font.Font('freesansbold.ttf', 20) + self.game_action_font = pygame.font.Font('freesansbold.ttf', 20) + + self.game_over_color = (255, 0, 0) + self.game_info_color = (0, 0, 0) + self.game_action_color = (0, 0, 0) + + self.center = width / 2.0, height / 2.0 + self.score = score + self.lives = lives + + def __get_game_over__(self): + text = 'Game Over' + text_surface = self.game_over_font.render(text, True, self.game_over_color) + rect = text_surface.get_rect() + rect.center = self.center + + return text_surface, rect + + def __get_game_info__(self): + text = f'Score: {self.score}, Lives: {self.lives}' + text_surface = self.game_info_font.render(text, True, self.game_info_color) + rect = text_surface.get_rect() + rect.center = self.center[0], self.center[1] + 30 + + return text_surface, rect + + def __get_game_action__(self): + text = 'Hit "q" to quit. Hit "c" to continue.' + text_surface = self.game_action_font.render(text, True, self.game_action_color) + rect = text_surface.get_rect() + rect.center = self.center[0], self.center[1] + 60 + + return text_surface, rect + + def draw(self, surface): + text_surface, rect = self.__get_game_over__() + surface.blit(text_surface, rect) + + text_surface, rect = self.__get_game_info__() + surface.blit(text_surface, rect) + + text_surface, rect = self.__get_game_action__() + surface.blit(text_surface, rect) + + +class AudioEffects(object): + def __init__(self): + self.effects = { + 'bullet': pygame.mixer.Sound('./audio/bullet.wav'), + 'explosion': pygame.mixer.Sound('./audio/explosion.wav') + } + + def play(self, effect): + if effect in self.effects: + self.effects[effect].play() diff --git a/python/pygame/yappy-bird/game.py b/python/pygame/yappy-bird/game.py new file mode 100644 index 0000000..1f000d3 --- /dev/null +++ b/python/pygame/yappy-bird/game.py @@ -0,0 +1,98 @@ +import os +import sys + +import pygame +from pygame.constants import QUIT, K_SPACE + +from objects import Bird, Pipe, PipeGenerator + + +def quit_game(): + pygame.quit() + sys.exit() + + +def get_params(): + width = 900 + height = 600 + + DISPLAYSURF = pygame.display.set_mode((width, height)) + DISPLAYSURF.fill((255, 255, 255)) + + score = 0 + + return { + 'FPS': 30, + 'width': width, + 'height': height, + 'DISPLAYSURF': DISPLAYSURF, + 'fps_clock': pygame.time.Clock(), + 'score': score, + 'pipes': [], + 'pipe_group': pygame.sprite.Group(), + 'bird': Bird((width / 10.0, height / 2.0)) + } + + +def start_game(**params): + width, height = params['width'], params['height'] + bird = params['bird'] + score = params['score'] + pipes = params['pipes'] + pipe_group = params['pipe_group'] + DISPLAYSURF = params['DISPLAYSURF'] + fps_clock, FPS = params['fps_clock'], params['FPS'] + + started = False + pipe_gen = PipeGenerator() + + while True: + if not started: + started = pygame.key.get_pressed()[K_SPACE] + + kwargs = { + 'width': width, + 'height': height, + 'keys': pygame.key.get_pressed(), + 'score': score, + 'started': started + } + + for event in pygame.event.get(): + if event.type == QUIT: + quit_game() + + DISPLAYSURF.fill((255, 255, 255, 0)) + + if pipe_gen.should_generate() and started: + t_pipe, b_pipe = pipe_gen.next(**kwargs) + pipes.extend([t_pipe, b_pipe]) + pipe_group.add(t_pipe) + pipe_group.add(b_pipe) + + bird.draw(DISPLAYSURF, **kwargs) + + for pipe in pipes: + pipe.draw(DISPLAYSURF, **kwargs) + + pygame.display.update() + fps_clock.tick(FPS) + + collisions = pygame.sprite.spritecollide(bird, pipes, False) + n_collisions = len(collisions) + if n_collisions > 0: + break + + +def start(): + pygame.init() + pygame.display.set_caption('Yappy Bird') + + params = get_params() + start_game(**params) + + +if __name__ == '__main__': + os.environ['SDL_VIDEO_CENTERED'] = '1' + start() + diff --git a/python/pygame/yappy-bird/images/frame-1.png b/python/pygame/yappy-bird/images/frame-1.png new file mode 100644 index 0000000..3364bed Binary files /dev/null and b/python/pygame/yappy-bird/images/frame-1.png differ diff --git a/python/pygame/yappy-bird/images/frame-2.png b/python/pygame/yappy-bird/images/frame-2.png new file mode 100644 index 0000000..a697b82 Binary files /dev/null and b/python/pygame/yappy-bird/images/frame-2.png differ diff --git a/python/pygame/yappy-bird/images/frame-3.png b/python/pygame/yappy-bird/images/frame-3.png new file mode 100644 index 0000000..ce44ba7 Binary files /dev/null and b/python/pygame/yappy-bird/images/frame-3.png differ diff --git a/python/pygame/yappy-bird/images/frame-4.png b/python/pygame/yappy-bird/images/frame-4.png new file mode 100644 index 0000000..d6f1736 Binary files /dev/null and b/python/pygame/yappy-bird/images/frame-4.png differ diff --git a/python/pygame/yappy-bird/images/frame-5.png b/python/pygame/yappy-bird/images/frame-5.png new file mode 100644 index 0000000..6e4e942 Binary files /dev/null and b/python/pygame/yappy-bird/images/frame-5.png differ diff --git a/python/pygame/yappy-bird/images/frame-6.png b/python/pygame/yappy-bird/images/frame-6.png new file mode 100644 index 0000000..80cecf1 Binary files /dev/null and b/python/pygame/yappy-bird/images/frame-6.png differ diff --git a/python/pygame/yappy-bird/images/frame-7.png b/python/pygame/yappy-bird/images/frame-7.png new file mode 100644 index 0000000..ad726be Binary files /dev/null and b/python/pygame/yappy-bird/images/frame-7.png differ diff --git a/python/pygame/yappy-bird/images/frame-8.png b/python/pygame/yappy-bird/images/frame-8.png new file mode 100644 index 0000000..f7b0d28 Binary files /dev/null and b/python/pygame/yappy-bird/images/frame-8.png differ diff --git a/python/pygame/yappy-bird/objects.py b/python/pygame/yappy-bird/objects.py new file mode 100644 index 0000000..aad94c3 --- /dev/null +++ b/python/pygame/yappy-bird/objects.py @@ -0,0 +1,113 @@ +import random +import time +import uuid + +import pygame +from pygame.constants import K_SPACE + + +class Bird(pygame.sprite.Sprite): + def __init__(self, position, scale=0.1): + pygame.sprite.Sprite.__init__(self) + + paths = [f'./images/frame-{i + 1}.png' for i in range(8)] + imgs = [pygame.image.load(p) for p in paths] + rect = imgs[0].get_rect() + + w, h = rect.size[0], rect.size[1] + w, h = int(w * scale), int(h * scale) + + self.uuid = str(uuid.uuid4()) + self.width, self.height = w, h + self.imgs = [pygame.transform.scale(img, (w, h)) for img in imgs] + self.rect = self.imgs[0].get_rect() + self.rect.center = position[0] - w / 2.0, position[1] - h / 2.0 + self.index = 0 + self.is_killed = False + + def draw(self, surface, **kwargs): + if self.is_killed: + return + + if kwargs['started']: + if 'keys' in kwargs and kwargs['keys'][K_SPACE]: + dy = -10 + else: + dy = 10 + else: + dy = 0 + + x, y = self.rect.center[0], self.rect.center[1] + dy + y = max(0, y) + y = min(kwargs['height'] - self.height, y) + + self.rect.center = x, y + + surface.blit(self.imgs[self.index], self.rect.center) + self.index += 1 + if self.index >= len(self.imgs): + self.index = 0 + + if y >= kwargs['height'] - self.height: + self.is_killed = True + self.kill() + + +class Pipe(pygame.sprite.Sprite): + def __init__(self, position, width, height): + pygame.sprite.Sprite.__init__(self) + + self.uuid = str(uuid.uuid4()) + self.color = (10, 200, 10, 1) + self.position = position + self.dimension = width, height + self.rect = (self.position, self.dimension) + self.is_killed = False + + def draw(self, surface, **kwargs): + if self.is_killed: + return + + pygame.draw.rect(surface, self.color, (self.position, self.dimension)) + self.position = self.position[0] - 5, self.position[1] + self.rect = (self.position, self.dimension) + + if self.position[0] <= 0: + self.is_killed = True + self.kill() + + def __repr__(self): + return f'pipe: pos={self.position} | dim={self.dimension}' + + +class PipeGenerator(object): + def __init__(self, pipe_width=70, tb_spacing=200): + self.pipe_width = pipe_width + self.tb_spacing = tb_spacing + self.start_time = None + + def should_generate(self): + if self.start_time is None: + self.start_time = time.time() + return True + + stop_time = time.time() + diff = int(stop_time - self.start_time) + if diff >= 2: + self.start_time = stop_time + return True + return False + + def next(self, **kwargs): + width, height = kwargs['width'], kwargs['height'] + + top_height = random.randint(int(height * 0.25), int(height * 0.50)) + bot_height = height - (top_height + self.tb_spacing) + + top_x, top_y = width, 0 + bot_x, bot_y = width, top_height + self.tb_spacing + + top_pipe = Pipe((top_x, top_y), self.pipe_width, top_height) + bot_pipe = Pipe((bot_x, bot_y), self.pipe_width, bot_height) + + return top_pipe, bot_pipe