#include<iostream>
#include<vector>
#include<cstdio>
#include<queue>
#include<algorithm>
#define int long long
using namespace std;
#define LOCAL
using namespace std;
namespace ly
{
namespace IO
{
#ifndef LOCAL
#define SIZE (1<<20)
char in[SIZE],out[SIZE],*p1=in,*p2=in,*p3=out;
#define getchar() (p1==p2&&(p2=(p1=in)+fread(in,1,SIZE,stdin),p1==p2)?EOF:*p1++)
#define flush() (fwrite(p3=out,1,SIZE,stdout))
#define putchar(ch) (p3==out+SIZE&&flush(),*p3++=(ch))
class Flush{public:~Flush(){flush();}}_;
#endif
template<typename type>
inline void read(type &x)
{
x=0;bool flag(0);char ch=getchar();
while(!isdigit(ch)) flag^=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
flag?x=-x:0;
}
template<typename type>
inline void write(type x,bool flag=1)
{
x<0?x=-x,putchar('-'):0;static short Stack[50],top(0);
do Stack[++top]=x%10,x/=10;while(x);
while(top) putchar(Stack[top--]|48);
flag?putchar('\n'):putchar(' ');
}
#ifndef LOCAL
#undef SIZE
#undef getchar
#undef putchar
#undef flush
#endif
}
}using namespace ly::IO;
const int MAXN = 4e5 + 5;
int n,m,k,d;
typedef struct Node{
int l,r;
long long v;
bool operator < (const Node& b){
return r < b.r;
}
}Node;
Node clg[MAXN];
typedef struct TR{
int l,r;
long long tag,v;
}TR;
TR tr[MAXN << 2];
int ls(int pos){
return pos << 1;
}
int rs(int pos){
return pos << 1 | 1;
}
void build(int pos,int l,int r){
tr[pos].l = l;
tr[pos].r = r;
tr[pos].v = 0;
tr[pos].tag = 0;
if(l == r){
return;
}
int mid = (l + r) >> 1;
build(ls(pos),l,mid);
build(rs(pos),mid + 1,r);
}
inline void push_up(int pos){
tr[pos].v = max(tr[ls(pos)].v,tr[rs(pos)].v);
}
inline void push_down(int pos){
tr[ls(pos)].v = tr[ls(pos)].v + tr[pos].tag;
tr[rs(pos)].v = tr[rs(pos)].v + tr[pos].tag;
tr[ls(pos)].tag = tr[ls(pos)].tag + tr[pos].tag;
tr[rs(pos)].tag = tr[rs(pos)].tag + tr[pos].tag;
tr[pos].tag = 0;
}
inline void update(int pos,int ql,int qr,int k){
int l = tr[pos].l;
int r = tr[pos].r;
if(l >= ql && r <= qr){
tr[pos].v = tr[pos].v + k;
tr[pos].tag = tr[pos].tag + k;
return;
}
int mid = (l + r) >> 1;
push_down(pos);
if(ql <= mid){
update(ls(pos),ql,qr,k);
}
if(qr > mid){
update(rs(pos),ql,qr,k);
}
push_up(pos);
}
inline long long query(int pos,int ql,int qr){
int l = tr[pos].l;
int r = tr[pos].r;
if(l >= ql && r <= qr){
return tr[pos].v;
}
int mid = (l + r) >> 1;
long long res = -1e18;
push_down(pos);
if(ql <= mid){
res = max(res,query(ls(pos),ql,qr));
}
if(qr > mid){
res = max(res,query(rs(pos),ql,qr));
}
push_up(pos);
return res;
}
int t[MAXN];
inline void solve(){
read(n),read(m),read(k),read(d);
for(int i = 1; i <= m; i++){
int x,y,z;
read(x),read(y),read(z);
clg[i] = {x - y,x,z};
t[(i << 1) - 1] = x - y;
t[i << 1] = x;
}
sort(t + 1,t + 1 + 2 * m);
int len = unique(t + 1,t + 1 + 2 * m) - t - 1;
for(int i = 1; i <= m; i++){
clg[i].l = lower_bound(t + 1,t + 1 + len,clg[i].l) - t;
clg[i].r = lower_bound(t + 1,t + 1 + len,clg[i].r) - t;
}
sort(clg + 1,clg + 1 + m);
build(1,0,len);
long long res = 0;
int p = 1,u = 0;
for(int i = 1; i <= len; i++){
update(1,i,i,res + d * t[i]);
while(p <= m && clg[p].r == i){
update(1,0,clg[p].l,clg[p].v);
p++;
}
for(; u < i && t[u] < t[i] - k; u++);
res = max(res,query(1,u,i - 1) - d * t[i]);
}
write(res);
}
signed main(){
int T = 1,c;
read(c),read(T);
while(T--){
solve();
}
}