Crossfire Server, Branches 1.12  R18729
time.c
Go to the documentation of this file.
1 /*
2  * static char *rcsid_time_c =
3  * "$Id: time.c 11578 2009-02-23 22:02:27Z lalo $";
4  */
5 
6 /*
7  CrossFire, A Multiplayer game for X-windows
8 
9  Copyright (C) 2006 Mark Wedel & Crossfire Development Team
10  Copyright (C) 1992 Frank Tore Johansen
11 
12  This program is free software; you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation; either version 2 of the License, or
15  (at your option) any later version.
16 
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with this program; if not, write to the Free Software
24  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 
26  The authors can be reached via e-mail at crossfire-devel@real-time.com
27 */
28 
34 #include <global.h>
35 #include <tod.h>
36 
37 #ifndef WIN32 /* ---win32 exclude header */
38 #include <stdio.h>
39 #include <sys/types.h>
40 #include <sys/time.h>
41 #endif /* win32 */
42 
47 struct timeval last_time;
48 
50 #define PBUFLEN 100
52 static uint32 psaveind;
54 static uint32 process_min_utime = 999999999;
60 static const char *const season_name[SEASONS_PER_YEAR+1] = {
61  "The Season of New Year",
62  "The Season of Growth",
63  "The Season of Harvest",
64  "The Season of Decay",
65  "The Season of the Blizzard",
66  "\n"
67 };
68 
70 static const char *const weekdays[DAYS_PER_WEEK] = {
71  "the Day of the Moon",
72  "the Day of the Bull",
73  "the Day of the Deception",
74  "the Day of Thunder",
75  "the Day of Freedom",
76  "the Day of the Great Gods",
77  "the Day of the Sun"
78 };
79 
81 static const char *const month_name[MONTHS_PER_YEAR] = {
82  "Month of Winter", /* 0 */
83  "Month of the Ice Dragon",
84  "Month of the Frost Giant",
85  "Month of Valriel",
86  "Month of Lythander",
87  "Month of the Harvest",
88  "Month of Gaea",
89  "Month of Futility",
90  "Month of the Dragon",
91  "Month of the Sun",
92  "Month of the Great Infernus",
93  "Month of Ruggilli",
94  "Month of the Dark Shades",
95  "Month of the Devourers",
96  "Month of Sorig",
97  "Month of the Ancient Darkness",
98  "Month of Gorokh"
99 };
100 
101 static const char *const periodsofday[PERIODS_PER_DAY] = {
102  "Night",
103  "Dawn",
104  "Morning",
105  "Noon",
106  "Evening",
107  "Dusk"
108 };
109 
113 const char *get_periodofday(const int index) {
114  return ((index >= 0) && (index < PERIODS_PER_DAY)) ? periodsofday[index] : NULL;
115 }
116 
120 const char *get_month_name(const int index) {
121  return ((index >= 0) && (index < MONTHS_PER_YEAR)) ? month_name[index] : NULL;
122 }
123 
127 const char *get_weekday(const int index) {
128  return ((index >= 0) && (index < DAYS_PER_WEEK)) ? weekdays[index] : NULL;
129 }
130 
134 const char *get_season_name(const int index) {
135  return ((index >= 0) && (index < (SEASONS_PER_YEAR+1))) ? season_name[index] : NULL;
136 }
137 
141 void reset_sleep(void) {
142  int i;
143 
144  for (i = 0; i < PBUFLEN; i++)
145  process_utime_save[i] = 0;
146  psaveind = 0;
147  process_max_utime = 0;
148  process_min_utime = 999999999;
149  process_tot_mtime = 0;
150  pticks = 0;
151 
152  (void)GETTIMEOFDAY(&last_time);
153 }
154 
158 static void log_time(uint32 process_utime) {
159  pticks++;
160  if (++psaveind >= PBUFLEN)
161  psaveind = 0;
162  process_utime_save[psaveind] = process_utime;
163  if (process_utime > process_max_utime)
164  process_max_utime = process_utime;
165  if (process_utime < process_min_utime)
166  process_min_utime = process_utime;
167  process_tot_mtime += process_utime/1000;
168 }
169 
176  static struct timeval new_time;
177  uint32 elapsed_utime;
178 
179  (void)GETTIMEOFDAY(&new_time);
180 
181  elapsed_utime = (new_time.tv_sec-last_time.tv_sec)*1000000+new_time.tv_usec-last_time.tv_usec;
182  if (elapsed_utime > max_time) {
183  log_time(elapsed_utime);
184  last_time.tv_sec = new_time.tv_sec;
185  last_time.tv_usec = new_time.tv_usec;
186  return 1;
187  }
188  return 0;
189 }
190 
195 void sleep_delta(void) {
196  static struct timeval new_time;
197  long sleep_sec, sleep_usec;
198 
199  (void)GETTIMEOFDAY(&new_time);
200 
201  sleep_sec = last_time.tv_sec-new_time.tv_sec;
202  sleep_usec = max_time-(new_time.tv_usec-last_time.tv_usec);
203 
204  /* This is very ugly, but probably the fastest for our use: */
205  while (sleep_usec < 0) {
206  sleep_usec += 1000000;
207  sleep_sec -= 1;
208  }
209  while (sleep_usec > 1000000) {
210  sleep_usec -= 1000000;
211  sleep_sec += 1;
212  }
213 
214  log_time((new_time.tv_sec-last_time.tv_sec)*1000000+new_time.tv_usec-last_time.tv_usec);
215 
216  if (sleep_sec >= 0 && sleep_usec > 0) {
217  static struct timeval sleep_time;
218 
219  sleep_time.tv_sec = sleep_sec;
220  sleep_time.tv_usec = sleep_usec;
221 
222 #ifndef WIN32 /* 'select' doesn't work on Windows, 'Sleep' is used instead */
223  select(0, NULL, NULL, NULL, &sleep_time);
224 #else
225  if (sleep_time.tv_sec)
226  Sleep(sleep_time.tv_sec*1000);
227  Sleep((int)(sleep_time.tv_usec/1000.));
228 #endif
229  } else
231  /*
232  * Set last_time to when we're expected to wake up:
233  */
234  last_time.tv_usec += max_time;
235  while (last_time.tv_usec > 1000000) {
236  last_time.tv_usec -= 1000000;
237  last_time.tv_sec++;
238  }
239  /*
240  * Don't do too much catching up:
241  * (Things can still get jerky on a slow/loaded computer)
242  */
243  if (last_time.tv_sec*1000000+last_time.tv_usec <
244  new_time.tv_sec*1000000+new_time.tv_usec) {
245  last_time.tv_sec = new_time.tv_sec;
246  last_time.tv_usec = new_time.tv_usec;
247  }
248 }
249 
256 void set_max_time(long t) {
257  max_time = t;
258 }
259 
260 extern unsigned long todtick;
261 
268 void get_tod(timeofday_t *tod) {
269  tod->year = todtick/HOURS_PER_YEAR;
272  tod->dayofweek = tod->day%DAYS_PER_WEEK;
273  tod->hour = todtick%HOURS_PER_DAY;
275  if (tod->minute > 58)
276  tod->minute = 58; /* it's imprecise at best anyhow */
277  tod->weekofmonth = tod->day/WEEKS_PER_MONTH;
278  if (tod->month < 3)
279  tod->season = 0;
280  else if (tod->month < 6)
281  tod->season = 1;
282  else if (tod->month < 9)
283  tod->season = 2;
284  else if (tod->month < 12)
285  tod->season = 3;
286  else
287  tod->season = 4;
288 
289  if (tod->hour < 5) /*until 4:59*/
290  tod->periodofday = 0;
291  else if (tod->hour < 8)
292  tod->periodofday = 1;
293  else if (tod->hour < 13)
294  tod->periodofday = 2;
295  else if (tod->hour < 15)
296  tod->periodofday = 3;
297  else if (tod->hour < 20)
298  tod->periodofday = 4;
299  else if (tod->hour < 23)
300  tod->periodofday = 5;
301  else /*back to night*/
302  tod->periodofday = 0;
303 }
304 
311 static void print_tod(object *op) {
312  timeofday_t tod;
313  const char *suf;
314  int day;
315 
316  get_tod(&tod);
317 
319  "It is %d minute%s past %d o'clock %s, on %s",
320  "It is %d minute%s past %d o'clock %s, on %s",
321  tod.minute+1, ((tod.minute+1 < 2) ? "" : "s"),
322  ((tod.hour%14 == 0) ? 14 : ((tod.hour)%14)),
323  ((tod.hour >= 14) ? "pm" : "am"),
324  weekdays[tod.dayofweek]);
325 
326  day = tod.day+1;
327  if (day == 1 || ((day%10) == 1 && day > 20))
328  suf = "st";
329  else if (day == 2 || ((day%10) == 2 && day > 20))
330  suf = "nd";
331  else if (day == 3 || ((day%10) == 3 && day > 20))
332  suf = "rd";
333  else
334  suf = "th";
335 
337  "The %d%s Day of the %s, Year %d",
338  "The %d%s Day of the %s, Year %d",
339  day, suf, month_name[tod.month], tod.year+1);
340 
342  "Time of Year: %s",
343  "Time of Year: %s",
344  season_name[tod.season]);
345 }
346 
353 void time_info(object *op) {
354  int tot = 0, long_count = 0;
355  uint32 maxt = 0, mint = 99999999, i;
356 
357  print_tod(op);
358 
359  if (!QUERY_FLAG(op, FLAG_WIZ))
360  return;
361 
363  "Total time:", NULL);
364 
366  "ticks=%d time=%d.%2d",
367  "ticks=%d time=%d.%2d",
369 
371  "avg time=%dms max time=%dms min time=%dms",
372  "avg time=%dms max time=%dms min time=%dms",
374  process_min_utime/1000);
375 
377  "ticks longer than max time (%dms) = %d (%d%%)",
378  "ticks longer than max time (%dms) = %d (%d%%)",
379  max_time/1000,
381 
382 
384  "Time last %d ticks:",
385  "Time last %d ticks:",
386  MIN(pticks, PBUFLEN));
387 
388  for (i = 0; i < MIN(pticks, PBUFLEN); i++) {
389  tot += process_utime_save[i];
390  if (process_utime_save[i] > maxt)
391  maxt = process_utime_save[i];
392  if (process_utime_save[i] < mint)
393  mint = process_utime_save[i];
394  if (process_utime_save[i] > max_time)
395  long_count++;
396  }
397 
399  "avg time=%dms max time=%dms min time=%dms",
400  "avg time=%dms max time=%dms min time=%dms",
401  tot/MIN(pticks, PBUFLEN)/1000, maxt/1000,
402  mint/1000);
403 
405  "ticks longer than max time (%dms) = %d (%d%%)",
406  "ticks longer than max time (%dms) = %d (%d%%)",
407  max_time/1000, long_count,
408  100*long_count/MIN(pticks, PBUFLEN));
409 }
410 
417 long seconds(void) {
418  struct timeval now;
419 
420  (void)GETTIMEOFDAY(&now);
421  return now.tv_sec;
422 }
#define DAYS_PER_WEEK
Definition: tod.h:42
static void log_time(uint32 process_utime)
Definition: time.c:158
#define PBUFLEN
Definition: time.c:50
static uint32 process_max_utime
Definition: time.c:53
uint32 pticks
Definition: time.c:56
#define HOURS_PER_YEAR
Definition: tod.h:54
const char * get_season_name(const int index)
Definition: time.c:134
static uint32 process_min_utime
Definition: time.c:54
int minute
Definition: tod.h:67
void draw_ext_info(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *message, const char *oldmessage)
Definition: standalone.c:171
const char * get_weekday(const int index)
Definition: time.c:127
void draw_ext_info_format(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *new_format, const char *old_format,...)
Definition: standalone.c:175
#define PERIODS_PER_DAY
Definition: tod.h:46
static uint32 process_utime_long_count
Definition: time.c:57
static uint32 process_utime_save[PBUFLEN]
Definition: time.c:51
int periodofday
Definition: tod.h:70
struct timeval last_time
Definition: time.c:47
int year
Definition: tod.h:62
const char * get_month_name(const int index)
Definition: time.c:120
#define HOURS_PER_MONTH
Definition: tod.h:53
#define DAYS_PER_MONTH
Definition: tod.h:50
int month
Definition: tod.h:63
void set_max_time(long t)
Definition: time.c:256
long seconds(void)
Definition: time.c:417
#define MAX_TIME
Definition: config.h:221
static uint32 psaveind
Definition: time.c:52
static const char *const month_name[MONTHS_PER_YEAR]
Definition: time.c:81
int weekofmonth
Definition: tod.h:68
uint32 max_time
Definition: time.c:46
int day
Definition: tod.h:64
int dayofweek
Definition: tod.h:65
void time_info(object *op)
Definition: time.c:353
#define QUERY_FLAG(xyz, p)
Definition: define.h:514
#define FLAG_WIZ
Definition: define.h:527
#define MSG_TYPE_COMMAND_DEBUG
Definition: newclient.h:446
static void print_tod(object *op)
Definition: time.c:311
int enough_elapsed_time(void)
Definition: time.c:175
void reset_sleep(void)
Definition: time.c:141
#define MIN(x, y)
Definition: define.h:67
static const char *const periodsofday[PERIODS_PER_DAY]
Definition: time.c:101
static const char *const weekdays[DAYS_PER_WEEK]
Definition: time.c:70
static const char *const season_name[SEASONS_PER_YEAR+1]
Definition: time.c:60
void sleep_delta(void)
Definition: time.c:195
void get_tod(timeofday_t *tod)
Definition: time.c:268
#define HOURS_PER_DAY
Definition: tod.h:41
#define MSG_TYPE_COMMAND_INFO
Definition: newclient.h:444
Definition: tod.h:61
const char * get_periodofday(const int index)
Definition: time.c:113
#define WEEKS_PER_MONTH
Definition: tod.h:43
#define MSG_TYPE_COMMAND
Definition: newclient.h:326
int hour
Definition: tod.h:66
#define GETTIMEOFDAY(last_time)
Definition: global.h:442
unsigned long todtick
Definition: init.c:418
#define NDI_UNIQUE
Definition: newclient.h:219
unsigned int uint32
Definition: global.h:58
static uint32 process_tot_mtime
Definition: time.c:55
#define MONTHS_PER_YEAR
Definition: tod.h:44
#define PTICKS_PER_CLOCK
Definition: tod.h:38
#define SEASONS_PER_YEAR
Definition: tod.h:45
int season
Definition: tod.h:69