Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_FPS_Autotest.c
Go to the documentation of this file.
1// TODO(koudelkaluk): clean up this mess, get rid of unnecessary files saved for Confluence upload
2[EntityEditorProps(category: "GameScripted/Utility", description: "Modified Heatmap autotest", dynamicBox: true)]
3class SCR_HeatMap_AutotestClass: GenericEntityClass
4{
5};
6
7class HeatmapData
8{
9 float m_fps;
10 float m_fps_n;
11 float m_fps_e;
12 float m_fps_s;
13 float m_fps_w;
14
15 float m_x;
16 float m_y;
17 float m_z;
18
19 /*
20 void HeatmapData(float fps, float x, float y, float z)
21 {
22 m_fps = fps;
23 m_x = x;
24 m_y = y;
25 m_z = z;
26 }
27 */
28
29 void HeatmapData(float fps_avg, float fps_n, float fps_e, float fps_s, float fps_w, float x, float y, float z)
30 {
31 m_fps = fps_avg;
32 m_fps_n = fps_n;
33 m_fps_e = fps_e;
34 m_fps_s = fps_s;
35 m_fps_w = fps_w;
36 m_x = x;
37 m_y = y;
38 m_z = z;
39 }
40};
41
42class SCR_HeatMap_Autotest: GenericEntity
43{
44 [Attribute("ScriptCamera1", UIWidgets.EditBox, "Name of camera entity", "")]
45 private string m_cameraEntityName;
46
47 [Attribute("", UIWidgets.EditBox, "Name of Confluence page", "")]
48 private string m_pageName;
49
50 [Attribute("Unnamed test", UIWidgets.EditBox, "Title of particular test", "")]
51 private string m_testName;
52
53 [Attribute("Heatmap title", UIWidgets.EditBox, "Title of heatmap", "")]
54 private string m_heatmapName;
55
56 [Attribute("300", UIWidgets.Slider, "Measurements step", "10 2000 10")]
57 private int m_step;
58
59 [Attribute("1", UIWidgets.Slider, "Wait time", "0 20 0.1")]
60 private float m_stepWaitTime;
61
62 [Attribute("80", UIWidgets.Slider, "Camera height", "1 300 10")]
63 private float m_cameraHeight;
64
65 [Attribute("10", UIWidgets.Slider, "Number of slowest points for lowest FPS graph", "10 50 1")]
66 private int m_lowFrameCount;
67
68 [Attribute("", UIWidgets.EditBox)]
69 private string mapName;
70
71
72 [Attribute("false", UIWidgets.CheckBox, "Specify own world bounds if needed.")]
73 private bool OverwriteWorldBounds;
74
75 [Attribute("0", UIWidgets.Auto)]
76 private int WorldStartX;
77
78 [Attribute("0", UIWidgets.Auto)]
79 private int WorldStartZ;
80
81 [Attribute("0", UIWidgets.Auto)]
82 private int WorldEndX;
83
84 [Attribute("0", UIWidgets.Auto)]
85 private int WorldEndZ;
86
87
88 [Attribute("0", UIWidgets.Auto)]
89 private int startX;
90
91 [Attribute("0", UIWidgets.Auto)]
92 private int startZ;
93
94 [Attribute("0", UIWidgets.Auto)]
95 private int endX;
96
97 [Attribute("0", UIWidgets.Auto)]
98 private int endZ;
99
100 [Attribute("120", UIWidgets.EditBox)]
101 private int fpsRange;
102
103 [Attribute("14", UIWidgets.EditBox)]
104 private float timeOfTheDay;
105
106 [Attribute("", UIWidgets.Auto)]
107 private string mapID;
108
109 [Attribute("false", UIWidgets.CheckBox, "Skips actual measuring and only feed the json with fake data (meant for testing).")]
110 private bool SimulateHttpPost;
111
112 [Attribute("true", UIWidgets.CheckBox, "Send collected json data to WebApp via HttpPost.")]
113 private bool SendHttpPost;
114
115 private ref map<EPlatform, string> platforms = new map<EPlatform, string>();
116
117 private ref RestCallback m_jsonCallback = new RestCallback();
118
119 private const string HEATMAP_URL = "https://ar-heatmap.bistudio.com/";
120
121 protected bool m_bDoneGenerating = false; //< Used to stop the benchmark after processing and sending data
122 protected bool m_bDoneGeneratingMessage = false; //< true if message about generating done was already sent
123
124 protected float m_timer; //< Used for counting how long camera stays on one place
125
126 private IEntity m_camera; //< Entity used as camera, this one is auto moved by autotest
127
128 private int m_x = startX; //< Next camera x position
129 private int m_y; //< Camera y position
130 private int m_z = startZ; //< Next camera y position
131
132 private int endX_trimed = endX;
133 private int endZ_trimed = endZ;
134
135 private int m_worldSize; //< How big is world we are scanning
136 private int m_worldSizeX;
137 private int m_worldSizeZ;
138 private vector m_minBounds, m_maxBounds;
139
140 protected ref MeasurementFile m_heatmapfile; //< Heatmap output data
141
142 private ref array<ref HeatmapData> m_geojson_data = new array<ref HeatmapData>();
143 private ref array<int> image_file = new array<int>();
144
145 private float min_fps = 1000;
146 private float max_fps = 0;
147 private float avg_fps = 0;
148
149 protected ref AutotestRegister m_register;
150
151 private bool area_only; // do we want to measure only specified area?
152
153 private float fps_four_directions[4];
154 private int prev_dir = -1;
155
156 private int directions[4] = {
157 0,
158 90,
159 180,
160 270
161 };
162
163 private int colors[6] = {
164 0x0000ff,
165 0x00ffff,
166 0x00ff00,
167 0xffff00,
168 0xff0000,
169 0xff0000
170 };
171
172 void SCR_HeatMap_Autotest(IEntitySource src, IEntity parent)
173 {
174 m_timer = -5;
176 SetFlags(EntityFlags.ACTIVE, true);
177 }
178
179 void PrintToConsole(string text = "", LogLevel logLevel = LogLevel.NORMAL)
180 {
181 Print("[FPS_Autotest] " + text, logLevel);
182 }
183
184 override void EOnInit(IEntity owner)
185 {
186 if(SCR_Global.IsEditMode())
187 return;
188 ChimeraWorld world = GetGame().GetWorld();
189
190 if (world && world.GetTimeAndWeatherManager())
191 {
192 world.GetTimeAndWeatherManager().SetTimeOfTheDay(timeOfTheDay);
193 world.GetTimeAndWeatherManager().SetIsDayAutoAdvanced(false);
194 }
195
196
197 //area_only = (endX > 0 || endZ > 0 || startX > 0 || startZ > 0 || !(startX > endX) || !(startZ > endZ));
198 area_only = (!(startX > endX) || !(startZ > endZ) || !((endX - startX) >= m_step) || !((endZ - startZ) >= m_step));
200 m_camera = GetGame().FindEntity(m_cameraEntityName);
201
202
203 if (m_camera)
204 {
205 float groundY = m_camera.GetWorld().GetSurfaceY(m_x, m_z);
206 m_y = groundY + m_cameraHeight;
207 m_camera.SetOrigin(Vector(m_x, m_y, m_z));
208
209 vector new_angles = m_camera.GetAngles(); // rotate the camera in 4 directions
210 new_angles[1] = 0;
211 m_camera.SetAngles(new_angles);
212 }
213 else
214 {
215 PrintToConsole("Camera not found.", LogLevel.ERROR);
216 m_bDoneGenerating = true;
217 return;
218 }
219
220 if(OverwriteWorldBounds)
221 {
222 m_minBounds[0] = WorldStartX;
223 m_minBounds[2] = WorldStartZ;
224 m_maxBounds[0] = WorldEndX;
225 m_maxBounds[2] = WorldEndZ;
226 }
227
229 if (GetGame().GetWorldEntity())
230 {
231 if (!OverwriteWorldBounds)
232 GetGame().GetWorldEntity().GetWorldBounds(m_minBounds, m_maxBounds);
233
234 /*
235 vector m_minBounds2, m_maxBounds2;
236 GetGame().GetWorldEntity().GetWorldBounds(m_minBounds, m_maxBounds);
237 GetGame().GetWorldEntity().GetBounds(m_minBounds2, m_maxBounds2);
238 PrintFormat("GetWorldBounds: [%1, %2] [%3, %4]", m_minBounds[0], m_minBounds[2], m_maxBounds[0], m_maxBounds[2]);
239 PrintFormat("GetBounds: [%1, %2] [%3, %4]", m_minBounds2[0], m_minBounds2[2], m_maxBounds2[0], m_maxBounds2[2]);
240 */
241
242 m_worldSize = Math.Max(m_maxBounds[0] - m_minBounds[0], m_maxBounds[2] - m_minBounds[2]);
243
244 if (area_only)
245 {
246 m_worldSizeX = endX;
247 m_worldSizeZ = endZ;
248 }
249 else
250 {
251 m_worldSizeX = m_worldSize;
252 m_worldSizeZ = m_worldSize;
253
254 endX = m_worldSizeX;
255 endZ = m_worldSizeZ;
256 }
257 }
258 else
259 {
260 PrintToConsole("Cannot get the world entity.", LogLevel.ERROR);
261 m_bDoneGenerating = true;
262 return;
263 }
264
265 // Round the end so it is in m_step multiple.
266 endX_trimed = startX + m_step * ((endX - startX) / m_step);
267 endZ_trimed = startZ + m_step * ((endZ - startZ) / m_step);
268
269 platforms.Insert(EPlatform.WINDOWS, "62e0e57519098fc05e1b28fe");
270 platforms.Insert(EPlatform.XBOX_ONE, "62e0e58f19098fc05e1b28ff");
271 platforms.Insert(EPlatform.XBOX_SERIES_X, "632863b8211b59093a5afb79");
272 platforms.Insert(EPlatform.XBOX_SERIES_S, "632863cb211b59093a5afb7a");
273 platforms.Insert(EPlatform.PS5, "66cdc91e0a90565192210ae0");
274
275 m_timer = 0;
276
277 // Set example callbacks
278 m_jsonCallback.SetOnSuccess(OnSendDataSuccess);
279 m_jsonCallback.SetOnError(OnSendDataSuccess);
280 }
281
282 override void EOnFrame(IEntity owner, float timeSlice)
283 {
284 m_timer += timeSlice;
285 if (m_timer < 0)
286 return;
287
289 {
291 {
293 PrintToConsole("Measuring step is done or was skipped.");
294 }
295 if(!SendHttpPost)
296 GetGame().RequestClose();
297 return;
298 }
299
300 // If simulating, then the whole measuring is skipped and fake data are generated
301 if (SimulateHttpPost)
302 {
303 PrintToConsole("Simulating the measuring step by feeding it random data for.");
304 max_fps = 0;
305 min_fps = 0;
306 int stepsX = ((endX_trimed-startX)/m_step)+1;
307 int stepsZ = ((endZ_trimed-startZ)/m_step)+1;
308 for(int i = 0; i < stepsX; i++)
309 {
310 for(int j = 0; j < stepsZ; j++)
311 {
312 int fps_avg = 0;
313 for(int k = 0; k < 4; k++)
314 {
315 fps_four_directions[k] = Math.RandomInt(60,121);
316 fps_avg += fps_four_directions[k];
317 }
318 fps_avg = fps_avg / 4;
319 HeatmapData new_geojson_value = new HeatmapData(fps_avg, fps_four_directions[0], fps_four_directions[1], fps_four_directions[2], fps_four_directions[3],
320 startX+i*m_step, 0, startZ+j*m_step);
321 m_geojson_data.Insert(new_geojson_value);
322 }
323 }
324 GenerateGeoJSON();
325 m_bDoneGenerating = true;
326 return;
327 }
328
329 if (!m_camera)
330 {
331 PrintToConsole("Camera entity cannot be found!", LogLevel.ERROR);
332 GetGame().RequestClose();
333 return;
334 }
335
336 int cur_fps = System.GetFPS();
337 int cur_dir = ((m_timer / m_stepWaitTime - Math.Floor(m_timer / m_stepWaitTime)) * 4);
338
339 if (cur_dir != prev_dir)
340 {
341 vector new_angles = m_camera.GetAngles(); // rotate the camera in 4 directions
342 new_angles[1] = directions[cur_dir];//new_angles[1] + 90;
343 m_camera.SetAngles(new_angles);
344 prev_dir = cur_dir;
345 }
346
347 fps_four_directions[cur_dir] = cur_fps;
348
349 if (m_timer > m_stepWaitTime) //< When camera was still long enough
350 {
351 m_timer -= m_stepWaitTime;
352
353 if (!m_register)
354 {
355 m_register = new AutotestRegister();
356 m_register.Init(m_pageName);
357 }
358
359 if (!m_heatmapfile)
360 {
361 PrintToConsole("Registering measurement file (HTML): 0_fps_test_descr");
362 ref MeasurementFile descrFile = m_register.OpenMeasurementFile("0_fps_test_descr", "", MeasurementType.HTML);
363 if(!descrFile || !descrFile.IsValid())
364 {
365 PrintToConsole("Cannot create measurement file (HTML).", LogLevel.ERROR);
366 m_bDoneGenerating = true;
367 return;
368 }
369 descrFile.AddData(string.Format("<h1>" + m_heatmapName + "</h1><p>Camera step: %1m<br/>Step wait time: %2s<br/>Camera height above ground: %3m<br/>Number of worst FPS places: %4</p>", m_step, m_stepWaitTime, m_cameraHeight, m_lowFrameCount));
370
371 PrintToConsole("Registering measurement file (HeatMap): 1_fps_heatmap");
372 m_heatmapfile = m_register.OpenMeasurementFile("1_fps_heatmap", m_testName, MeasurementType.HeatMap);
373 if(!m_heatmapfile || !m_heatmapfile.IsValid())
374 {
375 PrintToConsole("Cannot create measurement file (HeatMap).", LogLevel.ERROR);
376 m_bDoneGenerating = true;
377 return;
378 }
379 }
380
381 int fps_avg = (fps_four_directions[0] + fps_four_directions[1] + fps_four_directions[2] + fps_four_directions[3]) / 4;
382
383 image_file.Insert(fps_avg);
384 m_heatmapfile.AddData(string.Format("%1,%2,%3", m_x, m_z, fps_avg)); //< output new data to heatmap
385 HeatmapData new_geojson_value = new HeatmapData(fps_avg, fps_four_directions[0], fps_four_directions[1], fps_four_directions[2], fps_four_directions[3], m_x, m_y, m_z);
386 m_geojson_data.Insert(new_geojson_value);
387
388 if (m_x + m_step <= m_worldSizeX)
389 {
390 if (fps_avg > max_fps)
391 max_fps = fps_avg;
392 if (fps_avg < min_fps)
393 min_fps = fps_avg;
395 m_x = m_x + m_step;
396 }
397 else
398 {
399 if (m_z + m_step <= m_worldSizeZ)
400 {
401 m_x = startX;
402 m_z = m_z + m_step;
403 }
404 else
405 {
406 PrintToConsole("All points measured.");
407 CalculateAvgFPS();
408 GenerateDDS();
409 GenerateGeoJSON();
410 GenerateCSV();
411 m_bDoneGenerating = true;
412 }
413 }
414
415 if (m_camera)
416 {
418 float groundY = m_camera.GetWorld().GetSurfaceY(m_x, m_z);
419 m_y = groundY + m_cameraHeight;
420 m_camera.SetOrigin(Vector(m_x, m_y, m_z));
421 }
422 }
423 }
424
425 private void CalculateAvgFPS()
426 {
427 int measured_points = m_geojson_data.Count();
428 for (int i = 0; i < measured_points; ++i)
429 {
430 avg_fps += m_geojson_data[i].m_fps / measured_points;
431 }
432
433 if (measured_points == 0)
434 return;
435
436 //avg_fps /= m_geojson_data.Count()*4;
437 PrintToConsole("Avg FPS: " + avg_fps);
438 }
439
440 private void ReverseArray(inout array<int> arr)
441 {
442 array<int> temp = new array<int>();
443 for (int i = arr.Count()-1; i >= 0; --i)
444 {
445 temp.Insert(arr[i]);
446 }
447 arr = temp;
448 }
449
450 private void GenerateDDS()
451 {
452#ifdef WORKBENCH
453 PrintToConsole("Generating DDS file.");
454 int width = (endX_trimed - startX) / m_step + 1;//2;
455 int height = (endZ_trimed - startZ) / m_step;//2;
456
457 int offset_x = startX / m_step;
458 int offset_z = startZ / m_step;
459
460 int image_size = m_worldSize / m_step;
461
462 int id = 0;
463 int id_z = 0;
464
465 array <int> image = new array <int>;
466
467 for (int i = 0; i < image_size * image_size; ++i)
468 {
469 image.Insert(ARGB(255, 0, 0, 0));
470 }
471
472 for (int y = 0; y < height; ++y)
473 {
474 array <int> row = new array <int>;
475 for (int i = 0; i < image_size; ++i)
476 {
477 row.Insert(ARGB(255, 0, 0, 0));
478 }
479
480 int id_x = 0;
481
482 for (int x = 0; x < width; ++x)
483 {
484 float range;
485 int col;
486
487 int fps = image_file[id];
488
489 float level = Math.Clamp(fps / fpsRange, 0, 1);
490 int phase = Math.Floor(level / 0.25);
491
492 range = Math.Clamp((level - phase * 0.25) / 0.25, 0, 1);
493
494 int from = colors[phase];
495 int to = colors[phase+1];
496
497 Color col1 = Color.FromInt(from);
498 Color col2 = Color.FromInt(to);
499
500 col1.Lerp(col2, range);
501 col = col1.PackToInt();
502
503 int index = offset_x + x;
504
505 if (index < row.Count())
506 row[index] = col;
507
508 id_x++;
509 id++;
510 }
511
512 ReverseArray(row);
513 for (int i = 0; i < row.Count(); ++i)
514 {
515 int index = (offset_z + id_z) * image_size + i;
516 if (index < image.Count())
517 image[index] = row[i];
518 }
519 id_z++;
520 }
521
522 ReverseArray(image);
523 const string ddsFile = "$logs:heatmap.dds";
524 if(!TexTools.SaveImageData(ddsFile, image_size, image_size, image))
525 {
526 PrintToConsole("Failed to save the data into the file: " + ddsFile, LogLevel.ERROR);
527 return;
528 }
529 PrintToConsole("Data sucessfully saved into dds file: " + ddsFile);
530#endif
531 }
532
533 private string GetGeoJSONLine(HeatmapData val) //vector val)
534 {
535 /*
536 string new_value = string.Format(
537 "{ \"properties\": { \"FPS\": \"%1\" }, \"geometry\": { \"coordinates\": [ %2, %3, %4] } }",
538 Math.Floor(val.m_fps), val.m_x, val.m_z, val.m_y);
539 */
540 // TODO use this when WebApp is ready
541
542 string new_value = string.Format(
543 "{ \"type\": \"Point\", \"properties\": { \"FPS_AVG\": \"%1\", \"FPS_N\": \"%2\", \"FPS_E\": \"%3\", \"FPS_S\": \"%4\", \"FPS_W\": \"%5\" }, \"geometry\": { \"coordinates\": [ %6, %7, %8] } }",
544 Math.Floor(val.m_fps), Math.Floor(val.m_fps_n), Math.Floor(val.m_fps_e), Math.Floor(val.m_fps_s), Math.Floor(val.m_fps_w),
545 val.m_x, val.m_z, val.m_y);
546
547 return new_value;
548 }
549
550 private string GetCSVLine(HeatmapData val) //vector val)
551 {
552 string new_value = string.Format(
553 "%1,%2,%3",
554 val.m_x, val.m_z, Math.Floor(val.m_fps) );
555
556 return new_value;
557 }
558
559 private void GenerateGeoJSON()
560 {
561 FileHandle file;
562
563 PrintToConsole("Creating the GeoJSON file.");
564
565 string directoryName = "$logs:/" + mapName;
566 if(!FileIO.MakeDirectory(directoryName))
567 {
568 PrintToConsole("Failed to make the directory \"" + directoryName + "\".", LogLevel.ERROR);
569 PrintToConsole("Failed to generate the GeoJSON file.");
570 return;
571 }
572 string fileName = FormatTimestamp() + ".geojson";
573 string filePath = directoryName + "/" + fileName;
574 file = FileIO.OpenFile(filePath, FileMode.WRITE);
575 if(!file || !file.IsOpen())
576 {
577 PrintToConsole("Failed to create/open the file \"" + filePath + "\". Cannot continue with generating and sending the GeoJSON file.", LogLevel.ERROR);
578 return;
579 }
580
581 WriteDataGJSON(file);
582 file.Close();
583 file = FileIO.OpenFile(filePath, FileMode.READ);
584 if(!file || !file.IsOpen())
585 {
586 PrintToConsole("Failed to open the file \"" + filePath + "\". Cannot continue with sending the GeoJSON file.", LogLevel.ERROR);
587 return;
588 }
589
590 string data;
591 file.Read(data, file.GetLength());
592 file.Close();
593
594 RestContext restContext = GetGame().GetRestApi().GetContext(HEATMAP_URL);
595
596 if (!restContext)
597 {
598 PrintToConsole("Failed to get RestAPI context. Unable to send data", LogLevel.ERROR);
599 return;
600 }
601
602 PrintToConsole("Attempting to POST json data");
603 restContext.SetHeaders("Content-Type,application/json");
604 int postReturnVal;
605 if(SendHttpPost)
606 postReturnVal = restContext.POST(m_jsonCallback, "api/fps-statistics", data);
607 PrintToConsole("Returned value of the POST: " + postReturnVal.ToString());
608
609 restContext = null;
610
611 PrintToConsole("Creating the GeoJSON done.");
612 }
613
614 private void GenerateCSV()
615 {
616 FileHandle file;
617
618 PrintToConsole("Creating a CSV file");
619
620 string directoryName = "$logs:/" + mapName;
621 if(!FileIO.MakeDirectory(directoryName))
622 {
623 PrintToConsole("Failed to make the directory \"" + directoryName + "\".", LogLevel.ERROR);
624 PrintToConsole("Failed to generate the CSV file.");
625 return;
626 }
627 string fileName = FormatTimestamp() + ".csv";
628 string filePath = directoryName + "/" + fileName;
629 file = FileIO.OpenFile(directoryName, FileMode.WRITE);
630 if(!file || !file.IsOpen())
631 {
632 PrintToConsole("Failed to create/open the file \"" + filePath + "\". Cannot continue with generating the CSV file.", LogLevel.ERROR);
633 return;
634 }
635 WriteDataCSV(file);
636 file.Close();
637
638 PrintToConsole("Creating a CSV done");
639 }
640
641 private void WriteDataGJSON(FileHandle file)
642 {
643 if(!file || !file.IsOpen())
644 {
645 PrintToConsole("No file to write GeoJson data to found.", LogLevel.ERROR);
646 return;
647 }
648
649 PrintToConsole("Adding data to geojson");
650
651 string platform;
652 platforms.Find(System.GetPlatform(), platform);
653
654 if (!platform)
655 {
656 platform = "Invalid";
657
658 PrintToConsole("SCR_FPS_Autotest::Invalid platform, GJSON file will fail to post to database", LogLevel.ERROR);
659 }
660
661 file.WriteLine("{");
662 file.WriteLine(string.Format("\"date\": \"%1\",", SCR_DateTimeHelper.GetDateTimeLocal()));
663 file.WriteLine(string.Format("\"platform\": \"%1\",", platform));
664 file.WriteLine(string.Format("\"map\": \"%1\",", mapID));
665 file.WriteLine(string.Format("\"heatmapName\": \"%1\",", m_heatmapName));
666 file.WriteLine("\"dimension\": {");
667 file.WriteLine(string.Format(" \"startX\": %1,", m_minBounds[0]));
668 file.WriteLine(string.Format(" \"startZ\": %1,", m_minBounds[2]));
669 file.WriteLine(string.Format(" \"endX\": %1,", m_maxBounds[0]));
670 file.WriteLine(string.Format(" \"endZ\": %1,", m_maxBounds[2]));
671 //file.WriteLine(string.Format(" \"startX\": %1,", startX));
672 //file.WriteLine(string.Format(" \"startZ\": %1,", startZ));
673 //file.WriteLine(string.Format(" \"endX\": %1,", endX_trimed));
674 //file.WriteLine(string.Format(" \"endZ\": %1,", endZ_trimed));
675 file.WriteLine(string.Format(" \"stepSize\": %1},", m_step));
676 file.WriteLine("\"featurecollection\": {");
677 file.WriteLine("\"type\": \"FeatureCollection\",");
678 file.WriteLine("\"name\": \"fps\",");
679 file.WriteLine(string.Format("\"minfps\": %1,", Math.Floor(min_fps)));
680 file.WriteLine(string.Format("\"maxfps\": %1,", Math.Floor(max_fps)));
681 file.WriteLine(string.Format("\"avgfps\": %1,", Math.Floor(avg_fps)));
682 file.WriteLine("\"crs\": { \"type\": \"name\", \"properties\": { \"name\": \"urn:ogc:def:crs:EPSG::32632\" } },");
683 file.WriteLine("\"features\": [");
684
685 for (int i = 0; i < m_geojson_data.Count(); ++i)
686 {
687 string line_end = ",";
688 if (i == m_geojson_data.Count()-1)
689 line_end = string.Empty;
690
691 file.WriteLine(GetGeoJSONLine(m_geojson_data[i]) + line_end);
692 }
693
694 file.WriteLine("]\n}\n}");
695 PrintToConsole("Data successfully written to the GeoJSON file.");
696 }
697
698 private void WriteDataCSV(FileHandle file)
699 {
700 if(!file || !file.IsOpen())
701 {
702 PrintToConsole("No file to write CSV data to found.", LogLevel.ERROR);
703 return;
704 }
705
706 PrintToConsole("Adding data to CSV");
707
708 file.WriteLine("x,z,fps");
709
710 for (int i = 0; i < m_geojson_data.Count(); ++i)
711 file.WriteLine(GetCSVLine(m_geojson_data[i]));
712
713 }
714 private string FormatTimestamp()
715 {
716 int year, month, day;
717 System.GetYearMonthDay(year, month, day);
718 string smonth, sday;
719 if (month < 10)
720 smonth = string.Format("0%1", month);
721 else
722 smonth = string.Format("%1", month);
723
724 if (day < 10)
725 sday = string.Format("0%1", day);
726 else
727 sday = string.Format("%1", day);
728
729 return string.Format("%1%2%3", year, smonth, sday);
730 }
731
732 private void OnSendDataError(RestCallback cb)
733 {
734 if (cb.GetRestResult() == ERestResult.EREST_ERROR_TIMEOUT)
735 {
736 Print("[FPS_Autotest] Sending data has timed out", LogLevel.WARNING);
737 }
738 else
739 {
740 Print("[FPS_Autotest] Sending data has failed with errorCode[" + cb.GetHttpCode() + "]", LogLevel.WARNING);
741 }
742
743 GetGame().RequestClose();
744 };
745
746 private void OnSendDataSuccess(RestCallback cb)
747 {
748 Print("[FPS_Autotest] Data sent successfully. Size: " + cb.GetData().Length());
749 GetGame().RequestClose();
750 };
751};
AddonBuildInfoTool id
MeasurementType
string FormatTimestamp()
ArmaReforgerScripted GetGame()
Definition game.c:1398
enum SCR_ECompassType EntityEditorProps(category:"GameScripted/Gadgets", description:"Compass", color:"0 0 255 255")
Prefab data class for compass component.
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
Get all prefabs that have the spawner data
void IEntity(IEntitySource src, IEntity parent)
protected script Constructor
proto external EntityEvent SetEventMask(EntityEvent e)
proto external EntityFlags SetFlags(EntityFlags flags, bool recursively=false)
ref MeasurementFile m_heatmapfile
ref AutotestRegister m_register
Definition Types.c:486
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
SCR_FieldOfViewSettings Attribute
EntityEvent
Various entity events.
Definition EntityEvent.c:14
EntityFlags
Various entity flags.
Definition EntityFlags.c:14
FileMode
Mode for opening file. See FileSystem::Open.
Definition FileMode.c:14
EPlatform
Definition EPlatform.c:13
proto native vector Vector(float x, float y, float z)
ERestResult
States and result + error code produced by RestApi.
Definition ERestResult.c:14
proto int ARGB(int a, int r, int g, int b)