Gelecekte fare işaretçisi izlerini görüntüleyin!


24

D3js kullanarak bu örnekten ilham alarak , fare işaretçisinin izini sürdüğü bir tuval (veya tercih ettiğiniz dil eşdeğeri) oluşturmak için aşağıdaki bükülmeyle sizi zorluyorum :

Büküm

Sen fare işaretçisi nerede yollar göstermek olmamalı idi ama nerede "yollar" olacak gelecekte (belki).

Aşağıdakilerden birini kullanarak yapabilirsiniz:

  1. Bir zaman makinesi veya

  2. Önceki fare hareketlerine dayanan olasılıklı tahminler

Varsayımlar

Zaman makinesi uygulamasını seçmediyseniz, fare eşik milisaniyeden fazla hareket etmediğinde , izlerin hiçbirini görüntüleyemezsiniz. ( Eşik değeri seçmek size kalmış).

İmleç görüntüsü size bağlıdır ve işletim sisteminin imleciyle aynı olması gerekmez (düz küçük daireler veya noktalar bile çizebilirsiniz).

Hiçbir kötü giriş test edilmeyecektir: Hareketlerin yumuşak olduğunu varsayabilirsiniz. Bu durum için 'yumuşak' tanım: fare hareketleri tuvalin x ve y eksenleri üzerinde bir işlevse - sürekli bir işlev olacaktır.

Kazanan

Koddaki en az karakterin bulunduğu geçerli cevap kazanacaktır. Beraberlik durumunda - ilk gönderilenler kazanacak.

EDIT: En fazla oy alan geçerli cevap kazanacak. Beraberlik durumunda - ilk gönderilenler kazanacak. Uygulamada yaratıcı olabilir veya tahminde bulunabilirsiniz. Artık yargıç değilim, hepimiz :)

  • Geçerli bir cevap, çevrimiçi bir araçta veya ücretsiz olarak indirilebilir bir derleyici / tercüman / çalışma zamanı / vb. İle oynamanın bir yolunu içermelidir (test! Test etmek istemiştim).

2
Bence bu soru kod golfünden ziyade popülerlik yarışmasına daha uygun olabilir, çünkü yeterince iyi bir tahmin olarak nitelendirilebilecek şeyler için oldukça özneldir. Bunu açıklamanızı veya etiketi değiştirmenizi tavsiye ederim. Bununla birlikte, eğlenceli görünüyor.
isaacg,

2
Haklısın. Soruyu düzenledim ve etiketi değiştirdim.
Jacob

Birinin makine öğrenme algoritmalarını uygulama zamanı!
Ingo Bürk

6
Test amacıyla, hangi zaman makinesi modellerine erişiminiz var? Ve onlarla arayüz oluşturmak için standart kütüphaneler kullanabilir miyiz?
Peter Taylor

1
Burada sızlanan sadece bir matematikçi: pürüzsüz! = Sürekli. Aslında vahşi sivri hareket hala sürekli olacak.
CompuChip

Yanıtlar:


33

JavaScript

Programım, son 20 fare hareketinin yönündeki açısal değişimin ortalamasını kullanarak işaretçinin yönünü tahmin ediyor. Ayrıca, işaretçinin olası konum ve yönlerinden bir "bulut" oluşturmak için açısal değişimin varyansını da kullanır. "Buluttaki" her işaretçinin renginin, daha koyu renklerin daha büyük bir olasılığı temsil ettiği fare işaretçisinin yeni konumu olma olasılığını temsil etmesi beklenir. İşaretçi bulutunun farenin önündeki mesafesi, farenin hareket hızı kullanılarak hesaplanır. En iyi tahminleri yapmaz ama temiz görünüyor.

İşte bir keman: http://jsfiddle.net/5hs64t7w/4/

İşaretçi bulutunun boyutunu artırmak, görmek ilginçtir. cloudSizeProgramın ilk satırındaki değişkeni değiştirerek ayarlanabilir . İşte bulut büyüklüğü 10 olan bir keman: http://jsfiddle.net/5hs64t7w/5/

Bu kaynakları dairesel ortalama ve varyans formüllerini almak için kullandım:
Dairesel Ortalama: http://en.wikipedia.org/wiki/Circular_mean
Dairesel Varyans: http://www.ebi.ac.uk/thornton-srv/software/ PROCHECK / nmr_manual / man_cv.html

