



import os
from pathlib import Path

import numpy as np
import pytest
from pack_dataset import pack_data_dir
from parameterized import parameterized
from save_len_file import save_len_file
from torch.utils.data import DataLoader

from transformers import AutoTokenizer
from transformers.models.mbart.modeling_mbart import shift_tokens_right
from transformers.testing_utils import TestCasePlus, slow
from utils import FAIRSEQ_AVAILABLE, DistributedSortishSampler, LegacySeqaSeqDataset, SeqaSeqDataset


_lowerCamelCase    :		Optional[int]		      =    """bert-base-cased"""
_lowerCamelCase    :		List[str]		      =    """google/pegasus-xsum"""
_lowerCamelCase    :		List[Any]		      =    [""" Sam ate lunch today.""", """Sams lunch ingredients."""]
_lowerCamelCase    :		Any		      =    ["""A very interesting story about what I ate for lunch.""", """Avocado, celery, turkey, coffee"""]
_lowerCamelCase    :		Any		      =    """patrickvonplaten/t5-tiny-random"""
_lowerCamelCase    :		List[Any]		      =    """sshleifer/bart-tiny-random"""
_lowerCamelCase    :		int		      =    """sshleifer/tiny-mbart"""
_lowerCamelCase    :		Dict		      =    """sshleifer/tiny-marian-en-de"""

def        __a			(   __lowerCAmelCase      ,	__lowerCAmelCase   )     ->     Any:
					SCREAMING_SNAKE_CASE							:     Union[str, Any]						=				'\n'.join(__lowerCAmelCase   )
					Path(__lowerCAmelCase   ).open('w'   ).writelines(__lowerCAmelCase   )

def        __a			(   __lowerCAmelCase   )     ->     Optional[int]:
					for split in ["train", "val", "test"]:
										_dump_articles(os.path.join(__lowerCAmelCase      ,	F'''{split}.source'''   )      ,	__lowerCAmelCase   )
										_dump_articles(os.path.join(__lowerCAmelCase      ,	F'''{split}.target'''   )      ,	__lowerCAmelCase   )
					return tmp_dir



