From e9114364bb24f59228770b16a86741ddc10a2dc7 Mon Sep 17 00:00:00 2001
From: "Rob Swindell (on Debian Linux)" <rob@synchro.net>
Date: Fri, 3 Mar 2023 12:54:15 -0800
Subject: [PATCH] Introduced user download_cps property

Will track the user's last succsesful file-download transfer rate
in characters (bytes) per second.

I'm not calculating or storing this rate yet, but will be soon. This
will make the file download ETAs more realistic and no longer
hard-coded to 3000 cps (which now defaults to 10000 cps, to keep up
with the times).

New field added to user.tab placed adjacent to the other File xfer stats,
which means the leech attempt counter (likely always 0) was moved to the end
of the user record.
---
 src/sbbs3/js_user.c    | 6 ++++++
 src/sbbs3/logon.cpp    | 3 +++
 src/sbbs3/main.cpp     | 1 -
 src/sbbs3/sbbs.h       | 2 +-
 src/sbbs3/sbbsdefs.h   | 1 +
 src/sbbs3/userdat.c    | 8 ++++++--
 src/sbbs3/userfields.h | 3 ++-
 7 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/src/sbbs3/js_user.c b/src/sbbs3/js_user.c
index 51cb9c159a..59f2f2a70d 100644
--- a/src/sbbs3/js_user.c
+++ b/src/sbbs3/js_user.c
@@ -81,6 +81,7 @@ enum {
 	,USER_PROP_ULS       
 	,USER_PROP_DLB       
 	,USER_PROP_DLS       
+	,USER_PROP_DLCPS
 	,USER_PROP_CDT		
 	,USER_PROP_MIN		
 	,USER_PROP_LEVEL 	
@@ -279,6 +280,9 @@ static JSBool js_user_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 		case USER_PROP_DLS:
 			val=p->user->dls;
 			break;
+		case USER_PROP_DLCPS:
+			val=p->user->dlcps;
+			break;
 		case USER_PROP_CDT:
 			*vp = DOUBLE_TO_JSVAL((jsdouble)p->user->cdt);
 			JS_RESUMEREQUEST(cx, rc);
@@ -961,6 +965,7 @@ static jsSyncPropertySpec js_user_stats_properties[] = {
 	{	"files_uploaded"	,USER_PROP_ULS        	,USER_PROP_FLAGS,		310 },
 	{	"bytes_downloaded"	,USER_PROP_DLB        	,USER_PROP_FLAGS,		310 },
 	{	"files_downloaded"	,USER_PROP_DLS        	,USER_PROP_FLAGS,		310 },
+	{	"download_cps"		,USER_PROP_DLCPS       	,USER_PROP_FLAGS,		320 },
 	{	"leech_attempts"	,USER_PROP_LEECH 	 	,USER_PROP_FLAGS,		310 },
 	{	"mail_waiting"		,USER_PROP_MAIL_WAITING	,USER_PROP_FLAGS,		312	},
 	{	"read_mail_waiting"	,USER_PROP_READ_WAITING	,USER_PROP_FLAGS,		31802 },
@@ -989,6 +994,7 @@ static char* user_stats_prop_desc[] = {
 	,"total files uploaded"
 	,"total bytes downloaded"
 	,"total files downloaded"
+	,"latest average download rate, in characters (bytes) per second"
 	,"suspected leech downloads"
 	,"total number of e-mail messages currently waiting in inbox"
 	,"number of read e-mail messages currently waiting in inbox"
diff --git a/src/sbbs3/logon.cpp b/src/sbbs3/logon.cpp
index 11e513bf26..066e6954b1 100644
--- a/src/sbbs3/logon.cpp
+++ b/src/sbbs3/logon.cpp
@@ -54,6 +54,9 @@ bool sbbs_t::logon()
 	js_create_user_objects(js_cx, js_glob);
 #endif
 
+	if(useron.dlcps)
+		cur_cps = useron.dlcps;
+
 	if(useron.rest&FLAG('Q'))
 		sys_status ^= SS_QWKLOGON;
 
diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp
index a48521b085..184993943d 100644
--- a/src/sbbs3/main.cpp
+++ b/src/sbbs3/main.cpp
@@ -4024,7 +4024,6 @@ void sbbs_t::reset_logon_vars(void)
 		curdir[i]=0;
 	for(i=0;i<cfg.total_grps;i++)
 		cursub[i]=0;
-	cur_cps=3000;
     cur_rate=30000;
     dte_rate=38400;
 	cur_output_rate = output_rate_unlimited;
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index 3aac8e04b8..da4368922d 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -543,7 +543,7 @@ public:
 	ushort	node_connection = NODE_CONNECTION_TELNET;
 	char	connection[LEN_MODEM+1];	/* Connection Description */
 	uint	cur_rate=0;		/* Current Connection (DCE) Rate */
-	uint	cur_cps=0;		/* Current Average Transfer CPS */
+	uint	cur_cps=10000;	/* Current Average Download CPS */
 	uint	dte_rate=0;		/* Current COM Port (DTE) Rate */
 	time_t 	timeout=0;		/* User inactivity timeout reference */
 	uint 	timeleft_warn=0;/* low timeleft warning flag */
diff --git a/src/sbbs3/sbbsdefs.h b/src/sbbs3/sbbsdefs.h
index 7662c74f0f..9f2b2dfd06 100644
--- a/src/sbbs3/sbbsdefs.h
+++ b/src/sbbs3/sbbsdefs.h
@@ -960,6 +960,7 @@ typedef struct {						/* Users information */
 	uint64_t freecdt;					/* Free credits (renewed daily) */
 	uint64_t ulb;						/* Total bytes uploaded */
 	uint64_t dlb;						/* Total bytes downloaded */
+	uint32_t dlcps;						/* Last download rate (in CPS) */
 	time32_t firston,					/* Date/Time first called */
 			laston, 					/* Last logoff date/time */
 			expire, 					/* Expiration date */
diff --git a/src/sbbs3/userdat.c b/src/sbbs3/userdat.c
index 343f7a8489..cc78be3924 100644
--- a/src/sbbs3/userdat.c
+++ b/src/sbbs3/userdat.c
@@ -450,6 +450,7 @@ int parseuserdat(scfg_t* cfg, char *userdat, user_t *user, char* field[])
 	user->uls = (ushort)strtoul(field[USER_ULS], NULL, 0);
 	user->dlb = strtoull(field[USER_DLB], NULL, 0);
 	user->dls = (ushort)strtoul(field[USER_DLS], NULL, 0);
+	user->dlcps = (uint32_t)strtoul(field[USER_DLCPS], NULL, 0);
 	user->leech = (uchar)strtoul(field[USER_LEECH], NULL, 0);
 
 	SAFECOPY(user->pass, field[USER_PASS]);
@@ -662,7 +663,7 @@ BOOL format_userdat(scfg_t* cfg, user_t* user, char userdat[])
 		"%u\t"			// USER_ULS
 		"%" PRIu64 "\t" // USER_DLB
 		"%u\t"			// USER_DLS
-		"%u\t"	// USER_LEECH
+		"%" PRIu32 "\t" // USER_DLCPS
 		"%s\t"	// USER_PASS
 		"%s\t"	// USER_PWMOD
 		"%u\t"	// USER_LEVEL
@@ -677,6 +678,7 @@ BOOL format_userdat(scfg_t* cfg, user_t* user, char userdat[])
 		"%" PRIu32 "\t" // USER_MIN
 		"%u\t"	// USER_TEXTRA
 		"%s\t"	// USER_EXPIRE
+		"%u\t"	// USER_LEECH
 		,user->number
 		,user->alias
 		,user->name
@@ -723,7 +725,7 @@ BOOL format_userdat(scfg_t* cfg, user_t* user, char userdat[])
 		,(uint)user->uls
 		,user->dlb
 		,(uint)user->dls
-		,(uint)user->leech
+		,user->dlcps
 		,user->pass
 		,pwmod
 		,(uint)user->level
@@ -738,6 +740,7 @@ BOOL format_userdat(scfg_t* cfg, user_t* user, char userdat[])
 		,user->min
 		,user->textra
 		,expire
+		,(uint)user->leech
 	);
 	if(len > USER_RECORD_LEN || len < 0) // truncated?
 		return FALSE;
@@ -3116,6 +3119,7 @@ size_t user_field_len(enum user_field fnum)
 		case USER_ULS:			return sizeof(user.uls);
 		case USER_DLB:			return sizeof(user.dlb);
 		case USER_DLS:			return sizeof(user.dls);
+		case USER_DLCPS:		return sizeof(user.dlcps);
 		case USER_LEECH:		return sizeof(user.leech);
 
 		// Security:
diff --git a/src/sbbs3/userfields.h b/src/sbbs3/userfields.h
index 67938011a8..9283da047a 100644
--- a/src/sbbs3/userfields.h
+++ b/src/sbbs3/userfields.h
@@ -81,7 +81,7 @@ enum user_field {
 	USER_ULS,
 	USER_DLB,
 	USER_DLS,
-	USER_LEECH,
+	USER_DLCPS,
 
 	// Security:
 	USER_PASS,
@@ -98,6 +98,7 @@ enum user_field {
 	USER_MIN,
 	USER_TEXTRA,
 	USER_EXPIRE,
+	USER_LEECH,
 
 	// Last:
 	USER_FIELD_COUNT
-- 
GitLab