--[[
---------------------------------------------------------------------------
Remote Train Control Program for Windows

© Copyright 2019 by Mark DiVecchio

	This file is part of Remote Train Control.

	Remote Train Control is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	Remote Train Control is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Remote Train Control.  If not, see <http://www.gnu.org/licenses/>.

 Home Page : http://www.silogic.com/trains/RTC_Running.html
---------------------------------------------------------------------------]]
-- Semicolons are not required in Lua code
title = "Odometer Test"

require("defines");
require("functions");

LastRunTime = 0.0;
LastDTO = 0.0;
CurrentDTO = 0.0;
Accuracy = 0.01;	-- 1.00%

SaveAcc = 0;
SaveDec = 0;

MyEngineNo = 0;

--[[---------------------------------------------------------------------------------------]]
function setup(Engine, TIU)
	-- this function is called once when the [Run Script] button is pushed
	print("setup()");
	SetLED(1, clGreen, "Speed");	-- set status LED to green
	SetLED(2, clGreen, "%");	-- set status LED to green	
	-- Engine number selected on the Main window is used
	if (Debug() > 0) then print(string.format("Debug level %d", Debug())); end
	MyEngineNo = Engine;
	Resp = InputQuery("Numeric Input Required", "Enter Engine Number", MyEngineNo);
	if (Resp == false or Resp == nil) then	-- user pressed [Cancel]
		return false;	-- false=setup failed, true=setup succeeded
		end;
	Enum = tonumber(Resp);
	if (Enum ~= nil) then	-- if the result is a number, then use it, otherwise, ignore it
		MyEngineNo = Enum;
		end
	print("Engine Number = " .. MyEngineNo);
	
	-- initialize the layout
	print(string.format("Startup Engine : %d", MyEngineNo));
	EngineStartUp(MyEngineNo, TIU);
	Sleep(25);			
	if (IsEngineRunning(MyEngineNo)) then	-- IsEngineRunning() REQUIRES use of StartUpActiveEngines() or EngineStartUp()
		print(string.format("Initalizing Engine %d", MyEngineNo));
		-- Set smoke off
		Smoke(OFF, 0, MyEngineNo, TIU);
		-- Cab Chatter Off
		CabChat(OFF, 0, MyEngineNo, TIU);
		-- get DTO at start
		CurrentDTO = DTO(MyEngineNo, TIU);
		print(string.format("Trip odometer at start = %.3f Smiles", CurrentDTO));
		-- read up and save the Acc/Dec rates
		SaveAcc, SaveDec = GetRate(MyEngineNo, TIU);
		if (SaveAcc == nil or SaveDec == nil) then
			print(string.format("Get Acc/Dec Rates Failed for Engine : %d", MyEngineNo));
			return false;	-- false=setup failed, true=setup succeeded
			else
			print(string.format("Saved Acc/Dec Rates for Engine : %d : %d - %d", MyEngineNo, SaveAcc, SaveDec));
			end
		-- Set Acc/Dec rate to 25 Smph/sec
		Rate(25, 25, 0, MyEngineNo, TIU);
		print("Acc/Dec rates set to 25 Smph/sec");
		else
		print(string.format("Startup Failed for Engine : %d", MyEngineNo));
		return false;	-- false=setup failed, true=setup succeeded
		end
	print(string.format("Required Odometer Accuracy : %.2f%%", Accuracy * 100.0));

	Speeds = {5,11,15,22,26,33,38,44,50,55}
	--Speeds = {25}
	for i,iSpeed in ipairs(Speeds) do
		print(string.format("SetSpeed %d Smph for Engine : %d", iSpeed, MyEngineNo));
		SetSpeed(iSpeed, 0, MyEngineNo, TIU);
		Sleep(20);			
		-- read up speed and check it against iSpeed
		CurrentSpeed = GetSetSpeed(MyEngineNo, TIU);	-- get Requested Speed
		if (CurrentSpeed ~= iSpeed) then
			print(string.format("Requested Speed Wrong : %d Smph", CurrentSpeed));
			SetLED(1, clRed);	-- set status LED to red
			--return false;
			else
			print(string.format("Requested Speed Correct : %d Smph", CurrentSpeed));
			end
		-- read up speed and check it against iSpeed
		InstantSpeed = GetSpeed(MyEngineNo, TIU);
		if (InstantSpeed ~= iSpeed) then
			print(string.format("Instantaneous Speed Wrong : %d Smph", InstantSpeed));
			SetLED(1, clRed);	-- set status LED to red
			--return false;
			else
			print(string.format("Instantaneous Speed Correct : %d Smph", InstantSpeed));
			end
		-- run for one test period
		print("Test " .. i .. " Started");
		
		-- read up the DOD and DTO
		LastDTO = DTO(MyEngineNo, TIU);
		LastDOD = DOD(MyEngineNo, TIU);
		LastRunTime = RunTime();
		print(string.format(" Run Time = %.2f seconds", LastRunTime)); 
		print(string.format(" Trip Odometer = %.6f Smiles", LastDTO)); 
		print(string.format(" Odometer = %.6f Smiles", LastDOD)); 
		
		-- run for awhile
		Sleep(30);			
		
		-- read up the DOD and DTO and check that equal Smiles were recorded
		CurrentDTO = DTO(MyEngineNo, TIU);
		CurrentDOD = DOD(MyEngineNo, TIU);
		CurrentRunTime = RunTime();
		print(string.format("Run Time = %.2f seconds (%.2f-%.2f)", CurrentRunTime - LastRunTime, CurrentRunTime, LastRunTime)); 
		print(string.format("Trip Odometer = %.6f Smiles (%.6f-%.6f)", CurrentDTO - LastDTO, CurrentDTO, LastDTO)); 
		print(string.format("Odometer = %.6f Smiles (%.6f-%.6f)", CurrentDOD - LastDOD, CurrentDOD, LastDOD)); 
		print(string.format("Odometers accurate to within %.2f%%", 100.0 * ((CurrentDOD - LastDOD) - (CurrentDTO - LastDTO)) / ((CurrentDOD - LastDOD)) ));
		if (((CurrentDTO - LastDTO) > ((CurrentDOD - LastDOD) * (1 + Accuracy))) or ((CurrentDTO - LastDTO) < ((CurrentDOD - LastDOD) * (1 - Accuracy)))) then
			print(string.format("*** Odometer not within %.2f%% of expected", Accuracy * 100.0));
			Beep();
			SetLED(2, clRed);	-- set status LED to red
			end		
		end		
	Sleep(15);			
	return Stop("Odometer Test Complete");
	end