class 						lowercase    (							SCREAMING_SNAKE_CASE_):
						'''simple docstring'''


						@parameterized.expand(
						    [
						        MBART_TINY,
						        MARIAN_TINY,
						        T5_TINY,
						        BART_TINY,
						        PEGASUS_XSUM,
						    ]       ,	)
						@slow
						def       lowerCamelCase_				(  self    :				str       ,	snake_case    :				List[str]	):



											'''simple docstring'''


											SCREAMING_SNAKE_CASE							:     int						=				AutoTokenizer.from_pretrained(snake_case	)
											SCREAMING_SNAKE_CASE							:     int						=				make_test_data_dir(tmp_dir=self.get_auto_remove_tmp_dir()	)
											SCREAMING_SNAKE_CASE							:     List[Any]						=				max(len(tokenizer.encode(snake_case	)	) for a in ARTICLES	)
											SCREAMING_SNAKE_CASE							:     Any						=				max(len(tokenizer.encode(snake_case	)	) for a in SUMMARIES	)
											SCREAMING_SNAKE_CASE							:     Optional[Any]						=				4
											SCREAMING_SNAKE_CASE							:     int						=				8
											assert max_len_target > max_src_len  # Will be truncated
											assert max_len_source > max_src_len  # Will be truncated
											SCREAMING_SNAKE_CASE					,  SCREAMING_SNAKE_CASE							:     List[Any]						=				'ro_RO', 'de_DE'  # ignored for all but mbart, but never causes error.
											SCREAMING_SNAKE_CASE							:     Union[str, Any]						=				SeqaSeqDataset(
											    snake_case       ,	data_dir=snake_case       ,	type_path='train'       ,	max_source_length=snake_case       ,	max_target_length=snake_case       ,	src_lang=snake_case       ,	tgt_lang=snake_case       ,	)
											SCREAMING_SNAKE_CASE							:     int						=				DataLoader(snake_case       ,	batch_size=2       ,	collate_fn=train_dataset.collate_fn	)
											for batch in dataloader:
																assert isinstance(snake_case       ,	snake_case	)
																assert batch["attention_mask"].shape == batch["input_ids"].shape
																# show that articles were trimmed.
																assert batch["input_ids"].shape[1] == max_src_len
																# show that targets are the same len
																assert batch["labels"].shape[1] == max_tgt_len
																if tok_name != MBART_TINY:
																					continue
																# check language codes in correct place
																SCREAMING_SNAKE_CASE							:     int						=				shift_tokens_right(batch['labels']       ,	tokenizer.pad_token_id	)
																assert batch["decoder_input_ids"][0, 0].item() == tokenizer.lang_code_to_id[tgt_lang]
																assert batch["decoder_input_ids"][0, -1].item() == tokenizer.eos_token_id
																assert batch["input_ids"][0, -2].item() == tokenizer.eos_token_id
																assert batch["input_ids"][0, -1].item() == tokenizer.lang_code_to_id[src_lang]

																break  # No need to test every batch







						@parameterized.expand([BART_TINY, BERT_BASE_CASED]	)
						def       lowerCamelCase_				(  self    :				Any       ,	snake_case    :				List[str]	):



											'''simple docstring'''


											SCREAMING_SNAKE_CASE							:     Tuple						=				AutoTokenizer.from_pretrained(snake_case	)
											SCREAMING_SNAKE_CASE							:     Dict						=				make_test_data_dir(tmp_dir=self.get_auto_remove_tmp_dir()	)
											SCREAMING_SNAKE_CASE							:     Any						=				max(len(tokenizer.encode(snake_case	)	) for a in ARTICLES	)
											SCREAMING_SNAKE_CASE							:     Dict						=				max(len(tokenizer.encode(snake_case	)	) for a in SUMMARIES	)
											SCREAMING_SNAKE_CASE							:     str						=				4
											SCREAMING_SNAKE_CASE							:     str						=				LegacySeqaSeqDataset(
											    snake_case       ,	data_dir=snake_case       ,	type_path='train'       ,	max_source_length=20       ,	max_target_length=snake_case       ,	)
											SCREAMING_SNAKE_CASE							:     Dict						=				DataLoader(snake_case       ,	batch_size=2       ,	collate_fn=train_dataset.collate_fn	)
											for batch in dataloader:
																assert batch["attention_mask"].shape == batch["input_ids"].shape
																# show that articles were trimmed.
																assert batch["input_ids"].shape[1] == max_len_source
																assert 20 >= batch["input_ids"].shape[1]  # trimmed significantly
																# show that targets were truncated
																assert batch["labels"].shape[1] == trunc_target  # Truncated
																assert max_len_target > trunc_target  # Truncated
																break  # No need to test every batch







						def       lowerCamelCase_				(  self    :				List[str]	):



											'''simple docstring'''


											SCREAMING_SNAKE_CASE							:     Tuple						=				AutoTokenizer.from_pretrained('facebook/mbart-large-cc25'	)

											SCREAMING_SNAKE_CASE							:     Optional[Any]						=				Path(make_test_data_dir(tmp_dir=self.get_auto_remove_tmp_dir()	)	)
											SCREAMING_SNAKE_CASE							:     int						=				tmp_dir.joinpath('train.source'	).open().readlines()
											SCREAMING_SNAKE_CASE							:     Optional[Any]						=				Path(make_test_data_dir(tmp_dir=self.get_auto_remove_tmp_dir()	)	)
											pack_data_dir(snake_case       ,	snake_case       ,	128       ,	snake_case	)
											SCREAMING_SNAKE_CASE							:     List[Any]						=				{x.name for x in tmp_dir.iterdir()}
											SCREAMING_SNAKE_CASE							:     Dict						=				{x.name for x in save_dir.iterdir()}
											SCREAMING_SNAKE_CASE							:     Union[str, Any]						=				save_dir.joinpath('train.source'	).open().readlines()
											# orig: [' Sam ate lunch today.\n', 'Sams lunch ingredients.']
											# desired_packed: [' Sam ate lunch today.\n Sams lunch ingredients.']
											assert len(snake_case	) < len(snake_case	)
											assert len(snake_case	) == 1
											assert len(packed_examples[0]	) == sum(len(snake_case	) for x in orig_examples	)
											assert orig_paths == new_paths







						@pytest.mark.skipif(not FAIRSEQ_AVAILABLE       ,	reason='This test requires fairseq'	)
						def       lowerCamelCase_				(  self    :				int	):



											'''simple docstring'''


											if not FAIRSEQ_AVAILABLE:
																return
											SCREAMING_SNAKE_CASE					,  SCREAMING_SNAKE_CASE					,  SCREAMING_SNAKE_CASE							:     Optional[int]						=				self._get_dataset(max_len=64	)
											SCREAMING_SNAKE_CASE							:     Optional[Any]						=				64
											SCREAMING_SNAKE_CASE							:     List[Any]						=				ds.make_dynamic_sampler(snake_case       ,	required_batch_size_multiple=snake_case	)
											SCREAMING_SNAKE_CASE							:     List[str]						=				[len(snake_case	) for x in batch_sampler]
											assert len(set(snake_case	)	) > 1  # it's not dynamic batch size if every batch is the same length
											assert sum(snake_case	) == len(snake_case	)  # no dropped or added examples
											SCREAMING_SNAKE_CASE							:     Any						=				DataLoader(snake_case       ,	batch_sampler=snake_case       ,	collate_fn=ds.collate_fn       ,	num_workers=2	)
											SCREAMING_SNAKE_CASE							:     Tuple						=				[]
											SCREAMING_SNAKE_CASE							:     List[Any]						=				[]
											for batch in data_loader:
																SCREAMING_SNAKE_CASE							:     List[Any]						=				batch['input_ids'].shape
																SCREAMING_SNAKE_CASE							:     List[str]						=				src_shape[0]
																assert bs % required_batch_size_multiple == 0 or bs < required_batch_size_multiple
																SCREAMING_SNAKE_CASE							:     List[Any]						=				np.product(batch['input_ids'].shape	)
																num_src_per_batch.append(snake_case	)
																if num_src_tokens > (max_tokens * 1.1):
																					failures.append(snake_case	)
											assert num_src_per_batch[0] == max(snake_case	)
											if failures:
																raise AssertionError(f'''too many tokens in {len(snake_case	)} batches'''	)







						def       lowerCamelCase_				(  self    :				Optional[int]	):



											'''simple docstring'''


											SCREAMING_SNAKE_CASE					,  SCREAMING_SNAKE_CASE					,  SCREAMING_SNAKE_CASE							:     Optional[int]						=				self._get_dataset(max_len=512	)
											SCREAMING_SNAKE_CASE							:     Any						=				2
											SCREAMING_SNAKE_CASE							:     Any						=				ds.make_sortish_sampler(snake_case       ,	shuffle=snake_case	)

											SCREAMING_SNAKE_CASE							:     Union[str, Any]						=				DataLoader(snake_case       ,	batch_size=snake_case       ,	collate_fn=ds.collate_fn       ,	num_workers=2	)
											SCREAMING_SNAKE_CASE							:     List[Any]						=				DataLoader(snake_case       ,	batch_size=snake_case       ,	collate_fn=ds.collate_fn       ,	num_workers=2       ,	sampler=snake_case	)

											SCREAMING_SNAKE_CASE							:     Union[str, Any]						=				tokenizer.pad_token_id

											def count_pad_tokens(snake_case    :				Union[str, Any]       ,	snake_case    :				List[str]="input_ids"	):
																return [batch[k].eq(snake_case	).sum().item() for batch in data_loader]

											assert sum(count_pad_tokens(snake_case       ,	k='labels'	)	) < sum(count_pad_tokens(snake_case       ,	k='labels'	)	)
											assert sum(count_pad_tokens(snake_case	)	) < sum(count_pad_tokens(snake_case	)	)
											assert len(snake_case	) == len(snake_case	)







						def       lowerCamelCase_				(  self    :				Optional[Any]       ,	snake_case    :				Dict=1000       ,	snake_case    :				Optional[Any]=128	):



											'''simple docstring'''


											if os.getenv('USE_REAL_DATA'       ,	snake_case	):
																SCREAMING_SNAKE_CASE							:     Any						=				'examples/seq2seq/wmt_en_ro'
																SCREAMING_SNAKE_CASE							:     int						=				max_len * 2 * 64
																if not Path(snake_case	).joinpath('train.len'	).exists():
																					save_len_file(snake_case       ,	snake_case	)
											else:
																SCREAMING_SNAKE_CASE							:     int						=				'examples/seq2seq/test_data/wmt_en_ro'
																SCREAMING_SNAKE_CASE							:     int						=				max_len * 4
																save_len_file(snake_case       ,	snake_case	)

											SCREAMING_SNAKE_CASE							:     Union[str, Any]						=				AutoTokenizer.from_pretrained(snake_case	)
											SCREAMING_SNAKE_CASE							:     int						=				SeqaSeqDataset(
											    snake_case       ,	data_dir=snake_case       ,	type_path='train'       ,	max_source_length=snake_case       ,	max_target_length=snake_case       ,	n_obs=snake_case       ,	)
											return ds, max_tokens, tokenizer







						def       lowerCamelCase_				(  self    :				Optional[int]	):



											'''simple docstring'''


											SCREAMING_SNAKE_CASE					,  SCREAMING_SNAKE_CASE					,  SCREAMING_SNAKE_CASE							:     Optional[Any]						=				self._get_dataset()
											SCREAMING_SNAKE_CASE							:     Any						=				set(DistributedSortishSampler(snake_case       ,	256       ,	num_replicas=2       ,	rank=0       ,	add_extra_examples=snake_case	)	)
											SCREAMING_SNAKE_CASE							:     Optional[Any]						=				set(DistributedSortishSampler(snake_case       ,	256       ,	num_replicas=2       ,	rank=1       ,	add_extra_examples=snake_case	)	)
											assert idsa.intersection(snake_case	) == set()







						@parameterized.expand(
						    [
						        MBART_TINY,
						        MARIAN_TINY,
						        T5_TINY,
						        BART_TINY,
						        PEGASUS_XSUM,
						    ]       ,	)
						def       lowerCamelCase_				(  self    :				Dict       ,	snake_case    :				Union[str, Any]	):



											'''simple docstring'''


											SCREAMING_SNAKE_CASE							:     Dict						=				AutoTokenizer.from_pretrained(snake_case       ,	use_fast=snake_case	)
											if tok_name == MBART_TINY:
																SCREAMING_SNAKE_CASE							:     str						=				SeqaSeqDataset(
																    snake_case       ,	data_dir=make_test_data_dir(tmp_dir=self.get_auto_remove_tmp_dir()	)       ,	type_path='train'       ,	max_source_length=4       ,	max_target_length=8       ,	src_lang='EN'       ,	tgt_lang='FR'       ,	)
																SCREAMING_SNAKE_CASE							:     List[str]						=				train_dataset.dataset_kwargs
																assert "src_lang" in kwargs and "tgt_lang" in kwargs
											else:
																SCREAMING_SNAKE_CASE							:     List[Any]						=				SeqaSeqDataset(
																    snake_case       ,	data_dir=make_test_data_dir(tmp_dir=self.get_auto_remove_tmp_dir()	)       ,	type_path='train'       ,	max_source_length=4       ,	max_target_length=8       ,	)
																SCREAMING_SNAKE_CASE							:     List[str]						=				train_dataset.dataset_kwargs
																assert "add_prefix_space" not in kwargs if tok_name != BART_TINY else "add_prefix_space" in kwargs
																assert len(snake_case	) == 1 if tok_name == BART_TINY else len(snake_case	) == 0