İlgilenen varsa kodu burada:

    var cloudSize = 3;

    var canvas = document.getElementById('canvas_element');
    var c = canvas.getContext('2d');
    var prevX = -1;
    var prevY = -1;
    var curX = -1;
    var curY = -1;
    var distance = 0;
    var direction = 0;

    function drawMouse(x, y, angle, gray){
        var grayVal = Math.round(gray*255);
        var grayString = "rgb(" + grayVal + "," + grayVal +"," + grayVal + ")";
        c.fillStyle = grayString;
        c.strokeStyle = grayString;
        c.lineWidth = 1;
        c.beginPath();
        c.moveTo(x, y);
        c.lineTo(x + 16*Math.cos(angle + Math.PI/2.0 + Math.PI/8.0), y + 16*Math.sin(angle + Math.PI/2.0 + Math.PI/8.0));
        c.moveTo(x, y);
        c.lineTo(x + 16*Math.cos(angle + Math.PI/2.0 - Math.PI/8.0), y + 16*Math.sin(angle + Math.PI/2.0 - Math.PI/8.0));
        c.lineTo(x + 16*Math.cos(angle + Math.PI/2.0 + Math.PI/8.0), y + 16*Math.sin(angle + Math.PI/2.0 + Math.PI/8.0));
        c.stroke();
        c.fill();
        c.beginPath();
        c.moveTo(x, y);
        c.lineTo(x + 24*Math.cos(angle + Math.PI/2), y + 24*Math.sin(angle + Math.PI/2));
        c.stroke();
    }

    function sum(array){
        var s = 0.0;
        for(var i=0; i<array.length; i++){
            s += array[i];
        }
        return s;
    }

    var sins = [];
    var coss = [];
    var lengths = [];
    var times = [];
    var index = 0;
    var limit = 20;
    var variance = 0;
    var prevTime = new Date().getTime();
    function updateDistanceAndDirection(x, y){
        var angle = Math.atan2(prevY - curY, prevX - curX);
        sins[index] = Math.sin(angle);
        coss[index] = Math.cos(angle);
        lengths[index] = Math.sqrt((curX-prevX)*(curX-prevX) + (curY-prevY)*(curY-prevY));
        var time = new Date().getTime();
        times[index] = time - prevTime;

        variance = 1.0 - Math.sqrt(sum(coss)*sum(coss)+sum(sins)*sum(sins))/sins.length;

        direction = Math.atan2(1/sins.length*sum(sins),1/coss.length*sum(coss));
        var speed = sum(lengths)/(sum(times)/200);
        distance = Math.min(Math.max(40, speed), 100);
        prevTime = time;
        index = (index+1)%limit;
    }

    function drawMice(count){
        c.clearRect(0, 0, canvas.width, canvas.height);

        for(var i=count; i>=0; i--){
            var dir = direction + i*variance;
            drawMouse(curX - distance*Math.cos(dir), curY - distance*Math.sin(dir), dir - Math.PI/2, i/count);
            dir = direction - i*variance;
            drawMouse(curX - distance*Math.cos(dir), curY - distance*Math.sin(dir), dir - Math.PI/2, i/count);
        }
    }

    canvas.onmousemove = function (event) {
        curX = event.clientX;
        curY = event.clientY;

        updateDistanceAndDirection(curX, curY);

        drawMice(cloudSize);

        prevX = curX;
        prevY = curY;
    };

2
Değişken yöne işaret eden işaretçi yerine fare işaretçisini (sabit yönlendirmeli) bir sıra gösterebilir misiniz? "Fare izlerini" görmeyi bekliyordum ama hiçbirini göremiyorum, haha
justhalf

Çok hoş, ama şu anda inerken işaretçinin gelecekte yukarı çıkması daha mantıklı değil mi? Imho, program tam tersini yapmalıdır, böylece işaretçinin ekranda kalmasını öngörür.
Madmenyo

@MennoGouw mükemmel değil ama oldukça lanet olası iyi
NimChimpsky

@nimchimpsky Fare şu anda düşerse, farenin yükselme ihtimalinin yüksek olduğunu söylemek. Programın kendisi harika.
Madmenyo

