# Stopwatch Manager

## Guide

When we use Stopwatch in some simple projects, we usually only create one Stopwatch instance.

```python
demo_stopwatch: Stopwatch = Stopwatch()
```

But in some medium and large projects, we may need to use multiple Stopwatch instances and share them globally. At this point, the Stopwatch instance created directly above may not be easy to share and maintain globally. When multiple Stopwatch instances are required, the management and maintenance of instance objects becomes complicated.

In 0.1.3 or higher, we can use one or more Stopwatch managers to host these Stopwatch instances and share them globally, without the developer having to maintain them.

In the following, we will show you how to use the Stopwatch Manager with a few paragraphs of Python code.

### Import module

Before using the Stopwatch Manager, we should import the `StopwatchManager`:

```python
from stopwatch import StopwatchManager
```

If you don't need multiple Stopwatch Manager instances, you can use the default Stopwatch Manager directly and share it globally.

```python
from stopwatch import default_manager
```

The symbol `default_manager` is a variable of data type `StopwatchManager` that is created when the package `stopwatch` is first imported. Therefore, you can import this variable globally to share the Stopwatch default manager instance globally.

### Create manager

If the Stopwatch default manager is not sufficient to meet your needs, you can create additional Stopwatch manager instances.

```python
demo_manager: StopwatchManager = StopwatchManager(
    max_stopwatch_count = None
)
```

The constructor method of class `StopwatchManager` has an optional parameter `max_stopwatch_count` of data type int that indicates how many Stopwatch instances can be hosted by the Stopwatch manager being created at the same time. If this parameter is not supplied or the value is `None`, the number of Stopwatch instances is not limited.

### Add Stopwatch

At the beginning of this tutorial, we defined a variable called `demo_stopwatch`, which is a Stopwatch instance. Now we try to add `demo_stopwatch` to the Stopwatch manager instance `demo_manager` created above.

```python
demo_manager.add(
    stopwatch_name = 'guide::demo1', 
    stopwatch_instance = demo_stopwatch
)
```

The method `add` has 2 parameters, which are:

| Parameter           | Type      | Required | Description                                   |
| ------------------- | --------- | -------- | --------------------------------------------- |
| stopwatch\_name     | str       | True     | The unique name of the Stopwatch instance.    |
| stopwatch\_instance | Stopwatch | True     | The Stopwatch instance object that was added. |

We strongly recommend that you name the Stopwatch instance unique name in the form of a `namespace::name` so that when multiple collaborative projects are in the same global scope, the Stopwatch instance unique name conflict is not raised and the Namespace can be the project name.

{% hint style="danger" %}
Note that the Stopwatch instance name must be unique within the current Stopwatch manager scope, otherwise a StopwatchNameError exception will be thrown.
{% endhint %}

If the number of Stopwatch instances that are currently hosted in the Stopwatch Manager equals or exceeds the limit of the `max_stopwatch_count` parameter, a `MaxLimitError` exception is thrown.

### Create Stopwatch

In addition to adding an existing Stopwatch instance to the Stopwatch manager, we can also create a new Stopwatch instance with the default constructor method parameters directly in the Stopwatch manager.

```python
new_stopwatch: Stopwatch = demo_manager.create(
    stopwatch_name = 'guide::demo2'
)
```

The method `create` has a parameter `stopwatch_name` of data type `str`, which indicates the unique name of the newly created and added Stopwatch instance. When created and added, this method returns a Stopwatch instance object of data type Stopwatch.

We can also create and add a Stopwatch instance to make it start timing.

```python
new_stopwatch: Stopwatch = demo_manager.create_and_start(
    stopwatch_name = 'guide::demo2'
)
```

### Remove Stopwatch

We can do this when we need to remove the Stopwatch instance with the specified unique name from the Stopwatch Manager.

```python
demo_manager.remove(
    stopwatch_name = 'guide::demo2'
)
```

If you need to remove all Stopwatch instances, you can use the `clear` method.

```python
demo_manager.clear()
```

