#define LOAD
#define SAVEX
#define DrawImage
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using Common;
namespace PetriDish
{
public partial class Form1 : Form
{
//static string Filepath = Path.Combine( "../../..", "State." + Engine.X + "x" + Engine.Y + ".bin" );
static string Filepath = "State." + Engine.X + "x" + Engine.Y + ".bin";
static int ProcessorCount = Environment.ProcessorCount;
SynchronizationContext _UIContext = null;
Stopwatch _Stopwatch = new Stopwatch();
TimeSpan _PreviousStopwatch = TimeSpan.Zero;
Process _Process = Process.GetCurrentProcess();
TimeSpan _InitialProcessor = TimeSpan.Zero;
TimeSpan _PreviousProcessor = TimeSpan.Zero;
Modal<int> _ProcessorUsage = new Modal<int>();
int _ProcessorUsageAverage = 0;
class Modal<T>
{
T[] _Data = new T[ 42 ];
int _Index = 0;
public void Add( T o )
{
_Data[ _Index ] = o;
_Index = ( _Index + 1 ) % _Data.Length;
}
public T Average { get { return _Data.Modal(); } }
}
Modal<double> _FPS = new Modal<double>();
Modal<long> _PPS = new Modal<long>();
Modal<int> _SPPPC = new Modal<int>();
double _afps = 0;
long _apps = 0;
int _aspp = 0;
double _afpspc = 0;
long _appspc = 0;
int _aspppc = 0;
int _Frame = 0;
public Form1()
{
InitializeComponent();
_UIContext = SynchronizationContext.Current;
PictureBox box = new PictureBox();
using ( Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream( "PetriDish.Images.key.png" ) )
box.Image = Image.FromStream( s );
ToolStripItem item = new ToolStripControlHost( box );
item.Width = box.Image.Width;
_ShowKey.DropDownItems.Add( item );
Load += Form1_Load;
FormClosing += Form1_Closing;
DoubleBuffered = true;
}
private void Form1_Load( object sender, EventArgs e )
{
ProcessorCount = ( Engine.ThreadCount < Environment.ProcessorCount ? Engine.ThreadCount : Environment.ProcessorCount );
Text += " ( " + Engine.X + " x " + Engine.Y + ")";
_Stopwatch.Start();
_InitialProcessor = _Process.TotalProcessorTime;
#if LOAD
if ( File.Exists( Filepath ) ) Engine.Load( Filepath );
#endif
Engine.Update += Updated;
Engine.Start();
int width = Engine.X;
if ( width < 500 ) width = 500;
FormPosition.Restore( this );
ClientSize = new Size( width, _ToolStrip.Height + 100 + Engine.Y );
}
private void Form1_Closing( object sender, EventArgs e )
{
Engine.Stop();
FormPosition.Save( this );
}
void Updated( object sender, EventArgs e )
{
if ( _Frame == 1764 )
#if !SAVE
if ( !File.Exists( Filepath ) )
#endif
Engine.Save( Filepath );
//_UIContext.Post( Updated, null );
Updated( null );
}
void Updated( object state )
{
TimeSpan tsStopwatch = _Stopwatch.Elapsed;
TimeSpan tsProcessor = _Process.TotalProcessorTime;
TimeSpan tsStopwatchDelta = tsStopwatch - _PreviousStopwatch;
TimeSpan tsProcessorDelta = tsProcessor - _PreviousProcessor;
if ( tsStopwatchDelta > TimeSpan.Zero )
{
double fps = 1000 / tsStopwatchDelta.TotalMilliseconds;
long pps = Engine.PixelsPerSecond;
int threadCount = Engine.ThreadCount;
_FPS.Add( fps );
_PPS.Add( pps );
_SPPPC.Add( ( int ) ( 1000000000d * threadCount / pps ) );
_afps = _FPS.Average;
_apps = _PPS.Average;
_aspppc = _SPPPC.Average;
_afpspc = _afps / threadCount;
_appspc = _apps / threadCount;
_aspp = _aspppc / threadCount;
_ProcessorUsageAverage = ( int )
( 100d * (
( tsProcessor.TotalSeconds - _InitialProcessor.TotalSeconds ) /
tsStopwatch.TotalSeconds )
/ ProcessorCount );
//if ( tsProcessorDelta > TimeSpan.Zero )
//{
// double percent = 100d * ( tsProcessorDelta.TotalMilliseconds / tsStopwatchDelta.TotalMilliseconds ) / Engine.ThreadCount;
// _ProcessorUsage.Add( ( int ) percent );
// _ProcessorUsageAverage = _ProcessorUsage.Average;
//}
}
_Frame++;
_PreviousStopwatch = tsStopwatch;
_PreviousProcessor = tsProcessor;
Invalidate();
}
protected override void OnPaint( PaintEventArgs e )
{
//base.OnPaint( e );
try
{
#if DrawImage
lock ( Engine.BitmapLock )
{
int x = ( ClientSize.Width - Engine.X ) / 2;
e.Graphics.DrawImageUnscaled( Engine.Bitmap, x, _ToolStrip.Height + 100 );
}
#endif
Font f = SystemFonts.DialogFont;
Brush b = SystemBrushes.WindowText;
int dx = 100;
int x0 = 20;
int x1 = x0 + dx;
int x2 = x1 + dx;
int x3 = x2 + dx;
int dy = 20;
int y0 = _ToolStrip.Height + 10;
int y1 = y0 + dy;
int y2 = y1 + dy;
int y3 = y2 + dy;
e.Graphics.DrawString( "per core", f, b, x1, y0 );
e.Graphics.DrawString( Engine.ThreadCount + " cores", f, b, x2, y0 );
e.Graphics.DrawString( "FPS:", f, b, x0, y1 );
e.Graphics.DrawString( "P/s:", f, b, x0, y2 );
e.Graphics.DrawString( "ns/P:", f, b, x0, y3 );
e.Graphics.DrawString( _afpspc.ToString( "N2" ), f, b, x1, y1 );
e.Graphics.DrawString( _appspc.ToString( "N0" ), f, b, x1, y2 );
e.Graphics.DrawString( _aspppc.ToString( "N0" ), f, b, x1, y3 );
e.Graphics.DrawString( _afps.ToString( "N2" ), f, b, x2, y1 );
e.Graphics.DrawString( _apps.ToString( "N0" ), f, b, x2, y2 );
e.Graphics.DrawString( _aspp.ToString( "N0" ), f, b, x2, y3 );
e.Graphics.DrawString( "frames: " + _Frame.ToString( "N0" ), f, b, x3, y0 );
e.Graphics.DrawString( "runtime: " + ( _PreviousStopwatch.TotalMilliseconds / 1000f ).ToString( "N1" ), f, b, x3, y1 );
e.Graphics.DrawString( "mean fps: " + ( _Frame / _PreviousStopwatch.TotalSeconds ).ToString( "N2" ), f, b, x3, y2 );
e.Graphics.DrawString( "mean cpu: " + _ProcessorUsageAverage.ToString( "N0" ), f, b, x3, y3 );
}
finally
{
Engine.Painted();
}
}
}
}