from __future__ import annotations

import time
from math import sqrt

# 1 for manhattan, 0 for euclidean
_lowerCamelCase    :		List[str]		      =    0

_lowerCamelCase    :		Tuple		      =    [
    [0, 0, 0, 0, 0, 0, 0],
    [0, 1, 0, 0, 0, 0, 0],  # 0 are free path whereas 1's are obstacles
    [0, 0, 0, 0, 0, 0, 0],
    [0, 0, 1, 0, 0, 0, 0],
    [1, 0, 1, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 1, 0, 0],
]

_lowerCamelCase    :		Tuple		      =    [[-1, 0], [0, -1], [1, 0], [0, 1]]  # up, left, down, right

_lowerCamelCase    :		Union[str, Any]		      =    tuple[int, int]


class 						lowercase    :
						'''simple docstring'''


						def __init__(  self    :				Optional[Any]       ,	snake_case    :				int       ,	snake_case    :				int       ,	snake_case    :				int       ,	snake_case    :				int       ,	snake_case    :				int       ,	snake_case    :				Node | None       ,	):



											'''simple docstring'''


											SCREAMING_SNAKE_CASE							:     Tuple						=				pos_x
											SCREAMING_SNAKE_CASE							:     str						=				pos_y
											SCREAMING_SNAKE_CASE							:     Any						=				(pos_y, pos_x)
											SCREAMING_SNAKE_CASE							:     List[str]						=				goal_x
											SCREAMING_SNAKE_CASE							:     Optional[Any]						=				goal_y
											SCREAMING_SNAKE_CASE							:     int						=				g_cost
											SCREAMING_SNAKE_CASE							:     Any						=				parent
											SCREAMING_SNAKE_CASE							:     List[Any]						=				self.calculate_heuristic()
											SCREAMING_SNAKE_CASE							:     str						=				self.g_cost + self.h_cost







						def       lowerCamelCase_				(  self    :				Optional[int]	):



											'''simple docstring'''


											SCREAMING_SNAKE_CASE							:     int						=				self.pos_x - self.goal_x
											SCREAMING_SNAKE_CASE							:     str						=				self.pos_y - self.goal_y
											if HEURISTIC == 1:
																return abs(snake_case	) + abs(snake_case	)
											else:
																return sqrt(dy**2 + dx**2	)







						def __lt__(  self    :				Any       ,	snake_case    :				Node	):



											'''simple docstring'''


											return self.f_cost < other.f_cost