--[[---------------------------------------------------------------------------------------]]
function cleanup(Engine, TIU)
	-- this function is called once when the user presses the [STOP] button
	print("cleanup()");
	-- Restore Acc/Dec rates if saved
	if (SaveAcc > 0 and SaveDec > 0) then
		Rate(SaveAcc, SaveDec, 0, MyEngineNo, TIU);
		Sleep(5);
		-- read up the restored Acc/Dec rates
		SaveAcc, SaveDec = GetRate(MyEngineNo, TIU);
		if (SaveAcc == nil or SaveDec == nil) then
			print(string.format("Get Acc/Dec Rates Failed for Engine : %d", MyEngineNo));
			return false;	-- false=setup failed, true=setup succeeded
			else
			print(string.format("Saved Acc/Dec Rates for Engine : %d : %d - %d", MyEngineNo, SaveAcc, SaveDec));
			end
		SetSpeed(0, 0, MyEngineNo, TIU);
		print("begin cleanup() Sleep(15) call");
		Sleep(15)			
		print("end cleanup() Sleep(15) call");
		print("Shutdown Engine " .. MyEngineNo .. " - Please Wait");
		EngineShutdown(MyEngineNo, TIU);
		end;
	print("Script Finished");
	return true;		-- false=cleanup failed, true=cleanup succeeded
	end
--[[---------------------------------------------------------------------------------------]]
function StopEngine(Eng, TIU)		
	print("Stopping Engine " .. MyEngineNo);
	SetSpeed(0, 0, MyEngineNo, TIU);
	return true;
end
Function01Name, Function01Label = StopEngine, "Stop";
--[[---------------------------------------------------------------------------------------]]
function StartEngine(Eng, TIU)		
	print("Starting Engine " .. MyEngineNo);
	SetSpeed(20, 0, MyEngineNo, TIU);	
	return true;
end
Function02Name, Function02Label = StartEngine, "Start 20 Smph";
--[[---------------------------------------------------------------------------------------]]
function Forward(Eng, TIU)		
	print("Forward Engine " .. MyEngineNo);
	SetDirection(FORWARD, 0, MyEngineNo, TIU);
	return true;
end
Function03Name, Function03Label = Forward, "Forward";
--[[---------------------------------------------------------------------------------------]]
function Reverse(Eng, TIU)	
	print("Reverse Engine " .. MyEngineNo);
	SetDirection(REVERSE, 0, MyEngineNo, TIU);
	return true;
