import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Iterator;
import java.io.BufferedWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.Comparator;
import java.util.NoSuchElementException;
import java.io.InputStream;
/**
* Built using CHelper plug-in
* Actual solution is at the top
*/
public class Main {
public static void main
(String[] args
) { InputReader in = new InputReader(inputStream);
OutputWriter out = new OutputWriter(outputStream);
C solver = new C();
int testCount
= Integer.
parseInt(in.
next()); for (int i = 1; i <= testCount; i++)
solver.solve(i, in, out);
out.close();
}
static class C {
int DIV = 10 * 1000 * 1000;
double[][] mem;
int[] prefixPre;
double dp
(int travelIndex,
boolean prevFound,
Integer[] perm,
int[] saved,
int[] x
) { if (travelIndex == perm.length) return 0;
if (mem[travelIndex][prevFound ? 1 : 0] > -1) return mem[travelIndex][prevFound ? 1 : 0];
int idx = perm[travelIndex];
double res = prevFound ? saved[idx] : 0;
if (prevFound) {
res += dp(travelIndex + 1, true, perm, saved, x);
} else {
int prefix = prefixPre[travelIndex];
double probFind = (DIV - prefix == 0) ? 0 : ((double) x[idx] / (DIV - prefix));
double savedIfFound = dp(travelIndex + 1, true, perm, saved, x);
double savedIfNotFound = dp(travelIndex + 1, false, perm, saved, x);
res += probFind * savedIfFound;
res += (1 - probFind) * savedIfNotFound;
}
return mem[travelIndex][prevFound ? 1 : 0] = res;
}
public void solve(int testNumber, InputReader in, OutputWriter out) {
int n = in.readInt();
mem = new double[n][2];
ArrayUtils.fill(mem, -2);
int[] a = new int[n], b = new int[n], x = new int[n];
IOUtils.readIntArrays(in, a, b, x);
int[] saved = new int[n];
for (int i = 0; i < saved.length; i++) saved[i] = a[i] - b[i];
for (int i = 0; i < perm.length; i++) perm[i] = i;
Arrays.
sort(perm,
new Comparator
<Integer
>() { double val1 = (double) saved[o1] / x[o1];
double val2 = (double) saved[o2] / x[o2];
return Double.
compare(val1, val2
); }
});
prefixPre = new int[n + 1];
for (int i = 1; i < prefixPre.length; i++) {
prefixPre[i] = prefixPre[i - 1] + x[perm[i - 1]];
}
double savings = dp(0, false, perm, saved, x);
out.printLine(ArrayUtils.sumArray(a) - savings);
}
}
static class OutputWriter {
}
public OutputWriter
(Writer writer
) { }
public void print
(Object...
objects) { for (int i = 0; i < objects.length; i++) {
if (i != 0) {
writer.print(' ');
}
writer.print(objects[i]);
}
}
public void printLine
(Object...
objects) { print(objects);
writer.println();
}
public void close() {
writer.close();
}
}
static class InputReader {
private byte[] buf = new byte[1024];
private int curChar;
private int numChars;
private InputReader.SpaceCharFilter filter;
this.stream = stream;
}
public int read() {
if (numChars == -1) {
throw new InputMismatchException();
}
if (curChar >= numChars) {
curChar = 0;
try {
numChars = stream.read(buf);
throw new InputMismatchException();
}
if (numChars <= 0) {
return -1;
}
}
return buf[curChar++];
}
public int readInt() {
int c = read();
while (isSpaceChar(c)) {
c = read();
}
int sgn = 1;
if (c == '-') {
sgn = -1;
c = read();
}
int res = 0;
do {
if (c < '0' || c > '9') {
throw new InputMismatchException();
}
res *= 10;
res += c - '0';
c = read();
} while (!isSpaceChar(c));
return res * sgn;
}
int c = read();
while (isSpaceChar(c)) {
c = read();
}
StringBuilder res = new StringBuilder();
do {
res.appendCodePoint(c);
}
c = read();
} while (!isSpaceChar(c));
return res.toString();
}
public boolean isSpaceChar(int c) {
if (filter != null) {
return filter.isSpaceChar(c);
}
return isWhitespace(c);
}
public static boolean isWhitespace(int c) {
return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
}
return readString();
}
public interface SpaceCharFilter {
public boolean isSpaceChar(int ch);
}
}
static class ArrayUtils {
public static void fill(double[][] array, double value) {
for (double[] row : array) {
}
}
public static long sumArray(int[] array) {
return new IntArray(array).sum();
}
}
static interface IntStream extends Iterable<Integer>, Comparable<IntStream> {
public IntIterator intIterator();
default public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
private IntIterator it = intIterator();
public boolean hasNext() {
return it.isValid();
}
int result = it.value();
it.advance();
return result;
}
};
}
default public int compareTo(IntStream c) {
IntIterator it = intIterator();
IntIterator jt = c.intIterator();
while (it.isValid() && jt.isValid()) {
int i = it.value();
int j = jt.value();
if (i < j) {
return -1;
} else if (i > j) {
return 1;
}
it.advance();
jt.advance();
}
if (it.isValid()) {
return 1;
}
if (jt.isValid()) {
return -1;
}
return 0;
}
default public long sum() {
long result = 0;
for (IntIterator it = intIterator(); it.isValid(); it.advance()) {
result += it.value();
}
return result;
}
}
static interface IntCollection extends IntStream {
public int size();
}
static class IOUtils {
public static void readIntArrays(InputReader in, int[]... arrays) {
for (int i = 0; i < arrays[0].length; i++) {
for (int j = 0; j < arrays.length; j++) {
arrays[j][i] = in.readInt();
}
}
}
}
static abstract class IntAbstractStream implements IntStream {
StringBuilder builder = new StringBuilder();
boolean first = true;
for (IntIterator it = intIterator(); it.isValid(); it.advance()) {
if (first) {
first = false;
} else {
builder.append(' ');
}
builder.append(it.value());
}
return builder.toString();
}
public boolean equals
(Object o
) { if (!(o instanceof IntStream)) {
return false;
}
IntStream c = (IntStream) o;
IntIterator it = intIterator();
IntIterator jt = c.intIterator();
while (it.isValid() && jt.isValid()) {
if (it.value() != jt.value()) {
return false;
}
it.advance();
jt.advance();
}
return !it.isValid() && !jt.isValid();
}
public int hashCode() {
int result = 0;
for (IntIterator it = intIterator(); it.isValid(); it.advance()) {
result *= 31;
result += it.value();
}
return result;
}
}
static interface IntList extends IntReversableCollection {
public abstract int get(int index);
public abstract void removeAt(int index);
default public IntIterator intIterator() {
return new IntIterator() {
private int at;
private boolean removed;
public int value() {
if (removed) {
}
return get(at);
}
public boolean advance() {
at++;
removed = false;
return isValid();
}
public boolean isValid() {
return !removed && at < size();
}
public void remove() {
removeAt(at);
at--;
removed = true;
}
};
}
}
static interface IntIterator {
public boolean advance();
public boolean isValid();
}
static interface IntReversableCollection extends IntCollection {
}
static class IntArray extends IntAbstractStream implements IntList {
private int[] data;
public IntArray(int[] arr) {
data = arr;
}
public int size() {
return data.length;
}
public int get(int at) {
return data[at];
}
public void removeAt(int index) {
}
}
}