{% hint style="danger" %}
Note that if the specified Stopwatch instance unique name does not exist, a StopwatchNameError exception will be thrown.
{% endhint %}

### Get Stopwatch

When we need to share a Stopwatch instance globally within the project, we don't need to maintain these Stopwatch instances, we use the unique name of the Stopwatch instance to get it from the Stopwatch manager.

```python
demo_stopwatch: Stopwatch = demo_manager.get(
    stopwatch_name = 'guide::demo1'
)
```

If we need to determine if a Stopwatch instance exists, we can check it with the `has` method.

```python
if not demo_manager.has(
    stopwatch_name = 'guide::demo2'
):
    print('no such stopwatch')
```

### Manage Stopwatch

#### Get the number of instances

The `get_count` method can be used when we need to get the number of Stopwatch instances that the specified Stopwatch manager has hosted.

```python
number_of_stopwatchs: int = demo_manager.get_count()
```

The method `get_count` has a return value of the `int` data type, which indicates the number of Stopwatch instances.

#### Make the instance start timing

The `starts` method can be used when we need to start specifying a batch or all of the Stopwatch instances.

```python
demo_manager.starts(
    stopwatch_names = [
        'guide::demo1', 
        ...
    ]
)
```

The method `starts` has an optional parameter `stopwatch_names` with the data type `list`, which indicates a list of unique names for the Stopwatch instance that needs to be started. If this parameter is not supplied or the value is `None`, all Stopwatch instances are started.

This method returns a return value of data type int indicating the number of Stopwatch instances that actually started.

{% hint style="danger" %}
Note that if one or more instances have started timing, the method will skip instead of raising a StatusError exception.
{% endhint %}

### Stop the instance timing

Similarly, we can also stop specifying a batch or all of the Stopwatch instances.

```python
demo_manager.stops(
    stopwatch_names = [
        'guide::demo1', 
        ...
    ]
)
```

This method returns a return value of data type `int` indicating the number of Stopwatch instances that were actually stopped.

{% hint style="danger" %}
Note that if one or more instances have stopped timing, the method will skip instead of raising a StatusError exception.
{% endhint %}

#### Reset the instance

In addition to starting timing and stopping timing, we can also reset a specified batch or all of the Stopwatch instances.

```python
demo_manager.resets(
    stopwatch_names = [
        'guide::demo1', 
        ...
    ]
)
```

#### Get the total duration of the instance

The `get_watchs` method can be used when we need to get the current total duration for a specified batch or all of the Stopwatch instances.

```python
total_of_watch: float = demo_manager.get_watchs(
    stopwatch_names = [
        'guide::demo1', 
        ...
    ], 
    watch_precision = 3
)
```

The method `get_watchs` has an optional parameter `watch_precision` with an extra data type of `int` relative to the other methods mentioned above, which indicates the precision of the total time (the number of decimal places). If this parameter is not supplied or the value is `None`, its behavior is consistent with the behavior of the `watch_precision` of the Stopwatch instance's `get_watch` method.

## Example

### Source code

{% code title="quickstart.py" %}

```python
# quickstart.py is python-3.7.4 source file

import time

from stopwatch import Stopwatch
from stopwatch import StopwatchManager


# define main function

def main():

    # create a stopwatch manager
    
    demo_manager: StopwatchManager = StopwatchManager(
        max_stopwatch_count = 64
    )
    
    # Start timing after creating and adding a stopwatch instance to the manager
    
    demo_manager.create('guide::demo1').start()
    
    # simulated program time-consuming operation
    
    time.sleep(1)
    
    # get the stopwatch instance from the manager and stop timing.
    
    demo_manager.get('guide::demo1').stop()
    
    # total time duration after getting a stopwatch instance from the manager
    
    print(demo_manager.get('guide::demo1').get_watch())
    
    # remove the stopwatch instance from the manager.
    
    demo_manager.remove('guide::demo1')


# define virtual main function

if __name__ == '__main__':
    main()
```

{% endcode %}

### Result

```
1.0
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://smallso.gitbook.io/stopwatch/en/python/getting-started/stopwatch-manager.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
