#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const double eps = 1e-8;
int dcmp(double x) {
if(fabs(x) < eps) return 0;
else return x < 0 ? -1 : 1;
}
struct point{
double x,y;
point(){}
point(double _x,double _y)
{
x=_x;y=_y;
}
double operator ^(const point &c)const
{
return x*c.y - y*c.x;
}
};
point operator + (point A, point B) { return point(A.x + B.x, A.y + B.y); }
point operator - (point A, point B) { return point(A.x - B.x, A.y - B.y); }
point operator * (point A, double p) { return point(A.x * p, A.y * p); }
point operator / (point A, double p) { return point(A.x/p, A.y/p); }
bool operator < (const point& a, const point& b) {
return a.x < b.x || (a.x == b.x && a.y < b.y); // 逆时针求凸包a.y < b.y || (a.y == b.y && a.x < b.x);
}
bool operator == (const point& a, const point& b) {
return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}
struct LINE{
point a,b;
LINE(){}
LINE(point _a,point _b){
a=_a;b=_b;
}
};
double Dot(point A, point B) { return A.x * B.x + A.y * B.y; } //点积
double Cross(point A, point B) { return A.x * B.y - A.y * B.x; } //叉积
double intersection(point A,point B,point C,point D) // 求两直线交点的x坐标
{
double area1=Cross(B-A,C-A);
double area2=Cross(B-A,D-A);
int c=dcmp(area1);
int d=dcmp(area2);
if(c*d<0) //CD在AB的两侧,规范相交
return (area2*C.x - area1*D.x)/(area2-area1); //黑书P357交点计算公式
if(c*d==0) //CD的其中一个端点在AB上,不规范相交
if(c==0)
return C.x;//C在AB上,返回AB与CD非规范相交时的交点C的横坐标
else
return D.x;//D在AB上,返回AB与CD非规范相交时的交点D的横坐标
return -99999; //CD在AB同侧,无交点,返回 负无穷
}
//两直线交点(点,向量,点,向量)
point Getlinenode(point P, point v, point Q, point w) {
// printf("w.x=%f,w.y=%f\n",w.x,w.y);
point u = P - Q;
double t = Cross(w, u) / Cross(v, w);
return P + v * t;
}
//判断两线段是否相交(不包括端点)
bool seg_seg_Cross(point s1,point e1,point s2,point e2)
{
///第一步,快速排斥实验
if(!(min(s1.x,e1.x)<=max(s2.x,e2.x)&&min(s2.x,e2.x)<=max(s1.x,e1.x)&&
min(s1.y,e1.y)<=max(s2.y,e2.y)&&min(s2.y,e2.y)<=max(s1.y,e1.y))) return false;
double c1=Cross(s2-s1,e1-s1),c2=Cross(e1-s1,e2-s1);
double c3=Cross(s1-s2,e2-s2),c4=Cross(e2-s2,e1-s2);
if(dcmp(c1*c2)>=0&&dcmp(c3*c4)>=0) return 1;
return 0;
}
//判断线段相交
bool inter(LINE l1,LINE l2)
{
return
max(l1.a.x,l1.b.x) >= min(l2.a.x,l2.b.x) &&
max(l2.a.x,l2.b.x) >= min(l1.a.x,l1.b.x) &&
max(l1.a.y,l1.b.y) >= min(l2.a.y,l2.b.y) &&
max(l2.a.y,l2.b.y) >= min(l1.a.y,l1.b.y) &&
dcmp((l2.a-l1.b)^(l1.a-l1.b))*dcmp((l2.b-l1.b)^(l1.a-l1.b)) <= 0 &&
dcmp((l1.a-l2.b)^(l2.a-l2.b))*dcmp((l1.b-l2.b)^(l2.a-l2.b)) <= 0;
}
//判断点在线段上
bool OnSeg(point P,LINE L)
{
return
dcmp((L.a-P)^(L.b-P)) == 0 &&
dcmp((P.x - L.a.x) * (P.x - L.b.x)) <= 0 &&
dcmp((P.y - L.a.y) * (P.y - L.b.y)) <= 0;
}
//判断直线与线段相交,s1e1表示直线,s2e2表示线段
bool line_seg_Cross(point s1,point e1,point s2,point e2)
{
double c1=Cross(s2-s1,e1-s1),c2=Cross(e1-s1,e2-s1);
//==0表示,相交于端点也认定为相交
if(dcmp(c1*c2)>=0) return true;
return false;
}
//点距离
double distance(double x1,double y1,double x2,double y2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
// 点集凸包
// 如果不希望在凸包的边上有输入点,把两个 <= 改成 <
// 如果不介意点集被修改,可以改成传递引用
vector<point> ConvexHull(vector<point> p) {
// 预处理,删除重复点
sort(p.begin(), p.end());
p.erase(unique(p.begin(), p.end()), p.end());
int n = p.size();
int m = 0;
vector<point> ch(n+1);
for(int i = 0; i < n; i++) {
while(m > 1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) < 0) m--;
ch[m++] = p[i];
}
int k = m;
for(int i = n-2; i >= 0; i--) {
while(m > k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) < 0) m--;
ch[m++] = p[i];
}
if(n > 1) m--;
ch.resize(m);
return ch;
}
bool OnSegment(const point& p, const point& a1, const point& a2) {
return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) < 0;
}
//点是否在凸包内
int IsPointInPolygon(const point& p, const vector<point>& poly) {
int wn = 0;
int n = poly.size();
for(int i=0; i<n; ++i) {
const point& p1 = poly[i];
const point& p2 = poly[(i+1)%n];
if(p1 == p || p2 == p || OnSegment(p, p1, p2)) return -1;//在边界上
int k = dcmp(Cross(p2-p1, p-p1));
int d1 = dcmp(p1.y - p.y);
int d2 = dcmp(p2.y - p.y);
if(k > 0 && d1 <= 0 && d2 > 0) wn++;
if(k < 0 && d2 <= 0 && d1 > 0) wn--;
}
if(wn != 0) return 1;
return 0;
}
bool SegmentProperIntersection(const point& a1, const point& a2, const point& b1, const point& b2) {
double c1 = Cross(a2-a1,b1-a1), c2 = Cross(a2-a1,b2-a1),
c3 = Cross(b2-b1,a1-b1), c4=Cross(b2-b1,a2-b1);
return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
}
//判断2个凸包是否相交
bool ConvexPolygonDisjoint(const vector<point> ch1, const vector<point> ch2) {
int c1 = ch1.size();
int c2 = ch2.size();
for(int i=0; i<c1; ++i)
if(IsPointInPolygon(ch1[i], ch2) != 0) return false;
for(int i=0; i<c2; ++i)
if(IsPointInPolygon(ch2[i], ch1) != 0) return false;
for(int i=0; i<c1; ++i)
for(int j=0; j<c2; ++j)
if(SegmentProperIntersection(ch1[i], ch1[(i+1)%c1], ch2[j], ch2[(j+1)%c2])) return false;
return true;
}
LINE l[10];
//极角排序 速度快,精度小
int cmps(point aa,point bb){
return atan2(aa.y,aa.x) < atan2(bb.y,bb.x);
}
//关于c点极角排序
bool cmp2(point a,point b)
{
point c;//原点
c.x = 0 , c.y = 0;//可修改
if(Cross(a-c,b-c)>0) return 1;
return 0;
}
int Quadrant(point a) //象限排序,注意包含四个坐标轴
{
if(a.x>0&&a.y>=0) return 1;
if(a.x<=0&&a.y>0) return 2;
if(a.x<0&&a.y<=0) return 3;
if(a.x>=0&&a.y<0) return 4;
}
bool cmp3(point a,point b) //先按象限从小到大排序 再按极角从小到大排序
{
if(Quadrant(a)==Quadrant(b))//返回值就是象限
return cmps(a,b);
else Quadrant(a)<Quadrant(b);
}
int main(){
int n;
scanf("%d",&n);
double xx,xxx,yy,yyy;
int f;
while(n--){
f=0;
scanf("%lf %lf %lf %lf",&l[0].a.x,&l[0].a.y,&l[0].b.x,&l[0].b.y);
scanf("%lf %lf %lf %lf",&xx,&yy,&xxx,&yyy);
double mxx = max(xx,xxx),mixx = min(xx,xxx);
xx = mixx , xxx = mxx;
double myy = max(yy,yyy),miyy = min(yy,yyy);
yy = miyy , yyy = myy;
if(l[0].a.x < l[0].b.x){
swap(l[0].a , l[0].b);
}
l[1].a.x = xx , l[1].a.y = yy , l[1].b.x = xx , l[1].b.y = yyy;
l[2].a.x = xx , l[2].a.y = yy , l[2].b.x = xxx , l[2].b.y = yy;
l[3].a.x = xxx , l[3].a.y = yyy , l[3].b.x = xx , l[3].b.y = yyy;
l[4].a.x = xxx , l[4].a.y = yyy , l[4].b.x = xxx , l[4].b.y = yy;
for(int i=1;i<=4;i++){
if(l[i].a.x > l[i].b.x) swap(l[i].a,l[i].b);
if( inter(l[0],l[i]) || (OnSeg(l[0].a,l[i]) || (OnSeg(l[0].b,l[i])) )/*OnSeg(l[0].a,l[i]) || OnSeg(l[0].b,l[i])|| line_seg_Cross(l[0].a,l[0].b,l[i].a,l[i].b)*/){
f=1;
break;
}
}
if(l[0].a.x+eps < xxx && l[0].a.x >eps+ xx && l[0].a.y > eps+yy && l[0].a.y+eps < yyy)
f=1;
if(f==0){
cout << "F" <<endl;
}
else{
cout << "T" <<endl;
}
}
}