#include <iostream>
#include <algorithm>
#include <numeric>
#include <vector>
#include <cassert>
#include <string>
#include <memory.h>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <set>
#include <map>
#include <cctype>
#include <iomanip>
#include <sstream>
#include <cctype>
#include <fstream>
#include <cmath>
using namespace std;

#define REP2(i, m, n) for(int i = (int)(m); i < (int)(n); i++)
#define REP(i, n) REP2(i, 0, n)
#define ALL(c) (c).begin(), (c).end()
#define ITER(c) __typeof((c).begin())
#define PB(e) push_back(e)
#define FOREACH(i, c) for(ITER(c) i = (c).begin(); i != (c).end(); ++i)
#define MP(a, b) make_pair(a, b)
#define PARITY(n) ((n) & 1)
#define SQR(x) ((x) * (x))

typedef long long ll;
typedef pair<ll, ll> P;
const int INF = 1000 * 1000 * 1000 + 7;
const double EPS = 1e-12;

class BipartiteMatching{
  int V;
  int W;
  vector<int> match;
  vector<int> level;
  vector<vector<int> > graph;
  
  int bfs(){
    fill(level.begin(), level.end(), -1);
    queue<int> que;
    for(int v = 0; v < V; v++){
      if(match[v] == -1){
        que.push(v);
        level[v] = 0;
      }
    }
    bool done = true;
    while(!que.empty()){
      int v = que.front(); que.pop();
      for(size_t i = 0; i < graph[v].size(); i++){
        int w = graph[v][i], nextv = match[w];
        if(nextv == -1){
          done = false;
        }else if(level[nextv] == -1){
          level[nextv] = level[v] + 1;
          que.push(nextv);
        }
      }
    }
    return !done;
  }
  
  bool dfs(int v){
    for(size_t i = 0; i < graph[v].size(); i++){
      int w = graph[v][i], nextv = match[w];
      if(nextv == -1 || (level[nextv] == level[v] + 1 && dfs(nextv))){
        match[v] = w;
        match[w] = v;
        return true;
      }
    }
    level[v] = -2;
    return false;
  }

public:
  BipartiteMatching(int _V, int _W) :
    V(_V), W(_W),
    match(vector<int>(V + W, -1)),
    level(vector<int>(V)),
    graph(vector<vector<int> >(V)){}
  
  void add_edge(int from, int to){
    assert(0 <= from && from < V && V <= to && to < V + W);
    graph[from].push_back(to);
  }
  
  int solve(){
    int ans = 0;
    while(bfs()){
      for(int v = 0; v < V; v++){
        if(match[v] == -1 && dfs(v)) ans++;
      }
    }
    return ans;
  }
};


int main(){
  int N, M;
  while(cin >> N >> M && N + M){
    vector<double> tx(N), ty(N), tv(N), bx(M), by(M);
    REP(i, N) cin >> tx[i] >> ty[i] >> tv[i];
    REP(i, M) cin >> bx[i] >> by[i];


    vector<double> times(1, 0.0);
    REP(i, N)REP(j, M){
      double t = sqrt(SQR(tx[i] - bx[j]) + SQR(ty[i] - by[j])) / tv[i];
      times.push_back(t);
    }
    sort(ALL(times));
    int lb = 0;
    int ub = N * M;
    
    while(ub - lb > 1){
      int mb = (ub + lb) / 2;

      bool can_deploy = true;
      BipartiteMatching bm(N, M);
        
      REP(i, N){
        bool ok = false;
        REP(j, M){
          double time = sqrt(SQR(tx[i] - bx[j]) + SQR(ty[i] - by[j])) / tv[i];
          if(time < times[mb] + EPS){
            bm.add_edge(i, j + N);
            ok = true;
          }
        }
        can_deploy |= ok;
      }
      
      if(can_deploy && bm.solve() == M){
        ub = mb;
      }else{
        lb = mb;
      }      
    }
    printf("%.9f\n", times[ub]);
  }
  return 0;
}
  

Measured memory_bytes: 1404