#include "bits/stdc++.h"
using namespace std;

//#define int long long
#define DBG 1
#define dump(o) if(DBG){cerr<<#o<<" "<<(o)<<" ";}
#define dumpl(o) if(DBG){cerr<<#o<<" "<<(o)<<endl;}
#define dumpc(o) if(DBG){cerr<<#o; for(auto &e:(o))cerr<<" "<<e;cerr<<endl;}
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define rrep(i,a,b) for(int i=(b)-1;i>=(a);i--)
#define all(c) begin(c),end(c)
const int INF = sizeof(int) == sizeof(long long) ? 0x3f3f3f3f3f3f3f3fLL : 0x3f3f3f3f;
const int MOD = (int)(1e9 + 7);
template<class T> bool chmax(T &a, const T &b) { if (a < b) { a = b; return true; } return false; }
template<class T> bool chmin(T &a, const T &b) { if (a > b) { a = b; return true; } return false; }

using Weight = double;
class Edge {
public:
	int s; //source
	int d; //destination
	Weight w; //weight
	Edge(int s = 0, int d = 0, Weight w = INF) : s(s), d(d), w(w) {};
	bool operator<(const Edge &e)const { return w < e.w; }
};
using Edges = vector<Edge>;
using Graph = vector<Edges>;
using Array = vector<Weight>;
using Matrix = vector<Array>;
//???????????\
//G[s].emplace_back(s, d, w);
//G[d].emplace_back(d, s, w); ????????¨?????´???


enum { WHITE, GRAY, BLACK }; //?????¢?´¢, ??¢?´¢???, ??¢?´¢???
							 //???????§?????????????(???????????????) Single Source Shortest Path
							 //Dijkstra O((E+V)logV)
							 //dist: ?§????????????????????????§??????????????¢ distance
							 //?????????: ???????????¨????????????(??????-1)
vector<int> dijkstra(const Graph &g, int s, vector<Weight> &dist) {
	using State = tuple<Weight, int, int>; //?§?????????????????°?????????? ??? ???
	priority_queue<State, vector<State>, greater<State>> PQ;
	int n = g.size();
	vector<int> color(n, WHITE);
	vector<int> prev(n, -1);
	dist.assign(n, INF);
	dist[s] = 0; PQ.emplace(0, s, -1); color[s] = GRAY; //?§????
	while (PQ.size()) {
		Weight d; int v, u;
		tie(d, v, u) = PQ.top(); PQ.pop(); //dist???????°???¨??????State???????????????
		if (dist[v] < d)continue; //?????§???????????§???????????°??????
		color[v] = BLACK;
		prev[v] = u;
		for (auto &e : g[v]) { //??£??\????????????????????¨????????????		
			if (color[e.d] == BLACK)continue; //??¢?´¢????????????
			if (dist[e.d] > dist[v] + e.w) {
				dist[e.d] = dist[v] + e.w;
				PQ.emplace(dist[e.d], e.d, v);
				color[e.d] = GRAY;
			}
		}
	}
	return prev;
}

//???????§?????????????(???????????????) Single Source Shortest Path
//Bellman Ford O(VE)
//dist: ?§????????????????????????§??????????????¢
//?????????: ???????????¨????????????, ???????????????:true ??????:false
pair<vector<int>, bool> bellman_ford(const Graph &g, int s, vector<Weight> &dist) {
	int n = g.size();
	vector<int> prev(n, -1);
	Edges es; for (int i = 0; i < n; i++) for (auto &e : g[i]) es.emplace_back(e);
	dist.assign(n, INF); dist[s] = 0;
	bool negative_cycle = false;
	for (int i = 0;; i++) {
		bool update = false;
		for (auto &e : es) {
			if (dist[e.s] != INF && dist[e.d] > dist[e.s] + e.w) {
				dist[e.d] = dist[e.s] + e.w;
				prev[e.d] = e.s;
				update = true;
			}
		}
		if (!update) break;
		if (i > n) { negative_cycle = true; break; }
	}
	return make_pair(prev, !negative_cycle);
}

//?§?????????????????????§??????????????????
//???????????????????????°?????????????§??????????????????§?????????????????¢????????????
//?????¨???????????´???????????????: vector<int>()
vector<int> get_path(int s, int d, vector<int> prev) {
	vector<int> path;
	path.emplace_back(d);
	for (int i = d; i != s; ) {
		if (i == -1)return vector<int>();
		path.emplace_back(i = prev[i]);
	}
	reverse(path.begin(), path.end());
	return path;
}