class 						lowercase    :
						'''simple docstring'''


						def __init__(  self    :				Optional[Any]       ,	snake_case    :				TPosition       ,	snake_case    :				TPosition	):



											'''simple docstring'''


											SCREAMING_SNAKE_CASE							:     Union[str, Any]						=				Node(start[1]       ,	start[0]       ,	goal[1]       ,	goal[0]       ,	0       ,	snake_case	)
											SCREAMING_SNAKE_CASE							:     int						=				Node(goal[1]       ,	goal[0]       ,	goal[1]       ,	goal[0]       ,	99999       ,	snake_case	)

											SCREAMING_SNAKE_CASE							:     Any						=				[self.start]
											SCREAMING_SNAKE_CASE							:     list[Node]						=				[]

											SCREAMING_SNAKE_CASE							:     int						=				False







						def       lowerCamelCase_				(  self    :				str	):



											'''simple docstring'''


											while self.open_nodes:
																# Open Nodes are sorted using __lt__
																self.open_nodes.sort()
																SCREAMING_SNAKE_CASE							:     Dict						=				self.open_nodes.pop(0	)

																if current_node.pos == self.target.pos:
																					return self.retrace_path(snake_case	)

																self.closed_nodes.append(snake_case	)
																SCREAMING_SNAKE_CASE							:     int						=				self.get_successors(snake_case	)

																for child_node in successors:
																					if child_node in self.closed_nodes:
																										continue

																					if child_node not in self.open_nodes:
																										self.open_nodes.append(snake_case	)
																					else:
																										# retrieve the best current path
																										SCREAMING_SNAKE_CASE							:     Union[str, Any]						=				self.open_nodes.pop(self.open_nodes.index(snake_case	)	)

																										if child_node.g_cost < better_node.g_cost:
																															self.open_nodes.append(snake_case	)
																										else:
																															self.open_nodes.append(snake_case	)

											return [self.start.pos]







						def       lowerCamelCase_				(  self    :				str       ,	snake_case    :				Node	):



											'''simple docstring'''


											SCREAMING_SNAKE_CASE							:     Tuple						=				[]
											for action in delta:
																SCREAMING_SNAKE_CASE							:     Optional[Any]						=				parent.pos_x + action[1]
																SCREAMING_SNAKE_CASE							:     Union[str, Any]						=				parent.pos_y + action[0]
																if not (0 <= pos_x <= len(grid[0]	) - 1 and 0 <= pos_y <= len(snake_case	) - 1):
																					continue

																if grid[pos_y][pos_x] != 0:
																					continue

																successors.append(
																    Node(
																        snake_case       ,	snake_case       ,	self.target.pos_y       ,	self.target.pos_x       ,	parent.g_cost + 1       ,	snake_case       ,	)	)
											return successors







						def       lowerCamelCase_				(  self    :				Optional[int]       ,	snake_case    :				Node | None	):



											'''simple docstring'''


											SCREAMING_SNAKE_CASE							:     Optional[int]						=				node
											SCREAMING_SNAKE_CASE							:     List[Any]						=				[]
											while current_node is not None:
																path.append((current_node.pos_y, current_node.pos_x)	)
																SCREAMING_SNAKE_CASE							:     Dict						=				current_node.parent
											path.reverse()
											return path


