So I am making a Robbery system the timer works perfectly on the first start but on second try it minuses the time 2ice.. meaning the sequence by the timer goes down is 10,9,8,7...... But on the 2nd try the sequence is 10,8,6,4...... on the 3rd try its 10,7,4,1..... Etc meaning on each start the timer sequence increase the decrease time? How is it possible?
public void robberyCountdown(User player)
{
time = 10;
cd.Elapsed += (source, e) => OnTimer(player);
cd.Start();
}
public void OnTimer(User player)
{
cd.Stop();
cd.Elapsed -= (source, e) => OnTimer(player);
}
Save the delegate you create into a private field so you can access it later:
private ElapsedEventHandler _onTimer;
public void robberyCountdown(User player)
{
time = 10;
_onTimer = (source, e) => OnTimer(player)
cd.Elapsed += _onTimer;
cd.Start();
}
public void OnTimer(User player)
{
cd.Stop();
cd.Elapsed -= _onTimer;
}
Of course, this approach assumes that player will be the same for both. A better way is probably to make your delegate just be constant, and use a private field to keep track of which players are being timed.
private HashSet<Player> _timedPlayers = new HashSet<Player>();
public MyClass() // or whatever your constructor is called
{
cd.Elapsed += OnTimer;
}
public void OnTimer(Object source, ElapsedEventArgs e)
{
foreach(var player in _timedPlayers)
{
// ...
}
}
public void robberyCountdown(User player)
{
time = 10;
_timedPlayers.Add(player);
cd.Start();
}
public void OnTimer(User player)
{
cd.Stop();
_timedPlayers.Remove(player);
}
Related
I am currently developing a multiplayer web game with timer using ASP.NET Core. For real time communication I am using SignalR. Everythning up to the moment had been working just fine.
The way I implemented the timer functionality was the following: I created a static dictionary where the key is the Id of the game and the value is the timer corresponding to the given game. Then I exposed public methods for managing the state of the dictionary:
public class TimerManager
{
private static readonly Dictionary<string, GameTimer> gameTimersByGameIds = new();
public void AttachTimerToGameState(GameTimer timer, string gameId)
{
if (!gameTimersByGameIds.ContainsKey(gameId))
{
gameTimersByGameIds.Add(gameId, timer);
return;
}
gameTimersByGameIds[gameId] = timer;
}
public GameTimer? GetTimer(string gameId)
{
if (!gameTimersByGameIds.ContainsKey(gameId))
{
return null;
}
return gameTimersByGameIds[gameId];
}
public GameTimer CreateTimer(GameState gameState)
{
if (gameState.RemainingSecondsByUserNames.Count == 0)
{
return ActivatorUtilities.CreateInstance<StandardTimer>(_serviceProvider, gameState);
}
else
{
return ActivatorUtilities.CreateInstance<ChessTimer>(_serviceProvider, gameState, _gamesService);
}
}
}
I created my own base GameTimer class which encapsulates a System.Timers.Timer inside of it:
public abstract class GameTimer
{
protected readonly System.Timers.Timer _timer = new();
public virtual void Reset()
{
_timer.AutoReset = true;
_timer.Interval = 1_000;
}
public virtual void Start()
{
_timer.Start();
}
public virtual void Dispose()
{
_timer.Dispose();
}
}
Then I inherited from the abstract GameTimer class to create different types of timers.
public class StandardTimer : GameTimer
public class ChessTimer : GameTimer
The problem is inside of the ChessTimer class:
public class ChessTimer : GameTimer
{
private readonly GameState _gameState;
private readonly IGameService _gameService;
private readonly IHubContext<GameHub, IGameClient> _hubContext;
private readonly IMatchmakingService _matchmakingService;
private readonly IGamesService _gamesService;
public ChessTimer(
GameState gameState,
IGamesService gamesService,
IGameService gameService,
IHubContext<GameHub, IGameClient> hubContext,
IMatchmakingService matchmakingService)
{
_gameState = gameState;
_gameService = gameService;
_hubContext = hubContext;
_matchmakingService = matchmakingService;
_gamesService = gamesService;
Reset();
_timer.Elapsed += async (sender, args) => await OnTimedEvent(sender, args);
}
public int SecondsRemaining { get; private set; }
public override void Reset()
{
string currentPlayerName = _gameState.CurrentTeam.CurrentPlayer.UserName;
SecondsRemaining = _gameState.RemainingSecondsByUserNames[currentPlayerName];
base.Reset();
}
private async Task OnTimedEvent(object? sender, ElapsedEventArgs args)
{
if (SecondsRemaining >= 0)
{
string currentPlayerUserName = _gameState.CurrentTeam.CurrentPlayer.UserName;
_gameState.RemainingSecondsByUserNames[currentPlayerUserName] = SecondsRemaining;
int minutes = SecondsRemaining / 60;
int seconds = SecondsRemaining % 60;
var viewModel = new UpdateGameTimerViewModel
{
Minutes = minutes,
Seconds = seconds,
};
foreach (Player player in _gameState.Players)
{
if (player.ConnectionId == null)
{
continue;
}
await _hubContext.Clients
.Client(player.ConnectionId)
.UpdateGameTimer(viewModel);
}
SecondsRemaining--;
return;
}
if (_gameState.RemainingSecondsByUserNames.All(x => x.Value <= 0))
{
_gameState.EndGame();
}
else
{
_gameState.NextTeam();
}
foreach (Player player in _gameState.Players)
{
_gameService.FillPlayerTiles(_gameState, player);
}
foreach (Player player in _gameState.Players)
{
if (player.ConnectionId == null)
{
continue;
}
var viewModel = _gameService.MapFromGameState(_gameState, player.UserName);
await _hubContext.Clients
.Client(player.ConnectionId)
.UpdateGameState(viewModel);
if (_gameState.IsGameOver)
{
_matchmakingService.RemoveUserFromGame(player.UserName);
await _hubContext.Groups
.RemoveFromGroupAsync(
player.ConnectionId, _gameState.GameId);
}
}
if (_gameState.IsGameOver)
{
_matchmakingService.RemoveGameState(_gameState.GameId);
await _gamesService!.SaveGameAsync(new SaveGameInputModel
{
GameId = _gameState.GameId,
Players = _gameState.Players
});
Dispose();
}
Reset();
}
}
Basically the way my OnTimedEvent method works is that it executes every second. Then checks whether the time of all players has run out. If it hasn't it updates the state of the game, otherwise is ends the game. After everything else is done, I try to save the game inside my database in order to enable the users to see summary about their played games. I am using a class called GamesService for this task. It uses UserManager internally to perform some work with the Users in the database.
if (_gameState.IsGameOver)
{
_matchmakingService.RemoveGameState(_gameState.GameId);
await _gamesService!.SaveGameAsync(new SaveGameInputModel
{
GameId = _gameState.GameId,
Players = _gameState.Players
});
Dispose();
}
Reset();
The problem is that when the game ends and the above code is executed it produces the following exception:
Unhandled exception. Unhandled exception. System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'UserManager`1'.
at Microsoft.AspNetCore.Identity.UserManager`1.ThrowIfDisposed()
at Microsoft.AspNetCore.Identity.UserManager`1.FindByNameAsync(String userName)
at SuperScrabble.Services.Data.Users.UsersService.GetByUserNameAsync(String userName) in C:\Users\georg\Source\Github\SuperScrabble\src\Server\Services\SuperScrabble.Services.Data\Users\UsersService.cs:line 64
at SuperScrabble.Services.Data.Games.GamesService.SaveGameAsync(SaveGameInputModel input) in C:\Users\georg\Source\Github\SuperScrabble\src\Server\Services\SuperScrabble.Services.Data\Games\GamesService.cs:line 52
at SuperScrabble.WebApi.Timers.ChessTimer.OnTimedEvent(Object sender, ElapsedEventArgs args) in C:\Users\georg\Source\Github\SuperScrabble\src\Server\WebApi\SuperScrabble.WebApi\Timers\ChessTimer.cs:line 120
at SuperScrabble.WebApi.Timers.ChessTimer.<.ctor>b__5_0(Object sender, ElapsedEventArgs args) in C:\Users\georg\Source\Github\SuperScrabble\src\Server\WebApi\SuperScrabble.WebApi\Timers\ChessTimer.cs:line 35
at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_1(Object state)
at System.Threading.QueueUserWorkItemCallback.<>c.<.cctor>b__6_0(QueueUserWorkItemCallback quwi)
at System.Threading.ExecutionContext.RunForThreadPoolUnsafe[TState](ExecutionContext executionContext, Action`1 callback, TState& state)
at System.Threading.QueueUserWorkItemCallback.Execute()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
at System.Threading.Thread.StartCallback()
It seems to me that the _gamesService object which I pass to the CreateInstance() method inside the TimerManager.CreateTimer() method is already disposed or that some of the services it uses internally are.
public GameTimer CreateTimer(GameState gameState)
{
if (gameState.RemainingSecondsByUserNames.Count == 0)
{
return ActivatorUtilities.CreateInstance<StandardTimer>(_serviceProvider, gameState);
}
else
{
return ActivatorUtilities.CreateInstance<ChessTimer>(_serviceProvider, gameState, _gamesService);
}
}
I am not sure if what I am trying to do is correct. I need to use service classes inside my timer classes to perform operations every time the timer ticks. However, I cannot use dependency injection and that's the reason why I use the ActivatorUtilities class to instantiate the object.
I create all timers from a method inside my SignalR hub class:
private async Task StartGameAsync()
{
var gameState = _matchmakingService.GetGameState(UserName);
string gameId = gameState.GameId;
foreach (Player player in gameState.Players)
{
await Groups.AddToGroupAsync(player.ConnectionId!, gameId);
}
var timer = _timerManager.CreateTimer(gameState);
Console.WriteLine(timer.GetType().Name);
_timerManager.AttachTimerToGameState(timer, gameId);
await Clients.Group(gameId).StartGame(gameId);
await UpdateGameStateAsync(gameState);
timer.Start();
}
So my question would be: Is it possible to find a work around of the problem?
If you need any more clarification please feel free to ask me anything. Any help would be greatly appreciated! Thanks
When I click a button to load a reward video ad the score should double. Instead the reward ad plays and when I close after watching it, nothing happens. I am using public static variable points to get the score value from the in game scene to the level finished scene, and then I get the total score from player prefabs.
I am new to coding.
Bellow is code.
using GoogleMobileAds.Api;
using System;
using UnityEngine;
using UnityEngine.UI;
public class Admob : MonoBehaviour
{
private BannerView adBanner;
private RewardBasedVideoAd adReward;
int pointts;
int Totalpointts;
private string idApp, idBanner, idReward;
bool saveit = false;
float Timer;
public Text TotalPointsText;
public GameObject congratulationspop;
//public WatchVideo x2coinsWatch;
[SerializeField] Button BtnX2;
// Start is called before the first frame update
[Obsolete]
void Start()
{
//get data
//
idApp = "ca-app-pub-3940256099942544~3347511713";
idBanner = "ca-app-pub-3940256099942544/6300978111";
idReward = "ca-app-pub-3940256099942544/5224354917";
adReward = RewardBasedVideoAd.Instance;
MobileAds.Initialize(idApp);
Debug.LogWarning("Banner Ad Embeded");
RequestBannerAd();
}
// Update is called once per frame
void Update()
{
}
public void GiveRewards()
{
BtnX2.interactable = false;
BtnX2.GetComponentInChildren<Text>().text = "Loading...";
RequestRewardAd();
}
public void RequestBannerAd()
{
adBanner = new BannerView(idBanner, AdSize.Banner, AdPosition.Bottom);
AdRequest request = AdRequestBuild();
adBanner.LoadAd(request);
}
public void DestroyBannerAd()
{
if (adBanner != null)
{
adBanner.Destroy();
}
}
public void RequestRewardAd()
{
AdRequest request = AdRequestBuild();
adReward.LoadAd(request, idReward);
adReward.OnAdLoaded += this.HandleOnRewardedAdLoaded;
adReward.OnAdRewarded += this.HandleOnRewarded;
adReward.OnAdClosed += this.HandleOnRewardedAdClosed;
}
public void ShowRewardAd()
{
if (adReward.IsLoaded())
adReward.Show();
}
public void HandleOnRewardedAdLoaded(object sender, EventArgs args) // Ad Loaded
{
ShowRewardAd();
}
public void HandleOnRewardedAdOpening(object sender, EventArgs args) // Ad Opening
{
}
public void HandleOnRewarded(object sender, EventArgs args) // User Finished Wacthing The Ad
{
// Funtion here to double the coins
x2Thepoints();
}
public void HandleOnRewardedAdClosed(object sender, EventArgs args) // ad closed not watching the
ad
{
BtnX2.interactable = false;
BtnX2.GetComponentInChildren<Text>().text = "X2 Points";
//testing
//testing till here
adReward.OnAdLoaded -= this.HandleOnRewardedAdLoaded;
adReward.OnAdRewarded -= this.HandleOnRewarded;
adReward.OnAdClosed -= this.HandleOnRewardedAdClosed;
}
AdRequest AdRequestBuild()
{
return new AdRequest.Builder().Build();
}
void OnDestroy()
{
DestroyBannerAd();
adReward.OnAdLoaded -= this.HandleOnRewardedAdLoaded;
adReward.OnAdRewarded -= this.HandleOnRewarded;
adReward.OnAdClosed -= this.HandleOnRewardedAdClosed;
}
private void FixedUpdate()
{
Totalpointts = PlayerPrefs.GetInt("points" , Totalpointts);
TotalPointsText.text = "Total Points : " + Totalpointts;
pointts = destination.Mypoint;
Debug.Log(pointts);
if (saveit == true)
{
Timer += Time.deltaTime;
if (Timer >= 2f)
{
Points.inc.OnSavePoint();
saveit = false;
}
}
}
public void x2Thepoints()
{
Totalpointts += pointts;
PlayerPrefs.SetInt("points", Totalpointts);
PlayerPrefs.Save();
saveit = true;
BtnX2.interactable = false;
congratulationspop.SetActive(true);
TotalPointsText.text = "Total Points : " + Totalpointts;
}
}
Set the ad related event handlers before
adReward.LoadAd(request, idReward);
adReward.OnAdLoaded += this.HandleOnRewardedAdLoaded;
adReward.OnAdRewarded += this.HandleOnRewarded;
adReward.OnAdClosed += this.HandleOnRewardedAdClosed;
adReward.LoadAd(request, idReward);
Event handlers are not guaranteed to execute in the Unity main thread. So, force execute them in the next update:
public void HandleOnRewarded(object sender, EventArgs args)
{
MobileAdsEventExecutor.ExecuteInUpdate(() => {
x2Thepoints();
});
}
Unity Google Ads callback events are not guaranteed to be called in the main Unity thread. Try to set you score this way:
public void HandleOnRewarded(object sender, EventArgs args) // User Finished Wacthing The Ad
{
MobileAdsEventExecutor.ExecuteInUpdate(() =>
{
// Funtion here to double the coins
x2Thepoints();
});
}
The method MobileAdsEventExecutor.ExecuteInUpdate runs the callback in the main Unity thread (unity is mono thread).
I'm interested creating an event handling object that you can subscribe for one time execution only and then the action is automatically unsubscribed
Is there similar native functionality in .NET?
Here is what works for me right now:
public class CustomTimer
{
private event Action OneSecond;
private readonly Timer timer;
// Registered actions that should be called only once
private readonly ICollection<Action> oneOffs;
public CustomTimer()
{
this.timer = new Timer { Interval = 1000 };
this.timer.Elapsed += this.OnOneSecond;
this.oneOffs = new HashSet<Action>();
}
public bool IsRunning => this.timer.Enabled;
public void Start()
{
this.timer.Start();
}
public void Stop()
{
this.timer.Stop();
}
public void Subscribe(Action callback)
{
this.OneSecond += callback;
}
public void SubscribeOnce(Action callback)
{
this.oneOffs.Add(callback);
this.Subscribe(callback);
}
public void Unsubscribe(Action callback)
{
this.OneSecond -= callback;
this.oneOffs.Remove(callback);
}
protected virtual void OnOneSecond(object sender, ElapsedEventArgs elapsedEventArgs)
{
this.OneSecond?.Invoke();
this.UnsubscribeOneOffs();
}
private void UnsubscribeOneOffs()
{
if (this.oneOffs.Count > 0)
{
foreach (var action in this.oneOffs)
{
this.OneSecond -= action;
}
this.oneOffs.Clear();
}
}
}
Here the events are set to execute every second.
How can I use similar strategy in other object that trigger events unpredictably
and prevent events execution while the UnsubscribeOneOffs() method is running.
Should I use some kind of lock?
There is no need to register one time actions as OneSecond event handlers. Just keep them in a separate list.
public class CustomTimer
{
List<Action> _oneTimeActions = new List<Action>();
public void SubscribeOnce(Action handler)
{
lock(_oneTimeActions)
{
_oneTimeActions.Add(handler);
}
}
protected virtual void OnOneSecond(object sender, ElapsedEventArgs elapsedEventArgs)
{
// get a local copy of scheduled one time items
// removing them from the list.
Action[] oneTimers;
lock(_oneTimeActions)
{
oneTimers = _oneTimeActions.ToArray();
_oneTimeActions.Clear();
}
// Execute periodic events first
this.OneSecond?.Invoke();
// Now execute one time actions
foreach(var action in oneTimers)
{
action();
}
}
}
I'm trying to measure the time between when I unplug my laptop and battery level reaching 10%.
I've managed to wire up the event so far but I can't figure out where I can store the values of time so that I can do subtraction later.
public class Program
{
public static void Main(string[] args)
{
SystemEvents.PowerModeChanged += OnPowerModeChanged;
Console.ReadLine();
}
public static void OnPowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
if (SystemInformation.PowerStatus.PowerLineStatus.ToString() == "Offline")
{
}
}
}
In this case I would use a member variable to store the DateTimes that you want to observe.
public class Program
{
private static DateTime startTime;
public static void Main(string[] args)
{
SystemEvents.PowerModeChanged += OnPowerModeChanged;
Console.ReadLine();
}
public static void OnPowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
if (SystemInformation.PowerStatus.PowerLineStatus.ToString() == "Offline")
{
this.startTime = DateTime.Now();
}
}
}
Using DateTimes also depends on what level of accuracy you want. If you are talking about measuring anything under a few seconds I would recommend using a System.Diagnostics.Stopwatch instead.
As I mentioned in this question, I am trying to implement a feature in my app whereby placing a cursor over some point for a while (say 3-5 seconds) triggers a double-click event. Based on the answers provided in that thread, I wrote the following. This code is not working as expected. Can someone please help?
#region Timer Mouse Double Click event
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
//Here, the timer for Timer click event will start when mouse hovers over an area
private void form_MouseHover(object sender, System.EventArgs e)
{
timer.Start();
}
private void form_MouseLeave(object sender, System.EventArgs e)
{
timer.Stop();
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
timer.Stop();
DoubleClickEvent();
}
//This method allows the user to click a file/folder by hovering/keeping still the mouse for specified time
void DoubleClickEvent()
{
DoClickMouse(0x2); // Left mouse button down
DoClickMouse(0x4); // Left mouse button up
}
static void DoClickMouse(int mouseButton)
{
var input = new INPUT()
{
dwType = 0, // Mouse input
mi = new MOUSEINPUT() { dwFlags = mouseButton }
};
if (SendInput(1, input, Marshal.SizeOf(input)) == 0)
{
throw new Exception();
}
}
[StructLayout(LayoutKind.Sequential)]
struct MOUSEINPUT
{
int dx;
int dy;
int mouseData;
public int dwFlags;
int time;
IntPtr dwExtraInfo;
}
struct INPUT
{
public uint dwType;
public MOUSEINPUT mi;
}
[DllImport("user32.dll", SetLastError = true)]
static extern uint SendInput(uint cInputs, INPUT input, int size);
#endregion
At first glance if your expecting a double click your are only doing a single click.
Down then up is one mouse click, shouldn't you do.
void DoubleClickEvent()
{
DoClickMouse(0x2); // Left mouse button down
DoClickMouse(0x4); // Left mouse button up
DoClickMouse(0x2); // Left mouse button down
DoClickMouse(0x4); // Left mouse button up
}
I hope it's not bad etiquette to provide two answers, however this is very different from my previous answer I felt editing for improvements wasn't correct.
By the looks of it you only have an event handler on the form, once you hover over a control on your form that will trigger your MouseLeave event of the form.
What you need is to add an event handler to every control on your form, something like this should do it.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.MouseHover += new EventHandler(MouseHoverEvent);
this.MouseLeave +=new EventHandler(MouseLeaveEvent);
timer1.Tick += new EventHandler(timer1_Tick);
foreach (Control item in this.Controls)
{
item.MouseHover += new EventHandler(MouseHoverEvent);
item.MouseLeave += new EventHandler(MouseLeaveEvent);
}
}
void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
DoubleClickEvent();
}
void MouseLeaveEvent(object sender, EventArgs e)
{
timer1.Stop();
}
void MouseHoverEvent(object sender, EventArgs e)
{
timer1.Start();
}
}
It might be better to write this code as a single call to SendInput passing all the mouse downs and ups in one array. If you do this, SendInput guarantees that no other keys get in between the sequence. For example if a user has Alt + N keys held in theory it could sneak in - and change the auto-clicker clicking Yes to instead trigger a No (with a Alt + N keys held).
That being said however, I think the answer to our question is here: SendInput doesn't perform click mouse button unless I move cursor
Basic Idea:
I use MouseAdapter so that I don't have to override everything under the sun.
my MouseAdapter object has a MouseTimer which extends a swing Timer,
and an ActionListener with an overridden anonymous actionPerformed method.
I may have over thought/ or under thought when to start and stop the timer object.
Basically all it does is print out when it is single clicked or when it is double clicked.
package mouseUtils;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.Timer;
/**
*
* #author jcpartri
*/
public class MyMouseAdapter extends MouseAdapter{
private Integer mouseDoubleClickInterval = (int)
Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval");
private MouseEvent event = null;
private ActionListener taskPerformer = new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
if(event.getClickCount() == 2){
//mouseDoubleClicked(event);
mouseTimer.stop();
}
if(event.getClickCount() == 1){
//mouseSingleClicked(event);
mouseTimer.stop();
}
}
};
Class MouseTimer is a child of class Timer. When the Timer fires after a delay, there is a check to see if there was a single or double click within that timespan.
private MouseTimer mouseTimer = new
MouseTimer(getMouseDoubleClickInterval(),taskPerformer);
//The DebugClock helps me to see how long a process that I have programmed takes from
start to finish.
private DebugClock clock = new DebugClock();
//Constructors
public MyMouseAdapter(){
super();
}
#Override
public void mouseClicked(MouseEvent e){
event = e;
if(e.getClickCount() == 1){
mouseTimer.setInitialDelay(mouseDoubleClickInterval);
mouseTimer.start();
}
mouseTimer.setNumOfClicks();
}
public void mouseSingleClicked(MouseEvent e){
p("Mouse was SingleClicked!!!\n");
}
public void mouseDoubleClicked(MouseEvent e){
p("Mouse was DoubleClicked!!!\n");
}
#Override
public void mouseMoved(MouseEvent e){
event = e;
mouseTimer.resetNumOfClicks();
mouseTimer.stop();
}
//Setters and Getters for MouseAdapter
public Integer getMouseDoubleClickInterval(){
return this.mouseDoubleClickInterval;
}
//Timer Classes
private class MouseTimer extends Timer{
//Constructors
public MouseTimer(int delay, ActionListener taskPerformer){
super(delay,taskPerformer);
}
//Instance variables
private int numOfClicks = 0;
//Setters and Getters
public int getNumOfClicks(){
return this.numOfClicks;
}
public void setNumOfClicks(){
this.numOfClicks++;
}
public void resetNumOfClicks(){
this.numOfClicks = 0;
}
}
//Basic Printing Classes
private void p(String message){
System.out.print(message);
}
}
class DebugClock{
private long startTime = 0;
private long endTime = 0;
//Setters and Getters
public long getStartTime(){
return this.startTime;
}
public void setStartTime(long start){
this.startTime = start;
}
public long getEndTime(){
return this.endTime;
}
public void setEndTime(long end){
this.endTime = end;
}
//Constructors
public DebugClock(){
}
//Methods
public float getTimeInMilliSeconds(){
float seconds = (this.endTime - this.startTime);
return seconds;
}
}