//??¨????????????????????? All Pairs Shortest Path
//Warshall Floyd O(|V|^3)
//?????????: ???????????????:true ??????:false
bool warshall_floyd(const Graph &g, Matrix &dist) {
	int n = g.size();
	dist.assign(n, Array(n, INF));
	for (int i = 0; i < n; i++) dist[i][i] = 0;
	for (int i = 0; i < n; i++)
		for (auto e : g[i])
			dist[e.s][e.d] = min(dist[e.s][e.d], e.w);
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			for (int k = 0; k < n; k++)
				if (dist[j][i] != INF&&dist[i][k] != INF)
					dist[j][k] = min(dist[j][k], dist[j][i] + dist[i][k]);
	bool negative_cycle = false;
	for (int i = 0; i < n; i++)
		if (dist[i][i] != 0)
			negative_cycle = true;
	return !negative_cycle;
}

//??????????????????????????? O(E+V)
//??\?¬???°???0????????¨???????????????????????????ret????????£??????
vector<int> topological_sort(const Graph &g) {
	int n = g.size(), k = 0;
	vector<int> ord(n), indeg(n); //??\?¬???°
	for (auto &es : g) for (auto &e : es) indeg[e.d]++;
	queue<int> Q;
	for (int i = 0; i < n; i++) if (indeg[i] == 0) Q.push(i);
	while (!Q.empty()) {
		int v = Q.front(); Q.pop(); ord[k++] = v;
		for (auto &e : g[v]) if (--indeg[e.d] == 0) Q.push(e.d);
	}
	return *max_element(indeg.begin(), indeg.end()) == 0 ? ord : vector<int>();
}

//??¨?????´???
Edge diameter(const Graph &g, int s = 0) {
	vector<Weight> dist;
	dijkstra(g, s, dist);
	int n = g.size(), u = -1, v = -1;
	for (int i = 0; i < n; i++) if (dist[i] != INF && (u == -1 || dist[i] > dist[u])) u = i;
	dijkstra(g, u, dist);
	for (int i = 0; i < n; i++) if (dist[i] != INF && (v == -1 || dist[i] > dist[v])) v = i;
	Weight d = dist[v];
	if (u > v) swap(u, v);
	return Edge(u, v, d);
}

//#include "UnionFind.cpp"
////????°???¨?????¨
////Kruskal O(|E|log|E|)
//pair<Weight, Edges> kruskal(const Graph &g) {
//	UnionFind UF(g.size());
//	Edges es;
//	for (int i = 0; i < g.size(); i++) for (auto &e : g[i]) es.emplace_back(e);
//	sort(es.begin(), es.end());
//	Weight total = 0;
//	Edges T;
//	for (auto &e : es) if (!UF.same(e.s, e.d)) {
//		T.push_back(e); total += e.w; UF.unite(e.s, e.d);
//	}
//	return make_pair(total, T);
//}
//
////????°???¨?????¨
////Prim O(ElogV)
////r????????°?????????????????????????±?
////Edge??? bool operator<(const Edge &e)const { return w > e.w; } ????????????????????????
//pair<Weight, Edges> prim(const Graph &g, int r = 0) {
//	Edges T; Weight total = 0; vector<int> v(g.size());
//	priority_queue <Edge> q;
//	q.emplace(-1, r, 0);
//	while (q.size()) {
//		Edge e = q.top(); q.pop();
//		if (v[e.d]) continue;
//		v[e.d] = true;
//		total += e.w; if (e.s != -1) T.emplace_back(e);
//		for (auto &f : g[e.d]) if (!v[f.d]) q.emplace(f);
//	}
//	return make_pair(total, T);
//}

//#define double long double
const double EPS = 1e-8; //???????????¨????????´
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define next(P,i) P[(i+1)%P.size()]
#define prev(P,i) P[(i+P.size()-1)%P.size()]

class Point {
public:
	double x, y;
	Point() {}
	Point(double x, double y) :x(x), y(y) {}