Normal insan davranışını fare kullanımı için de kullanmanın mümkün olduğunu düşünüyor musunuz? Daireler, düz çizgiler gibi ... Bunlar gelecekte daha da ileriye doğru tahmin edilebilir (birkaç mesure sonrası dairenin yarıçapı hesaplanır ve siz çizmeden önce bile daireyi tamamlar)
Saffron

14

Java

Zaman makinesi yaklaşımını almaya karar verdim. Bir zaman makinesinin anahtar bileşeninin java.awt.Robot olduğu ortaya çıktı. Programım farenizi 10 saniye boyunca hareket ettirmenizi sağlar. 10 saniye sonra, zamanda geriye gider ve fare hareketini yeniden yaratırken mükemmel bir şekilde tahmin eder.

görüntü tanımını buraya girin

İşte kod:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.TimerTask;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;


public class TimeMachine extends JPanel implements MouseMotionListener {

    Timer timer;
    int time = 10;
    java.util.Timer taskTimer;
    ArrayList<Point> mousePoints;
    ArrayList<Long> times;
    Robot robot;
    int width, height;
    ArrayList<Point> drawMousePoints;

    public TimeMachine(){
        width = 500;
        height = 500;
        drawMousePoints = new ArrayList<Point>();

        robot = null;
        try{
            robot = new Robot();
        }
        catch(Exception e){
            System.out.println("The time machine malfunctioned... Reverting to 512 BC");
        }
        mousePoints = new ArrayList<Point>();
        times = new ArrayList<Long>();

        taskTimer = new java.util.Timer();

        ActionListener al = new ActionListener(){
            public void actionPerformed(ActionEvent e){
                time--;
                if(time == 0)
                    rewind();
                repaint();
            }
        };
        timer = new Timer(1000, al);
        start();
    }

    public void paint(Graphics g){
        g.clearRect(0, 0, width, height);
        g.drawString("Time Machine activiates in: " + time, 15, 50);
        for(int i=0; i<drawMousePoints.size(); i++){
            Point drawMousePoint = drawMousePoints.get(i);
            drawMouse(drawMousePoint.x-getLocationOnScreen().x, drawMousePoint.y-getLocationOnScreen().y, g, Color.BLACK, Color.LIGHT_GRAY, (double)i/drawMousePoints.size());
        }
    }

    public void drawMouse(int x, int y, Graphics g, Color line, Color fill, double alpha){
        Graphics2D g2d = (Graphics2D)g;
        g2d.setColor(new Color(fill.getRed(), fill.getGreen(), fill.getBlue(), (int)Math.max(Math.min(alpha*255, 255), 0)));
        g2d.fillPolygon(new int[]{x, x, x+4, x+8, x+10, x+7, x+12}, new int[]{y, y+16, y+13, y+20, y+19, y+12, y+12}, 7);

        g2d.setColor(new Color(line.getRed(), line.getGreen(), line.getBlue(), (int)Math.max(Math.min(alpha*255, 255), 0)));
        g2d.drawLine(x, y, x, y + 16);
        g2d.drawLine(x, y+16, x+4, y+13);
        g2d.drawLine(x+4, y+13, x+8, y+20);
        g2d.drawLine(x+8, y+20, x+10, y+19);
        g2d.drawLine(x+10, y+19, x+7, y+12);
        g2d.drawLine(x+7, y+12, x+12, y+12);
        g2d.drawLine(x+12, y+12, x, y);
    }

    public void start(){
        timer.start();
        prevTime = System.currentTimeMillis();
        mousePoints.clear();
    }

    public void rewind(){
        timer.stop();
        long timeSum = 0;
        for(int i=0; i<times.size(); i++){
            timeSum += times.get(0);
            final boolean done = i == times.size()-1;
            taskTimer.schedule(new TimerTask(){
                public void run(){
                    Point point = mousePoints.remove(0);
                    drawMousePoints.clear();
                    drawMousePoints.addAll(mousePoints.subList(0, Math.min(mousePoints.size(), 30)));
                    robot.mouseMove(point.x, point.y);
                    repaint();
                    if(done)
                        System.exit(0);
                }
            }, timeSum);
        }
    }