class 						lowercase    :
						'''simple docstring'''


						def __init__(  self    :				str       ,	snake_case    :				TPosition       ,	snake_case    :				TPosition	):



											'''simple docstring'''


											SCREAMING_SNAKE_CASE							:     Any						=				AStar(snake_case       ,	snake_case	)
											SCREAMING_SNAKE_CASE							:     Optional[int]						=				AStar(snake_case       ,	snake_case	)
											SCREAMING_SNAKE_CASE							:     str						=				False







						def       lowerCamelCase_				(  self    :				Optional[int]	):



											'''simple docstring'''


											while self.fwd_astar.open_nodes or self.bwd_astar.open_nodes:
																self.fwd_astar.open_nodes.sort()
																self.bwd_astar.open_nodes.sort()
																SCREAMING_SNAKE_CASE							:     Dict						=				self.fwd_astar.open_nodes.pop(0	)
																SCREAMING_SNAKE_CASE							:     Any						=				self.bwd_astar.open_nodes.pop(0	)

																if current_bwd_node.pos == current_fwd_node.pos:
																					return self.retrace_bidirectional_path(
																					    snake_case       ,	snake_case	)

																self.fwd_astar.closed_nodes.append(snake_case	)
																self.bwd_astar.closed_nodes.append(snake_case	)

																SCREAMING_SNAKE_CASE							:     str						=				current_bwd_node
																SCREAMING_SNAKE_CASE							:     int						=				current_fwd_node

																SCREAMING_SNAKE_CASE							:     str						=				{
																    self.fwd_astar: self.fwd_astar.get_successors(snake_case	),
																    self.bwd_astar: self.bwd_astar.get_successors(snake_case	),
																}

																for astar in [self.fwd_astar, self.bwd_astar]:
																					for child_node in successors[astar]:
																										if child_node in astar.closed_nodes:
																															continue

																										if child_node not in astar.open_nodes:
																															astar.open_nodes.append(snake_case	)
																										else:
																															# retrieve the best current path
																															SCREAMING_SNAKE_CASE							:     List[Any]						=				astar.open_nodes.pop(
																															    astar.open_nodes.index(snake_case	)	)

																															if child_node.g_cost < better_node.g_cost:
																																				astar.open_nodes.append(snake_case	)
																															else:
																																				astar.open_nodes.append(snake_case	)

											return [self.fwd_astar.start.pos]







						def       lowerCamelCase_				(  self    :				str       ,	snake_case    :				Node       ,	snake_case    :				Node	):



											'''simple docstring'''


											SCREAMING_SNAKE_CASE							:     Union[str, Any]						=				self.fwd_astar.retrace_path(snake_case	)
											SCREAMING_SNAKE_CASE							:     Optional[Any]						=				self.bwd_astar.retrace_path(snake_case	)
											bwd_path.pop()
											bwd_path.reverse()
											SCREAMING_SNAKE_CASE							:     Union[str, Any]						=				fwd_path + bwd_path
											return path


if __name__ == "__main__":
			# all coordinates are given in format [y,x]
			_lowerCamelCase    :		Tuple		      =    (0, 0)
			_lowerCamelCase    :		Dict		      =    (len(grid) - 1, len(grid[0]) - 1)
			for elem in grid:
						print(elem)

			_lowerCamelCase    :		Union[str, Any]		      =    time.time()
			_lowerCamelCase    :		List[str]		      =    AStar(init, goal)
			_lowerCamelCase    :		Optional[int]		      =    a_star.search()
			_lowerCamelCase    :		str		      =    time.time() - start_time
			print(f"""AStar execution time = {end_time:f} seconds""")

			_lowerCamelCase    :		Optional[Any]		      =    time.time()
			_lowerCamelCase    :		Union[str, Any]		      =    BidirectionalAStar(init, goal)
			_lowerCamelCase    :		List[Any]		      =    time.time() - bd_start_time
			print(f"""BidirectionalAStar execution time = {bd_end_time:f} seconds""")