	Point operator+(const Point &p)const { return Point(x + p.x, y + p.y); }
	Point operator-(const Point &p)const { return Point(x - p.x, y - p.y); }
	Point operator*(double a)const { return Point(a * x, a * y); }
	Point operator/(double a)const { return Point(x / a, y / a); }
	bool operator<(const Point &p)const {
		//return y != p.y ? y < p.y : x < p.x; // y?????? -> x??????
		return x != p.x ? x < p.x : y < p.y; // x?????? -> y??????
	}
	bool operator==(const Point &p)const { return equals(x, p.x) && equals(y, p.y); }

	double abs() { return sqrt(norm()); }
	double norm() { return x*x + y*y; }
};
inline ostream &operator << (ostream &os, const Point &p) { os << p.x << " " << p.y; return os; }
inline istream &operator >> (istream &is, Point &p) { double x, y; is >> x >> y; p = Point(x, y); return is; }

class Vector :public Point {
public:
	using Point::Point;
	Vector() {}
	Vector(const Point &P) { x = P.x; y = P.y; }
	Vector rotate(double rad) { return Vector(x*cos(rad) - y*sin(rad), x*sin(rad) + y*cos(rad)); }
	Vector unit() { return *this / abs(); }
};

//?????? dot product
double dot(Vector a, Vector b) { return a.x*b.x + a.y*b.y; }
//?????? cross product ?????§???????????£????????????
double cross(Vector a, Vector b) { return a.x*b.y - a.y*b.x; }

class Line {
public:
	Point p1, p2;
	Line() {}
	Line(Point p1, Point p2) :p1(p1), p2(p2) {}
};

class Segment :public Line {
public:
	using Line::Line;
	Segment() {}
	Segment(const Line &L) { p1 = L.p1; p2 = L.p2; }
	Vector vec() { return p2 - p1; }
};

class Circle {
public:
	Point c; //center
	double r; //radius
	Circle() {}
	Circle(Point c, double r) :c(c), r(r) {}
};
using Polygon = vector<Point>;

//?????????????????¢??? degree to radian
double rad(double deg) { return acos(-1)*deg / 180; }
//????§? argument
double arg(Vector p) { return atan2(p.y, p.x); }
//?\???¢??? polar form
Vector polar(double r, double a) { return Point(cos(a)*r, sin(a)*r); }
//2??????????????????????§????
double angle(Vector a, Vector b) {
	double lena = a.abs(), lenb = b.abs();
	if (lena == 0 || lenb == 0)return 0; //?§£??????
	double costheta = dot(a, b) / (lena*lenb);
	if (equals(costheta, 1))costheta = 1; //????????????
	return acos(costheta);
}

bool inrange(Point p, double x1, double y1, double x2, double y2) {
	return x1 <= p.x&&p.x <= x2&&y1 <= p.y&&p.y <= y2;
}