    long prevTime = 0;
    public void record(MouseEvent m){
        if(timer.isRunning()){
            long time = System.currentTimeMillis();
            mousePoints.add(new Point(m.getXOnScreen(), m.getYOnScreen()));
            times.add((time-prevTime)/10);
            prevTime = time;
        }
    }

    public static void main(String[] args){

        TimeMachine timeMachine = new TimeMachine();

        JFrame frame = new JFrame("Time Machine");
        frame.setSize(timeMachine.width, timeMachine.height);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.addMouseMotionListener(timeMachine);

        frame.add(timeMachine);
    }

    public void mouseDragged(MouseEvent m) {
        record(m);
    }

    public void mouseMoved(MouseEvent m) {
        record(m);
    }

}

Kod Netbeans tarafından biraz optimize edilmiş (uyarılardan kurtulmuş): pastebin.com/E57LZ4zY
Kaz Wolfe

10

Vanilya Javascript

Sadece işleri başlatmak için, işte iki değere dayalı basit bir tahmin. Son nfare postiyonları hafızaya alınır ve bir sıraya konur, tahmin, sıradaki ilk ve son elemanın basit bir doğrusal ekstrapolasyonudur.

Bu sadece tahmin kodudur, gösterimi içeren tam kod şöyledir this fiddle:

function predict(trail) {
    var b = trail.pop(),
        a = trail[0],
        d = {
            x: b.x - a.x,
            y: b.y - a.y
        },
        m = Math.sqrt( d.x * d.x + d.y * d.y );

    d.x = 5 * d.x / m;
    d.y = 5 * d.y / m;

    var predictions = [];
    for(var i = 1; i <= 10; i++) {
        predictions.push({
            x: b.x + i * d.x,
            y: b.y + i * d.y
        });
    }

    return predictions;
}

Demo, öngörmede, sıradaki son iki öğeyi tahmin için kullanmanıza izin veren bir yorum içerir. Sonucu daha "gerçek zamanlı", aynı zamanda daha az "düzgün" yapar.

Herkes boilerplate workfarklı bir tahmin algoritması uygulamak için kullanmak isterse , çekinmeyin. Zaten çok fazla iş değil.


Satır yerine fare işaretçisini görüntüleyebilir misiniz? "Fare izlerini" görmeyi bekliyordum ama göremiyorum, haha
justhalf

Soru bir imleç olmak zorunda olmadığını söylüyor;)
Ingo Bürk

4

JavaScript

Geçmiş, gelecek için en iyi tahmin - ben ve muhtemelen bir başkası

Benim çözümüm çok basit. İlk olarak, işte >>> Fiddle! <<<

Tek yaptığı geçmiş izini kaydırmak, yani gelecek izine benziyor. Temel olarak hiçbir Matematik dahil değildir (Biliyorum, oldukça sıkıcı). Özellikle imleci daireler halinde hareket ettirirken hataları kolayca görebilirsiniz. Bu yüzden izi çok kısa yaptım;)

Kod:

<!DOCTYPE html>
<html>
    <head>
        <style type="text/css">
            .cursor {
                width: 12px;
                height: 19px;
                position: absolute;
                background-image: url(https://i.imgur.com/h8imKBP.png);
            }
        </style>
        <script type="text/javascript">

            var x, y;
            window.onmousemove = function(e) {x=e.clientX; y=e.clientY;}

            var p = [0,0,0,0,0,0,0,0,0,0];
            window.setInterval(function() {
                p.shift();
                p.push([x, y]);
                var diff = [x-p[0][0], y-p[0][1]];
                for (var i = 0; i < 10; i++) {
                    var e = document.getElementById(i);
                    e.style.left = (p[9-i][0]+diff[0])+"px";
                    e.style.top = (p[9-i][1]+diff[1])+"px";
                }
            }, 10);

        </script>
    </head>
    <body>
    <div id="0" class="cursor"></div>
    <div id="1" class="cursor"></div>
    <div id="2" class="cursor"></div>
    <div id="3" class="cursor"></div>
    <div id="4" class="cursor"></div>
    <div id="5" class="cursor"></div>
    <div id="6" class="cursor"></div>
    <div id="7" class="cursor"></div>
    <div id="8" class="cursor"></div>
    <div id="9" class="cursor"></div>
    </body>
</html>

haha Sadece tarihe baktım. Ne olursa olsun, ben gibi
Felk
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.