end
Function04Name, Function04Label = Reverse, "Reverse";
--[[---------------------------------------------------------------------------------------]]
--[[-----------------------------------------
Success compiling C:\trains\MTH\PC Control\Scripts\Odometer Test.lua
setup()
Engine Number = 12
Startup Engine : 12
Initalizing Engine 12
Trip odometer at start = 0.000 Smiles
Saved Acc/Dec Rates for Engine : 12 : 1 - 1
Acc/Dec rates set to 25 Smph/sec
Required Odometer Accuracy : 1.00%
SetSpeed 5 Smph for Engine : 12
Requested Speed Correct : 5 Smph
Instantaneous Speed Correct : 5 Smph
Test 1 Started
 Run Time = 47.70 seconds
 Trip Odometer = 0.012886 Smiles
 Odometer = 213.170739 Smiles
Run Time = 61.00 seconds (108.70-47.70)
Trip Odometer = 0.084653 Smiles (0.097539-0.012886)
Odometer = 0.083897 Smiles (213.254635-213.170739)
Odometers accurate to within -0.90%
SetSpeed 11 Smph for Engine : 12
Requested Speed Correct : 11 Smph
Instantaneous Speed Correct : 11 Smph
Test 2 Started
 Run Time = 125.20 seconds
 Trip Odometer = 0.146294 Smiles
 Odometer = 213.304113 Smiles
Run Time = 61.00 seconds (186.20-125.20)
Trip Odometer = 0.186385 Smiles (0.332679-0.146294)
Odometer = 0.187154 Smiles (213.491267-213.304113)
Odometers accurate to within 0.41%
SetSpeed 15 Smph for Engine : 12
Requested Speed Correct : 15 Smph
Instantaneous Speed Correct : 15 Smph
Test 3 Started
 Run Time = 202.70 seconds
 Trip Odometer = 0.400156 Smiles
 Odometer = 213.557954 Smiles
Run Time = 61.00 seconds (263.70-202.70)
Trip Odometer = 0.254152 Smiles (0.654308-0.400156)
Odometer = 0.255992 Smiles (213.813947-213.557954)
Odometers accurate to within 0.72%
SetSpeed 22 Smph for Engine : 12
Requested Speed Correct : 22 Smph
Instantaneous Speed Correct : 22 Smph
Test 4 Started
 Run Time = 280.10 seconds
 Trip Odometer = 0.752827 Smiles
 Odometer = 213.912902 Smiles
Run Time = 61.00 seconds (341.10-280.10)
Trip Odometer = 0.372552 Smiles (1.125379-0.752827)
Odometer = 0.372157 Smiles (214.285059-213.912902)
Odometers accurate to within -0.11%
SetSpeed 26 Smph for Engine : 12
Requested Speed Correct : 26 Smph
Instantaneous Speed Correct : 26 Smph
Test 5 Started
 Run Time = 357.60 seconds
 Trip Odometer = 1.243505 Smiles
 Odometer = 214.403375 Smiles
Run Time = 61.00 seconds (418.60-357.60)
Trip Odometer = 0.440907 Smiles (1.684413-1.243505)
Odometer = 0.440995 Smiles (214.844370-214.403375)
Odometers accurate to within 0.02%
SetSpeed 33 Smph for Engine : 12
Requested Speed Correct : 33 Smph
Instantaneous Speed Correct : 33 Smph
Test 6 Started
 Run Time = 435.10 seconds
 Trip Odometer = 1.833501 Smiles
 Odometer = 214.994954 Smiles
Run Time = 61.00 seconds (496.10-435.10)
Trip Odometer = 0.559421 Smiles (2.392921-1.833501)
Odometer = 0.559311 Smiles (215.554265-214.994954)
Odometers accurate to within -0.02%
SetSpeed 38 Smph for Engine : 12
Requested Speed Correct : 38 Smph
Instantaneous Speed Correct : 38 Smph
Test 7 Started
 Run Time = 512.60 seconds
 Trip Odometer = 2.565483 Smiles
 Odometer = 215.726361 Smiles
Run Time = 61.00 seconds (573.60-512.60)
Trip Odometer = 0.643809 Smiles (3.209292-2.565483)
Odometer = 0.645359 Smiles (216.371720-215.726361)
Odometers accurate to within 0.24%
SetSpeed 44 Smph for Engine : 12
Requested Speed Correct : 44 Smph
Instantaneous Speed Correct : 44 Smph
Test 8 Started
 Run Time = 590.10 seconds
 Trip Odometer = 3.409013 Smiles
 Odometer = 216.571782 Smiles
Run Time = 61.10 seconds (651.20-590.10)
Trip Odometer = 0.746113 Smiles (4.155126-3.409013)
Odometer = 0.746465 Smiles (217.318247-216.571782)
Odometers accurate to within 0.05%
SetSpeed 50 Smph for Engine : 12
Requested Speed Correct : 50 Smph
Instantaneous Speed Correct : 50 Smph
Test 9 Started
 Run Time = 667.70 seconds
 Trip Odometer = 4.382804 Smiles
 Odometer = 217.546274 Smiles
Run Time = 61.10 seconds (728.80-667.70)
Trip Odometer = 0.848588 Smiles (5.231392-4.382804)
Odometer = 0.849723 Smiles (218.395997-217.546274)
Odometers accurate to within 0.13%
SetSpeed 55 Smph for Engine : 12
Requested Speed Correct : 55 Smph
Instantaneous Speed Correct : 55 Smph
Test 10 Started
 Run Time = 745.20 seconds
 Trip Odometer = 5.482238 Smiles
 Odometer = 218.645536 Smiles
Run Time = 61.10 seconds (806.30-745.20)
Trip Odometer = 0.931981 Smiles (6.414219-5.482238)
Odometer = 0.933620 Smiles (219.579155-218.645536)
Odometers accurate to within 0.18%
Test Complete
setup() returned false
cleanup()
begin cleanup() Sleep(15) call
end cleanup() Sleep(15) call
Shutdown Engine 12 - Please Wait
Script Finished

----------------------------------------------]]




