import std.stdio;
import std.ascii;
import std.c.stdio;
import std.range;
import std.array;
import std.functional;
import std.algorithm;
import std.conv;
import std.container;
import std.math;
import std.numeric;
import std.string;
import std.c.string;
import std.regex;
import std.typecons;

struct Troop {
    int y, x, v;
}
struct Point {
    int y, x;
}
double distance2D(in Point a, in Point b) {
    int dx = a.x - b.x;
    int dy = a.y - b.y;
    return dx * dx + dy * dy;
}
double distance(in Point a, in Point b) {
    return sqrt(distance2D(a, b));
}

class Dinic {
    static const INF = int.max / 2;
    class Edge {
        int from, to;
        int cap;
        Edge rev;
    }
    size_t size;
    Edge[][] G;
    int[] level;
    int[] done;
    this(size_t size) {
        this.size = size;
        G = new Edge[][size];
        level = new int[size];
        done = new int[size];
    }
    void addEdge(int from, int to, int cap) {
        auto edge = new Edge;
        auto rev = new Edge;
        edge.from = from; edge.to = to; edge.cap = cap; edge.rev = rev;
        rev.from = to; rev.to = from; rev.cap = 0; rev.rev = edge;
        G[from] ~= edge;
        G[to] ~= rev;
    }
    void bfs(int s) {
        level[] = -1;
        DList!int Q;
        level[s] = 0;
        Q.insert(s);
        while (!Q.empty) {
            int v = Q.front; Q.removeFront;
            foreach (e; G[v]) {
                if (e.cap > 0 && level[e.to] < 0) {
                    level[e.to] = level[v] + 1;
                    Q.insert(e.to);
                }
            }
        }
    }
    int dfs(int v, int t, int f) {
        if (v == t) return f;
        for (; done[v] < G[v].length; done[v]++) {
            auto e = G[v][done[v]];
            if (e.cap > 0 && level[v] < level[e.to]) {
                int d = dfs(e.to, t, min(f, e.cap));
                if (d > 0) {
                    e.cap -= d;
                    e.rev.cap += d;
                    return d;
                }
            }
        }
        return 0;
    }
    int maxFlow(int s, int t) {
        int flow = 0;
        while (true) {
            bfs(s);
            if (level[t] < 0) return flow;
            done[] = 0;
            int f;
            while ((f = dfs(s, t, INF)) > 0) {
                flow += f;
            }
        }
        assert(0);
    }
}

void main() {
    int N, M;
    Troop[] ts;
    Point[] bs;
    bool input() {
        scanf("%d %d\n", &N, &M);
        if (N == 0 && M == 0) return false;
        ts = new Troop[N];
        foreach (i; 0 .. N) {
            int y, x, v; scanf("%d %d %d\n", &x, &y, &v);
            ts[i] = Troop(y, x, v);
        }
        bs = new Point[M];
        foreach (i; 0 .. M) {
            int y, x; scanf("%d %d\n", &x, &y);
            bs[i] = Point(y, x);
        }
        return true;
    }
    void solve() {
        bool check(double time) {
            auto X = new Dinic(N + M + 2);
            int s = N + M,
                t = N + M + 1;
            foreach (i; 0 .. N) {
                X.addEdge(s, i, 1);
            }
            foreach (j; 0 .. M) {
                X.addEdge(N + j, t, 1);
            }
            foreach (i; 0 .. N) {
                auto p = Point(ts[i].y, ts[i].x);
                foreach (j; 0 .. M) {
                    if (distance(p, bs[j]) <= time * ts[i].v) {
                        X.addEdge(i, N + j, 1);
                    }
                }
            }
            return X.maxFlow(s, t) == M;
        }

        double lb = 0, ub = 1e10;
        foreach (_; 0 .. 100) {
            double mid = (lb + ub) / 2;
            if (check(mid)) {
                ub = mid;
            } else {
                lb = mid;
            }
        }
        writefln("%.10f", ub);
    }
    while (input) solve;
}

Measured memory_bytes: 7504