File: multi_rate.cpp

package info (click to toggle)
freespace2 24.0.2%2Brepack-1
  • links: PTS, VCS
  • area: non-free
  • in suites: trixie
  • size: 43,188 kB
  • sloc: cpp: 583,107; ansic: 21,729; python: 1,174; sh: 464; makefile: 248; xml: 181
file content (213 lines) | stat: -rw-r--r-- 5,204 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/*
 * Copyright (C) Volition, Inc. 1999.  All rights reserved.
 *
 * All source code herein is the property of Volition, Inc. You may not sell 
 * or otherwise commercially exploit the source or things you created based on the 
 * source.
 *
*/




// -----------------------------------------------------------------------------------------------------------------------
// MULTI RATE DEFINES/VARS
//

#include "network/multi_rate.h"

#ifdef MULTI_RATE

#include "io/timer.h"
#include "globalincs/alphacolors.h"



// how many records in the past we'll keep track of
#define NUM_UPDATE_RECORDS							5

// rate monitoring info
typedef struct mr_info {
	// type
	char type[MAX_RATE_TYPE_LEN+1];

	// all time info		
	int total_bytes;												// total bytes alltime

	// per second info
	int stamp_second;												// stamp for one second
	int bytes_second;												// how many bytes we've sent in the last second	
	int records_second[NUM_UPDATE_RECORDS];				// records
	int records_second_count;									// how many records we have
	float avg_second;												// avg bytes/sec

	// per frame info
	int bytes_frame;												// how many bytes we've sent this frame	
	int records_frame[NUM_UPDATE_RECORDS];					// records
	int records_frame_count;									// how many records we have
	float avg_frame;												// avg bytes/frame				
} mr_info;


// all records
mr_info Multi_rate[MAX_RATE_PLAYERS][MAX_RATE_TYPES];


// -----------------------------------------------------------------------------------------------------------------------
// MULTI RATE FUNCTIONS
//

// notify of a player join
void multi_rate_reset(int np_index)
{
	int idx;

	// sanity checks
	if((np_index < 0) || (np_index >= MAX_RATE_PLAYERS)){
		return;
	}

	// blast the index clear
	for(idx=0; idx<MAX_RATE_TYPES; idx++){
		memset(&Multi_rate[np_index][idx], 0, sizeof(mr_info));
		Multi_rate[np_index][idx].stamp_second = -1;
	}
}

// add data of the specified type to datarate processing, returns 0 on fail (if we ran out of types, etc, etc)
int multi_rate_add(int np_index, const char *type, int size)
{	
	int idx;
	mr_info *m;
	// sanity checks
	if((np_index < 0) || (np_index >= MAX_RATE_PLAYERS)){
		return 0;
	}
	if((type == NULL) || (strlen(type) <= 0)){
		return 0;
	}

	// see if the type already exists
	for(idx=0; idx<MAX_RATE_TYPES; idx++){
		// empty slot
		if(strlen(Multi_rate[np_index][idx].type) <= 0){
			break;
		}
		// existing
		else if(!stricmp(Multi_rate[np_index][idx].type, type)){
			break;
		}
	}

	// if we couldn't find a slot
	if(idx >= MAX_RATE_TYPES){
		return 0;
	}

	// otherwise add the data
	m = &Multi_rate[np_index][idx];

	// type string
	strcpy_s(m->type, type);

	// alltime
	m->total_bytes += size;

	// per-second
	m->bytes_second += size;

	// per-frame
	m->bytes_frame += size;		

	// success
	return 1;
}

// process
#define R_AVG(ct, ar, avg)		do {int av_idx; float av_sum = 0.0f; if(ct == 0){ avg = 0;} else { for(av_idx=0; av_idx<ct; av_idx++){ av_sum += (float)ar[av_idx]; } avg = av_sum / (float)ct; } }while(false)
void multi_rate_process()
{
	int idx, s_idx;
	mr_info *m;

	// process all active players
	for(idx=0; idx<MAX_RATE_PLAYERS; idx++){
		for(s_idx=0; s_idx<MAX_RATE_TYPES; s_idx++){
			m = &Multi_rate[idx][s_idx];

			// invalid entries
			if(strlen(m->type) <= 0){
				continue;
			}

			// process alltime
			if(m->stamp_second == -1){
				m->stamp_second = timestamp(1000);
			} else if(timestamp_elapsed(m->stamp_second)){
				// if we've reached max records
				if(m->records_second_count >= NUM_UPDATE_RECORDS){
					memmove(m->records_second, m->records_second+1, sizeof(int) * (NUM_UPDATE_RECORDS - 1)); 
					m->records_second[NUM_UPDATE_RECORDS-1] = m->bytes_second; 
				}
				// haven't reached max records
				else {
					m->records_second[m->records_second_count++] = m->bytes_second;
				}

				// recalculate the average
				R_AVG(m->records_second_count, m->records_second, m->avg_second);

				// reset bytes/second and timestamp
				m->bytes_second = 0;
				m->stamp_second = timestamp(1000);
			}

			// process per-frame
			// if we've reached max records
			if(m->records_frame_count >= NUM_UPDATE_RECORDS){
				memmove(m->records_frame, m->records_frame+1, sizeof(int) * (NUM_UPDATE_RECORDS - 1)); 
				m->records_frame[NUM_UPDATE_RECORDS-1] = m->bytes_frame; 
			}
			// haven't reached max records
			else {
				m->records_frame[m->records_frame_count++] = m->bytes_frame;
			}

			// recalculate the average
			R_AVG(m->records_frame_count, m->records_frame, m->avg_frame);

			// reset bytes/frame
			m->bytes_frame = 0;			
		}
	}	
}

// display
void multi_rate_display(int np_index, int x, int y)
{	
	int idx;
	mr_info *m;
	int line_height = gr_get_font_height() + 1;

	// sanity checks
	if((np_index < 0) || (np_index >= MAX_RATE_PLAYERS)){
		return;
	}

	// get info
	for(idx=0; idx<MAX_RATE_TYPES; idx++){
		m = &Multi_rate[np_index][idx];

		// if we have a 0 length string, we're done
		if(strlen(m->type) <= 0){
			break;
		}

		// display
		gr_set_color_fast(&Color_red);
		gr_printf_no_resize(x, y, "%s %d (%d/s) (%f/f)", m->type, m->total_bytes, (int)m->avg_second, m->avg_frame);
		y += line_height;
	}
}

#endif