//??´?????????
bool is_orthogonal(Vector a, Vector b) { return equals(dot(a, b), 0.0); }
bool is_orthogonal(Segment s1, Segment s2) { return equals(dot(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0); }

//????????????
bool is_parallel(Vector a, Vector b) { return equals(cross(a, b), 0.0); }
bool is_parallel(Segment s1, Segment s2) { return equals(cross(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0); }

//?°???±
Point project(Segment s, Point p) {
	Vector base = s.p2 - s.p1;
	double r = dot(p - s.p1, base) / base.norm();
	return s.p1 + base*r;
}
//????°?
Point reflect(Segment s, Point p) { return p + (project(s, p) - p)*2.0; }

//??????(p0,p1)????????????p2???????????¢???
enum { ONLINE_FRONT = -2, CLOCKWISE, ON_SEGMENT, COUNTER_CLOCKWISE, ONLINE_BACK };
int ccw(Point p0, Point p1, Point p2) {
	Vector a = p1 - p0, b = p2 - p0;
	if (cross(a, b) > EPS)return COUNTER_CLOCKWISE;
	if (cross(a, b) < -EPS)return CLOCKWISE;
	if (dot(a, b) < -EPS)return ONLINE_BACK; //p2 p0 p1
	if (a.norm() < b.norm())return ONLINE_FRONT; //p0 p1 p2
	return ON_SEGMENT;
}
int ccw(Vector a, Vector b) {
	if (cross(a, b) > EPS)return COUNTER_CLOCKWISE;
	if (cross(a, b) < -EPS)return CLOCKWISE;
	if (dot(a, b) < -EPS)return ONLINE_BACK; //p2 p0 p1
	if (a.norm() < b.norm())return ONLINE_FRONT; //p0 p1 p2
	return ON_SEGMENT;
}

//??´?????¨??´??????????????????
bool intersect(Segment a, Segment b) {
	Point p1 = a.p1, p2 = a.p2, p3 = b.p1, p4 = b.p2;
	return (ccw(p1, p2, p3)*ccw(p1, p2, p4) <= 0 &&
		ccw(p3, p4, p1)*ccw(p3, p4, p2) <= 0);
}
//(?????????????¶????)

//2??????????????¢
double get_distance(Point a, Point b) { return (a - b).abs(); }
//??´?????¨???????????¢
double get_distance(Line l, Point p) { return abs(cross(l.p2 - l.p1, p - l.p1) / (l.p2 - l.p1).abs()); }
//????????¨???????????¢
double get_distance(Segment s, Point p) {
	if (dot(s.p2 - s.p1, p - s.p1) < 0.0)return (p - s.p1).abs();
	if (dot(s.p1 - s.p2, p - s.p2) < 0.0)return (p - s.p2).abs();
	return get_distance(Line(s), p);
}
//????????¨??????????????¢
double get_distance(Segment s1, Segment s2) {
	if (intersect(s1, s2))return 0.0;
	return	min(
		min(get_distance(s1, s2.p1), get_distance(s1, s2.p2)),
		min(get_distance(s2, s1.p1), get_distance(s2, s1.p2))
	);
}

//?????¨??´??????????????????
bool intersect(Circle c, Line l) { return get_distance(l, c.c) <= c.r + EPS; }
//?????¨?????????????????? ??±?????\????????°
int intersect(Circle c1, Circle c2) {
	double d = get_distance(c1.c, c2.c);
	if (d > c1.r + c2.r)return 4;
	if (d == c1.r + c2.r)return 3;
	if (d + c1.r == c2.r || d + c2.r == c1.r)return 1;
	if (d + c1.r < c2.r || d + c2.r < c1.r)return 0;
	return 2;
}

//????????¨???????????????
Point get_cross_point(Segment a, Segment b) {
	assert(intersect(a, b));
	Vector base = b.p2 - b.p1;
	double area1 = abs(cross(base, a.p1 - b.p1));
	double area2 = abs(cross(base, a.p2 - b.p1));
	double t = area1 / (area1 + area2);
	return a.p1 + (a.p2 - a.p1)*t;
}

//?????¨??´????????????
pair<Point, Point> get_cross_points(Circle c, Line l) {
	assert(intersect(c, l));
	Vector pr = project(l, c.c);
	Vector e = (l.p2 - l.p1) / (l.p2 - l.p1).abs();
	double base = sqrt(c.r*c.r - (pr - c.c).norm());
	return make_pair(pr + e*base, pr - e*base);
}
//?????¨????????????
pair<Point, Point> get_cross_points(Circle c1, Circle c2) {
	int m = intersect(c1, c2);
	assert(m != 4 && m != 0);
	double d = (c1.c - c2.c).abs();
	double a = acos((c1.r*c1.r + d*d - c2.r*c2.r) / (2 * c1.r*d));
	double t = arg(c2.c - c1.c);
	return make_pair(c1.c + polar(c1.r, t + a), c1.c + polar(c1.r, t - a));
}

//????????????
enum { OUT = 0, ON, IN };
int contains(const Polygon &pl, Point p) {
	int n = pl.size();
	bool x = false;
	for (int i = 0; i < n; i++) {
		Point a = pl[i] - p, b = pl[(i + 1) % n] - p;
		if (abs(cross(a, b)) < EPS&&dot(a, b) < EPS)return ON;
		if (a.y > b.y)swap(a, b);
		if (a.y < EPS&&EPS<b.y&&cross(a, b)>EPS)x = !x;
	}
	return (x ? IN : OUT);
}

int contains(Circle c, Point p) {
	double d = get_distance(c.c, p);
	if (equals(d, c.r))return ON;
	if (d < c.r)return IN;
	return OUT;
}

//????§???¢?????¢???
double area(const Polygon &p) {
	double a = 0;
	for (size_t i = 0; i < p.size(); i++)
		a += cross(p[i], p[(i + 1) % p.size()]);
	return a / 2.0;
}

//?????§????????????????¨??????????
bool is_convex(Polygon g) {
	for (size_t i = 0; i < g.size(); i++)
		if (ccw(g[i], g[(i + 1) % g.size()], g[(i + 2) % g.size()]) == CLOCKWISE)
			return false;
	return true;
}

//??????
//Graham scan https://en.wikipedia.org/wiki/Graham_scan
//???????????????????????????
Polygon convex_hull(Polygon P) {
	sort(P.begin(), P.end());
	Polygon up;
	for (Point &p : P) {
		while (up.size() > 1 && ccw(up[up.size() - 2], up[up.size() - 1], p) != CLOCKWISE)up.pop_back();
		up.emplace_back(p);
	}
	Polygon down;
	for (Point &p : P) {
		while (down.size() > 1 && ccw(down[down.size() - 2], down[down.size() - 1], p) != COUNTER_CLOCKWISE)down.pop_back();
		down.emplace_back(p);
	}
	reverse(up.begin(), up.end()); // ???????¨??????????
	down.insert(down.end(), up.begin() + 1, up.end() - 1);
	return down;
}

//??????
//Graham scan https://en.wikipedia.org/wiki/Graham_scan
//?????????????????????
Polygon convex_hull_with_points_online(Polygon P) {
	sort(P.begin(), P.end());
	Polygon up;
	for (Point &p : P) {
		int _ccw;
		while (up.size() > 1 && (_ccw = ccw(up[up.size() - 2], up[up.size() - 1], p)) != CLOCKWISE &&_ccw != ONLINE_FRONT)
			up.pop_back();
		up.emplace_back(p);
	}
	Polygon down;
	for (Point &p : P) {
		int _ccw;
		while (down.size() > 1 && (_ccw = ccw(down[down.size() - 2], down[down.size() - 1], p)) != COUNTER_CLOCKWISE && _ccw != ONLINE_FRONT)
			down.pop_back();
		down.emplace_back(p);
	}
	reverse(up.begin(), up.end()); // ???????¨??????????
	down.insert(down.end(), up.begin() + 1, up.end() - 1);
	return down;
}

//???????§???¢??????????????????????????¢
//calipers https://en.wikipedia.org/wiki/Rotating_calipers
double diameter(Polygon P) {
	P = convex_hull(P);
	auto mima = minmax_element(P.begin(), P.end());
	int I = mima.first - P.begin();
	int J = mima.second - P.begin();
	double maxd = get_distance(P[I], P[J]);

	int maxi, maxj, i, j;
	i = maxi = I;
	j = maxj = J;
	do {
		if (ccw(next(P, i) - P[i], next(P, j) - P[j]) == COUNTER_CLOCKWISE)
			j = (j + 1) % P.size();
		else
			i = (i + 1) % P.size();
		if (maxd < get_distance(P[i], P[j])) {
			maxd = get_distance(P[i], P[j]);
			maxi = i, maxj = j;
		}
	} while (!(i == I&&j == J));
	return maxd;
}

//????§???¢???(0,0)???????????¨???????????¢
Polygon rotate(const Polygon &P, double rad) {
	Polygon ret;
	for (auto &p : P)
		ret.emplace_back(p.x*cos(rad) - p.y*sin(rad), p.x*sin(rad) + p.y*cos(rad));
	return ret;
}

//Heron's formula
double area(double a, double b, double c) {
	double s = (a + b + c) / 2;
	return sqrt(s*(s - a)*(s - b)*(s - c));
}

//????§???¢?????????
Point center(const Polygon &P) {
	Point ret(0, 0);
	for (auto &p : P)ret = ret + p;
	ret = ret / P.size();
	return ret;
}

signed main() {
	cout << fixed << setprecision(8);
	for (int n; cin >> n&&n;) {
		vector<Point> p(n);
		vector<double> v(n);
		rep(i, 0, n) cin >> p[i] >> v[i];

		double r = 0.98;
		Point o(0, 0);

		auto calc = [&](Point o) {
			auto mx = make_pair(0.0, 0);
			rep(i, 0, n) mx = max(mx, make_pair((o - p[i]).abs() / v[i], i));
			return mx;
		};

		for (double d = 10; d > 1e-8; d *= r) {
			auto mx = calc(o).second;
			o = o + (p[mx] - o) / (p[mx] - o).abs() * d;
		}
		cout << calc(o).first << endl;
	}
	return 0;
}

Measured memory_bytes: 3308