Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

341 lines
12 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Implemenation of CTFStatsReport
  4. //
  5. // $Workfile: $
  6. // $Date: $
  7. //
  8. //------------------------------------------------------------------------------------------------------
  9. // $Log: $
  10. //
  11. // $NoKeywords: $
  12. //=============================================================================//
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include "TFStatsReport.h"
  16. #include "LogEvent.h"
  17. #include "ScoreBoard.h"
  18. #include "WhoKilledWho.h"
  19. #include "memdbg.h"
  20. #include "awards.h"
  21. #include "MatchResults.h"
  22. #include "DialogueReadout.h"
  23. #include "cvars.h"
  24. #include "html.h"
  25. #include "TextFile.h"
  26. #include "CustomAward.h"
  27. #include "PlayerSpecifics.h"
  28. #include "util.h"
  29. //------------------------------------------------------------------------------------------------------
  30. // Function: CTFStatsReport::CTFStatsReport
  31. // Purpose: CTFStatsReport Constructor
  32. // Input: pLogFile - the list of events we'll be reporting on
  33. //------------------------------------------------------------------------------------------------------
  34. CTFStatsReport::CTFStatsReport()
  35. {
  36. init();
  37. generate();
  38. }
  39. void CTFStatsReport::genJavaScript()
  40. {
  41. errno=0;
  42. string jsname(g_pApp->supportDirectory);
  43. jsname+=g_pApp->os->pathSeperator();
  44. jsname+="support.js";
  45. FILE* f=fopen( jsname.c_str(),"wt");
  46. if (!f)
  47. g_pApp->fatalError("Can't open output file \"%s\"! (reason: %s)\nPlease make sure that the file does not exist OR\nif the file does exit, make sure it is not read-only",jsname.c_str(),strerror(errno));
  48. else
  49. fprintf(f,javaScriptSource);
  50. fclose(f);
  51. #ifndef WIN32
  52. chmod( jsname.c_str(),PERMIT);
  53. #endif
  54. }
  55. void CTFStatsReport::genStyleSheet()
  56. {
  57. errno=0;
  58. string cssname(g_pApp->supportDirectory);
  59. cssname+=g_pApp->os->pathSeperator();
  60. cssname+="style.css";
  61. FILE* f=fopen(cssname.c_str(),"wt");
  62. if (!f)
  63. g_pApp->fatalError("Can't open output file \"%s\"! (reason: %s)\nPlease make sure that the file does not exist OR\nif the file does exit, make sure it is not read-only",cssname.c_str(),strerror(errno));
  64. else
  65. fprintf(f,styleSheetSource);
  66. fclose(f);
  67. #ifndef WIN32
  68. chmod(cssname.c_str(),PERMIT);
  69. #endif
  70. }
  71. void CTFStatsReport::genAllPlayersStyleSheet()
  72. {
  73. errno=0;
  74. string cssname(g_pApp->playerDirectory.c_str());
  75. cssname+=g_pApp->os->pathSeperator();
  76. cssname+="support";
  77. cssname+=g_pApp->os->pathSeperator();
  78. cssname+="style.css";
  79. FILE* f=fopen(cssname.c_str(),"wt");
  80. if (!f)
  81. g_pApp->fatalError("Can't open output file \"%s\"! (reason: %s)\nPlease make sure that the file does not exist OR\nif the file does exit, make sure it is not read-only",cssname.c_str(),strerror(errno));
  82. else
  83. fprintf(f,styleSheetSource);
  84. fclose(f);
  85. #ifndef WIN32
  86. chmod(cssname.c_str(),PERMIT);
  87. #endif
  88. }
  89. void CTFStatsReport::genIndex()
  90. {
  91. CHTMLFile html("index.html","TF Match Report");
  92. html.write("<script language=\"JavaScript\">\n");
  93. html.write("<!--\n");
  94. html.write("function VerifyBrowser()\n");
  95. html.write("{\n");
  96. html.write(" if (navigator.appName != \"Microsoft Internet Explorer\" && navigator.appName != \"Netscape\")");
  97. html.write(" return false;");
  98. html.write(" version= new Number(navigator.appVersion.charAt(0));");
  99. html.write("// alert(version.valueOf());");
  100. html.write(" if (version.valueOf() >=4 )\n");
  101. html.write(" {\n");
  102. html.write(" return true;\n");
  103. html.write(" }\n");
  104. html.write(" return false;\n");
  105. html.write("}\n");
  106. html.write("\n");
  107. html.write("if (VerifyBrowser())\n");
  108. html.write(" top.location = \"index2.html\"\n");
  109. html.write("else\n");
  110. html.write("{\n");
  111. html.write(" document.write(\"<div class=whitetext align = left> Your browser:</div>\");\n");
  112. html.write(" document.write(\"<div class=whitetext align = left>\", navigator.appName, \"</div>\");\n");
  113. html.write(" document.write(\"<div class=whitetext align = left>\", navigator.appVersion, \"</div>\");\n");
  114. html.write(" document.write(\"<div class=whitetext align = left> is not compatible with TFStats </font></div>\");\n");
  115. html.write(" document.write(\"<div class=whitetext align = left> TFStats supports IE5, IE4 and Netscape 4</font></div>\");\n");
  116. html.write(" document.write(\"<div class=whitetext align = left> <a target=_top href=\\\"http://www.microsoft.com/windows/ie/download/ie5all.htm\\\">Download IE5</a></div>\");\n");
  117. html.write(" document.write(\"<div class=whitetext align = left> <a target=_top href=\\\"http://www.netscape.com/computing/download/index.html\\\">Download Netscape 4</a></div>\");\n");
  118. html.write("}\n");
  119. html.write("//-->\n");
  120. html.write("</script>\n");
  121. CHTMLFile html2("index2.html","TF Match Report",CHTMLFile::dontPrintBody);
  122. html2.write("<frameset border=0 framespacing=0 frameborder=0 rows=81,*>\n");
  123. html2.write("<frame src=top.html marginheight=0 marginwidth=0 scrolling=no name=top>\n");
  124. html2.write("<frameset framespacing=0 frameborder=0 cols=211,*>\n");
  125. html2.write("<frame src=nav.html marginheight=0 marginwidth=0 scrolling=no name=nav>\n");
  126. html2.write("<frame src=MatchResults.html marginheight=0 marginwidth=0 scrolling=yes name=data>\n");
  127. html2.write("</frameset>");
  128. html2.write("</frameset>");
  129. }
  130. #include <string>
  131. void CTFStatsReport::genImages()
  132. {
  133. int chresult=g_pApp->os->chdir(g_pApp->supportDirectory.c_str());
  134. gifAwards.writeOut();
  135. jpgBgLeft.writeOut();
  136. jpgBgTop.writeOut();
  137. gifBoxScore.writeOut();
  138. gifGameDialogOff.writeOut();
  139. gifGameDialogOn.writeOut();
  140. gifMatchStatsOff.writeOut();
  141. gifMatchStatsOn.writeOut();
  142. gifScores.writeOut();
  143. gifServerSettingsOff.writeOut();
  144. gifServerSettingsOn.writeOut();
  145. gifDetailedScores.writeOut();
  146. gifPlayerStatsMatchOff.writeOut();
  147. gifPlayerStatsMatchOn.writeOut();
  148. gifPlayerStatsServerOff.writeOut();
  149. gifPlayerStatsServerOn.writeOut();
  150. chresult=g_pApp->os->chdir(g_pApp->outputDirectory.c_str());
  151. }
  152. void CTFStatsReport::genTopFrame()
  153. {
  154. CHTMLFile html("top.html","top",CHTMLFile::printBody,NULL,0,0);
  155. html.write("<table width=100%% height=100%% cellpadding=0 cellspacing=0 border=0 background=\"%s/bgtop.jpg\">\n",g_pApp->supportHTTPPath.c_str());
  156. html.write("\t<tr valign=top>\n");
  157. html.write("\t\t<td>\n");
  158. html.write("\t\t<div class=server>\n");
  159. html.write("\t\t<nobr>%s Match Report</nobr>\n",g_pMatchInfo->getServerName().c_str());
  160. html.write("\t\t</div>\n");
  161. html.write("\t\t<div class=match>\n");
  162. if(g_pMatchInfo->mapName()!="")
  163. html.write("\t\tmap: %s ",g_pMatchInfo->mapName().c_str());
  164. char buf[1000];
  165. html.write(" %s\n",Util::makeDurationString(matchstart,matchend,buf));
  166. html.write("\t\t</div>\n");
  167. html.write("\t\t</td>\n");
  168. html.write("\t</tr>\n");
  169. html.write("</table>\n");
  170. }
  171. inline void writeEventHandlers(CHTMLFile& html, char* id)
  172. {
  173. html.write(" OnClick=\" clearAll(); %sImgLink.on(); return true; \" ",id,id);
  174. //html.write(" OnMouseDown=\"imageOn('%s');return true;\" ",id);
  175. html.write(" OnMouseOver=\" window.status='%s'; %sImgLink.over();return true; \" ",id,id);
  176. html.write(" OnMouseOut=\" window.status=' ';%sImgLink.out();return true; \" ",id,id);
  177. }
  178. void CTFStatsReport::genNavFrame()
  179. {
  180. string imgname(g_pApp->supportHTTPPath);
  181. imgname+="/bgleft.jpg";
  182. CHTMLFile html("nav.html","top",CHTMLFile::printBody,imgname.c_str(),0,0);
  183. string jshttppath(g_pApp->supportHTTPPath);
  184. jshttppath+="/support.js";
  185. html.write("<script language=\"JavaScript\" src=\"%s\"></script>\n",jshttppath.c_str());
  186. html.write("<script language=\"JavaScript\">\n");
  187. html.write("<!--\n");
  188. html.write("MatchStatsImgLink = new SuperImage(\"MatchStats\",\"%s/match.statistics.on.gif\",\"%s/match.statistics.off.gif\");\n",g_pApp->supportHTTPPath.c_str(),g_pApp->supportHTTPPath.c_str());
  189. html.write("DialoguePageImgLink = new SuperImage(\"DialoguePage\",\"%s/game.dialog.on.gif\",\"%s/game.dialog.off.gif\");\n",g_pApp->supportHTTPPath.c_str(),g_pApp->supportHTTPPath.c_str());
  190. html.write("ServerSettingsImgLink = new SuperImage(\"ServerSettings\",\"%s/server.settings.on.gif\",\"%s/server.settings.off.gif\");\n",g_pApp->supportHTTPPath.c_str(),g_pApp->supportHTTPPath.c_str());
  191. html.write("PlayerStatsMatchImgLink = new SuperImage(\"PlayerStatsMatch\",\"%s/player.statistics.match.on.gif\",\"%s/player.statistics.match.off.gif\");\n",g_pApp->supportHTTPPath.c_str(),g_pApp->supportHTTPPath.c_str());
  192. html.write("PlayerStatsServerImgLink = new SuperImage(\"PlayerStatsServer\",\"%s/player.statistics.server.on.gif\",\"%s/player.statistics.server.off.gif\");\n",g_pApp->supportHTTPPath.c_str(),g_pApp->supportHTTPPath.c_str());
  193. html.write("function clearAll()\n");
  194. html.write("{\n");
  195. html.write("\tMatchStatsImgLink.off();\n");
  196. html.write("\tDialoguePageImgLink.off();\n");
  197. html.write("\tServerSettingsImgLink.off();\n");
  198. html.write("\tPlayerStatsMatchImgLink.off();\n");
  199. html.write("\tPlayerStatsServerImgLink.off();\n");
  200. html.write("}\n");
  201. html.write("//-->\n");
  202. html.write("</script>\n");
  203. html.write("<table width=100%% height=100%% cellpadding=0 cellspacing=0 border=0 >\n");
  204. html.write("\t<tr valign=top>\n");
  205. html.write("\t\t<td>\n");
  206. html.write("\t\t\t<div class=nav>\n");
  207. html.write("\t\t\t<p><a href=\"MatchResults.html\" target=\"data\"");writeEventHandlers(html,"MatchStats");html.write("><img name=\"MatchStats\"src=\"%s/match.statistics.off.gif\" border=0></a>\n",g_pApp->supportHTTPPath.c_str());
  208. html.write("\t\t\t<p><a href=\"players.html\" target=\"data\"");writeEventHandlers(html,"PlayerStatsMatch");html.write("><img name=\"PlayerStatsMatch\" src=\"%s/player.statistics.match.off.gif\" border=0></a>\n",g_pApp->supportHTTPPath.c_str());
  209. html.write("\t\t\t<p><a href=\"dialogue.html\" target=\"data\"");writeEventHandlers(html,"DialoguePage");html.write("><img name=\"DialoguePage\" src=\"%s/game.dialog.off.gif\" border=0></a>\n",g_pApp->supportHTTPPath.c_str());
  210. if(g_pApp->cmdLineSwitches["persistplayerstats"]=="yes" && !g_pMatchInfo->isLanGame())
  211. {
  212. string s(g_pApp->playerHTTPPath);
  213. s+="/allplayers.html";
  214. html.write("\t\t\t<p><a href=\"%s\" target=\"data\"",s.c_str());writeEventHandlers(html,"PlayerStatsServer");html.write("><img name=\"PlayerStatsServer\" src=\"%s/player.statistics.server.off.gif\" border=0></a>\n",g_pApp->supportHTTPPath.c_str());
  215. }
  216. html.write("\t\t\t<p><a href=\"cvars.html\" target=\"data\"");writeEventHandlers(html,"ServerSettings");html.write("><img name=\"ServerSettings\" src=\"%s/server.settings.off.gif\" border=0></a>\n",g_pApp->supportHTTPPath.c_str());
  217. html.write("\t\t\t</div>\n");
  218. html.write("\t\t</td>\n");
  219. html.write("\t</tr>\n");
  220. html.write("</table>\n");
  221. html.write("<script language=\"JavaScript\">\n");
  222. html.write("<!--\n");
  223. html.write("clearAll();\n");
  224. html.write("MatchStatsImgLink.on();\n");
  225. html.write("//-->\n");
  226. html.write("</script>\n");
  227. }
  228. CTFStatsReport::~CTFStatsReport()
  229. {
  230. }
  231. void CTFStatsReport::init()
  232. {
  233. matchstart=0;
  234. matchend=0;
  235. matchhours=0;
  236. matchminutes=0;
  237. matchseconds=0;
  238. }
  239. /*
  240. const char* CTFStatsReport::makeDurationString()
  241. {
  242. //TODO:
  243. //handle case where start and end dates are not the same day
  244. tm* pstart=localtime(&matchstart);
  245. if (!pstart)
  246. {
  247. sprintf(DurationString,"");
  248. return DurationString;
  249. }
  250. int sday=pstart->tm_mday;
  251. int sweekday=pstart->tm_wday;
  252. int smo=pstart->tm_mon;
  253. int syear=pstart->tm_year+1900;
  254. int shour=pstart->tm_hour;
  255. if (pstart->tm_isdst)
  256. shour=(shour+23)%24; //this substracts 1 while accounting for backing up past 0
  257. int smin=pstart->tm_min;
  258. tm* pend=localtime(&matchend);
  259. if (!pend)
  260. pend=pstart;
  261. int ehour=pend->tm_hour;
  262. int emin=pend->tm_min;
  263. if (pend->tm_isdst)
  264. ehour=(ehour+23)%24; //this substracts 1 while accounting for backing up past 0
  265. char* matchtz=NULL;
  266. matchtz=g_pApp->os->gettzname()[0];
  267. sprintf(DurationString,"%02li:%02li - %02li:%02li %s, %s %s %li%s %li",shour,smin,ehour,emin,matchtz, Util::daysofWeek[sweekday],Util::Months[smo],sday,(sday%10)<4?Util::numberSuffixes[sday%10]:"th",syear);
  268. return DurationString;
  269. }*/
  270. void CTFStatsReport::generate()
  271. {
  272. if (g_pMatchInfo->eventList()->empty())
  273. {
  274. matchstart=0;
  275. matchend=0;
  276. }
  277. else
  278. {
  279. matchstart=(*(g_pMatchInfo->eventList()->begin()))->getTime();
  280. CEventListIterator it=g_pMatchInfo->eventList()->end();
  281. --it;
  282. matchend=(*it)->getTime();
  283. }
  284. time_t matchtime=matchend-matchstart;
  285. tm* pmatchtime=gmtime(&matchtime);
  286. matchhours=pmatchtime->tm_hour;
  287. matchminutes=pmatchtime->tm_min;
  288. matchseconds=pmatchtime->tm_sec;
  289. }