#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1010;
const int M=20010;
const int INF=0x3f3f3f;
struct Time
{
int x1,x2,h;
}a[N];
int dp[N+2][2]; // 0:表示第i的木板左边到底部的最短时间
// 1: 表示第i的木板右边到底部的最短时间
int n,x,y,max_h;
int cmp(Time c,Time b) //排序函数
{
return c.h > b.h; //从大到小排列
}
void left(int i)//左
{
//如果平台i下面有平台,且两者相距不超过MAX
int k = i+1;
while( k<n+1 && a[i].h-a[k].h<=max_h ) //n+1处是地面
{
//确保平台k在平台i的左下方,且小鼠可以跳到上面
if(a[i].x1>=a[k].x1&&a[i].x1<= a[k].x2)
{
//从i的左端跳到地面的时间
//i先跳到k的时间+
//min(从k左端跳到地面的时间+从i的左端到k的左端的时间,从k的右端跳到地面的时间+从i左端到k的右端)
dp[i][0]=a[i].h-a[k].h+min(dp[k][0]+a[i].x1-a[k].x1,dp[k][1]+a[k].x2-a[i].x1);
return;
}
k++;
}
//因为第二个条件出的循环即:不能到达下一平台
if(a[i].h-a[k].h>max_h)
dp[i][0]=INF;
//因为它下面没木板,直接落地
else
dp[i][0]=a[i].h;
}
void right(int i)//右
{
//如果平台i下面有平台,且两者相距不超过MAX
int k=i+1;
while(k<n+1 && a[i].h-a[k].h<=max_h)
{
//确保平台k在平台i的右下方,且小鼠可以跳到上面
if(a[i].x2<=a[k].x2 && a[i].x2 >= a[k].x1)
{
dp[i][1]=a[i].h-a[k].h+min(dp[k][0] + a[i].x2-a[k].x1 , dp[k][1] + a[k].x2-a[i].x2);
return;
}
k++;
}
//不能到达下一平台
if(a[i].h-a[k].h > max_h)
dp[i][1]=INF;
//因为它下面没木板,直接落地
else
dp[i][1]=a[i].h;
}
int main()
{
int t,i;
cin>>t;
while(t--)
{
//木板个数、老鼠的初始坐标、最大跳跃高度
cin>>n>>x>>y>>max_h;
//地面也当做一块木板
a[0].x1=-20000;
a[0].x2=20000;
a[0].h=0;
//老鼠初始位置也当做一块木板
a[1].x1=x;
a[1].x2=x;
a[1].h=y;
//输入数据
for(i=2;i<=n+1;i++)
cin>>a[i].x1>>a[i].x2>>a[i].h;
//高度从大到小
sort(a,a+n+2,cmp);
//初始化
memset(dp,0,sizeof(dp));
//n+1是地面
//所以从n开始
for(i=n; i>=0 ;i--)
{
//进行左:去bfs
left(i);
//进行右:去bfs
right(i);
}
cout<<min(dp[0][0],dp[0][1])<<endl;
}
return 0;
}